Re: Statelessのinstance属性
微妙...
単純に singleton にマッピングだと,今度は (というか元に戻って) 「4.7.11 Non-reentrant Instances」を満たすことができません.
The container must ensure that only one thread can be executing an instance at any time.
セッションビーンは再入不可であり,スレッドセーフに作る必要がありません.
やはりスレッドセーフであることが保証されない EntityManager
を安心して使えるのも,セッションビーンが再入不可だからです.
そんなわけで (どんなわけで?),SLSB を singleton にマッピングするのはまずいです.
SynchInterceptor
を使えば singleton でも再入不可にできますが,これは性能面でのペナルティが大きくて問題あり.
といってやたらと javax.ejb.ConcurrentAccessException
を吹っ飛ばすのもいかがなものか.
結局,prototype にマッピングするしかないと思います.
じゃあ「3.4.5.2 Stateless Session Beans」をどうするかというと,ちゃんとサポートするならセッションビーンのインスタンスとクライアントが持つ参照は別にするべきかと.
要するにクライアントはプロキシを参照するということですね.たとえローカルでも.
そしてプロキシの equals()
は「3.4.5.2 Stateless Session Beans」の通りに振る舞うけれども,その背後にあるセッションビーンのインスタンスはメソッド呼出しの都度違っているかもしれない,みたいな.
つまり,プロキシは singleton,セッションビーン本体は prototype.
たぶん,まっとうな EJB コンテナはそうなってると思うのですが,お手軽サポートでいくなら SLSB の equals()
をオーバーライドして (あるいは AOP 使って) ComponentDef
の同一性をチェックするようにするという手もありかも.
とりあえず「3.4.5.2 Stateless Session Beans」「4.7.11 Non-reentrant Instances」両方を満たせるはず.
あ,SLSB が複数のビジネスインタフェースを持ってる場合に,型が異なる参照は equals
が false
を返さなきゃいけないのに対応できないか (これは singleton の場合も同じ問題あり).
やっぱりプロキシでのサポートが必要なような...
例えば PrototypeDelegateInteceptor を使って,
<component class="Foo"> <aspect> <component class="PrototypeDelegateInterceptor"> <property name="targetName">fooBean</property> </component> </aspect> </component> <component name="fooBean" class="FooBean" instance="prototype"/>
みたいな状況を作ってあげればよさげ.
んで,@EJB
に対しては FooBean
ではなく,Foo
の方を設定.
まぁ,実際にはこんなに簡単にはいかないと思いますが,方向はこうじゃないかなぁ.