4 Replies Latest reply on Jun 30, 2009 2:19 PM by kukeltje.ronald.jbpm.org

    How to create nested conversation for <a4j:include> content

    skidvd.seamframework.abilsoft.com
      Hello,

      My app has a "<rich:panelMenu>" whose "<rich:panelMenuItem>" member elements cause the reRender of an "<a4j:outputPanel>".  The "<a4j:outPutPanel>" contains an <a4j:include> for a viewId that is controlled by the previously selected "<rich:panelMenuItem>".

      All of this works just as desired and the <a4:outputPanel> contents get reRendered with the user selected Facelet.

      My problem is that I need to start a nested conversation for the first (and only the first) invocation of any given Facelet that will be rendered for a given <rich:panelMenuItem>.

      Why, you might ask?

      Some of the Facelets in question need to bind to a JSF component.  So I use:

      @Scope( ScopeType.EVENT )
      @Name( "extendedDataTableController" )
      public class ExtendedDataTableControllerBean

      I subsequently reference this in the Conversation component for each Facelet like:

          @In( value="extendedDataTableController", required=false )
          protected ExtendedDataTableControllerBean table;

      The problem is that different Facelets have different ExtendedDataTables (i.e. different columms, etc).  However, as the controllers for those Facelets are Conversation scoped (I want to keep them this way), all Facelets that need to use this JSF binding are referencing the same instance .... not good and quite problematic as you switch between the menuItems/Facelets.

      The obvious answer to me seems to be to have each of the menuItems/Facelets running in their own individual nested Conversation...  This, I presume, would allow each Conversation to interact with its own 'unique' instance of the JSF binding EVENT scoped object?

      However, I cannot seem to force a nested conversation creation in pages.xml or by other means.  I tried the following addition (for one of the menuItem controlled Facelet contents) to pages.xml:

          <page view-id="/pages/configuration/pagea.xhtml">
              <begin-conversation nested="true"/>
              <description>Page A</description>
          </page>     

      However, this does not appear to work (verified via output of #{conversationList} - no nested conversation is created I presume because this rule is never 'invoked' as the pagea.xhtml is only referenced via an <a4j:include> in response to a POST on the main page (....there is no navigation or direct link to it, just AJAX include)???? 

      I've also placed @Begin(nested=true) on a @Factory method invoked by the included Facelets; but while this creates the nested conversation, it is invoked/created AFTER the @In injection of the EVENT scoped binding component, so does not solve the issue.

      I'm sure there is a way to work around this or a better way to approach it, but as I'm still fairly new to Seam (and Conversations in particular), I'm not sure how.

      Any and all help will be greatly appreciated!

      TIA!


        • 1. Re: How to create nested conversation for <a4j:include> content

          Todd Gould wrote on Apr 30, 2009 05:03:


          Hello,

          My app has a <rich:panelMenu> whose <rich:panelMenuItem> member elements cause the reRender of an <a4j:outputPanel>.  The <a4j:outPutPanel> contains an <a4j:include> for a viewId that is controlled by the previously selected <rich:panelMenuItem>.

          All of this works just as desired and the <a4:outputPanel> contents get reRendered with the user selected Facelet.

          My problem is that I need to start a nested conversation for the first (and only the first) invocation of any given Facelet that will be rendered for a given <rich:panelMenuItem>.

          Why, you might ask?

          Some of the Facelets in question need to bind to a JSF component.  So I use:

          @Scope( ScopeType.EVENT )
          @Name( "extendedDataTableController" )
          public class ExtendedDataTableControllerBean
          
          I subsequently reference this in the Conversation component for each Facelet like:
          
              @In( value="extendedDataTableController", required=false )
              protected ExtendedDataTableControllerBean table;
          
          



          The problem is that different Facelets have different ExtendedDataTables (i.e. different columms, etc).  However, as the controllers for those Facelets are Conversation scoped (I want to keep them this way), all Facelets that need to use this JSF binding are referencing the same instance .... not good and quite problematic as you switch between the menuItems/Facelets.

          The obvious answer to me seems to be to have each of the menuItems/Facelets running in their own individual nested Conversation...  This, I presume, would allow each Conversation to interact with its own 'unique' instance of the JSF binding EVENT scoped object?



          So... you want to that each menuItems/Facelets to be linked to a different seam component, with one component @PerNestedConversation. If I were you, I wouldn't event try to go there @PerNestedConversation is, in words of Seam authors ill defined and even Dan Allen decided to skip the subject, for its Seam in Action book.  And that is just the beginning of the problems with nested conversations.



          However, I cannot seem to force a nested conversation creation in pages.xml or by other means.  I tried the following addition (for one of the menuItem controlled Facelet contents) to pages.xml:

              <page view-id="/pages/configuration/pagea.xhtml">
                  <begin-conversation nested="true"/>
                  <description>Page A</description>
              </page>      
          



          However, this does not appear to work (verified via output of #{conversationList} - no nested conversation is created I presume because this rule is never 'invoked' as the pagea.xhtml is only referenced via an <a4j:include> in response to a POST on the main page (....there is no navigation or direct link to it, just AJAX include)???? 

          I've also placed @Begin(nested=true) on a @Factory method invoked by the included Facelets; but while this creates the nested conversation, it is invoked/created AFTER the @In injection of the EVENT scoped binding component, so does not solve the issue.

          I'm sure there is a way to work around this or a better way to approach it, but as I'm still fairly new to Seam (and Conversations in particular), I'm not sure how.



          I dont think there is an easy way to solve this problem, I think Seam component model was not designed from the start to be able to deal with hierchical/nested stuff, so I guess you will have to find a complicated workaround to solve this (or plain switch from using a server side JSF based component model, and do this stuff with client side javascript). Of course, if you find a simple way to solve this, please share it here.



          Any and all help will be greatly appreciated!

          TIA!




          • 2. Re: How to create nested conversation for <a4j:include> content
            skidvd.seamframework.abilsoft.com

            Francisco,


            Thanks for you reply.  I want to make sure that I understand your comments....  Are you saying that @PerNestedConversation is not ideal/recommended (this seems to be clear from the documentation for it) - OR - are you stating that nested conversations in general are problematic and/or should be avoided?


            If the later, I'm perplexed as this seems to be a major design feature of the Seam Conversational model and is used in many of the examples???


            At present I'm looking into two different approaches to my dilema:


            1) Using an <a4j:support> element nested in the panelMenuItem that will 'immediate' invoke a component whose job it will be to verify (and create as necessary) the nested conversation via the Conversation API....


            2) Potentially do the same manual conversation management via Seam Remoting.


            Does anyone have any thoughts on these approaches and/or ideas for better ones?

            • 3. Re: How to create nested conversation for <a4j:include> content

              Todd Gould wrote on Apr 30, 2009 19:09:


              Francisco,

              Thanks for you reply.  I want to make sure that I understand your comments....  Are you saying that @PerNestedConversation is not ideal/recommended (this seems to be clear from the documentation for it) - OR - are you stating that nested conversations in general are problematic and/or should be avoided?


              Both :'( . Look at JBSEAM-3903  to see how easy is to make mistakes with conversations.


              If the later, I'm perplexed as this seems to be a major design feature of the Seam Conversational model and is used in many of the examples???


              AFAIK conversations are used in many of the examples, but nested conversations is used in only a few.


              At present I'm looking into two different approaches to my dilema:

              1) Using an <a4j:support> element nested in the panelMenuItem that will 'immediate' invoke a component whose job it will be to verify (and create as necessary) the nested conversation via the Conversation API....

              2) Potentially do the same manual conversation management via Seam Remoting.

              Does anyone have any thoughts on these approaches and/or ideas for better ones?

              • 4. Re: How to create nested conversation for <a4j:include> content
                kukeltje.ronald.jbpm.org

                I know nested conversations are kind of a PITA, but still, I'd like to have the option to have different conversations (not nested ones) within a page.


                In my example, I have a tabpanel with the first tab containing a list with 'searchresults' of some sort. Double clicking or using a context menu, you can open one of the results in a separate tab. All of this works great, but I have to maintain lists/maps of open tabs and the data used in each tab myself, pass keys on etc. Would be great if I could just start a new conversation and have it end if the tab closes or the conversation times out. Would be nice if you could e.g. pass a conversationId on to a a4j outputpanel, region, include or whatever and have all actions take place within the context of that conversation. Would not make any difference then if it is a nested conversation or not. So imo it is not realy a seam issue, but more a richfaces issue right?


                What do you think? Shall I file a jira issue?