4 Replies Latest reply on Jul 14, 2009 9:01 PM by wangliyu

    conversation question - improvement suggestions with @Begin

      Hello,


      i like the idea of the conversation model and in fact its all working for me but i have some questions left.
      One use-case i had problems with, is starting a long running conversation for each call of an action method.


      That limit long runnnig conversation already active - try join=true
      thing really is unneccesary and confusing in my opinion why not just start a new one? (should be the default beahaviour ill explain how i solved this problem)



      lets look at this code


      <a4j:commandLink id="selectMemberCommandLink"
                                       action="#{MultipleWindowTest.selectMember(member.id)}" 
                                       value="--SELECT A MEMBER"
                                       oncomplete="taskBar.createWindow();"
                                       reRender="memberPanel,popupWindowPanel"
                                       limitToList="true"
                                       ajaxSingle="true"
                                       eventsQueue="popupQueue">
              <s:conversationPropagation type="none">
              </s:conversationPropagation>
      </a4j:commandLink>




      <s:conversationPropagation type="none">
      </s:conversationPropagation>



      tells seam that the conversation shouldnt be propagated which means a new one can started without any problems
      (becourse for the action method no conversation is existent)


      That works fine - but theres 1 big problem with this solution- what if your action method needs values from the current active conversation?.


      action="#{MultipleWindowTest.selectMember(member.id)}" 

      member.id wil resolve to null and the action method wil get 0 as imput parameter - doh!


      The only solution i found was removing the conversationPropagation tag and hacking this in my action method


      Conversation.instance().leave(); //avoid "long running conversation already active stuff"
      Conversation.instance().begin();

      //start a new one


      So why i cant archieve the behaviour descriped above(just start a new long running conversation regardless what)
      with annotations / pages.xml but only from java code?


      @Begin join=false nested=false 

      should do the job from my understanding.
      Well i could maybe write an annotation doing the 2 lines of code above but is this really necesary?


      Any comment on this would be very helpfull!
      Anyway its working now and all is fine - theres only a bitter taste left and it really dont understand why its so complicated to start a conversation.























        • 1. Re: conversation question - improvement suggestions with @Begin
          asookazian

          I need a real name wrote on Jul 11, 2009 14:45:


          That limit long runnnig conversation already active - try join=true
          thing really is unneccesary and confusing in my opinion why not just start a new one?


          I've hit that problem myself as well.  It tends to happen more often in less well-defined pageflows where there is no set pattern of page submissions that a user must navigate thru (like in the booking example, that's very well-defined and obviously a happy path use case).


          It's obviously possible to start a new LRC (just open a new tab and execute your use case, no?)


          The bottom line is you can only have one active LRC per session.  But I don't understand why the Seam container doesn't just start a new LRC when there is already one running when it encounters the @Begin annotation on an action method for a backing bean.  Just create a new temporary conversation, immediately promote it to LRC and the previously current LRC becomes now a background LRC.


          Conversation mgmt in Seam is one of the reasons (along with bijection and some other concepts like remoting, drools and jBPM) that the learning curve with this framework (in addition to RF and EJB3) is so high...

          • 2. Re: conversation question - improvement suggestions with @Begin

            Hi - nice to have your opinion on that, and for explaining this issue in more detail.



            The bottom line is you can only have one active LRC per session.

            Ah ok i didnt knew this.But why not making the new started conversation the active one?




            Conversation mgmt in Seam is one of the reasons (along with bijection and some other concepts like remoting, drools and jBPM) that the learning curve with this framework (in addition to RF and EJB3) is so high...

            Bijection was easy to understand, theres nothing your can make wrong.
            Conversation model - well theres so much and so much you can do wrong.In fact i am just starting to understand how it works.
            Understanding the EJB3 Stuff was another big challenge.
            Sometime i think cant it just be plain simple but then i remember we are programmers



            But that


            long runnnig conversation already active - try join=true



            is really making a lot of unnecesary problem in my opinion

            • 3. Re: conversation question - improvement suggestions with @Begin
              asookazian

              the following code is from the Manager component:


              /**
                  * Look for a conversation propagation style in the request
                  * parameters and begin, nest or join the conversation,
                  * as necessary.
                  * 
                  * @param parameters the request parameters
                  */
                 public void handleConversationPropagation(Map parameters)
                 {      
                    ConversationPropagation propagation = ConversationPropagation.instance();
                    
                    if (propagation.getPropagationType() == null)
                    {
                       return;
                    }
              
                    switch (propagation.getPropagationType())
                    {
                       case BEGIN:
                          if ( isLongRunningConversation )
                          {
                             throw new IllegalStateException("long-running conversation already active");
                          }
                          beginConversation();
                          
                          if (propagation.getPageflow() != null)
                          {
                             Pageflow.instance().begin( propagation.getPageflow() );
                          }
                          break;
                       case JOIN:
                          if ( !isLongRunningConversation )
                          {
                             beginConversation();
                             
                             if (propagation.getPageflow() != null)
                             {
                                Pageflow.instance().begin( propagation.getPageflow() );
                             }
                          }
                          break;
                       case NEST:
                          if ( isLongRunningOrNestedConversation() ) 
                          {
                              beginNestedConversation();
                          }
                          else 
                          {
                              beginConversation();
                          }
                          
                          if (propagation.getPageflow() != null)
                          {
                             Pageflow.instance().begin( propagation.getPageflow() );
                          }
                          break;
                       case END:
                          endConversation(false);
                          break;
                    }
                 }



              So the question becomes, why can't we refactor this part of the method as follows:


               case BEGIN:
                          /*if ( isLongRunningConversation )
                          {
                             throw new IllegalStateException("long-running conversation already active");
                          }*/
              
                          beginConversation();
                          
                          if (propagation.getPageflow() != null)
                          {
                             Pageflow.instance().begin( propagation.getPageflow() );
                          }
                          break;
              



              and this as well:


              /**
                  * Promote a temporary conversation and make it long-running
                  */
                 public void beginConversation()
                 {
                    //if ( !isLongRunningConversation() )
                    //{
                       log.debug("Beginning long-running conversation");
                       setLongRunningConversation(true);
                       createConversationEntry();
                       Conversation.instance(); //force instantiation of the Conversation in the outer (non-nested) conversation
                       storeConversationToViewRootIfNecessary();
                       if ( Events.exists() ) Events.instance().raiseEvent(EVENT_CONVERSATION_BEGIN);
                    //}
                 }



              You can try that and see what happens...  Most likely there are repurcussions to doing this but I am unaware of what they may be...

              • 4. Re: conversation question - improvement suggestions with @Begin
                wangliyu
                See this link:
                http://www.seamframework.org/Community/HowToEndAndBeginANewConversationWithOneSignleSlink?cid=3015733