Problem with listShuttle, inside an explicit conversation
troeng Feb 12, 2009 2:06 AMHi,
I am a beginner in seam and pageflows, so perhaps I am doing some beginner misstake, but I am stuck with this problem for a couple of days and any help would be appriceated.
I have a registration flow, spanning over 3 pages conversation and the problem is with a listshuttle on page 2.
Let me describe the flow:
Page 1 is basic account registration values, such as name , email, phone, etc.
Page 2 is a page where a user can choose from a list of interests, to get the proper information in newsletters.
Page 3 is a summary page, where the user gets the chance to back if something should be changed in the user input, and then a submit.
If I navigate through the conversation, everything works fine. But, the problem is when I back from page 3 to page 2, where inte listshuttle is.
If I for example have choosen 1 interest the first time, and now adds another interest to the list, the value I first choosed (the current value in the targetValue) doesnt get into my converter, it gets a nullpointerexception when I submit the next-button again (from page 2 to page 3).
It seems that in some way, my value in the targetValue of the listshuttle is being cleared somewhere in the process after submitting the page 2 for the second time.
I use a custom converter (not an entityconverter), since the interest-values are not persisted in the database. That of course is a possible solution for now, but I will get the same problem further on when retreiving external values in other flows, and I really want to understand what causes this problem.
I use
sun facelets 1.1.13
richfaces 3.2.2.GA
ajax4jsf 1.1.1
seam 2.0.0.GA
jbpm-jpdl 3.2.3
jboss 4.2.2
Here is my code:
pages.xml
<page view-id="/account/registeraccount.xhtml"> <begin-conversation pageflow="registeraccount" join="true"/> </page> <page view-id="/account/interests.xhtml" conversation-required="true" no-conversation-view-id="/index.xhtml" back="enabled"/> <page view-id="/account/finnish.xhtml" conversation-required="true" no-conversation-view-id="/index.xhtml" back="enabled"/>
registeraccount.jpdl.xml
<start-page name="start" view-id="/account/registeraccount.xhtml"> <redirect/> <transition name="next" to="interests"/> <transition name="cancel" to="cancel"/> </start-page> <page name="interests" view-id="/account/interests.xhtml"> <redirect/> <transition name="next" to="summary"/> <transition name="back" to="start"/> <transition name="cancel" to="cancel"/> </page> <page name="summary" view-id="/account/finnish.xhtml"> <transition name="next" to="finnish"> <action expression="#{accountCtrl.saveAccount}" /> </transition> <transition name="back" to="interests"/> </page> <page name="finnish" view-id="/index.xhtml"> <end-conversation/> <redirect/> </page> <page name="cancel" view-id="/index.xhtml"> <end-conversation before-redirect="true"/> <redirect/> </page>
components.xml
<core:manager conversation-id-parameter="cid" conversation-timeout="60000" ></core:manager> <component class="org.jboss.seam.bpm.Jbpm"> <property name="pageflowDefinitions"> <value>registeraccount.jpdl.xml</value> </property> </component>
My action/controller class (removed unnecessary code)
@Stateful @Name("accountCtrl") @Scope(ScopeType.CONVERSATION) public class AccountControllerImpl implements AccountController, Serializable { @Out(required = false) private List<Interest> selectedInterests; @Out(required = false) private List<Interest> allInterests; // getters & setters
interest.xhtml
<a:form id="interests"> <h:panelGrid columns="1"> <rich:listShuttle id="interests" sourceValue="#{accountCtrl.allInterests}" targetValue="#{accountCtrl.selectedInterests}" var="item" converter="#{interestConverter}" sourceCaptionLabel="#{messages['interests.available']}" targetCaptionLabel="#{messages['interests.choosen']}" copyAllControlLabel="#{messages['interests.label.copyall']}" copyControlLabel="#{messages['interests.label.copy']}" removeAllControlLabel="#{messages['interests.label.removeall']}" removeControlLabel="#{messages['interests.label.remove']}" bottomControlLabel="#{messages['interests.label.bottom']}" topControlLabel="#{messages['interests.label.top']}" upControlLabel="#{messages['interests.label.up']}" downControlLabel="#{messages['interests.label.down']}"> <rich:column> <h:outputText value="#{item.interestName}"/> </rich:column> </rich:listShuttle> <f:facet name="footer"> <h:panelGroup styleClass="buttons"> <h:commandButton action="cancel" value="#{messages['form.cancel']}" styleClass="button"/> <h:commandButton action="back" value="#{messages['form.previous']}" styleClass="button"/> <h:commandButton action="next" value="#{messages['form.nextstep']}" styleClass="button"/> </h:panelGroup> </f:facet> </h:panelGrid> </a:form>
InterestConverter.java
@Name("interestConverter") @org.jboss.seam.annotations.faces.Converter public class InterestConverter implements Converter { @In(required = true, scope = ScopeType.SESSION, value = "#{accountCtrl.allInterests}") private List<Interest> interests; public Object getAsObject(FacesContext arg0, UIComponent arg1, String arg2) { for(Interest dto : interests) { if(dto.getInterestName().equals(arg2)) { return dto; } } return null; } public String getAsString(FacesContext arg0, UIComponent arg1, Object arg2) { if(arg2 != null) { // The problem is here, arg2 is null when this method is invoked for the targetValue values. return ((Interest)arg2).getInterestName(); } else { return null; } }
I could solve the problem with a dirty fix, by invoking a targetValue-clear method every time the interest.xhtml page is rendered, but that doesnt seem very nice since the user then have to start over with the listshuttle-adding from the beginning. But when doing so, the problem doesnt occur anymore..
Thanks in advance.