[jboss-user] [JBoss Seam] - Bug in explicit conversation id management in SEAM 1.2.1 (ma

raffaele.camanzo do-not-reply at jboss.com
Thu Mar 29 12:13:56 EDT 2007


This problem seems to affect both the current management of the explicit conversation id (@Begin(id=...)) and the future solution (with the declaration in the pages.xml).

Seam 1.2.1 seems to be unable to restore the current state of a conversation in this way: 

I made three simple POJOs:

ActionOne.java:

  | @Name("actionOne")
  | @Scope(ScopeType.CONVERSATION)
  | public class ActionOne {
  | 	
  | 	private List<String> starttimes;
  | 	private int counter = 0;
  | 	
  | 	@Create
  | 	public void createit() {
  | 		starttimes = new ArrayList<String>();
  | 		starttimes.add("Executing ActionOne @Create method");
  | 	}
  | 	
  | //	@Begin I don't know if this is needed or not, anyway, it does not work now both if it is
  | //  present or not
  | 	public String startConversation() {
  | 		Logger.getLogger(this.getClass()).info("<ACTIONONE> START CONVERSATION METHOD CALLED");
  | 
  | 		Logger.getLogger(this.getClass()).info("<START CONVERSATION> IS THERE A LONG RUNNING CONVERSATION: " + (Conversation.instance().isLongRunning() ? "YES" : "NO"));
  | 		Logger.getLogger(this.getClass()).info("<START CONVERSATION> IS THERE A NESTED CONVERSATION: " + (Conversation.instance().isNested() ? "YES" : "NO"));
  | 		Logger.getLogger(this.getClass()).info("<START CONVERSATION> LONG RUNNING CONVERSATION ID IS: " + Conversation.instance().getId());
  | 		Logger.getLogger(this.getClass()).info("<START CONVERSATION> LONG RUNNING CONVERSATION VIEW ID IS: " + Conversation.instance().getViewId());
  | 		Logger.getLogger(this.getClass()).info("<START CONVERSATION> LONG RUNNING CONVERSATION DESCRIPTION IS: " + Conversation.instance().getDescription());
  | 
  | 		return "one";
  | 	}
  | 	
  | 	@End
  | 	public String endConversation() {
  | 		Logger.getLogger(this.getClass()).info("<ACTIONONE> END CONVERSATION METHOD CALLED");
  | 		return "one";
  | 	}
  | 
  | 	/**
  | 	 * starttimes member Getter
  | 	 * 
  | 	 * @return starttimes member
  | 	 */
  | 	public List<String> getStarttimes() {
  | 		return starttimes;
  | 	}
  | 
  | 	/**
  | 	 * starttimes member Setter
  | 	 * 
  | 	 * @param starttimes New value for the starttimes member
  | 	 */
  | 	public void setStarttimes(List<String> starttimes) {
  | 		this.starttimes = starttimes;
  | 	}
  | 
  | 	public String doIt() {
  | 		counter++;
  | 		starttimes.add("ACTIONONE DOIT CALLED " + counter + " TIMES!");
  | 
  | 
  | 		Logger.getLogger(this.getClass()).info("<DOIT> IS THERE A LONG RUNNING CONVERSATION: " + (Conversation.instance().isLongRunning() ? "YES" : "NO"));
  | 		Logger.getLogger(this.getClass()).info("<DOIT> IS THERE A NESTED CONVERSATION: " + (Conversation.instance().isNested() ? "YES" : "NO"));
  | 		Logger.getLogger(this.getClass()).info("<DOIT> LONG RUNNING CONVERSATION ID IS: " + Conversation.instance().getId());
  | 		Logger.getLogger(this.getClass()).info("<DOIT> LONG RUNNING CONVERSATION VIEW ID IS: " + Conversation.instance().getViewId());
  | 		Logger.getLogger(this.getClass()).info("<DOIT> LONG RUNNING CONVERSATION DESCRIPTION IS: " + Conversation.instance().getDescription());
  | 
  | 		return "one";
  | 	}
  | }
  | 

ActionTwo.java:

  | @Name("actionTwo")
  | @Scope(ScopeType.CONVERSATION)
  | public class ActionTwo {
  | 	
  | 	private List<String> starttimes;
  | 	private int counter = 0;
  | 	
  | 	
  | 	@Create
  | 	public void createit() {
  | 		starttimes = new ArrayList<String>();
  | 		starttimes.add("<ACTIONTWO> Executing ActionTwo @Create method");
  | 	}
  | 
  | 	@Begin(id="myid2")
  | 	public String startConversation() {
  | 		Logger.getLogger(this.getClass()).info("<ACTIONTWO> START CONVERSATION METHOD CALLED");
  | 
  | 		Logger.getLogger(this.getClass()).info("<START CONVERSATION> IS THERE A LONG RUNNING CONVERSATION: " + (Conversation.instance().isLongRunning() ? "YES" : "NO"));
  | 		Logger.getLogger(this.getClass()).info("<START CONVERSATION> IS THERE A NESTED CONVERSATION: " + (Conversation.instance().isNested() ? "YES" : "NO"));
  | 		Logger.getLogger(this.getClass()).info("<START CONVERSATION> LONG RUNNING CONVERSATION ID IS: " + Conversation.instance().getId());
  | 		Logger.getLogger(this.getClass()).info("<START CONVERSATION> LONG RUNNING CONVERSATION VIEW ID IS: " + Conversation.instance().getViewId());
  | 		Logger.getLogger(this.getClass()).info("<START CONVERSATION> LONG RUNNING CONVERSATION DESCRIPTION IS: " + Conversation.instance().getDescription());
  | 
  | 		return "two";
  | 	}
  | 	
  | 	@End @Remove @Destroy
  | 	public String endConversation() {
  | 		Logger.getLogger(this.getClass()).info("<ACTIONTWO> END CONVERSATION METHOD CALLED");
  | 		return "two";
  | 	}
  | 	
  | 	/**
  | 	 * starttimes member Getter
  | 	 * 
  | 	 * @return starttimes member
  | 	 */
  | 	public List<String> getStarttimes() {
  | 		return starttimes;
  | 	}
  | 
  | 	/**
  | 	 * starttimes member Setter
  | 	 * 
  | 	 * @param starttimes New value for the starttimes member
  | 	 */
  | 	public void setStarttimes(List<String> starttimes) {
  | 		this.starttimes = starttimes;
  | 	}
  | 	
  | 	public String doIt() {
  | 		counter++;
  | 		starttimes.add("ACTIONTWO DOIT CALLED " + counter + " TIMES!");
  | 
  | 		Logger.getLogger(this.getClass()).info("<DOIT> IS THERE A LONG RUNNING CONVERSATION: " + (Conversation.instance().isLongRunning() ? "YES" : "NO"));
  | 		Logger.getLogger(this.getClass()).info("<DOIT> IS THERE A NESTED CONVERSATION: " + (Conversation.instance().isNested() ? "YES" : "NO"));
  | 		Logger.getLogger(this.getClass()).info("<DOIT> LONG RUNNING CONVERSATION ID IS: " + Conversation.instance().getId());
  | 		Logger.getLogger(this.getClass()).info("<DOIT> LONG RUNNING CONVERSATION VIEW ID IS: " + Conversation.instance().getViewId());
  | 		Logger.getLogger(this.getClass()).info("<DOIT> LONG RUNNING CONVERSATION DESCRIPTION IS: " + Conversation.instance().getDescription());
  | 
  | 		return "two";
  | 	}
  | 	
  | 
  | }
  | 

ActionThree.java:

  | @Name("actionThree")
  | @Scope(ScopeType.CONVERSATION)
  | public class ActionThree {
  | 	
  | 	private List<String> starttimes;
  | 	private int counter = 0;
  | 
  | 	@Begin
  | 	public String startConversation() {
  | 		Logger.getLogger(this.getClass()).info("<ACTIONTHREE> START CONVERSATION METHOD CALLED");
  | 		starttimes = new ArrayList<String>();
  | 		starttimes.add("Executing ActionThree @Begin method");
  | 
  | 		Logger.getLogger(this.getClass()).info("<START CONVERSATION> IS THERE A LONG RUNNING CONVERSATION: " + (Conversation.instance().isLongRunning() ? "YES" : "NO"));
  | 		Logger.getLogger(this.getClass()).info("<START CONVERSATION> IS THERE A NESTED CONVERSATION: " + (Conversation.instance().isNested() ? "YES" : "NO"));
  | 		Logger.getLogger(this.getClass()).info("<START CONVERSATION> LONG RUNNING CONVERSATION ID IS: " + Conversation.instance().getId());
  | 		Logger.getLogger(this.getClass()).info("<START CONVERSATION> LONG RUNNING CONVERSATION VIEW ID IS: " + Conversation.instance().getViewId());
  | 		Logger.getLogger(this.getClass()).info("<START CONVERSATION> LONG RUNNING CONVERSATION DESCRIPTION IS: " + Conversation.instance().getDescription());
  | 
  | 		return "three";
  | 	}
  | 	
  | 	@End
  | 	public String endConversation() {
  | 		Logger.getLogger(this.getClass()).info("<ACTIONTHREE> END CONVERSATION METHOD CALLED");
  | 		return "three";
  | 	}
  | 	
  | 	/**
  | 	 * starttimes member Getter
  | 	 * 
  | 	 * @return starttimes member
  | 	 */
  | 	public List<String> getStarttimes() {
  | 		return starttimes;
  | 	}
  | 
  | 	/**
  | 	 * starttimes member Setter
  | 	 * 
  | 	 * @param starttimes New value for the starttimes member
  | 	 */
  | 	public void setStarttimes(List<String> starttimes) {
  | 		this.starttimes = starttimes;
  | 	}
  | 	
  | 	public String doIt() {
  | 		counter++;
  | 		starttimes.add("ACTIONTHREE DOIT CALLED " + counter + " TIMES!");
  | 
  | 		Logger.getLogger(this.getClass()).info("<DOIT> IS THERE A LONG RUNNING CONVERSATION: " + (Conversation.instance().isLongRunning() ? "YES" : "NO"));
  | 		Logger.getLogger(this.getClass()).info("<DOIT> IS THERE A NESTED CONVERSATION: " + (Conversation.instance().isNested() ? "YES" : "NO"));
  | 		Logger.getLogger(this.getClass()).info("<DOIT> LONG RUNNING CONVERSATION ID IS: " + Conversation.instance().getId());
  | 		Logger.getLogger(this.getClass()).info("<DOIT> LONG RUNNING CONVERSATION VIEW ID IS: " + Conversation.instance().getViewId());
  | 		Logger.getLogger(this.getClass()).info("<DOIT> LONG RUNNING CONVERSATION DESCRIPTION IS: " + Conversation.instance().getDescription());
  | 
  | 		return "three";
  | 	}
  | 	
  | 
  | }
  | 

I configured the pages.xml in order to support the next explicit conversation id feature:

pages.xml

  | <!DOCTYPE pages PUBLIC
  |   "-//JBoss/Seam Pages Configuration DTD 1.1//EN"
  |   "http://jboss.com/products/seam/pages-1.2.dtd">
  | 
  | <pages>
  | 	<conversation name="convOne" parameter-name="aname" parameter-value="#{sessionHandler.seqOne}" />
  | 
  | 	<page view-id="/actionone.xhtml" conversation="convOne">
  | 	</page>
  | 
  | </pages>
  | 

the seqOne method simply returns a string with an incremental value postfix.

and added three links to call them all:

  | 		<div id="control">
  | 			<h:form>
  | 			<table>
  | 				<tr>
  | 					<td>
  | 						<h:outputText value="Press the button to call the @Begin action of the actionOne conversation" />
  | 					</td>
  | 				</tr>
  | 				<tr>
  | 					<td>
  | 						<h:commandLink action="#{actionOne.startConversation}" value="Start Conversation with pages conversation definition">
  | 							<s:conversationPropagation type="none" />
  | 						</h:commandLink>
  | 					</td>
  | 				</tr>
  | 			</table>
  | 			</h:form>
  | 			<h:form>
  | 			<table>
  | 				<tr>
  | 					<td>
  | 						<h:outputText value="Press the button to call the @Begin action of the actionTwo conversation" />
  | 					</td>
  | 				</tr>
  | 				<tr>
  | 					<td>
  | 						<h:commandLink action="#{actionTwo.startConversation}" value="Start Conversation with static @Begin(id='myId2')">
  | 							<s:conversationPropagation type="none" />
  | 						</h:commandLink>
  | 					</td>
  | 				</tr>
  | 			</table>
  | 			</h:form>
  | 			<h:form>
  | 			<table>
  | 				<tr>
  | 					<td>
  | 						<h:outputText value="Press the button to call the @Begin action of the actionThree conversation" />
  | 					</td>
  | 				</tr>
  | 				<tr>
  | 					<td>
  | 						<h:commandLink action="#{actionThree.startConversation}" value="Start Conversation with generated id">
  | 							<s:conversationPropagation type="none" />
  | 						</h:commandLink>
  | 					</td>
  | 				</tr>
  | 			</table>
  | 			</h:form>
  | 		</div>
  | 

disabling conversation propagation in order to avoid to ask for the LRC switch.

the three xhtml pages related to the components are almost identical and trivial:

  | <!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  | <ui:composition xmlns="http://www.w3.org/1999/xhtml"
  | 	    		xmlns:ui="http://java.sun.com/jsf/facelets"
  | 	  			xmlns:h="http://java.sun.com/jsf/html"
  | 	  			xmlns:f="http://java.sun.com/jsf/core"
  | 	  			xmlns:s="http://jboss.com/products/seam/taglib"
  | 	  			xmlns:c="http://java.sun.com/jstl/core"
  | 				template="main.xhtml">
  | 
  | <!-- context manager -->
  | <ui:define name="actioncontent">
  | 	<h:dataTable value="#{actionThree.starttimes}" var="iter">
  | 		<h:column>
  | 			<h:outputText value="#{iter}" />
  | 		</h:column>
  | 	</h:dataTable>
  | 	
  | 	<h:form>
  | 		<s:link action="#{actionThree.doIt}">
  | 			<h:outputText value="Press me I should run into #{conversation.id} conversation" />
  | 		</s:link>
  | 	</h:form>
  | </ui:define>
  | 
  | </ui:composition>
  | 

Basically what I expect to obtain is this:
Clicking on one of the three links I start a conversation, then, clicking on the doIt link see the list of strings to grow; unfortunately this is true only in the third case (when the id is generated by Seam), both in the first and in the second Seam seems to not bind the component to the conversation, indeed, running test on the component instance two, when I click on the doIt link, I read in the log this print:


  |  DEBUG [org.jboss.seam.core.Manager] Found conversation id in request parameter: myid2
  |  DEBUG [org.jboss.seam.core.Manager] Restoring conversation with id: myid2
  |  DEBUG [org.jboss.seam.jsf.AbstractSeamPhaseListener] After restoring conversation context: ConversationContext(myid2)
  | 

but the list does not grow, moreover if I create the list of strings in the @Begin method (as I do in the third example) the doIt method fails with a NullPointerException because the list is not present.

That's it. Is this a bug?

Two questions on conversation management: 
- Can I expect that if I click say on the second link (the static id.. not correct but to understand) Seam will understand that I'm asking for that conversation and resumes it?
- Is it legal to use the Redirect API knowing the conversation id (regardless generated or explicit) in order to redirect to that conversation?
Both the questions without a LRC in place (s:conversationPropagation type="none")

Regards, 
Raffaele Camanzo


View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4032845#4032845

Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4032845



More information about the jboss-user mailing list