1 Reply Latest reply on Feb 13, 2009 5:11 PM by troeng

    Problem with listShuttle, inside an explicit conversation

      Hi,
      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.