1 2 Previous Next 19 Replies Latest reply on Mar 4, 2008 4:42 AM by matt.drees

    Injection And Child Objects

    tom_goring

      Hi,


      I have a bean like:



      @Name("parent"
      class Parent {
         
         @In
         Dependency dependency;
      
         private child = null;
      
         public Parent() {
            new Child(this);
         }
      
         public Child getChild() {
            return child;
         }
      }



      Trouble is that if I access this in page e.g.


      <h:inputText value="#{parent.child.property}">



      Dependency Injection has not happened on the Parent and dependency is null.


      Is this expected behavior?



        • 1. Re: Injection And Child Objects
          jimk1723

          Using your example I got the following exception:


          org.jboss.seam.RequiredException: @In attribute requires non-null value: parent.dependency
                  at org.jboss.seam.Component.getValueToInject(Component.java:2160)
          



          Which is what I expected. Have you tried using:


          @In(create = true)
          Dependency dependency;
          



          A more fringe explanation: do you have a name collision anywhere with the parent component, i.e. are you referencing the component you think you're referencing?

          • 2. Re: Injection And Child Objects

            I'm a bit confused over what you're trying to do. 'dependency' will always be null if you haven't outjected it before. Have you done that?



            private child = null;


            seems a bit weird. Untyped?


            • 3. Re: Injection And Child Objects
              keithnaas

              What version of Seam are you using? 


              Also, can you provide the code for the Dependency object since that could likely be the issue.

              • 4. Re: Injection And Child Objects
                tom_goring

                The simple code was just for illustration (i.e. Child typo)


                I'm using jboss-seam-2.0.1.CR1.


                dependency already existed.


                I'll post a real example then if people think it should work.


                So having a EL expression with a child object injection should happen to every object that is a seam object in that expression ?




                • 5. Re: Injection And Child Objects
                  jimk1723

                  I'll post a real example then if people think it should work.


                  Yah. We're missing some crucial details here.



                  So having a EL expression with a child object injection should happen to every object that is a seam object in that expression ?


                  The question is oddly worded, but the Seam reference covers this pretty well:



                  dynamic - since the value of contextual variables changes over time, and since Seam components are stateful, bijection takes place every time a component is invoked
                  • 6. Re: Injection And Child Objects
                    tom_goring

                    Hi,


                    Here Goes then ....


                    @Name("seamDependency")
                    public class SeamDependency {
                    
                    }
                    



                    @Name("seamParent")
                    public class SeamParent {
                         
                         @In(create=true)
                         SeamDependency seamDependency;
                         
                         PojoChild pojoChild;
                         public String property; 
                         
                         public SeamParent() {
                              pojoChild = new PojoChild(this);
                         }
                         
                         public String getProperty() {
                              System.out.println("SeamParent.getProperty = "+this+"="+seamDependency);
                    
                              return property;
                         }
                    
                         public void setProperty(String property) {
                              this.property = property;
                         }
                    
                         
                         public PojoChild getPojoChild() {
                              return pojoChild;
                         }
                    
                         public void setPojoChild(PojoChild pojoChild) {
                              this.pojoChild = pojoChild;
                         }
                         
                    }



                    public class PojoChild {
                         
                         public SeamParent parent;
                         public String property; 
                    
                         public PojoChild(SeamParent parent) {
                              this.parent = parent; 
                         }
                         
                         public String getProperty() {
                              System.out.println("PojoChild.getProperty = "+parent+"="+parent.seamDependency);
                    
                              return property;
                         }
                    
                         public void setProperty(String property) {
                              this.property = property;
                         }
                    }



                    My Page


                    <html xmlns="http://www.w3.org/1999/xhtml"
                         xmlns:ui="http://java.sun.com/jsf/facelets"
                         xmlns:h="http://java.sun.com/jsf/html"
                         xmlns:f="http://java.sun.com/jsf/core"
                         xmlns:jnet="http://jnet.ltd.uk/taglib"
                         xmlns:s="http://jboss.com/products/seam/taglib">
                         
                    
                    <body>
                    
                         <h:form>
                              <h:inputText value="#{seamParent.pojoChild.property}"></h:inputText>
                              <h:inputText value="#{seamParent.property}"></h:inputText>
                         
                         </h:form>
                    
                    
                    </body>
                    
                    </html>




                    Console Output during a HTTP get


                    22:26:27,036 INFO  [STDOUT] PojoChild.getProperty = jnet.fui.bl.util.SeamParent@15fcabc=null
                    22:26:27,037 INFO  [STDOUT] SeamParent.getProperty = jnet.fui.bl.util.SeamParent@15fcabc=jnet.fui.bl.util.SeamDependency@1f72039
                    



                    I.e. you can see injection does not occur when the child property is referenced

                    • 7. Re: Injection And Child Objects
                      pmuir

                      No, this ain't going to work. this isn't a valid reference to the Seam component parent - it's just a reference to the POJO parent.


                      Try


                      @Create
                      public void create()
                        this.pojoChild = new PojoChild(instance());
                      }
                      
                      public static SeamParent instance() {
                        return Component.getInstance("seamParent");
                      }

                      • 8. Re: Injection And Child Objects
                        tom_goring

                        Hi Pete,


                        Nope that does not work.




                        @Name("seamParent")
                        public class SeamParent {
                             
                             @In(create=true)
                             SeamDependency seamDependency;
                             
                             PojoChild pojoChild;
                             public String property; 
                             
                             public SeamParent() {
                             }
                             
                             public String getProperty() {
                                  System.out.println("SeamParent.getProperty = "+this+"="+seamDependency);
                        
                                  return property;
                             }
                        
                             public void setProperty(String property) {
                                  this.property = property;
                             }
                        
                             
                             public PojoChild getPojoChild() {
                                  return pojoChild;
                             }
                        
                             public void setPojoChild(PojoChild pojoChild) {
                                  this.pojoChild = pojoChild;
                             }
                        
                             @Create
                             public void create() {
                               this.pojoChild = new PojoChild(instance());
                             }
                        
                             public static SeamParent instance() {
                               return (SeamParent)Component.getInstance("seamParent");
                             }
                        }
                        




                        [STDOUT] PojoChild.getProperty = jnet.fui.bl.util.SeamParent@df43b7=null
                        [STDOUT] SeamParent.getProperty = jnet.fui.bl.util.SeamParent@df43b7=jnet.fui.bl.util.SeamDependency@1ddae12
                        



                        • 9. Re: Injection And Child Objects
                          pmuir

                          Hmm. I guess the instantiation isn't complete by that point - file a feature request in JIRA - what you are trying to do seems reasonable - but we need to consider it carefully.


                          As a workaround, can you lazily create the pojoChild in the getter (by which point your component will be fully instatiated)?

                          • 10. Re: Injection And Child Objects
                            tom_goring

                            Hi Pete,


                            Nope that does not work for me,...



                            @Name("seamParent")
                            public class SeamParent {
                                 
                                 @In(create=true)
                                 SeamDependency seamDependency;
                                 
                                 PojoChild pojoChild;
                                 public String property; 
                                 
                                 public SeamParent() {
                                 }
                                 
                                 public String getProperty() {
                                      System.out.println("SeamParent.getProperty = "+this+"="+seamDependency);
                            
                                      return property;
                                 }
                            
                                 public void setProperty(String property) {
                                      this.property = property;
                                 }
                            
                                 
                                 public PojoChild getPojoChild() {
                                      if ( pojoChild==null ) {
                                           System.out.println("creating pojo");
                                           this.pojoChild = new PojoChild(instance());
                                      }
                                      return pojoChild;
                                 }
                            
                                 public void setPojoChild(PojoChild pojoChild) {
                                      this.pojoChild = pojoChild;
                                 }
                            
                                 @Create
                                 public void create() {
                                 }
                            
                                 public static SeamParent instance() {
                                   return (SeamParent)Component.getInstance("seamParent");
                                 }
                            }
                            





                            [LifeCycleListener] BeforePhase: RENDER_RESPONSE 6
                            [STDOUT] creating pojo
                            [STDOUT] PojoChild.getProperty = jnet.fui.bl.util.SeamParent@1bdcd96=null
                            [STDOUT] SeamParent.getProperty = jnet.fui.bl.util.SeamParent@1bdcd96=jnet.fui.bl.util.SeamDependency@4473c
                            [LifeCycleListener] AfterPhase: RENDER_RESPONSE 6
                            



                            It looks to me that during the EL expression resolution I would expect the injection to occur but it does not when you reference a child property....

                            • 11. Re: Injection And Child Objects
                              tom_goring

                              Added JIRA


                              http://jira.jboss.org/jira/browse/JBSEAM-2677


                              Workaround is to rather than store the parent reference in the PojoChild look it up every time it is required.
                              PojoChild in my case is like a utility class that can add functionality to the parent... Doing the look up or using injection makes the utility more cumbersome as it does not know the parent seam component name at runtime (and so this would have to be passed in).

                              • 12. Re: Injection And Child Objects
                                matt.drees

                                Tom Goring wrote on Feb 25, 2008 11:36 PM:



                                @Name("seamParent")
                                public class SeamParent {
                                     
                                     @In(create=true)
                                     SeamDependency seamDependency;
                                     
                                     ...
                                }



                                public class PojoChild {
                                     
                                     public SeamParent parent;
                                
                                     ...
                                     
                                     public String getProperty() {
                                          System.out.println("PojoChild.getProperty = "+parent+"="+parent.seamDependency);
                                
                                          return property;
                                     }
                                
                                     ...
                                }






                                I think your problem is you're directly referencing the parent's field.  Injection is only going to occur if you call a method, e.g.,


                                ... parent.getSeamDepency()



                                The reason is the SeamParent object that child has a reference to is a proxy, and its fields aren't ever used.

                                • 13. Re: Injection And Child Objects
                                  tom_goring

                                  Hi,


                                  Nope that does not work... I would be helpful if a Seam Expert could explain on what condition injection occurs (e.g. looking up a component in a context).


                                  Code Changed to:


                                  @Name("seamParent")
                                  public class SeamParent {
                                  ...
                                       public SeamDependency getSeamDependency() {
                                            System.out.println("SeamParent.getSeamDependency Accessor Called "+seamDependency);
                                            return seamDependency;
                                       }
                                  ...
                                  



                                  And :


                                  public class PojoChild {
                                  ...     
                                       public String getProperty() {
                                            System.out.println("PojoChild.getProperty = "+parent+"="+parent.getSeamDependency());
                                  
                                            return property;
                                       }
                                  ...
                                  }



                                  Output is:


                                  [STDOUT] creating pojo
                                  [STDOUT] SeamParent.getSeamDependency Accessor Called null
                                  [STDOUT] PojoChild.getProperty = jnet.fui.bl.util.SeamParent@1ccb4e6=null
                                  [STDOUT] SeamParent.getProperty = jnet.fui.bl.util.SeamParent@1ccb4e6=jnet.fui.bl.util.SeamDependency@786e17
                                  

                                  • 14. Re: Injection And Child Objects

                                    according to petes suggestion, did you use SeamParent.instance() on your child?


                                    public String getProperty() {
                                              System.out.println("PojoChild.getProperty = "+parent+"="+SeamParent.instance().seamDependency);
                                    
                                              return property;
                                         }

                                    1 2 Previous Next