Seam vs Weld: ajax and conversations in JSF views
Posted by mkouba in Martin Kouba's Blog on Aug 30, 2012 9:25:10 AMI assume everyone who has ever used Seam 2, JSF 1.x and RichFaces 3 knows the concept of Seam conversations and RF3 ajax components (a4j:support, a4j:commandLink, a4j:commandButton, etc.). The use of RF3 controls and Seam conversations is quite straightforward. Put the RF3 control on the facelet page, handle some ajax actions in Seam component, at some time promote temporary conversation to long-running, and finally rerender required parts of JSF page. Everything works. No need to put conversation id somewhere provided you don't leave the JSF view (or do non-JSF request).
Today's applications mostly switched to CDI (Weld), JSF 2 and RichFaces 4. As expected some problems may occur during migration of programming techniques. One of them might disrupt the previous experience...
Check following facelets fragment - Seam2/JSF/RF3:
<h:form id="form"> <a4j:commandButton value="Begin conversation" id="A" action="#{action.beginConversation}" /> <a4j:commandButton value="Do action" id="B" action="#{action.doSomethingInContextOfLongRunningConversation}" /> </h:form>
Clicking button A - begins conversation (Action#beginConversation promotes temporary conversation to long-running). Then clicking button B - the conversation is automatically propagated. Note that we do no rerendering. However for the same facelets fragment running on Weld/JSF2/RF4 the conversation is not automatically propagated. This also applies to native JSF components (f:ajax). Where is the problem? CDI does not define built-in JSF page/view scope so that it cannot restore conversation id from this context (like Seam 2 does). It only relies on HTTP request parameter cid. To have it working you will have to...
1) Rerender the whole form (Weld will automatically append the conversation id to form's action attribute):
<h:form id="form"> <a4j:commandButton value="Begin conversation" id="A" action="#{action.beginConversation}" render="@form" /> <a4j:commandButton value="Do action" id="B" action="#{action.doSomethingInContextOfLongRunningConversation}" /> </h:form>
2) Propagate conversation id manually:
<h:form id="form"> <a4j:commandButton value="Begin conversation" id="A" action="#{action.beginConversation}" render="B" /> <a4j:commandButton value="Do action" id="B" action="#{action.doSomethingInContextOfLongRunningConversation}"> <f:param name="cid" value="#{javax.enterprise.context.conversation.id}"/> </a4j:commandButton> </h:form>
See also org.jboss.weld.jsf.ConversationAwareViewHandler.
Comments