GWT-RPCでCDI @ConversationScoped を成立させる
要約
Conversationを伝播させるためには、リクエストパラメータにconversation IDを設定してやる必要が有ります。しかし、GWT-RPCではユーザがリクエストボディ部を操作することは想定されておらず、困難なようでした。
そこで、クライアントからはヘッダ部にconversation IDをセットしておき、サーバサイドでその値をリクエストパラメータとして取得できるよう前処理を行うことにしました。
(これは、CDI処理前にサーブレットフィルタを用いリクエストを改変することで実現しています。)
この結果、GWT-RPCでもCDI @ConversationScoped機能を用いることができるようになりました。
説明
試した環境は以下のとおりです。- Java1.8.0u60
- Wildfly10Beta2(Weld2.3.0.CR1)
- GWT(Google Web Toolkit) 2.7.0
CDI1.2 spec:
6.7.4. Conversation context lifecycleWeld doc:
The long-running conversation associated with a request may be propagated to any Servlet request via use of a request parameter named cid containing the unique identifier of the conversation.
5.3.2. Conversation propagation
We can force the conversation to propagate with a non-faces request by including the unique identifier of the conversation as a request parameter. The CDI specification reserves the request parameter named cid for this use.
ソースコードを眺めたところ、リクエストパラメータからcidを取得しているのは ConversationContextActivator であることがわかり、またドキュメントの以下の記述から、この処理を行う前にユーザープログラムで前処理を挟めることがわかりました。 "CDI Conversation Filter"という名前のフィルタの前に、独自のフィルタを設定しそこで処理すれば良いわけです。
CDI1.2 spec:
6.7.4. Conversation context lifecycleまた、Weldドキュメントの 5.3.4. CDI Conversation filter, A.2.3. CDI Conversation Filter, FAQ: Why does Weld set character encoding of an HTTP request/response body to ISO-8859-1? で言及されています。
The container provides a filter with the name "CDI Conversation Filter", which may be mapped in web.xml, allowing the user alter when the conversation is associated with the servlet request.
この機能を使い、クライアントで作成するメッセージはcidリクエストパラメータを含まないが、 Weldから要求された際にはcidを渡せる、ということが可能になります。
冒頭で示したソースコードについて説明します。
GWTクライアント側では、RpcRequestBuilderを用いてヘッダにConversation IDを設定するようにしています。
サーバ側では、web.xmlでCDI Conversation Fiterより前にカスタムフィルタを適用する旨を定義し、
このフィルタの中でHttpServletRequestWrapperを利用してcidリクエストパラメータを要求された際には予めヘッダに設定していた値を返すようにしています。
最近のコメント