6 Replies Latest reply on Nov 6, 2012 5:40 PM by tony.herstell1

    Two conversations created instead of one with conversation.begin() in @PostConstruct method

    lucaster

      Before issuing a bug, I'd like someone to try the following, which exposes a weird  behaviour in Weld's conversation management.

       

      All will work fine if you use this bean/page as they are, but if you move the outputText with id 'convout' inside the form, two conversations will be started instead of one!!! The first conversation will be righfully created when the pages is requested the rist time. But another one will be created when you press the 'Increment' button.

       

      (I'm experiencing this with JBoss AS 7.1.1.Final, JBoss Developer Studio 5, with a Java EE Web Project)

       

      ConvTest.java

       

      @Named
      @ConversationScoped
      public class ConvTest implements Serializable {
      
          private static final long serialVersionUID = 2866431447137331469L;
      
          @Inject
          private Conversation conversation;
      
          private int counter;
      
          @PostConstruct
          public void postCon() {
              if (conversation.isTransient())
                  conversation.begin();
          }
      
          public void increment() {
              counter++;
          }
      
          public Conversation getConversation() {
              return conversation;
          }
      
          public int getCounter() {
              return counter;
          }
      
      }
      

       

      index.xhtml

       

      <?xml version="1.0" encoding="UTF-8"?>
      <html xmlns="http://www.w3.org/1999/xhtml"
          xmlns:ui="http://java.sun.com/jsf/facelets"
          xmlns:f="http://java.sun.com/jsf/core"
          xmlns:h="http://java.sun.com/jsf/html">
      <h:head>
      </h:head>
      <h:body>
      
          <!-- Moving this outputText inside the form causes the side effect -->
          <h:outputText value="#{convTest.conversation}" id="convout"/>
      
          <h:form>
              <h:commandButton value="Increment" action="#{convTest.increment}" />        
          </h:form>
      
          <h:outputText value="#{convTest.counter}" />
      
      </h:body>
      </html>
      
        • 1. Re: Two conversations created instead of one with conversation.begin() in @PostConstruct method
          luksa

          Yup, exactly as you say. A second conversation is created. Please file an issue and I'll take a look at it.

          1 of 1 people found this helpful
          • 2. Re: Two conversations created instead of one with conversation.begin() in @PostConstruct method
            luksa

            Ah, yes. When the <form> tag is rendered, the conversation hasn't been started, since ConvTest hasn't been instantiated yet (and @PostConstruct hasn't been invoked yet). As a result, the action url of the <form> tag contains no cid parameter, because there's no conversation active when the url is generated.

             

            Need to figure out what, if anything, we should do about this.

            • 3. Re: Two conversations created instead of one with conversation.begin() in @PostConstruct method
              lucaster

              Thanks for the clarification!

               

              As a matter of fact, the side effect also occurs when the outputText is after the </h:form>

              • 4. Re: Two conversations created instead of one with conversation.begin() in @PostConstruct method
                luksa

                Yes, of course. The key thing here is that the conversation must be long-running before rendering the starting form tag.

                 

                Basically, the main problem with your approach is that you are starting the conversation in the render-response jsf phase. Ideally, you should start the conversation before this phase, otherwise the urls in html will not have the cid parameter, which is necessary for propagating the conversation.

                1 of 1 people found this helpful
                • 5. Re: Two conversations created instead of one with conversation.begin() in @PostConstruct method
                  mkouba

                  I think you might also use <f:param name="cid" value="#{javax.enterprise.context.conversation.id}"/> inside the commandButton provided you have the outputText before commandButton. But Marko is right that this approach is not convenient...

                   

                  See also my blog post about ajax-related issues you might encounter: Seam vs Weld: ajax and conversations in JSF view

                  • 6. Re: Two conversations created instead of one with conversation.begin() in @PostConstruct method
                    tony.herstell1

                    Going with KISS...

                     

                    I land on a page via a menu that calls an "init" function in a controller...

                     

                     

                     // A good place to START a conversation from. ** land here off a menu
                        // click...
                        public String init() {
                            this.logger.info(">>>init");
                            if (!this.conversation.isTransient()) {
                                this.logger.info("Existing conversation found:" + this.conversation.getId() + " Ending it...");
                                this.conversation.end();
                            }
                            this.logger.info("+++CONVERSATION START");
                            this.conversation.begin(); // START THE LONG RUNNING CONVERSATION
                            this.logger.info("conversation:" + this.conversation.getId());
                            this.setupXXXXValues();
                            this.logger.info("<<<init");
                            return "pretty:manageXXXXs";
                        }
                    

                    and yes Buttons need the cid applied (especailly if you use prettyfaces)

                     

                                <ui:fragment rendered="#{xxxManagementController.CRUDMode eq 'DELETE'}">
                                   <p:commandButton id="deleteButton" update=":xxxxForm:xxxxxPanel :messagesForm" icon="ui-icon ui-icon-disk" action="#{xxxxManagementController.deleteXxxx(xxxxx)}"
                                      value="#{messages.button_delete} #{messages.xxxx}" onstart="return confirm('#{messages.are_you_really_sure}')">
                                      <f:param name="cid" value="#{xxxxxxManagementController.cid}" /> <!-- FORCE ConverstionId to be added -->
                                   </p:commandButton>
                                </ui:fragment>
                    
                    //Tell prettyfaces to use this bean when the pattern matches and show the manage xxxx page. Also support a Query Param (cid).
                    @URLMappings(mappings = { @URLMapping(id = "manageXXXs", pattern = "/xxxx/manage", viewId = "/pages/xxxx/manageXxxx.xhtml"),
                    

                     

                    Keeps it very simple though and avoida a lot of problems with Conversation Handling in JEE 6 Weld.