1 2 Previous Next 15 Replies Latest reply on Sep 1, 2008 7:23 AM by Matt Drees

    Factory method does not create objects properly

    Bogdan Minciu Newbie

      Hello,


      It seems that my @Factory method is recognizing the created objects only in its command block. I have this class:


      @Stateful
      @Name("xtw")
      @Scope(ScopeType.SESSION)
      @AutoCreate
      public class XTextSessionWrapper implements LocalXTextSessionWrapper {
      
      ...
      
          @In(required=false, create=true)
          @Out
          private XLanguage activeLanguage;
      
          public String getText(String identifier) {
              log.info("getText(1): identifier= #0, activeLanguage= #1", identifier, getActiveLanguage());
              XTextEntry xte = xTextEntryDAO.findXTextEntry(identifier, getActiveLanguage());
              log.info("getText(2): identifier= #0, activeLanguage= #1", identifier, getActiveLanguage());
              xte.getXtext();
          }
      
          @Factory(value="activeLanguage", autoCreate=true)
          public void initActiveLanguage() {
              XLanguage xl = xLanguageDAO.findXLanguageByIdentifier("ro");
              log.info("initActiveLanguage(1): activeLanguage initialized to #0", xl.getIdentifier());
              setActiveLanguage(xl);
              log.info("initActiveLanguage(1): activeLanguage initialized to #0", getActiveLanguage().getIdentifier());
          }
      
          public XLanguage getActiveLanguage() {
              return activeLanguage;
          }
      
          public void setActiveLanguage(XLanguage activeLanguage) {
              this.activeLanguage = activeLanguage;
          }
      ...
      
      }
      



      And i am calling the getText() method. The method calling is as expected:



      1. the injected activeLanguage is detecting that it has a null value,

      2. the initActiveLanguage() factory method is called

      3. then the getText() method is continuing its execution.



      But, the problem is that when the application exists the @Factory method block, the created objects: activeLanguage is lost and reported again as null.


      Here is the output:


      12:43:48,203 INFO  [XTextSessionWrapper] initActiveLanguage(1): activeLanguage initialized to ro
      12:43:48,203 INFO  [XTextSessionWrapper] initActiveLanguage(1): activeLanguage initialized to ro
      
      12:43:48,703 INFO  [XTextSessionWrapper] initActiveLanguage(1): activeLanguage initialized to ro
      12:43:48,703 INFO  [XTextSessionWrapper] initActiveLanguage(1): activeLanguage initialized to ro
      12:43:48,703 INFO  [XTextSessionWrapper] getText(1): identifier= com.brit.xcms.cms.Category.12.name, activeLanguage= null
      12:43:49,234 INFO  [XTextSessionWrapper] getText(2): identifier= com.brit.xcms.cms.Category.12.name, activeLanguage= null
      



      Where did I went wrong? Why is the activeLanguage factoried value lost when i leave the initActiveLanguage() method?


      Thanks in advance,
      Bogdan.

        • 1. Re: Factory method does not create objects properly
          Daniel Hinojosa Master

          Can you show us how you mapped activeLanguage?

          • 2. Re: Factory method does not create objects properly
            Bogdan Minciu Newbie

            Thank you for your reply Daniel,


            I don't really understand what you mean by mapping activeLanguage, but in case you are requesting for the XLanguage class, here it is(except the getters and setters):


            @Entity
            @Table(name = "XLANGUAGE")
            public class XLanguage {
            
                @Id
                @GeneratedValue
                @Column(name = "XLANGUAGE_ID")
                private Long id;
            
                @Version
                @Column(name = "OBJ_VERSION", nullable = false)
                private int version = 0;
            
                @Column(name = "IDENTIFIER", nullable = false)
                private String identifier;
            
                @Column(name = "FLAG", nullable = false)
                private String flag = null;
            }
            

            • 3. Re: Factory method does not create objects properly
              Matt Drees Master

              This looks like a bug to me.  Unless you hear differently from a Seam developer, I think you should create a jira issue.  Also, if possible, it'd be helpful if you'd create a simple SeamTest that reproduces this.

              • 4. Re: Factory method does not create objects properly
                Daniel Hinojosa Master

                You don't have a name or scope for XLanguage.....

                • 5. Re: Factory method does not create objects properly
                  Matt Drees Master

                  XLanguage shouldn't need a @Name or @Scope.  The variable in question (activeLanguage) is provided by a @Factory.  (It just so happens that the factory resides in this component, instead of somewhere else.)

                  • 6. Re: Factory method does not create objects properly
                    Bogdan Minciu Newbie

                    I agree with you that XLanguage shouldn't need a @Name or @Scope, since this is a POJO. It it my model class.


                    Instead, when created it should be scoped to SESSION, since the class in which it is injected (XTextSessionWrapper) is scoped to SESSION.

                    • 8. Re: Factory method does not create objects properly
                      Daniel Hinojosa Master

                      Sorry I meant activeLanguage, and Factory doesn't create anything if I remember correctly.  It just runs when that particular member variable is called. You still need to map active language.  ;)

                      • 9. Re: Factory method does not create objects properly
                        Bogdan Minciu Newbie

                        Daniel,


                        What do you mean by 'map active language'? activeLanguage is the name of the session-scoped variable of XLanguage type. XLanguage is mapped as an entity.


                        Can you please explain what you mean by map the active language? I am new to Seam, and maybe some terms are not clear to me.


                        Thank you,


                        Bogdan.

                        • 10. Re: Factory method does not create objects properly
                          Matt Drees Master

                          Actually, thinking about it a little further, I don't think this is doable.  I don't think Seam's injection could support that type of cylic dependency.  In this case, I think the best thing Seam can do is throw an exception, instead of behaving oddly as you are seeing.

                          • 11. Re: Factory method does not create objects properly
                            Daniel Hinojosa Master

                            Oh sorry, but what I was saying is XTextSessionWrapper is mapped to a session scope with the variable 'xtw' which is great.  You do have this:


                                @In(required=false, create=true)
                                @Out
                                private XLanguage activeLanguage;
                            



                            But you must have a activeLanguage mapped somewhere in your app.  So either in your XLanguage you must have:


                            @Name("activeLanguage")
                            @Scope(ScopeType.SESSION)
                            public class XLanguage { ... }
                            



                            or you have it mapped in your components.xml file


                            <component name="activeLanguage" class="com.foo.XLanguage">
                               <property name="someProperty">foo</property>
                            </component>
                            



                            Otherwise you will receive the null value.


                            • 12. Re: Factory method does not create objects properly
                              Pete Muir Master

                              Matt I think you are correct and this sort of cyclic dependency doesn't work, but I agree there is something a bit odd going on here.


                              Bogodan, could you attach a runnable example, or a patch against one of the examples so we can see the problem locally and make sure we fix the correct one.

                              • 13. Re: Factory method does not create objects properly
                                Bogdan Minciu Newbie

                                Sure,


                                My application is kind of hard to start, but let me build a patch for the booking example, and I will attach the zip to the JIRA issue.

                                • 14. Re: Factory method does not create objects properly
                                  Frank Harter Newbie

                                  Bogdan, did you solve your problem already?


                                  I encountered a problem like this also, but I tried to do the same thing with a simple String value. It works for me now, but I can't really recall how I solved the problem because I simply tried too many things!


                                  Anyways, I can see different things which can cause the problems here. You're calling the getText()-method you say right? So Seam should be doing this since your bean is bijection-enabled:



                                  1. bijecting fields if any getter() method is called

                                  2. bijecting fields if the getText()-method is called

                                  3. bijecting fields if the Factory method is called



                                  How do refer to the activeLanguage property? Are you calling '#{activeLanguage}' or are you calling '#{xtw.activeLanguage}'? The second way effectively uses the getter()-method and therefore triggers bijection. In that case it might be that the activeLanguage property was not created and you get the 'cannot outject a null value'.


                                  So what you have to do is set the @Out to @Out(required=false) since it can be that Seam is having the just described status of the activeLanguage property. This should be enough to remove the error message.


                                  But there is some more. Seam should create this instance with the help of the factory you declared, so you should not need the create=true on the @In annotation. The autocreate=true attribute should also only be necessary if you're not accessing the property with e.g. an EL-expression and you want to have it created anyways...


                                  I hope I'm telling you the right stuff here, so it would be nice if others could confirm what I just mentioned here. I also had this problems and somehow it works for me now. Unfortunately I can't really recall why it didn't work anymore, but above explanation makes sense to me...


                                  I have one more thing. If I set the @In annotation to @In(create=true), then my factory gets called 3 times, but I'm really requesting the property only once. The only difference from before is the create attribute set to true instead of nothing and causes such a weird factory call. I had situations where the factory was called even several times. But this might have been because of the outjection problem with the null value and this is solved now for me.


                                  Does anyone have an answer for the reason that the factory is called 3 times instead of only once when I set the create attribute of the @In annotation to true?


                                  Well....maybe I could give a hint with that...


                                  Frank

                                  1 2 Previous Next