読者です 読者をやめる 読者になる 読者になる

ぶり2.3を適当に読む

s2buri

新年も明けたので、心を入れ替えてぼちぼち読んでみようかと思います。
脱線しまくりだったりもしますが。

あと、自分向けのメモをエイヤッと載っけただけなので雑な文体ですが、その辺はご了承くださいませ。

BuriEngineConfig#getFileConfigs()

ってdeprecatedなのかな?
誰も使ってないみたい。
add/getResouceConfigs()で事足りてるように見える...。
それとも将来的に何かに利用する予定があったりする?

カスタマイズが必要なdicon

ユーザはburi-user.diconをカスタマイズすればいいらしい。

buri/dicon配下をコピペで持ってきて自前アプリにずらっと並べるのも気持ち悪いなぁ...。
必要なdiconだけ用意して残りはjar内のdiconでOK!みたく使えないかな?★

Scriptの抽象化

org.seasar.coffee.scriptパッケージ配下にScript関係のクラスがある。
OGNLなどのScriptを抽象的に取り扱うためのs2coffeeのパッケージっぽい。

OgnlScript.diconでの定義をみるに、ScriptFactoryにScriptインタフェースの実装クラスをコンポーネント名=スクリプト種別として登録しておいて使うらしい。

AbstBuriExecProcess#getConditionScript()での使われ方をみると、

    protected Script getConditionScript() {
        return scriptFactory.getScript(buriExePackages.getConditionExpressionType());
    }

AbstBuriExePackagesクラスでデフォルト設定されているフィールドの値が"ognl"なんだけど、この文字列を元にOgnlスクリプトを実行可能なScript実装インスタンスを取得するということみたい。

インスタンスをがんがん再利用しているみたいなので、Scriptはステートレスかつスレッドセーフじゃないといけないということか。

たとえばJavaScriptImplかなんかを追加して、ScriptFactoryに登録しておけば、XPDLでJavaScriptが使えると。
なでじゃこも同じように突っ込むんだろうな。
と思って、s2coffee-scriptをSVNから持ってきてみたらあったあった。NadejakoScriptImpl。

s2coffee-scriptからBuriExceptionへの依存性

s2coffee-scriptがせっかくburiから独立して良い感じなんだけど、OgnlScriptImplでinstanceofによるBuriException判定が入っているのがちょっとイケてない。
逆向きの依存性が発生してしまってる。
buriの中でOGNLを実行したときにBuriExceptionが発生するんだけど、その場合は例外を連鎖させずに巣のまま再throwしたいからなんですなぁ。確認してないけど。きっと。

↓じゃだめかなぁ。RuntimeExceptionなら巣のまま再スロー。それ以外ならラッピングして例外連鎖。

OgnlScriptImpl...
    public Object eval(Object tgtObj,Object compileResult, Map context) {
        context = getContext(context);
        Object ret=null;
        if(tgtObj==null) {
            tgtObj = container.getRoot();
        }
        try {
            Map ognlContext = Ognl.createDefaultContext(null);
            ognlContext.putAll(context);
            ret = Ognl.getValue(compileResult, ognlContext, tgtObj);
        } catch (RuntimeException re) {
            logger.debug("[OGNL ERROR]" + compileResult.toString() + "" + re.toString());
            logger.debug(re.getStackTrace().toString());
            throw re;
        } catch (Exception re) {
            logger.debug("[OGNL ERROR]" + compileResult.toString() + "" + re.toString());
            logger.debug(re.getStackTrace().toString());
            throw new ScriptExecuteException("ESCS0002", re);
        }
        return ret;
    }

BuriException以外のRuntimeExceptionはラッピングしたいんだ!ということなら、どうせ気持ち悪いついでにorg.seasar.coffee.exceptions.ExceptionUnchainableみたいなマーカインタフェースかなんかを導入して

public class BuriException extends RuntimeException implements ExceptionUnchainable {
  // ...
}

としておいて、

