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 & settersinterest.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.