9 Replies Latest reply on Jun 24, 2009 8:03 PM by xsa lefter

    Recursive Entity causes strange behavior with EntityHome Id when trying to add child Entities

    Francisco Jose Peredo Noguez Master

      Hi!
      Here is a description of my problem:
      Create a Seam 2 project using JBossTools, create an @Entity with a recursive relationship (lets name it Category).


      @Entity
      public class Category {
           
           public Category() {
           }
           
           private Integer id;
           private String name;
           private Category parentCategory;
           private Set<Category>childrenCategories = new HashSet<Category>();
           
           @Id
           @GeneratedValue(strategy=GenerationType.AUTO)
           public Integer getId() {
                return id;
           }
           public void setId(Integer id) {
                this.id = id;
           }
           public String getName() {
                return name;
           }
           public void setName(String name) {
                this.name = name;
           }
           
           @ManyToOne
           public Category getParentCategory() {
                return parentCategory;
           }
           
           public void setParentCategory(Category parentCategory) {
                this.parentCategory = parentCategory;
           }
           
           @OneToMany(mappedBy="parentCategory")
           public Set<Category> getChildrenCategories() {
                return childrenCategories;
           }
           
           public void setChildrenCategories(Set<Category> childrenCategories) {
                this.childrenCategories = childrenCategories;
           }
      
      }
      



      Then run Seam Generate Entities, run the application and create a category using the generated UI, save it with name category 1 and edit it.


      If in Category.xhtml you click Add category, instead of presenting a clean form for adding the new children, it will present a form with currently selected category: category 1).


      This is a bug, but it is not the one I am reporting here, but lets say you decide you want to fix it, and for starters you change the code in the Add category button to this:


      <s:button
                     value="Add category"
                      view="/CategoryEdit.xhtml">
                  <f:param name="categoryId" value=""/>
                  <f:param name="categoryFrom" value="Category"/>
      </s:button>
      



      Note that the value for the categoryId is now empty (it used to have the #{categoryHome.instance.id} value). After making that change you run the application again and:


      Edit category1
      in Category.xhtml you click Add category and you get what you would expect, an empty form to add the child category (of course many more changes are needed to make it possible to really add a child category, but that is not the issue here)


      Now for the real bug:Lets say you are in a experimentative mood and you decide to play with conversations, so, in layout/menu.xhtml you have a link to the CategoryList that looks like this:


      <s:link view="/CategoryList.xhtml"
                 value="Category List"
           propagation="none"/>
      



      well, lets say you decide to add another one (just for the sake of experimenting) that looks like this:


      <s:link view="/CategoryList.xhtml"
                 value="Category List Propagation Begin"
           propagation="begin"/>
      



      And then you Edit category1
      in Category.xhtml you click Add category and.... here comes the bug... the form is not empty, the <f:param name="categoryId" value=""/> plain just gets ignored.


      Why? I think it that the fact that now everything is running inside a long running conversation shouldn't screw up things like this... Am I wrong?


      Thanks,


      Regards,

        • 1. Re: Recursive Entity causes strange behavior with EntityHome Id when trying to add child Entities
          Francisco Jose Peredo Noguez Master

          Since I believe this behavior is a bug, I created a JBSEAM-3454 , I also think this is related to the strange problems reported in this thread, and this thread.


          I use to belive that the strange behavior of the instance field of Home getting a value, in such a way that it can not be detected by a breakpoint or a watchpoint in eclipse, even if the parameter with the primary key was explicitly set to an empty value was only related to using nested conversations and or @PerNestedConversation, but now I believe there is something wrong in the implementation of  EntityHome, or perhaps something wrong in the way it is used by the applications generated by seam-gen, but I can't quite put my finger on it... so... please... if you understand what is going on here... help me!

          • 2. Re: Recursive Entity causes strange behavior with EntityHome Id when trying to add child Entities
            Francisco Jose Peredo Noguez Master

            Yesteday I started thinking that maybe this bug will not get a lot of attention because it seems to be almost a theoretical thing done just for the sake of experimenting (and my fear was confirmed today when Priority was set to Minor in JIRA).


            But in fact, I think this it is a major issue, but not only because complicates the creation of recursive navigation paths, the reason I think it is important to understand and fix this is navigation graph reutilization:


            Lets say you have a seam-gen created or hand made created code that allows you to save new categories in your system, and, if ran inside a conversation becomes crazy, but, as in this case, by default, it is being called from the menu with propagation=none. Now, lets also say that you are asked to be able to do CRUD of Category as a part of a larger process, and that larger process is inside a conversation... you will be tempted to plain just call your navigation graph for Category CRUD from your main navigation graph, as if it were some kind of subroutine. Of course you may say, well, lets just call the Category CRUD using propagation=none, well, what if for example, you need to link each of your newly created Categories to some entity stored in the long running conversation... (of course you could do that using query strings but... what is the point of doing that if have conversations? or maybe I should say: what is the point of having conversations if the query string is the way to go?)


            Well, thanks to this bug, you will not be able to that because strange things are going to start happening. In other words, navigation graphs are not reusable because a perfectly valid one will become invalid if used inside a long running conversation....either that, or the code produced by seam-gen is the example of a bad practice... and since a lot of people are going to base their code in what seam-gen produces, I think it should be a priority to only generate code based on the recommedend best practices.


            Thanks,


            Regards,



            • 3. Re: Recursive Entity causes strange behavior with EntityHome Id when trying to add child Entities
              Pete Muir Master

              If you think the issue is super important, create a patch, I promise to give to a review and include it if it is good.

              • 4. Re: Recursive Entity causes strange behavior with EntityHome Id when trying to add child Entities
                Francisco Jose Peredo Noguez Master

                It is serialization magic! (At least in this variation of the problem)


                I decided to override getInstance and setInstance and store the instance in my own custom variable with some other name. (Thinking that maybe reflection was doing some trick and preserving the variable with the special name instance).


                I was completely astonished when that didn't help. My variable, was being magically preserved, as if @PerNestedConversation wouldn't be creating a new EntityHome object.


                But then, I decided to do something crazy:


                private transient Category anyNameYouLike;
                



                Please not the transient keyword...well... the problem disappeared. The strange magic that was preserving the variable anyNameYouLike stopped.


                Now... Why is @PerNestedConversation doing a serialization/desarialization to copy the values of variables in the EntityHome of the parent transaction?


                I have absolutely no idea, I don't even have a clue on where in Seam code this serialization/desarialization is being called. Any hints? Or should I just requestion this modification in org.jboss.seam.framework.Home:


                  protected transient E instance;
                



                Not much of patch, don't you think? I am officially 100% puzzled.


                • 5. Re: Recursive Entity causes strange behavior with EntityHome Id when trying to add child Entities
                  Francisco Jose Peredo Noguez Master

                  Ok, so, serialization is the black magic corrupting @PerNestedConversation, I don't know why, but it does fix it, but how about the simpler case, the case simple case describe here where, after starting a long running transaction the <f:param name="categoryId" value=""/> becomes ineffective.


                  Well, for that case, i think the problem is in org.jboss.seam.navigation.Pages.applyConvertedValidatedValuesToModel:


                   private void applyConvertedValidatedValuesToModel(FacesContext facesContext)
                     {
                        String viewId = getViewId(facesContext);
                        for ( Page page: getPageStack(viewId) )
                        {
                           for ( Param pageParameter: page.getParameters() )
                           {         
                              ValueExpression valueExpression = pageParameter.getValueExpression();
                              if (valueExpression!=null)
                              {
                                 Object object = Contexts.getEventContext().get( pageParameter.getName() );
                                 if (object!=null)
                                 {
                                    valueExpression.setValue(object);
                                 }
                              }
                           }
                        }
                     }
                  
                  



                  As you can notice the line Object object = Contexts.getEventContext().get( pageParameter.getName() ); gets the value for the parameter, so, what is the value for <f:param name="categoryId" value=""/> or <f:param name="categoryId"/>? the value is null. And then, the code proceeds to set it in valueExpression.setValue(object); Upps!! that is guarded by a if (object!=null) and therefore  valueExpression.setValue(object); is never called.


                  I think that solves the second mistery, all we have to do is remove that if (object!=null), it must be possible to set something to null with f:param don't you agree?


                  Am I right? (Should I submit this 2 changes (the transient keyword for the instance variable and the removal of the if (object!=null) as patches?)

                  • 6. Re: Recursive Entity causes strange behavior with EntityHome Id when trying to add child Entities
                    Pete Muir Master

                    Please submit as many bug reports as there are distinct issues. Please attach an example to reproduce the problem, along with a concise, clear description of the problem (bnot being rude, but I find your bug reports very hard to understand). You can also attach patches if you have a fix.

                    • 7. Re: Recursive Entity causes strange behavior with EntityHome Id when trying to add child Entities
                      Francisco Jose Peredo Noguez Master

                      Ok, don't worry, I know I can be very confusing, the problem initially described in this thread is still the one referenced in JBSEAM-3454, I added a new comment in JIRA explaining what I believe is its root cause (the if (object!=null) in org.jboss.seam.navigation.Pages.applyConvertedValidatedValuesToModel. That JIRA already includes a full example project showing the problem.

                      • 8. Re: Recursive Entity causes strange behavior with EntityHome Id when trying to add child Entities
                        Francisco Jose Peredo Noguez Master

                        Now, the second bug is the one discusse in the one initially discussed in this other thread, that is the one that gets fixed by adding in org.jboss.seam.framework.Home the transient keyword to the instance variable (but I do not understad why this fixes it):


                          protected transient E instance;
                        



                        I copied Stephan DUCAS initial description of the problem to the JIRA: JBSEAM-3493. I also added a comment to JIRA with my proposed solution. If you think it will help, I can post a full example project showing the problem.


                        • 9. Re: Recursive Entity causes strange behavior with EntityHome Id when trying to add child Entities
                          xsa lefter Newbie
                          Hello.. I'm new user in this community forum..

                          I want to ask about the issues. Can someone resolve this issues? find at jira and found nothing resolved problem there.

                          I'm facing the same problem now. This problem look like the EntityHome doesn't care which instance to be managed, as long as the entity is the same class (eg, Category).

                          By the way, I try some trick like this:
                          I create 2 EntityHome class, for example CatagoryHome and CategoryParentHome. The CategoryHome class and have a Relationship to the ParentCategory (smiliar like "master detail" relationship). I add a new link at ViewList called "add children" and the parameter is bound to, eg #{categoryParentHome.categoryId} instead of #{categoryHome.categoryId} . At this time the trick work correctly.

                          But my question is, there is someone here try this trick??? I want to know other issues related to the way I used to. Please share if you know. Thanks :) .

                          Sorry for my bad english grammar. Thanks. :D