1 2 3 Previous Next 32 Replies Latest reply on Nov 5, 2007 7:36 AM by wschwendt Go to original post
      • 15. Re: Feature request regarding nested conversations
        matt.drees

        Hi Jacob,

        So you're not using a SMPC. I guess I tend to assume everybody uses them. :-) My bad.

        So I understand more, but I'm still missing a few pieces.

        "jacob.orshalick" wrote:
        ...Seam has taken a snapshot of my Person entity in the outer conversation on nesting (which didn't have the new addresses). The original Person instance will be reverted back to should the user back up to the original edit Person screen and submit. Seam retrieves the outer conversation by id on submit and restores the state of my Person object at the time of the snapshot which doesn't include the new addresses.


        It seems like you're embellishing Seam's behavior a little bit. It's my understanding that when you begin a nested conversation, Seam doesn't take a snapshot, it just creates a new empty "container", and prevents you from storing new objects in the parent container. While in the nested conversation, new objects are stored in this new container, and lookups look there before looking in the parent container; there's no automatic cloning going on. And if a user backbuttons out of a nested conversation, then there's no "restoring" going on, either; the nested container is simply not there, so new objects get stored in the parent container and lookups look there first.

        So, to get the behavior you're talking about, I think you'd need to manually clone the person object when starting a nested conversation. The "original state" Person would stay in the parent conversation, and the new cloned Person, which might be edited, goes in the nested conversation. I'm guessing you must be doing this cloning manually somehow to get the behavior you describe, but you speak as if it's automatic. Could you explain a little more or show some code?

        Thanks!

        • 16. Re: Feature request regarding nested conversations
          matt.drees

           

          "jacob.orshalick" wrote:


          1. Does the snapshot of the Conversation context include a snapshot of the *managed entity*?
          2. If I make changes to the Person in the nested conversation, since this is a *managed entity* does it make any difference in the semantics of the outer vs. nested conversation?
          3. Will I still be able to revert back to the outer conversation snapshot of my Person object as I can with a detached entity?


          I think I need to better understand how your detached-entity system works in order to intelligently answer these, but I'm pretty sure you'll find that seam-managed persistence contexts and nested conversations don't behave how you'd like them to (ie, like continuation servers). Here are some posts that relate:

          http://www.jboss.com/index.html?module=bb&op=viewtopic&t=111384


          http://www.jboss.org/index.html?module=bb&op=viewtopic&t=113362


          • 17. Re: Feature request regarding nested conversations

            Thanks for the excellent information and the informative links Matt!

            It seems like you're embellishing Seam's behavior a little bit. It's my understanding that when you begin a nested conversation, Seam doesn't take a snapshot, it just creates a new empty "container", and prevents you from storing new objects in the parent container....

            So, to get the behavior you're talking about, I think you'd need to manually clone the person object when starting a nested conversation. The "original state" Person would stay in the parent conversation, and the new cloned Person, which might be edited, goes in the nested conversation.


            You are absolutely correct Matt! I suppose I am embellishing Seam's behavior ;) I am cloning the Person object when starting a nested conversation which would obviously be problematic when using an SMPC since the instance would no longer be managed on cloning.

            The reason the approach works is performing the merge at the end. The detached instance is merged back with the attached "managed" instance. Thus, whichever instance it finds first during the lookup (the clone in the nested conversation or the original in the outer conversation) is the instance that is merged.

            Thanks for increasing my understanding here on use of SMPCs with your information and the provided links. The approach I've used works well for my client (who have many of these mother-child scenarios and do not require an SMPC) but it is important to note that this is not viable for managed entities.

            One question. If I cloned my Person in the nested conversation and then merged the clone to retrieve the attached instance, I'm assuming I would now have the same reference in both my outer and inner conversation. Is this assumption correct? Thanks again.

            By the way, on an unrelated note, how are you guys crediting quotes (e.g. "jacob orshalick" wrote). I want to make sure I'm giving credit where credit is due :)

            • 18. Re: Feature request regarding nested conversations
              wschwendt

               

              "matt.drees" wrote:
              Hi Jacob,

              So you're not using a SMPC. I guess I tend to assume everybody uses them. :-) My bad.

              So I understand more, but I'm still missing a few pieces.


              As for Jacob's approach, I think I roughly understand what he wants to achieve with his use of nested conversations, but so far I cannot completely follow either because some details of his approach are still unknown to us.

              "matt.drees" wrote:

              "jacob.orshalick" wrote:
              ...Seam has taken a snapshot of my Person entity in the outer conversation on nesting (which didn't have the new addresses). The original Person instance will be reverted back to should the user back up to the original edit Person screen and submit. Seam retrieves the outer conversation by id on submit and restores the state of my Person object at the time of the snapshot which doesn't include the new addresses.


              It seems like you're embellishing Seam's behavior a little bit. It's my understanding that when you begin a nested conversation, Seam doesn't take a snapshot, it just creates a new empty "container", and prevents you from storing new objects in the parent container. While in the nested conversation, new objects are stored in this new container, and lookups look there before looking in the parent container; there's no automatic cloning going on. And if a user backbuttons out of a nested conversation, then there's no "restoring" going on, either; the nested container is simply not there, so new objects get stored in the parent container and lookups look there first.



              Exactly, I already thought the same yesterday evening. Jacob has repeatedly mentioned that Seam saves "snapshots", but I think that is not really the case. Seam manages contexts which are conceptually map-like data structures that associate context variable names (Strings) with object values. As regards contexts and nested conversations, when a new nested conversation is begun, Seam does in fact NOT clone the objects to which context variables from the parent conversation are bound. When a component class is annotated with @PerNestedConversation, however, any component instance of the same name that might exists in the parent conversation is invisible to its child conversations. This may lead to instantiation of a fresh component instance in the scope of a nested conversation when a @PerNestedConversationcomponent is being looked up. Do you make use of this @PerNestedConversationcomponent feature, Jacob?

              Alternatively, regarding Jacob's mentions of "saved snapshots", I was wondering whether perhaps he interprets the side-effects of the ManagedEntityIndentityInterceptor as "saving of snapshots". As described in my first post in this thread (#1), when a conversation-scoped component of the parent conversation is called from a nested conversation, the ManagedEntityIndentityInterceptor saves its wrappers for Entity fields
              or Entity collection fields in the scope of the nested conversation and not the parent conversation. It follows that once the nested conversation context is destroyed and the parent conversation resumes, these saved wrappers are gone, too (if I'm not mistaken). This may appear to be a reversion to a previous snapshot, but it is a reversion only as far as Entity fields or Entity collection fields are concerned. All other fields no wrappers are saved for by the ManagedEntityIndentityInterceptor are not reverted to old values.

              I'm not sure however whether Jacob's snapshot behavior is caused by the
              ManagedEntityIndentityInterceptor. If a Seam component is an Entity, no interceptor is added by Seam, thus no ManagedEntityIndentityInterceptor either.

              "matt.drees" wrote:

              I'm guessing you must be doing this cloning manually somehow to get the behavior you describe, but you speak as if it's automatic. Could you explain a little more or show some code?


              we need to know exactly how Jacob's does the management of Entity instances. How are they accessed, are context variables bound to them, and if so, with what scope?


              • 19. Re: Feature request regarding nested conversations
                wschwendt

                our posts have just overlapped, Jacob. Wasn't aware of your latest follow-up when I clicked the submit button.

                • 20. Re: Feature request regarding nested conversations

                  Not a problem Wolfgang, I hope that my post cleared up a lot of your questions.

                  • 21. Re: Feature request regarding nested conversations
                    wschwendt

                    and it should always read ManagedEntityIdentityInterceptor,
                    not ManagedEntityIndentityInterceptor

                    (was using copy & paste to save some typing and always copied the mistake name with an additional 'n')

                    • 22. Re: Feature request regarding nested conversations
                      wschwendt

                       

                      "baz" wrote:
                      Very interesting thread.
                      i like to give a new usecase (or workflow)
                      We have a search screen, where the user can search for an object(e.g. an experiment)
                      When navigation to the show/edit screen ocurs a conversation is started and the object(the experiment) is shown.

                      Now the user can work with the object(the experiment)

                      What comes in now is a subworkflow. This workflow uses a nested conversation and could be started on any page. When this subworkflow ends, the nested conversation ends and redirection to the starting page occurs.

                      (...)

                      My question is how this kind of workflows can be correctly implemented with seam and conversations? For now, it seems to me that it is nessacary to deliver results from the nested conversation to the outer conversation.


                      This exactly is the motive why I opened this tread: to request a better (or more elegant) way to transfer state (an ending result) back to the parent conversation when the nested conversation ends.

                      From a modeling perspective, it makes a lot of sense to model a use case (or an activity or workflow) as a composition of sub use cases (or sub-activities). For example, in UML use case diagrams you could define include- or extend- relationships between use cases. In activity diagrams it is possible to model the invocation of sub activities etc.

                      When using Seam for the implementation, these models eventually would have to be mapped to Seam-based code. Clearly, Seam's nested conversation feature is somewhat limited as long as it is akward to transfer state back to the parent conversation (eg. if artificial POJO classes just for this state transfer have to be written).


                      • 23. Re: Feature request regarding nested conversations
                        matt.drees

                         

                        "jacob.orshalick" wrote:


                        One question. If I cloned my Person in the nested conversation and then merged the clone to retrieve the attached instance, I'm assuming I would now have the same reference in both my outer and inner conversation. Is this assumption correct? Thanks again.


                        That's my understanding, yes. I haven't thought enough about it, but maybe you could get continuation-like behavior with SMPCs through careful use of merging. In particular, I wonder if you could create a new persistence context in the nested conversation, merge everything down to it from the parent context, do your editing, and then when you're done, either merge everything back, or flush the child persistence context and refresh the appropriate entities in the parent context.

                        "jacob.orshalick" wrote:

                        By the way, on an unrelated note, how are you guys crediting quotes (e.g. "jacob orshalick" wrote). I want to make sure I'm giving credit where credit is due :)


                        Click on the "quote" button to the far right of someone's name, and it'll show you the additional syntax you need. Took me a while to catch on, too. :-)

                        • 24. Re: Feature request regarding nested conversations

                           

                          "wschwendt" wrote:
                          This exactly is the motive why I opened this tread: to request a better (or more elegant) way to transfer state (an ending result) back to the parent conversation when the nested conversation ends.


                          I absolutely agree with you guys that this is a must if you could simply carry the required state changes (and maintain the snapshot of the original conversation for back-button purposes) the problem would be resolved. The issue is if you directly write into the parent conversation, the back-button is always going to cause problems in master-details scenarios unless a snapshot exists.

                          e.g. if Person has addresses added and this is updated to the parent conversation, backing up to the page that does not show the addresses will still persist the addresses on submit as they are a part of that conversation.

                          Spring Web Flow provides a very elegant solution to this through its continuation approach but warn of the potential for high-memory usage. This could be limited if you could specify ONLY the objects that need a snapshot (which is essentially what I've been doing by cloning).

                          "matt.drees" wrote:
                          I wonder if you could create a new persistence context in the nested conversation, merge everything down to it from the parent context, do your editing, and then when you're done, either merge everything back, or flush the child persistence context and refresh the appropriate entities in the parent context.


                          This is definitely, interesting, will have to look into it. It would be nice if the @PerNestedConversation (which was mentioned before) or some other annotation indicated this type of snapshot behavior. Currently, it looks like it simply means the object is not visible to the nested conversation and is recreated if needed (the documentation also says don't use it). This would be an easy way to specify only which objects you wanted a snapshot of to limit memory usage in a continuation approach.

                          Any other thoughts?

                          ...

                          By the way, thanks for the tip on the quotes Matt :)

                          • 25. another question about Jacob's master-detail editing example
                            wschwendt

                            I want to go back to your master-detail editing example, Jacob. There is still one important question left. You gave a good description that you use nested conversations to "simulate" a kind of continuation approach. And to create "snapshots" that represent continuable state, you are using a clever mechanism to clone Entities and merge them again with a persistence context. So far, so good.

                            But in your first post you also mentioned that you're continuing the nested conversations until the end of the application transaction. My question: When the user finally clicks the submit button and your action method persists the state that has been accumulated by the long-running conversation, how do you end all nested conversations up to including the root conversation?

                            The problem ist that an @End annotation does only end the current conversation. And if the current conversation is a nested conversation, it is popped from the conversation stack and then parent conversation resumes again. The same applies to the "end-conversation" element used in pages.xml config file.

                            When you end the innermost nested conversation, do you simply use the timeout mechanism to destroy all enclosing conversations up to including the root conversation?

                            Or do you use some tricks such as calling the Seam Conversation manager to explicitly end all conversations on the conversation stack? (I don't know if that would easily be possible, given that some methods of the Conversation Manager we probably would have to call aren't public but instead private methods.)


                            In July I already wrote on this forum that it would be nice if there was a way to end all conversations on the conversation stack (some sort of "transitive" end), but unfortunately there was any interest.

                            See last post of the following thread:
                            http://www.jboss.com/index.html?module=bb&op=viewtopic&t=112414&postdays=0&postorder=asc&start=10



                            "jacob.orshalick" wrote:

                            The main issue that comes in with conversations is the master-details editing where the master controls the persistence of the data. For example, a Person and their Addresses:

                            1. Select Person for editing which displays a Person edit screen
                            2. Select Add Addresses which forwards to a secondary screen
                            3. Addresses are added and the screen is submitted which updates the in-memory Person
                            4. The Person edit screen is redisplayed with the Addresses added
                            5. The user then uses the back button to return to the original Person edit screen and submits which persists Person with new addresses

                            If a single long-running conversation was used, you end up submitting addresses that were not intended by the user (at least not what they saw on the browser-cached edit screen) since the Person was updated in the conversation context. If the conversation is nested for the Address details screen, the addition of addresses does not affect the outer conversation. In other words, we have a snapshot of state prior to adding the Addresses.

                            We do NOT end this conversation when the Addresses are submitted. Instead we continue the nested conversation on the new Person edit screen. Now, if the user was to back up to the original Person edit screen, the snapshot of conversation state is restored (the outer conversation) unaffected by the user's actions. If the user then submits, the state is persisted consistent with what the user "sees."



                            • 26. Re: another question about Jacob's master-detail editing exa
                              wschwendt

                              Correction:

                              In July I already wrote on this forum that it would be nice if there was a way to end all conversations on the conversation stack (some sort of "transitive" end), but unfortunately there wasn't any interest.

                              • 27. Re: Feature request regarding nested conversations

                                Very good point Wolfgang. I also questioned the forum on this and posted a solution to the issue in the following post:

                                http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4078360#4078360


                                This is how I am destroying the conversation stack. As per the semantics, destroying the root, destroys the entire stack. Hope that helps.

                                • 28. Re: Feature request regarding nested conversations
                                  wschwendt

                                  Thanks, Jacob. Great solution.

                                  I'd like to see that included in Seam. And btw, we need the endRoot attribute for the end-conversation element, too.

                                  Otherwise we cannot really end the entire conversation stack when a nested conversation throws an exception.

                                  // pages.xml
                                  
                                  <exception class="javax.persistence.OptimisticLockException">
                                   <end-conversation endRoot="true"/> // end all conversations up to top-level long-running root conversation (inclusive)
                                   <redirect view-id="/error.xhtml">
                                   <message>Another user changed the same data, please try again</message>
                                   </redirect>
                                   </exception>
                                  


                                  cf.
                                  http://www.jboss.com/index.html?module=bb&op=viewtopic&t=112414&postdays=0&postorder=asc&start=10


                                  • 29. Re: Feature request regarding nested conversations

                                    I raised a feature request in JIRA for this:

                                    http://jira.jboss.com/jira/browse/JBSEAM-1943

                                    Maybe it could get included in the next release.

                                    I would also like to see a feature for more out-of-the-box continuation support with nested conversations. While the solution I've been using works, it would be nice if you could specify @Begin(nested=true, snapshot=true) to get this behavior auto-magically. Turn it on only when needed to avoid needless memory usage on the server.