1 2 3 Previous Next 32 Replies Latest reply on Jul 13, 2006 1:04 PM by gavin.king Go to original post
      • 15. Re: Beginning conversations in @Factory methods
        iradix

         

        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 :)


        Good point, I wasn't thinking about how page scope worked. Unfortunately, I have tried this in the past and it adds another big problem.... serializing/reconstituting data. Since my lists consist of attached Entity Beans this is problematic.

        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'.


        Disabling propogation sounds perfect.... but how do you do it?

        • 16. Re: Beginning conversations in @Factory methods
          pmuir

           

          Disabling propogation sounds perfect.... but how do you do it?


          http://docs.jboss.com/seam/1.0.1.GA/reference/en/html/conversations.html#d0e2814

          Good point, I wasn't thinking about how page scope worked. Unfortunately, I have tried this in the past and it adds another big problem.... serializing/reconstituting data. Since my lists consist of attached Entity Beans this is problematic.


          Well I think your Entities will be serializable? An SMPC should get over the LIE problem!?

          • 17. Re: Beginning conversations in @Factory methods
            iradix

            Ok Gavin, let me try to explain. I have a page that outputs a DataTable of objects. A user can click on an object's name to select it and bring up an update form or use a button below the list to bring up a form for new object creation. When either of these forms is successfully submitted, the user is returned to the page with the DataTable

            I want to set the conversation that the @DataModel is outjected into as long running so that when the postback occurs for a selection and my @DataModelSelection is injected it will be sure to come from the same @DataModel displayed to the user.

            When a new object is created, I want to end the conversation so that the @DataModel, which was retrieved using a now stale query and any state associated with it is dropped before the page with the DataTable is redisplayed.

            So therein lies my problem. If I begin the conversation from the page containing the DataTable and the conversation is ended by an action method that redisplays that page, the conversation will always be restarted, even after issuing a redirect.

            Make sense?

            I'm not married to doing things this way, but it's the best I've come up with, so if it can be done differently please point me in the right direction.

            -Dave

            • 18. Re: Beginning conversations in @Factory methods
              gavin.king

               

              Well I think your Entities will be serializable? An SMPC should get over the LIE problem!?


              Once you serialize the entity, it becomes detached.

              • 19. Re: Beginning conversations in @Factory methods
                iradix

                 

                Well I think your Entities will be serializable? An SMPC should get over the LIE problem!?


                Yup, they're serializable, and everything works great until I try to access something that's loaded lazily and find out that the Seam Managed EntityManager that loaded the object in the list page has been closed along with the temporary conversation the list page occured in.

                Of course I could set that conversation to be long running but then... well, I'm back to square one.

                That fact that no one else has seen this problem leads me to believe that I'm missing something... I'm just not sure what that something is.

                By the way... what's an SMPC and an LIE?

                • 20. Re: Beginning conversations in @Factory methods
                  pmuir

                  Seam Managed Persistence Context
                  LazyIntitialisationException

                  You could reload the object when the conversation starts?

                  I have to say, in my search screens (stateless)I just pass the id of the object across using f:param and load it in the @Create @Begin method of my editing bean (Coversation Scoped) which works, but isn't perhaps the most elegant way of doing it.

                  • 21. Re: Beginning conversations in @Factory methods

                    If this ID is being added as a request param please make sure that it's a non-important ID (ie, not a DB key). If it is, you run the risk of a malicious user accessing or possibly updating data they shouldn't via manipulation of this request param.

                    • 22. Re: Beginning conversations in @Factory methods
                      iradix

                       

                      You could reload the object when the conversation starts?


                      I'm not sure I follow.

                      If this ID is being added as a request param please make sure that it's a non-important ID (ie, not a DB key). If it is, you run the risk of a malicious user accessing or possibly updating data they shouldn't via manipulation of this request param.


                      I've got to agree with the captain on this one :) Passing an id is the way I've always done this in the past, but the security concerns/workarounds are a good reason for the JSF DataModel usage in the first place. In order for the DataModel to work however, it needs to stay consistent between the rendered response and the postback. I can't serialize it, so it seems to make sense that I would store it in the conversation, which means starting the conversation from the page that requests the @DataModel.

                      CptnKirk, do you have a different method for handling this?

                      • 23. Re: Beginning conversations in @Factory methods
                        gavin.king

                         

                        "iradix" wrote:
                        Ok Gavin, let me try to explain. I have a page that outputs a DataTable of objects. A user can click on an object's name to select it and bring up an update form or use a button below the list to bring up a form for new object creation. When either of these forms is successfully submitted, the user is returned to the page with the DataTable

                        I want to set the conversation that the @DataModel is outjected into as long running so that when the postback occurs for a selection and my @DataModelSelection is injected it will be sure to come from the same @DataModel displayed to the user.

                        When a new object is created, I want to end the conversation so that the @DataModel, which was retrieved using a now stale query and any state associated with it is dropped before the page with the DataTable is redisplayed.

                        So therein lies my problem. If I begin the conversation from the page containing the DataTable and the conversation is ended by an action method that redisplays that page, the conversation will always be restarted, even after issuing a redirect.

                        Make sense?

                        I'm not married to doing things this way, but it's the best I've come up with, so if it can be done differently please point me in the right direction.

                        -Dave



                        So you have

                        (1) A conversational search screen

                        I usually recommend that search screens be page scoped, session scoped, or even purely stateless.

                        http://blog.hibernate.org/cgi-bin/blosxom.cgi/2006/06/22#stages-of-adoption

                        (2) A conversation that edits the data and then returns to the search screen

                        Shouldn't it be a nested conversation then?

                        (3) the need to update the search screen when done editing the data

                        why not just use a Seam event that forces refresh of the list (just like the booking list in the booking demo)


                        Have I understood everything here?

                        • 24. Re: Beginning conversations in @Factory methods
                          gavin.king

                          By the way, I just made a commit to CVS that lets you call

                          Redirect.instance().setConversationPropagation(false)


                          When using the Redirect component to control redirects.

                          But I suppose you are using a navigation rule....

                          I guess I could add something else like:

                          Conversation.setRedirectPropagation(false);


                          if you really need it. I don't love it however....

                          Perhaps even:

                          @End(beforeRedirect=true)


                          which a bit more palatable to me....

                          • 25. Re: Beginning conversations in @Factory methods

                            Too many conversations going on at once.

                            CptnKirk, do you have a different method for handling this?


                            You could use some indirection here. You can have your request param id be a key to a session/conversation value. This way the actual id is never exposed. If the param is manipulated it won't be found in the session/conversation and you provide error handling from there.

                            • 26. Re: Beginning conversations in @Factory methods
                              gavin.king

                              I added @End(beforeRedirect=true), @EndTask(beforeRedirect=true) and Conversation.endBeforeRedirect() to CVS.

                              • 27. Re: Beginning conversations in @Factory methods
                                pmuir

                                 

                                You could reload the object when the conversation starts?
                                I'm not sure I follow.

                                I think
                                em.refresh(myEntity);

                                If this ID is being added as a request param please make sure that it's a non-important ID (ie, not a DB key).


                                Yup. This is something I need to fix ;)

                                I've just tested what was discussed on this thread which works well
                                http://www.jboss.com/index.html?module=bb&op=viewtopic&t=86564&start=10

                                SearchBean
                                @DataModel
                                private List<Foo> foos;
                                
                                // Factory etc.
                                


                                EditorBean
                                @In(required=false, value="#{foos.rowData}")
                                private Foo selectedFoo;
                                
                                @In(required=true) @Out
                                private Foo foo;
                                ...
                                @Create @Begin
                                public void begin() {
                                 foo = selectedFoo;
                                }
                                ...
                                


                                Which, with some (basic) testing, seems to work and not give an LIE (which surprises me)

                                • 28. Re: Beginning conversations in @Factory methods
                                  pmuir

                                  Sorry, that should be

                                  @DataModel(scope=PAGE)
                                  private List<Foo> foos;
                                  
                                  // Factory etc.


                                  • 29. Re: Beginning conversations in @Factory methods
                                    iradix

                                    Gavin,

                                    I think you understand where I'm coming from and thanks for the link. I've been thinking that it would be really helpful to have a resource for Seam design patterns before. There are a couple of things I think I'm missing though.

                                    We've already discussed why a page scoped DataModel ends up with detached objects, a session scoped one seems to have a similar problem whereby whether you load your list by a seam managed or an extended EM, if you inject the DataModelSelection into a conversation scoped bean, that bean will possibly contain a different EM. This is a problem that I'd like to avoid.

                                    When it comes to SLSB searches, I might be missing something but it seems like that wouldn't work correctly with a JSF DataTable. If I display a DataTable populated from an SLSB and then in the apply request values phase of the postback the DataTable recieves a DataModel from a new SLSB the new DataModel might be different and the row index may not correspond. Or am I wrong there? This could be solved by avoiding the use of DataTable and passing a custom entity identifier but then it seems that I'm missing out on one of the cool new features of JSF. Or maybe this is just the beginning of my dissolusionment........

                                    Anyway, thanks a lot for the additions. They are exactly what I was looking for. Maybe when I've got this all figured out I can put in a wiki entry to help any one else with similar problems.