1 Reply Latest reply on Feb 13, 2011 2:12 AM by infinity2heaven

    Conversation example with faces-config navigation doesn't work

    infinity2heaven

      I have an example app extending seam-javaee-booking app (shipped with seam-3beta1)


      Here's my flow (page - action):




      1. members.xhtml (members listing) - select member (@Begin)

      2. program-registration.xhtml - selectProgram

      3. program-registration-select-program.xhtml - register

      4. program-registration-confirm.xhtml - confirm (@End)




      step 1 is fine, selectedMember gets set


      But in Step 2, when selectProgram is called from jsf actionMethod, the page doesn't navigate to next page as per faces-config file, instead it stays same with cid=1 on request param.


      Conversation Stateful Bean


      @Stateful
      @ConversationScoped
      @Named( "programRegistration" )
      public class MemberProgramRegistration
           implements Serializable {
      
           private static final long serialVersionUID = 985615785945128136L;
      
           @Inject
           private Logger log;
      
           @PersistenceContext( type = PersistenceContextType.EXTENDED )
           private EntityManager em;
      
           @Inject
           @Confirmed
           private Event< ProgramRegistration > programRegisteredEvent;
      
           private Member selectedMember;
           private Program selectedProgram;
           private ProgramRegistration registration;
      
           private boolean registrationValid;
      
              @Inject
            Conversation conversation;
      
           // @Begin # I've used this from Seam 3 instead of conversation.begin but still get the same error
           public void selectMember(
                final String _id ) {
      
                 conversation.begin();
      
                      Long id = Long.valueOf( _id );
      
                // get a fresh reference that's managed by the extended persistence context
                selectedMember = em.find( Member.class, id );
                if ( selectedMember != null ) {
                     log.info( "Member selected:" + selectedMember );
                }
           }
      
           public void selectProgram() {
                selectedProgram = loadDefaultProgram();
           }
      
           public void register() {
                if ( selectedProgram != null ) {
                     log.info( "selectedProgram selected:" + selectedProgram );
                }
                registration = new ProgramRegistration( selectedMember, selectedProgram, new Date(), 1 );
                      selectedMember = null;
              }
      
           @End
           public void confirm() {
                em.persist( registration );          
                      conversation.end();
           }
      
              @Produces
           @ConversationScoped
           @Named
           public ProgramRegistration getRegistration() {
                return registration;
           }
      
           @Produces
           @Named
           public Member getSelectedMember() {
                return registration.getMember() != null ? registration.getMember() : selectedMember;
           }
      
           @Produces
           @Named
           public Program getSelectedProgram() {
                return registration != null ? registration.getProgram() : selectedProgram;
           }
      
           private Program loadDefaultProgram() {
                return em.find( Program.class, 1L );
           }
      
           @Produces
           @Named
           @SessionScoped
           public List< Program > getPrograms() {
                return em.createNamedQuery( "Program.findAll", Program.class ).getResultList();
           }
      }



      jsf


           
      <ui:define name="content">
                <h:messages />
      
                <h3> Regitration </h3>
      
                <h1> Member </h1>
                <h:form>
      
                     <h:panelGroup layout="block">
                          <h:panelGrid columns="1">
                               <b>first name:</b>
                               <h:outputText value="#{selectedMember.firstName}" required="true" />
                               <b>last name:</b>
                               <h:outputText value="#{selectedMember.lastName}" required="true" />
                               <b>dob:</b>
                               <h:outputText value="#{selectedMember.lastName}" required="true" />
                               <b>email:</b>
                               <h:outputText value="#{selectedMember.email}" required="true" />
                               <b>phone number:</b>
                               <h:outputText value="#{selectedMember.phone}" />
                               <b>notes:</b>
                               <h:outputText value="#{selectedMember.notes}" />
                          </h:panelGrid>
                     </h:panelGroup>
      
                     <h:commandButton action="#{programRegistration.selectProgram}"
                          value="Register a program" />
                     #{' '}
                     <h:commandButton id="cancel"
                          action="#{programRegistration.cancel}" value="Return to Search"
                          immediate="true" />
                </h:form>
      
           </ui:define>
      



      faces-config.xml


      <?xml version="1.0" encoding="UTF-8"?>
      <!-- This file is not required if you don't need any extra configuration. -->
      <faces-config version="2.0" xmlns="http://java.sun.com/xml/ns/javaee"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="
            http://java.sun.com/xml/ns/javaee
            http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd">
      
           <!-- Navigation rules -->
      
           <navigation-rule>
                <from-view-id>*</from-view-id>
      
                <navigation-case>
                     <from-action>#{authenticator.login}</from-action>
                     <if>#{true}</if>
                     <to-view-id>/pages/home.xhtml</to-view-id>
                     <redirect />
                </navigation-case>
      
                <navigation-case>
                     <from-action>#{authenticator.logout}</from-action>
                     <to-view-id>/pages/auth/login.xhtml</to-view-id>
                     <redirect />
                </navigation-case>
      
                <navigation-case>
                     <from-action>#{programRegistration.cancel}</from-action>
                     <to-view-id>/pages/home.xhtml</to-view-id>
                     <redirect />
                </navigation-case>
           </navigation-rule>
         
           <navigation-rule>
                <from-view-id>/pages/secure/program-registration.xhtml</from-view-id>
      
                <navigation-case>
                     <from-action>#{programRegistration.selectProgram}</from-action>
                     <to-view-id>/pages/secure/program-registration-select-program.xhtml</to-view-id>
                     <redirect />
                </navigation-case>
           </navigation-rule>
      
           <navigation-rule>
                <from-view-id>/pages/secure/program-registration-select-program.xhtml</from-view-id>
      
                <navigation-case>
                     <from-action>#{programRegistration.register}</from-action>
                     <to-view-id>/pages/secure/program-registration-confirm.xhtml</to-view-id>
                     <redirect />
                </navigation-case>
           </navigation-rule>
      
           <navigation-rule>
                <from-view-id>/pages/secure/program-registration-confirm.xhtml</from-view-id>
      
                <navigation-case>
                     <from-action>#{programRegistration.confirm}</from-action>
                     <to-view-id>/pages/secure/members.xhtml</to-view-id>
                     <redirect />
                </navigation-case>
           </navigation-rule>
      
      </faces-config>
      



      Replacing Weld's Conversation interface with Seam's @Begin and @End along with ConversationBoundaryInterceptor results in no change. Removing the navigation elements from faces-config and simply returning the page identifiers in action methods gives another error:


      java.lang.IllegalStateException: Context is already active
           at org.jboss.weld.context.AbstractConversationContext.activate(AbstractConversationContext.java:301)
           at org.jboss.weld.jsf.WeldPhaseListener.activateConversations(WeldPhaseListener.java:110)



      I've spent 3 days trying to figure out but in vain. Seam 3's hotel booking example is BROKEN (conversation doesn't work either) and there's no end to end example anywhere. Any help, appreciated.

        • 1. Re: Conversation example with faces-config navigation doesn't work
          infinity2heaven

          Update: I got this working without using faces-config naviagtion and returning viewIds from action methods, instead. Also, originally, memberId was passed via <f:link> from members.xhtml to program-registration page via


          <f:metadata>
               <f:viewParam name="id" value="#{memberId}" />
               <s:viewAction action="#{programRegistration.selectMember(memberId)}" />
          </f:metadata>



          This was causing issues and I'm using h:commandBitton instead.



          Will have to debug why navigation isn't working later ...