1 2 Previous Next 21 Replies Latest reply on Oct 19, 2010 4:46 AM by kwutzke

    Component not instantiated?

    kwutzke

      Hello,


      It's my first time trying to build a Seam app. Even though I have Seam in Action, my component (EntityQuery subsubclass) doesn't seem to be instantiated.


      Here's the class:


      @Name("seasonListQuery")
      public class SeasonListQuery extends GenericListQuery<Season, Integer> 
      {
          public SeasonListQuery()
          {
              super("se");
              setOrder("se.startYear");
              
              System.out.println("----------------------------------------");
              System.out.println(getEjbql());
          }
          
      }
      



      GenericListQuery is just a base class for all entities that I will need lists for, so it just derives EJBQL from the generic class and the passed alias, so that


      "SELECT :alias FROM :entity :alias"



      will become


      "SELECT se FROM Season se"



      for each concrete subclass like SeasonListQuery.


      I have season-list.xhtml as my home page (I'll paste the reduced body only):


        <body>
          <ui:composition template="/templates/default.xhtml">
            ...
            <ui:define name="content">
              <h2>Welcome to Basketball Stats</h2>
              <p>Available seasons:
                <ul>
                  <ui:repeat id="listResult" value="#{seasonListQuery.resultList}" var="_season">
                  <li>
                    <s:link id="season" view="/club-list.xhtml" value="Season #{_season.startYear}">
                      <f:param name="season" value="#{_season.startYear}"/>
                    </s:link>
                  </li>
                  </ui:repeat>
                </ul>
              </p>
            </ui:define>
          </ui:composition>
        </body>
      



      What I want to do here is simple: display a list of available seasons in the DB. However, I only get an empty UL. There are no LIs, so the ui:repreat doesn't iterate at all.


      The println's in the class' constructor should write something into my logs, but there's nothing, hinting the component isn't even instantiated (?). I assume there's something fundamentally wrong, but what?


      Karsten

        • 1. Re: Component not instantiated?
          mkiel

          I'm not sure if it's related to your problem, but as far as I know, you should not use a constructor for setup of components, but rather put the setup code in a normal method and annotate it with @Create. When the constructor is called, Seam has not yet had a chance to inject other components. The @Create method is called after everything is hooked up.

          • 2. Re: Component not instantiated?
            kwutzke

            I'll try that.


            FYI this is what my GenericListQuery looks like:


            /**
             * Generic list query that derives a standard select from the alias passed in and the generic classes.
             * 
             * @author Kawu
             *
             * @param <E> The entity (element) type
             * @param <I> The entity's primary key class (can be Integer, Long etc. if the primary key is a simple ID)
             */
            public abstract class GenericListQuery<E extends Serializable,I extends Serializable> extends EntityQuery<E>
            {
                // the JPQL select template (most WHERE restrictions are set by subclasses)
                private static final String DEFAULT_EJBQL =
                    "SELECT :alias FROM :entity :alias";
            
                // parameterized class
                private final Class<E> clEntity;
                
                // query alias
                private final String sAlias;
                
                protected GenericListQuery(String sAlias)
                {
                    if ( sAlias == null )
                    {
                        throw new NullArgumentException("Alias is null!");
                    }
            
                    if ( sAlias.isEmpty() )
                    {
                        throw new IllegalArgumentException("Alias is empty!");
                    }
                    
                    this.clEntity = determineEntityClass();
                    this.sAlias = sAlias;
            
                    // replace entity name in QL with simple class name of this class' generic type
                    // and set the alias to some passed-in abbreviation
                    setEjbql(DEFAULT_EJBQL.replace(":entity", clEntity.getSimpleName()).replace(":alias", sAlias));
                }
                
                public Class<E> getEntityClass()
                {
                    return clEntity;
                }
                
                public String getAlias()
                {
                    return sAlias;
                }
                
                @SuppressWarnings("unchecked")
                private Class<E> determineEntityClass()
                {
                    Class<E> clEntity = null;
                    
                    Type tGenericClass = getClass().getGenericSuperclass();
                    
                    if ( tGenericClass instanceof ParameterizedType )
                    {
                        // find the class of the first parametrized type!
                        ParameterizedType ptGenericClass = (ParameterizedType)tGenericClass;
                        clEntity = (Class<E>)ptGenericClass.getActualTypeArguments()[0];
                    }
                    else
                    {
                        throw new IllegalArgumentException("Failed to determine generic class!");
                    }
            
                    return clEntity;
                }
                
                /**
                 * Uses the entity manager to find a single entity instance by generic primary key class.
                 * 
                 * @param
                 * @return A single entity as found by getEntityManager(E, id) 
                 */
                public E selectByPrimaryKey(I id)
                {
                    return getEntityManager().find(clEntity, id);
                }
            
            }
            



            It looks pretty straightforward to me, but I can't tell whether it is the way to go via constructor or, as hinted in the previous reply, must be put into the overridden getter methods.


            If so, there's some information missing in the Seam manual and Seam in Action as to how to correctly implement EntityQuery subclasses!


            To me, this raises the question of how in the world Seam instantiates components, if it doesn't call constructors...


            Karsten

            • 3. Re: Component not instantiated?
              kwutzke

              I admit, I changed the idea of someone else a bit. The code can be found here:


              http://seamframework.org/Community/ExtendingEntityQuerySemiDAOPattern


              So, either this code didn't work, too or there's really something strange going on.


              Karsten




              • 4. Re: Component not instantiated?
                lvdberg

                Hi,


                I´ve looked at your code at you basically want to add some minor things to EntityQuery. Why don't you take the original EntityQuery sourcecode and make the extensions there?


                In that way you prevent the enormous chain of subclaeees with theit annotations in the different classes and have a more logical inheritance, because you are now making an abstract subclass from a not-abstract EntityQuery class.


                I found that sometimes I can't see some annotations in abstract sub-classes and tehrefor I always have the annotations in the closest abstract superclass.


                Leo


                • 5. Re: Component not instantiated?
                  kwutzke

                  Hello, thanks for replying,



                  Leo van den Berg wrote on Oct 15, 2010 10:24:


                  Hi,

                  I´ve looked at your code at you basically want to add some minor things to EntityQuery. Why don't you take the original EntityQuery sourcecode and make the extensions there?


                  Well, that pretty much sounds like a hack. I didn't intend to use such a massive framework like Seam just to start creating workarounds. EntityQuery was obviously made to be subclasses, so I'd really like to leave it that way.



                  In that way you prevent the enormous chain of subclaeees with theit annotations in the different classes and have a more logical inheritance, because you are now making an abstract subclass from a not-abstract EntityQuery class.


                  I find creating abstract subclasses from non-abstract ones nothing but unusual, honestly. I have (a small) reason to so in my case. It really almost empties all entity list subclasses, which is a maintenance advantage.



                  I found that sometimes I can't see some annotations in abstract sub-classes and tehrefor I always have the annotations in the closest abstract superclass.

                  Leo


                  Hmmm, I didn't fully get your final statement...


                  FYI: I've just implemented my classes using no constructors, but only the getters (some overridden from Query or EntityQuery). There's no difference in the behavior. No output at all.


                  Might there be anything wrong with my Seam setup? I fear there is, but it's hard for me to describe and for you to guess what might be wrong. Note, I haven't defined a pages.xml yet.


                  Karsten

                  • 6. Re: Component not instantiated?
                    lvdberg

                    Hi,


                    I fully agree that EntityQuery is ment for subclassing, but basically in a pretty straightforward way.
                    But IMHO you're optimizing a bit too much. You can easily reatrieve a class name from




                    <Entity>.getClass().getSimpleName()





                    and add the alias in a property, both used after the Create method.


                    The create method is on the validate method of the Query class, so you can't override it with another created-annotated method.  Overriding the getEjbQl method should provide what you want. Additionally there is nothing wrong with re-using the EntityQuery code for a new component (GenericEntityQuery) which can be used side by side with the old one.


                    Concerning my annotation problem, I made a simple abstract class with all the annotations, which was subclassed with another abstract class to add additional functionality and finally the real class. Don't ask me why, but the Injected Events didn't work. Just moving it up in the class hiearchy and it worked.



                    Leo




                    • 7. Re: Component not instantiated?
                      kwutzke

                      OK again, thanks for helping on this.


                      I reimplemented SeasonListQuery to an almost bare minimum, but there's still no output.


                      @Name("seasonListQuery")
                      public class SeasonListQuery extends EntityQuery<Season> 
                      {
                          public SeasonListQuery()
                          {
                              setEjbql("SELECT se FROM " + Season.class.getSimpleName() + " se");
                              setOrder("se.startYear");
                              
                              System.out.println("----------------------------------------");
                              System.out.println(getEjbql());
                          }
                      }



                      Still the same XHTML from the original post.


                      There is something wrong in my setup, I just don't know what it is. I'm beginning to believe it's not the Java code...


                      Any more guesses on this? What are the minimum prerequisites setup-wise? Do I need a pages.xml? JARs missing??


                      Karsten

                      • 8. Re: Component not instantiated?
                        lvdberg

                        Hi.


                        Have a look at the Seam code and see how these components are created. As mentioned before use the standard way of extending the EntityQuery, which is basically overriding the needed getters (in this case getEjbQL (and use the @override annotation on the methods) . EntityQuery has a lot more methods which you can override!


                        Do not use the constructor based initialization and use the bare minimum of the sub-classed EntityQuery first and see if that works. If that works, there is nothing wrong with your setup.


                        Use Seam as a COMPONENT based framework; so use it as intended.


                        Leo

                        • 9. Re: Component not instantiated?
                          lvdberg

                          Hi,


                          An example of extending the EntityQuery:


                          Example



                          Leo

                          • 10. Re: Component not instantiated?
                            kwutzke

                            See my comment above,


                            http://seamframework.org/Community/ComponentNotInstantiated-comment141013


                            I linked to the very same example, which I used as a statring point for GenericListQuery.


                            The example however also uses a constructor-based implementation, so there seems to be nothing wrong with that approach.


                            I tested a little with the tags, the EL seems to be working for all tags ui:, h:, f:, and s:, but as soon as I reference one of the @Name names, the tag seems to crash leaving nothing behind in the HTML.


                            I had hoped for the EL failing in general, but now I'm back to where I was. I'll try the getter only implementation. I'll be back.


                            Karsten

                            • 11. Re: Component not instantiated?
                              kwutzke

                              As I suspected, still no output. Here's the bare minimum implementation:


                              @Name("seasonListQuery")
                              public class SeasonListQuery extends EntityQuery<Season> 
                              {    
                                  @Override
                                  public String getEjbql()
                                  {
                                      return "SELECT se FROM Season se";
                                  }
                              }
                              



                              Note, the result is the same when using any of my entity class' @Name's in the EL instead of the EntityQuery @Name. It really looks like some setup madness. I'm out of ideas.


                              Karsten

                              • 12. Re: Component not instantiated?
                                lvdberg

                                Hi,


                                sorry missed the mesage in the middle with your link.....


                                Are you creating a war or EAR ? Well in both cases, see with the unzipper if everything is present. Sometimes the IDE works great, but the build file misses stuff or has too much.


                                Leo

                                • 13. Re: Component not instantiated?
                                  kwutzke

                                  WAR. My setup is Tomcat 6, Embedded JBoss used by Ant (Catalina Ant deploy/undeploy tasks). I don't use Eclipse for anything but to show me the errors etc. while typing.


                                  My list of webapp (not server) JARs currently includes:


                                  commons-lang-2.5.jar
                                  jstl-api-1.2.jar
                                  jstl-impl-1.2.jar
                                  jboss-el.jar
                                  jboss-seam.jar
                                  jboss-seam-ui.jar
                                  jsf-api.jar
                                  jsf-facelets.jar
                                  jsf-impl.jar


                                  The rest (Embedded JBoss) is in tomcat/lib.


                                  I also have a standard HTTP servlet, Hibernate and all entities are working, I tried to load almost any entity once via the EntityManager. It must be something connecting the @Name'd components and EL. I have no insight into Seam what could be the cause.


                                  I already checked the WAR contents, everything's in place AFAI can see.


                                  Any other ideas?


                                  Karsten

                                  • 14. Re: Component not instantiated?
                                    kwutzke

                                    The formatter here needs improvement, as well as a function to edit posts:


                                    commons-lang-2.5.jar
                                    jstl-api-1.2.jar
                                    jstl-impl-1.2.jar
                                    jboss-el.jar
                                    jboss-seam.jar
                                    jboss-seam-ui.jar
                                    jsf-api.jar
                                    jsf-facelets.jar
                                    jsf-impl.jar




                                    1 2 Previous Next