OgnlScriptImpl...
    public Object eval(Object tgtObj,Object compileResult, Map context) {
        context = getContext(context);
        Object ret=null;
        if(tgtObj==null) {
            tgtObj = container.getRoot();
        }
        try {
            Map ognlContext = Ognl.createDefaultContext(null);
            ognlContext.putAll(context);
            ret = Ognl.getValue(compileResult, ognlContext, tgtObj);
        } catch (RuntimeException re) {
            logger.debug("[OGNL ERROR]" + compileResult.toString() + "" + re.toString());
            logger.debug(re.getStackTrace().toString());
            if (re instanceof ExceptionUnchainable) {
                throw re;
            }
            throw new ScriptExecuteException("ESCS0002", re);
        } catch (Exception re) {
            logger.debug("[OGNL ERROR]" + compileResult.toString() + "" + re.toString());
            logger.debug(re.getStackTrace().toString());
            throw new ScriptExecuteException("ESCS0002", re);
        }
        return ret;
    }

いやさすがにこれは気持ち悪すぎかな(^^;

第3の案としては、s2coffee側では問答無用でScriptExecuteExceptionでラッピングしておいて、Buri側で必要な箇所に

   if (e.getCause() instanceof BuriException) {
      e = e.getCause();
   }

みたいに取り出すようにするのじゃだめかな。


しかし関係ないけど、Java言語仕様的になんでチェックされない例外を表すのにマーカインタフェースを使わなかったんだろう...。なんか副作用あるのかな?
UncheckedExceptionをimplementsすると、チェックされなくなりますみたいな。
そうするともうちょっと柔軟にいろいろできそうな気がするんだけど...。

複数のxpdlを使う

bri-user.diconで

<initMethod name="addResourceConfig">
	<arg>"wakanagoxpdl/FurnitureManagement.xpdl"</arg>
	<arg>"資産管理"</arg>
</initMethod>
<initMethod name="addResourceConfig">
	<arg>"wakanagoxpdl/FurnitureManagement2.xpdl"</arg>
	<arg>"資産管理2"</arg>
</initMethod>

のようにどんどんXPDLを登録すればよい。

BaoではPROCESSで"パッケージ名.プロセス名"と指定する。
パッケージ名の部分が「資産管理」だったり「資産管理2」だったりするので、Baoごとに自由にXPDLを切り替えられるというわけ。

ACTIVITYが必須に

0.2.0と違って処理系のメソッドでACTIVITYアノテーションが必須になった。
つまり、必ずどのアクティビティに対する処理なのかが明示的に指定される。
わかりやすくなった。
カンマ区切りで複数個のアクティビティが指定できるので、一度に複数アクティビティ上のデータを操作することもできる。

所属ACTIVITYが1つに限定されている場合の権限チェック

以前はチェックはスルーされていたけど、0.3.0ではチェックされるようになったかな?
→★確認しよう!!

思ったこと

何でもかんでもぶりにまかせるんじゃなくて、単なる編集画面なんかはいつも通りの方法でつくるべきか。ぶりにはフローを流れる場合の処理だけを任せると。まあ、そりゃそうだ。

コンポーネント名の命名規約

Seasar2で一般的なのは小文字始まりのCamelCaseだと思うので、それに統一されているとうれしいなぁ。ぶりの処理系が大文字始まりで、自前のコンポーネント群が小文字始まりなんて気持ち悪いし。
OgnlInvokerで処理するときにコンテナ上のコンポーネントにアクセスする場合も、参照型変数に対するメソッド呼び出しをしているイメージがあるので、小文字始まりの方がしっくりくるなぁ。

クラス名の命名規約

結構、省略英語とか、Exec/Exeのゆれとか気になる...。
#そういうのが気になる質なので。

あと、abstractじゃないけどAbstBuriExePackagesだとか...。
いや、これはもしかするとabstractを付け忘れてるだけ?

OgnlInvokerというコンポーネント

実際はBuriScriptComponentImplというBuriComponentの実装クラスだったりする。
んで、このクラスとしては特別にOGNLに特化している雰囲気ではない。
OGNLにバインドされてるのは、AbstBuriExePackagesの中の各種scriptTypeだけっぽい。
AbstBuriExePackages中のscriptTypeを別のスクリプトIDに差し替えれば、OGNL以外のスクリプトにも対応できそうに見える。
ということは、とりあえずはOGNLしか対応しないにしてもScriptInvokerとかいうコンポーネント名にしておいた方がよいのでは?

Invoker→Component

0.2.0のときのInvokerが、0.3.0系では(Buri)Componentにあたるっぽい。

謎のFurnitureManagement_Wor1.java

AbstBuriExecProcessの実装サンプルかなと思ったけど、誰にも使われてない。テストもない。