13 Replies Latest reply on Oct 20, 2008 12:48 AM by pmuir

    EntityConverter - Page Scope

    joblini

      Hello,


      Is it possible to use <s:convertEntity> with a post-redirect-get ?


      I added a <h:selectOneMenu to a page which uses the post-redirect-get pattern.  The selectyOneMenu would always return to the noSelection state after submitting the form.


      I was using the <s:convertEntity> tag.  In debugging I discovered that EntityConverter assigns an index to the entity and stores the entity and its index in EntityIdentifierStore, which has @page scope.  Therefore the association between the assigned id and the entity goes out of scope when the get is performed, resulting in noSelection state. 


      To resolve this problem I wrote a standard JSF converter, but I wonder if there is not some way to use <s:convertEntity> with the post-redirect-get ?


      Thanks!

        • 1. Re: EntityConverter - Page Scope
          pmuir

          Eh?


          The EntityConverter doesn't store a the selected item, that's the job of the backing bean which is referrred to in the value attribute of the parent input component. The EntityConverter is simply responsible for converting to/from a String representation of the entity betweeen the form being rendered and the resultant post back.


          Try storing the backing bean in a longer scope.

          • 2. Re: EntityConverter - Page Scope
            joblini

            I know that its not the job of EntityConverter to store the selected item, nonetheless, I see in debug that it does store it, here is the method from org.jboss.seam.ui.EntityIdentifierStore, which is called by EntityConverter:


               public String put(Identifier identifier, Object entity)
               {      
                  if (!store.contains(identifier))
                  {
                     store.add(identifier);
                     setDirty();
                  }
                  return ((Integer) store.indexOf(identifier)).toString();
               }
            
            


            • 3. Re: EntityConverter - Page Scope
              pmuir

              Yes, it stores it between page render and page submit, this is how the conversion is implemented. At the form submit, JSF will convert the string back into an object (using this store to load it) and save it to your backing bean. What scope is your backing bean? Are you in a LRC?

              • 4. Re: EntityConverter - Page Scope
                joblini

                I'm sorry, I didn't explain it clearly.  What I observed was that the identifier for the entity was stored in @page scope.  After the page redirect, the identifier was no longer found in the store.


                • 5. Re: EntityConverter - Page Scope
                  pmuir

                  Correct, a new store will be created, the current value and option list values read again from the backing beans, reconverted etc.

                  • 6. Re: EntityConverter - Page Scope
                    joblini

                    I think the problem is that in EntityIdentifierStore, the index within the store is used to identify the entity.


                    public String put(Identifier identifier, Object entity)
                       {      
                          if (!store.contains(identifier))
                          {
                             store.add(identifier);
                             setDirty();
                          }
                          return ((Integer) store.indexOf(identifier)).toString();
                       }
                    


                    So, when the store goes out of @page scope, this identifier is meaningless.


                    Therefore, for example, a bookmark for mypage?selectedId=13 (GET) does not work correctly, because the id 13 is either no longer in the store, or now represents a different entity. 


                    • 7. Re: EntityConverter - Page Scope
                      pmuir

                      Yes, the EntityConverter is not intended for use with GET parameters.

                      • 8. Re: EntityConverter - Page Scope
                        joblini

                        Pete Muir wrote on Oct 19, 2008 23:47:


                        Yes, the EntityConverter is not intended for use with GET parameters.


                        OK!  That means the answer to my question



                        Is it possible to use <s:convertEntity> with a post-redirect-get ?


                        is NO. Incidentally, I originally came across this problem when I added a SelectOneMany to a seam-gen search page.  Its too bad, because I would much rather use s:convertEntity than write converters for every entity.


                        Is there a reason for using the index within the store instead of the real id of the identity (toString) ?


                        Also, what is advantage of the store?  The entities have already been read from the database in any case, so I don't think it is for performance reasons?





                        • 9. Re: EntityConverter - Page Scope
                          pmuir

                          I don't know the pattern well, but I think what you are asking is How to I put the id of the selected entity into a GET parameter? then it should be possible with page parameters to bind the entity id to a get parameter.


                          If you do a simple toString() you can't deal with composite ids of any sort. Also, exposing real ids to the user is potentially a security risk. But I agree, we need a simple mode for the converter which just does an toString() on the ID. Write me one, I'll commit it.

                          • 10. Re: EntityConverter - Page Scope
                            joblini

                            Pete Muir wrote on Oct 20, 2008 00:06:


                            I don't know the pattern well, but I think what you are asking is How to I put the id of the selected entity into a GET parameter? then it should be possible with page parameters to bind the entity id to a get parameter.


                            Exactly what I do (bind the id with page parameter).  The problem is that this id is no longer in the store.



                            If you do a simple toString() you can't deal with composite ids of any sort. Also, exposing real ids to the user is potentially a security risk. But I agree, we need a simple mode for the converter which just does an toString() on the ID. Write me one, I'll commit it.


                            I'll try!  Thanks for your help with this!

                            • 11. Re: EntityConverter - Page Scope
                              pmuir

                              Ingo Jobling wrote on Oct 20, 2008 00:14:



                              Pete Muir wrote on Oct 20, 2008 00:06:


                              I don't know the pattern well, but I think what you are asking is How to I put the id of the selected entity into a GET parameter? then it should be possible with page parameters to bind the entity id to a get parameter.


                              No, no. Bind the real id of the entity to the page parameter, and back onto the model after the redirect.


                              If you do a simple toString() you can't deal with composite ids of any sort. Also, exposing real ids to the user is potentially a security risk. But I agree, we need a simple mode for the converter which just does an toString() on the ID. Write me one, I'll commit it.


                              I'll try!  Thanks for your help with this!



                              Click HELP for text formatting instructions. Then edit this text and check the preview.

                              • 12. Re: EntityConverter - Page Scope
                                joblini

                                This is the problem ... the real id is not available.


                                Here is the rendered HTML


                                With <s:entityConverter/>, (not real id)


                                <select name="productionType">
                                <option selected="selected" value="0">Commercial</option>
                                <option value="1">Pure bred</option>
                                



                                With JSF converter (real id)


                                <option selected="selected" value="1">Commercial</option>
                                <option value="2">Pure bred</option>
                                



                                In page.xml


                                <param name="productionType" value="#{productionHome.instance.type}" />
                                

                                • 13. Re: EntityConverter - Page Scope
                                  pmuir

                                  Try not connecting the html element and the page parameter, but just a page parameter and the model i.e.


                                  <h:selectOne value="#{productionHome.instance.type}>
                                     <s:selectItems ... />
                                     <s:convertEntity />



                                  <param name="productionType" value="#{productionHome.instance.type}" />



                                  I have a feeling it won't work as the page parameter will update the model with the wrong value on entry to the page. Actually, try just putting the page parameter on the page you redirect to.