1 2 3 Previous Next 32 Replies Latest reply on Jul 13, 2006 1:04 PM by Gavin King

    Beginning conversations in @Factory methods

    Dave Whittaker Novice

      I have a pretty typical CRUD application. A @DataModel is generated by a @Factory method which is also annotated with @Begin(join = true); so far so good. However when a create operation occurs the corresponding method is annotated with @End and this is where things go wrong. If I don't set the list to null my subsequent page displays the list generated by the ended conversation, even though I've issued a redirect. I'd imagine this is because a conversation's state is not cleared until a response is rendered? Anyway, if I do set the list to null, it seems that the @DataModel annotation causes the @Factory method to be called directly after the create method thereby re-propogating the conversation I just tried to end. I can't seem to find a way around this. Any suggestions on how to fix the problem or an alternate design?

      -Dave

        • 1. Re: Beginning conversations in @Factory methods
          Gavin King Master

          Right.

          (1) conversations span redirects (a Good Thing)
          (2) factory methods are called every time a variable is referenced - you can't really "clear" it


          I would use some other solution than @Factory (eg. a page action)

          • 2. Re: Beginning conversations in @Factory methods
            Dave Whittaker Novice

            Conversations spanning redirects is certainly a good thing in general, but once I've ended a conversation shouldn't it go away? I'm not entirely certain I understand the conversation lifecycle here. If I invoke an action method annotated with @End it seems like the current conversation should be destroyed and a new temporary conversation should be started. That's not what's occuring however so when is the conversation actually destroyed?

            Doesn't it seem more intuitive that once I've called a method annotated with @End the next call to a @Begin(join = true) method will begin a new conversation? Is there no way to end a current conversation and begin an entirely new one in the course of a single request?

            I'm not using jPDL pageflows (I need to support back button usage) so does anyone have any other thoughts on how this could be accomplished? It makes sense to me that a conversation should be started when a @DataModel is accessed so that the corresponding @DataModelSelection matches up to the DataTable presented to the user. If the conversation didn't begin until a row was selected I'd imagine the postback would start a new conversation, retrieving a new List via the factory method with potentially different results. Or am I missing something about the conversation lifecycle again?

            Thanks for your help.

            -Dave

            • 3. Re: Beginning conversations in @Factory methods
              Pete Muir Master

               

              Is there no way to end a current conversation and begin an entirely new one in the course of a single request?


              I'm pretty sure there isn't, Gavin wrote about this sometime ago on the forum.

              I'm not using jPDL pageflows (I need to support back button usage)

              AFAIK you can use the back button when using jpdl:

              <page name="..." view-id="..."back="enabled">
              </page>
              



              It makes sense to me that a conversation should be started when a @DataModel is accessed so that the corresponding @DataModelSelection matches up to the DataTable presented to the user. If the conversation didn't begin until a row was selected I'd imagine the postback would start a new conversation, retrieving a new List via the factory method with potentially different results. Or am I missing something about the conversation lifecycle again?


              What about putting the datamodel into the PAGE scope? Then start a conversation on the next action.

              • 4. Re: Beginning conversations in @Factory methods
                Jim Hazen Expert

                 

                Is there no way to end a current conversation and begin an entirely new one in the course of a single request?


                Have you tried @Begin without the join=true? From your example it sounds like you're asking Seam to propagate the context you're trying to clear out. It make sense to me that resources are not immediately destroyed when @End methods are called, and that the rendered response is the last response of this (now ended) conversation.

                If continuing to render the response to the original request (of the ending conversation) is the default, then you may need to use a page action to instead kick the rendering over to a page running in the new conversation.

                • 5. Re: Beginning conversations in @Factory methods
                  Dave Whittaker Novice

                   

                  "petemuir" wrote:
                  Is there no way to end a current conversation and begin an entirely new one in the course of a single request?


                  I'm pretty sure there isn't, Gavin wrote about this sometime ago on the forum.


                  I searched the forum and hadn't run across anything. I'd be interested to know why this is the case. Even if it's not the default behaviour a @End(immediate = "true") feature seems like it would be useful. It would also help if sometime in the future the conversation lifecycle was documented in a bit more detail, although I realize it's a work in progress and that might take a while.

                  AFAIK you can use the back button when using jpdl:


                  Thanks for the tip. I hadn't noticed when that feature was added. Any idea how it works? Some type of unique token representing the current state that's placed in the component tree perhaps?

                  What about putting the datamodel into the PAGE scope? Then start a conversation on the next action.


                  My problem is that the next action after a list is displayed is often displaying a selection from the list. As I understand things, on a postback the DataTable component will reaccess the DataModel through EL variable resolution, then indicate the row selected. If the DataModel exists in a long running conversation, that will be returned and it'll work great. If the conversation wasn't started when the original DataModel was generated I'd imagine a new DataModel will be created on the postback (through the @Factory method) and it could be different from what was rendered to the user. Does that make sense?


                  • 6. Re: Beginning conversations in @Factory methods
                    Dave Whittaker Novice

                     

                    Have you tried @Begin without the join=true?


                    I have not, but I'd imagine it will do the same thing. I don't think the problem is that it's joining a long running conversation, but that it's seeing the ended conversation, thinking that it's a temporary conversation and setting it to be long running. Come to think of it, I might be off here, but from what I remember of looking over the Manager class that seems right.

                    you may need to use a page action to instead kick the rendering over to a page running in the new conversation.


                    Kind of seems that way. Anybody else doing things differently? Not using jPDL? Anybody starting the conversation when a row is selected, and if so any problems with the consistency of the list data?

                    -Dave


                    • 7. Re: Beginning conversations in @Factory methods
                      Dave Whittaker Novice

                      Upon further thought, the page action won't work either. It would start the conversation correctly the first time the list page was accessed, but after a creation occured and I wanted to display the list page again, my choices would be to begin the conversation with another page action (same problem as before, it wouldn't actually be a new conversation) or don't and end up with no long running conversation after the second list page is rendered.

                      It seems to me that the easiest way to fix this would be to strip the conversationId parameter when the redirect is issued. Unfortunately, I don't see any way to do that since I'm returning a symbolic view id from my action method and seam is "magically" adding it. Any suggestions?

                      • 8. Re: Beginning conversations in @Factory methods
                        Gavin King Master

                        All kinds of totally nonintuitive problems occur if you try to have requests that span bits of different conversations. This was what I initially implemented wayback, and it turned out to be Really Evil. So now, conversations begin and end at request boundaries.

                        • 9. Re: Beginning conversations in @Factory methods
                          Jim Hazen Expert

                          You may be able to use a combination of built in conversation components to help control the current/next conversation context programmatically. This may interact better with Seam's redirect filter (which is the guy that I think is adding your conversationId param).

                          http://docs.jboss.com/seam/latest/reference/en/html/components.html#d0e6402

                          • 10. Re: Beginning conversations in @Factory methods
                            Pete Muir Master

                             


                            My problem is that the next action after a list is displayed is often displaying a selection from the list. As I understand things, on a postback the DataTable component will reaccess the DataModel through EL variable resolution, then indicate the row selected. If the DataModel exists in a long running conversation, that will be returned and it'll work great. If the conversation wasn't started when the original DataModel was generated I'd imagine a new DataModel will be created on the postback (through the @Factory method) and it could be different from what was rendered to the user. Does that make sense?



                            Yes, but if it's in PAGE scope then on 'postback' the datamodel will be available through EL so won't be recreated. Your scenario is a big reason for PAGE scope :)


                            2.1.3. Page context

                            The page context allows you to associate state with a particular instance of a rendered page. You can initialize state in your event listener, or while actually rendering the page, and then have access to it from any event that originates from that page. This is especially useful for functionality like clickable lists, where the list is backed by changing data on the server side. The state is actually serialized to the client, so this construct is extremely robust with respect to multi-window operation and the back button.


                            A page action would work as well I think. Remember you can disable conversation propogation for actions and therefore @Begin would start a new conversation. This is equivalent to to your 'stripping the conversation Id'.

                            • 11. Re: Beginning conversations in @Factory methods
                              Dave Whittaker Novice

                               

                              All kinds of totally nonintuitive problems occur if you try to have requests that span bits of different conversations. This was what I initially implemented wayback, and it turned out to be Really Evil. So now, conversations begin and end at request boundaries.


                              Ah, but my problem is that the conversation isn't ending at the request boundary. It's continuing on through the redirect after a postback and I can't figure out how to disable that.

                              • 12. Re: Beginning conversations in @Factory methods
                                Dave Whittaker Novice

                                 

                                You may be able to use a combination of built in conversation components to help control the current/next conversation context programmatically.


                                I actually looked into that and didn't see anything that jumped out at me. I suppose Conversation.leave() would probably be my best bet. If that unassociates the request from the current conversation then maybe the conversationId won't be added to the redirect. I'll give it a shot.

                                • 13. Re: Beginning conversations in @Factory methods
                                  Gavin King Master

                                  Well, one way is to remove the RedirectFilter.

                                  Other than that, you would have to show me a really compelling usecase for why you need some extra functionality to disable conversation-propagation-over-redirect on a per-request basis.

                                  You havn't really described your usecase yet.

                                  • 14. Re: Beginning conversations in @Factory methods
                                    Gavin King Master

                                    Conversation.leave() will leave the current conversation in an orphaned state though. You probably don't want that.

                                    1 2 3 Previous Next