5 Replies Latest reply on May 23, 2006 3:39 PM by pmuir

    Transition out of pageflow

    pmuir

      Use case:

      Wizard style conversation (using jPDL) results in a summary page. Summary page summarises the information the user has entered and provides a list (selectOneRadio) of 'what do you want to do next' options (e.g. create another entry, generate paperwork). Summary page has back (defined transition) cancel (defined transition) and finish buttons. On clicking the finish button the selected option is carried out.

      My idea is to use a transition to a decision node on clicking finish; the decision nodes expression is the selected selectItems itemValue and the transistions map from the itemValue to a JSF outcome (probably itemValue == JSFOutcome). However I get told that the 'transition 'searchVenues' doesn't have destination' [1] as it is not in the pageflow.

      Suggestions? Trawling the forum I found a post in which Gavin says this (mixing jPDL and JSF navigation) is something that shoud/could be fixed.

      TIA

      Peter

      [1]

      18:10:24,314 ERROR [[Faces Servlet]] Servlet.service() for servlet Faces Servlet threw exception
      org.jbpm.JbpmException: transition 'searchVenues' doesn't have destination. check your processdefinition.xml
       at org.jbpm.graph.def.Transition.fireSuperStateEnterEvents(Transition.java:131)
       at org.jbpm.graph.def.Transition.take(Transition.java:109)
       at org.jbpm.graph.def.Node.leave(Node.java:382)
       at org.jbpm.graph.exe.ExecutionContext.leaveNode(ExecutionContext.java:136)
       at org.jbpm.graph.node.Decision.execute(Decision.java:145)
       at org.jbpm.graph.def.Node.enter(Node.java:316)
       at org.jbpm.graph.def.Transition.take(Transition.java:119)
       at org.jbpm.graph.def.Node.leave(Node.java:382)
       at org.jbpm.graph.exe.Token.signal(Token.java:174)
       at org.jbpm.graph.exe.Token.signal(Token.java:137)
       at org.jbpm.graph.exe.ProcessInstance.signal(ProcessInstance.java:229)
       at org.jboss.seam.core.Pageflow.navigate(Pageflow.java:183)
       at org.jboss.seam.jsf.SeamNavigationHandler.handleNavigation(SeamNavigationHandler.java:26)
       at org.apache.myfaces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:84)
       at javax.faces.component.UICommand.broadcast(UICommand.java:106)
       at javax.faces.component.UIViewRoot._broadcastForPhase(UIViewRoot.java:94)
       at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:168)
       at org.apache.myfaces.lifecycle.LifecycleImpl.invokeApplication(LifecycleImpl.java:343)
       at org.apache.myfaces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:86)
       at javax.faces.webapp.FacesServlet.service(FacesServlet.java:137)
       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:252)
       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
       at org.apache.myfaces.webapp.filter.ExtensionsFilter.doFilter(ExtensionsFilter.java:144)
       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
       at org.jboss.seam.servlet.SeamExceptionFilter.doFilter(SeamExceptionFilter.java:45)
       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
       at org.jboss.seam.servlet.SeamRedirectFilter.doFilter(SeamRedirectFilter.java:23)
       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
       at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)
       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
       at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
       at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:178)
       at org.jboss.web.tomcat.security.CustomPrincipalValve.invoke(CustomPrincipalValve.java:54)
       at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:174)
       at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:524)
       at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:74)
       at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:126)
       at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105)
       at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:107)
       at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:148)
       at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:869)
      


        • 1. Re: Transition out of pageflow
          gavin.king

          Sorry, you'll need to post your Java and jPDL code.

          • 2. Re: Transition out of pageflow
            pmuir

            Sure

            addVenue.jpdl.xml

            <?xml version="1.0" encoding="UTF-8"?>
            
            <pageflow-definition
             name="addVenue">
             <start-page name="details" view-id="/secure/venue/addVenue_details.xhtml">
             <transition name="next" to="travel"></transition>
             <transition name="cancel" to="cancel"></transition>
             <redirect />
             </start-page>
             <page name="travel" view-id="/secure/venue/addVenue_travel.xhtml">
             <transition name="back" to="details"></transition>
             <transition name="next" to="documents"></transition>
             <transition name="cancel" to="cancel"></transition>
            
             </page>
             <page name="documents" view-id="/secure/venue/addVenue_documents.xhtml">
             <transition name="next" to="summary"></transition>
             <transition name="back" to="travel"></transition>
             <transition name="cancel" to="cancel"></transition>
             <redirect />
             </page>
             <page name="summary" view-id="/secure/venue/addVenue_finish.xhtml">
             <transition name="finish" to="nextTask">
             <action expression="#{createVenue.create}" />
             </transition>
             <transition name="back" to="documents"></transition>
             <transition name="cancel" to="cancel"></transition>
             <redirect />
             </page>
            
             <decision name="nextTask" expression="#{addVenueNextTask}">
             <transition name="searchVenues" to="searchVenues"></transition>
             <!-- TODO other transitions at end of addVenue wizard
             </decision>
            
             <!--<page name="nextTask" view-id="/secure/venue/searchVenues.xhtml">
             <end-conversation />
             <redirect />
             </page>-->
            
             <page name="cancel" view-id="/secure/venue/searchVenues.xhtml" >
             <end-conversation />
             <redirect />
             </page>
            </pageflow-definition>
            


            CreateClientBean.java
            @Stateful
            @Name("createVenue")
            @Conversational(ifNotBegunOutcome="addVenue")
            public class CreateVenueBean implements CreateVenue {
            
             @In (create=true)
             private EntityManager smsDatabase;
            
             @In(create=true)
             @Out
             private Venue venue;
            
             @In(create=true)
             FacesMessages facesMessages;
            
             @In(create=true)
             private User authenticatedUser;
            
             private Folder rootFolder;
            
             // Initialise this to a nice default
            
             protected final Logger log = Logger.getLogger(this.getClass());
            
             private String nextTask;
            
             public String getNextTask() {
             return nextTask;
             }
            
             public void setNextTask(String nextTask) {
             this.nextTask = nextTask;
             }
            
             @Create
             @Begin(pageflow="addVenue", join=true)
             public void begin() {
             /*
             * Start the pageflow
             */
             log.info("Creating venue");
            
             // Next Task default
             nextTask = "searchVenues";
            
             if (venue == null) return;
             rootFolder = venue.getRootFolder();
            
             log.info("Root folder: " + rootFolder);
            
             // Hmm, having real issues outjecting the root folder
             Contexts.getConversationContext().set("rootFolder", rootFolder);
            
             }
            
             @End
             public void create() {
             venue.setBranch(authenticatedUser.getBranch());
             log.info("Next task: " + nextTask);
             smsDatabase.persist(venue);
             facesMessages.addFromResourceBundle(FacesMessage.SEVERITY_INFO, "screen.addVenue.create");
             Contexts.getSessionContext().set("addVenueNextTask", nextTask);
             }
            
             @Destroy @Remove
             public void destroy() {
            
             }
            
             public void instantiate() {
             }
            
            }
            


            As you can see I outject the addVenueNextTask variable to the session scope so it is available for the decision (and from the stacktrace above the correct transition is selected)

            Below is the relevant JSF navigation file

            main.xml
            <?xml version="1.0" encoding="UTF-8"?>
            
            <!DOCTYPE faces-config
            PUBLIC "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.0//EN"
             "http://java.sun.com/dtd/web-facesconfig_1_1.dtd">
            <faces-config>
            
             <navigation-rule>
             <!-- Navigation rules for venues -->
             <navigation-case>
             <from-outcome>editVenue</from-outcome>
             <to-view-id>/secure/venue/editVenue.xhtml</to-view-id>
            
             </navigation-case>
             <navigation-case>
             <from-outcome>searchVenues</from-outcome>
             <to-view-id>/secure/venue/searchVenues.xhtml</to-view-id>
             <redirect />
             </navigation-case>
             <navigation-case>
             <from-outcome>addVenue</from-outcome>
             <to-view-id>/secure/venue/addVenue_details.xhtml</to-view-id>
             <redirect />
             </navigation-case>
             </navigation-rule>
            ...
            </faces-config>
            


            From the docs/forum I don't think what I'm trying to do is supported currently - so I'm really asking whether it will be at some point (I can try to create a patch for it if wanted) or if not whether there is another way to do what I'm trying to do.

            If I've forgotten to post any code let me know :)

            Thanks

            Peter


            • 3. Re: Transition out of pageflow
              ido_tamir

              I don't know if I understood you completely.
              I am doing something similar and at least the transition to the second flow works:
              pageflow1 -> callenge.jsf -> pageflow2
              the bean responsible for pageflow2 is injected from session scope with an entity that is outjected from a bean responsible for pageflow1.
              Maybe there is a more elegant way to insert a property into the bean responsible for pageflow2.

              pageflow1 ends with challenge.jsf.

              <page name="submitted" view-id="/wizard/challengeItem.jsf">
               <redirect/>
               <end-conversation/>
              </page>
              


              I don't know if your pageflow code is the result of bug hunting,
              but maybe it simply lacks:
               <page name="searchVenues" view-id="/secure/venue/searchVenues.xhtml">
               <end-conversation />
               <redirect />
               </page>
              



              best wishes
              ido

              • 4. Re: Transition out of pageflow
                pmuir

                Ok, I'll try to explain better ;)

                I want to do pageflow -> decision -> JSF outcome (dependent on user selected option from list).

                You can get around it by entering each possible outcome from the decison as a page:

                
                <decision name="nextTask" expression="#{addVenueNextTask}">
                 <transition name="option1" to="option1"></transition>
                 <transition name="option2" to="option2"></transition>
                 <transition name="option3" to="option3"></transition>
                </decision>
                
                <page name="option1" view-id="/option1.jsf">
                 <redirect/>
                 <end-conversation/>
                </page>
                <page name="option2" view-id="/option2.jsf">
                 <redirect/>
                 <end-conversation/>
                </page>
                <page name="option3" view-id="/option3.jsf">
                 <redirect/>
                 <end-conversation/>
                </page>
                


                But thats pretty ugly and requires you to remember to update each pageflow when changing a outcome/viewid mapping.

                My problem is that jPDL transitions don't accept JSF outcomes as valid 'to' targets (AFAICT) - I think its a feature that should be added to Seam. I'm going to work on it next and then I'll see if Gavin will accept it ;)

                Unless you've somehow managed to move the 'decison' about where to go next to your challenge.jsf page?

                Let me know if I'm not clear here!

                • 5. Re: Transition out of pageflow
                  pmuir

                  For posterity:

                  Problem Statement

                  Next page to goto at end of wizard (using a pageflow) is determined by user-selected selectItem.

                  Implementation

                  Use a decision node to select an ad-hoc (JSF) outcome, decision based on value of selectItem

                  Flaw in implementation

                  Transitions from decision nodes cannot specify ad-hoc outcomes as targets (as they are embedded deep in jbpm)

                  Solution

                  If you directly specify an action method on the wizard page rather than a transition name, and return from this a String, the string will determine the transition used

                  AND

                  Transitions from page nodes can specify ad-hoc outcomes.

                  Not as neat as using a decision node (not as clear what is going on from the jpdl).