システム開発で思うところ

Javaで主にシステム開発をしながら思うところをツラツラを綴る。主に自分向けのメモ。EE関連の情報が少なく自分自身がそういう情報があったら良いなぁということで他の人の参考になれば幸い

ConversationScopedを扱うにあたっての課題

もしくは、JSFのConversationScopedをフォルダでBegin・Endの方式見直しに向けて。
あるいは、ConversationScopedにおけるExceptionハンドリング です。

vermeer.hatenablog.jp

で、f:viewActionで制御をしていたのですが、テンプレートを使って 同じことをやろうとしたら、上手く行かず f:event type="preRenderView"でとりあえず処理をしました。

その時は何でだろうと思いつつ、とりあえず まぁ良いかとしていたのですが、その後 Conversationに関して色々やっている中で 本件を放置したままでは 不安定な仕組みになり得ると分かりました。

原因

eclipse - f:viewAction does not invoke action method - Stack Overflow

In the target page, apparently index.xhtml, put this somewhere in top, right before <h:head>

JSFのテンプレート機能をつかって、ui:include先で f:viewActionを指定したのですが、URLを示す xhtmlで指定しないとアクションが起きないという仕様でした。

課題

対処する、しないは別にして、現時点で思いつく課題を整理します。

viewActionはルートとなるViewに記述しないといけない

これは上述の通りです。

Exceptionハンドリング

ServletFilterでBusyConversationExceptionを扱うために web.xmlへの以下の記述のために、全てのConversationに関する例外を一旦 Servlet Filterで処理します。
そのためNonexistentConversationExceptionを扱うにあたって、そのままでは 当初案であるExceptionHandlerWrapperで処理できません。
ServletFilterと同一レイヤーでハンドリングするか、ExceptionHandlerWrapperへ例外処理を委譲するような対処の検討が必要だと思います。

    <!-- ConversationExceptionFilter -->

    <filter>
        <filter-name>ConversationExceptionFilter</filter-name>
        <filter-class>ee.filter.conversationexception.ConversationExceptionFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>ConversationExceptionFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <filter-mapping>
        <filter-name>CDI Conversation Filter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <!-- ConversationExceptionFilter -->

メッセージの出力

Exception時のメッセージ出力情報を SessionScopedのクラスを介在して制御していましたが、そのやり方では エラーのトリガーとなったタブ以外のConversationScopedのアクションにも影響が起こり得ます。
実際に懸念を動作確認をしているわけではないので確実ではありませんが、想定としては複数タブを開いて 高負荷で登録処理を行った場合に不具合が発生する可能性があります。
RequestScoped相当か、Flashを使うやり方で見直す必要があると思います。

常にBeginさせる?

基本的に ControllerによるActionをトリガーとして ConversationScopedをBeginするという方式として、あとはDIされるクラス側のScopedによって実際にサーバー側で情報を保持するか しないか という方式で考えていました。
ただ、それだと コンテナ上に意味のない管理情報インスタンスが作成されてしまったり、無駄なConversationのカウントアップがされてしまいます。
実際のメモリ使用量までは調べていませんが、これは良くない可能性があります。
当初は、会話スコープを使うものと そうでないもので テンプレートを分けるだけで良いと考えたのですが、上述のviewActionの件も含めて テンプレートによる制御を分類するというやり方から駄目になったら そうもいきません。

全てのルートとなるxhtmlに共通で必要となるviewActionを記述すれば良いというのが、パッと思いつく案ではありますが、共通記述を強いる方式は避けられるのであれば避けたいです。

さいごに

今回は、課題の整理までです。
今後も 課題があったら、本記事に追記しようと思います。