9 Replies Latest reply on Apr 15, 2006 4:20 AM by g.tomassoni

    @In, @Out and @Factory. It's me or...

    g.tomassoni

      Dears,

      I have something like this in a Seam component of mines:

      @Name("myComp")
      @Scope(ScopeType.EVENT)
      @Intercept(InterceptionType.ALWAYS)
      public class MyComp {
       @In(create = true)
       private HibernateEntityManager theDatabase;
      
      
       @RequestParameter
       private String p;
      
       @In(create = true) @Out
       private Integer idCat;
      
       @Factory("idCat")
       public void initIdCat()
       { idCat = Integer.valueOf(c); }
      
      
       @In(create = true) @Out
       private Cat currentCategory;
      
       @Factory("currentCategory")
       public void initCurrentCategory() {
       currentCategory = (Cat)theDatabase.getSession().createCriteria(Cat.class)
       .add(Restrictions.idEq(idCat))
       .uniqueResult();
       }
      
      
       // Etc, etc...
      }
      


      Now, when I ask for the idCat value from a JSF page, I get a correct result. When I attempt from that page to get the value of currentCategory, I get a NullPointerException in which it is said that idCat in initCurrentCategory() is null.

      Is it a Seam issue or a Giampaolo's one?

      Regards,

      Giampaolo

        • 1. Re: @In, @Out and @Factory. It's me or...
          mirko27

          Please give me your JSF page. I have an idea, but then I can be sure. It seems to be your issue btw.

          • 2. Re: @In, @Out and @Factory. It's me or...
            g.tomassoni

            It is not that easy to post: it is based on a two-level template and two custom tags in a <ui:repeat>/<c:forEach>...

            What are you looking for? I'll post the needed fragment.

            This is the base page, however:

            <?xml version="1.0" encoding="UTF-8"?>
            <!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
            <ui:composition xmlns="http://www.w3.org/1999/xhtml"
             xmlns:ui="http://java.sun.com/jsf/facelets"
             xmlns:c="http://java.sun.com/jstl/core"
             xmlns:fmt="http://java.sun.com/jstl/fmt"
             xmlns:h="http://java.sun.com/jsf/html"
             xmlns:e="http://www.xxx.it/taglib/xxx"
             xmlns:f="http://java.sun.com/jsf/core"
             xmlns:fn="http://java.sun.com/jsp/jstl/functions"
             template="include/default.xhtml"
            >
             <ui:define name="title"><h:outputText value="#{e:localize(currentCategory).text}"/></ui:define>
            
             <ui:define name="subtitle">
             <h:outputLink value="index.jsf">Home</h:outputLink>
             <c:forEach var="c" items="#{currentCategoryPath}">
             <span class="px16"><h:outputText value=">"/></span>
             <c:choose>
             <c:when test="#{c == currentCategory}">
             <h:outputText value="#{e:localize(c).text}" transient="true"/>
             </c:when>
             <c:otherwise>
             <h:outputLink value="catalog.jsf">
             <f:param name="c" value="#{c.id}"/>
             <h:outputText value="#{e:localize(c).text}" transient="true"/>
             </h:outputLink>
             </c:otherwise>
             </c:choose>
             </c:forEach>
             </ui:define>
            
             <ui:define name="body">
             <c:if test="#{! empty currentCategory.childrenCats}">
             <div style="height: 8px"> </div>
             <ui:repeat var="category" value="#{e:orderASC(currentCategory.childrenCats)}">
             <ui:include src="/WEB-INF/facelets/includes/categoryAbstract.xhtml"/>
             <div style="height: 8px"> </div>
             </ui:repeat>
             <table class="sotto"><tr><td class="spc"></td></tr></table>
             </c:if>
             <c:if test="#{! empty currentCategoryProducts}">
             <div style="height: 8px"> </div>
             <c:forEach var="ph" items="#{currentCategoryProducts}">
             <ui:include src="/WEB-INF/facelets/includes/productAbstract.xhtml"/>
             <div style="height: 8px"> </div>
             </c:forEach>
             <table class="sotto"><tr><td class="spc"></td></tr></table>
             </c:if>
             </ui:define>
            </ui:composition>
            


            • 3. Re: @In, @Out and @Factory. It's me or...
              mirko27

              It seems to me that me or you have missunderstood the concept of seam component. I have understood that Factory works in context level, not in component level. If some page asks idcat from context(JSF page) then the Factory method will be called. But maybe it`s a bug and calling from component is allowed.
              What I suggest you to do is call idcat property in your page out before currentCategories. If it works then, then I am right, if not then it s a bug.

              • 4. Re: @In, @Out and @Factory. It's me or...
                g.tomassoni

                Well, context demarcation happens in component code, not in jsf page...

                However, actually I don't use it at all. I will for some pages, but not yet.

                @Out with @Factory always works to me when the outjected value is asked by jsf pages. It never works to me when it is used from inside the same component supplying it, as in the example provided.

                • 5. Re: @In, @Out and @Factory. It's me or...
                  g.tomassoni

                  Ok, my brain was elsewhere while writing my previous post... Now I got your point.

                  I think there shouldn't be any difference in grabbing an attr at context or from component level: after all, in any case there is an underlying faces context triggering the (in my case cascaded) bijections...

                  Also, Seam doesn't have to adhere to any (more or less silly) standard, so, taken I'm not the only dumb here to feel a feature like this useful, I wouldn't say that we "misunderstood the concept of seam component". Maybe that seam developers relied too much on the example Hotel app?

                  Also, calling the idCat property means I have to trash the Factory-based design, which I don't dislike at all. I would need to wrap my attrs within

                  if(attr == null) {
                   // Build attr
                  }
                  
                  return(attr);
                  

                  constructs. Not a big problem, but... oh my!

                  There is probably another way to let this work, which is to retrieve the idCat attribute in initCurrentCategory from a FacesContext. But, again, it's right few lines above! Why one would need to do that? Anyway, I'm going to try it...

                  • 6. Re: @In, @Out and @Factory. It's me or...
                    gavin.king

                     

                    @RequestParameter
                     private String p;
                    
                     @Factory("idCat")
                     public void initIdCat()
                     { idCat = Integer.valueOf(c); }


                    I don't quite get your code. do you mean "p" instead of "c"?

                    • 7. Re: @In, @Out and @Factory. It's me or...
                      g.tomassoni

                      Of course, it is:

                       @RequestParameter
                       private String c;
                      


                      Something went wrong in my previous cut'n'paste. The code I'm using is correct, however...

                      • 8. Re: @In, @Out and @Factory. It's me or...
                        gavin.king

                        Have you managed to solve this problem yet?

                        • 9. Re: @In, @Out and @Factory. It's me or...
                          g.tomassoni

                          Almost: splitting the MyClass in two classes, one outjecting idCat and one outjecting currentCategory, as well as emulating the behaviour of @Factory through @Out(s) on getters solved the problem.

                          It is not that elegant, but works.

                          After changes I thought that retrieving idCat in initCurrentCategory() using Component.getInstance(...) could have possibly forced the idCat factory invocation, but I didn't try it.

                          Do you have any suggestion to spare?