5 Replies Latest reply on Mar 1, 2006 6:39 PM by coryvirok

    inherited annotations

    coryvirok

      I've been going through the generated code for a Skeleton app based on Seam that Hibernate Tools gives you and have been trying to refactor it into a cleaner design to get rid of a lot of the repetitious code.

      One thing that I would like to do that would make the refactoring easier is to declare abstract base classes that defined the

      @DataModel and @DataModelSelection

      for the subclasses as well as the findFirstPage(), reorder(), findPrevPage(), etc...

      Is there a way to inherit the Seam annotations so that you don't have to declare them in the child classes?

      Ex:

      Local interface for all finder classes:
      
      @Local
      public interface Base {
       public String findFirstPage();
      }
      
      Base class for all finder classes:
      
      public abstract class BaseClass<T extends Serializable> implements Base, Serializable {
      
       @In(create = true)
       protected EntityManager em;
      
       @DataModel
       protected List<T> results;
      
       @DataModelSelection("results")
       protected T selectedResult;
      
       protected abstract String findFirstPage();
      }
      
      Find subclass for User objects:
      
      @Name("userFinder")
      @Stateful
      @Interceptors(...)
      public class UserFinder extends BaseFinder<User> implements Base, Serializable {
       public String findFirstPage() {
       this.results = (List<User>) em.createQuery("from User").getResultsList();
      
       return null;
       }
      }
      
      And somewhere in the jsf code:
      
      <h:dataTable value="#{results}" var="user">
       ...
       #{user.userName}
       ...
      </h:dataTable>
      


      The point being, that the methods and fields referred to by the #{...} expressions would be able to access the base class and not just the stateful UserFinder bean.

      Is this doable?

      Thanks,
      - Cory

        • 1. Re: inherited annotations

          I've tried this and all the annotations work apart from the datamodel and datamodelselection (for some reason it won't inject the datamodelselection when it should be).

          I had to implement anything datamodel related in the sub classes.

          HTH,

          James

          • 2. Re: inherited annotations
            coryvirok

            Thanks for the reply. I've gone over pretty much every possible combination of placing the DataModel annotations and have not gotten it to work in any place other than the subclass, just like you mentioned.

            I do, however, see some interesting behavior in regards to the @Factory annotation when I have it in the base, (abstract) class.

            Seems like even though the @Factory method is in the abstract class, it gets called and fills the model's list up with values. Not only does it get called once, but it gets called a second time and even though there are values in the data model, the dataTable never gets any elements to list out...

            Here's the setup:

            @Local
            public interface Test {
            
            // @DataModel //Doesn't work
             public List<String> getNames();
             public void setNames(List<String> names);
            
            // @DataModelSelection("names") //Doesn't work
             public String getName();
             public void setName(String name);
            
            // @Factory("names") //Doesn't work
             public void setupNames();
            }
            
            public abstract class TestBase implements Test {
            
             @Factory("names") //Gets called twice when the dataTable uses #{names}
             public void setupNames(){
             List<String> names = new LinkedList<String>();
             names.add("Cory");
             names.add("Dave");
             setNames(names);
             }
            }
            
            @Stateful
            @Name("test")
            @Interceptors(SeamInterceptor.class)
            public class TestBean extends TestBase implements Test {
            
             @DataModel
             List<String> names;
            
             @DataModelSelection("names")
             String name;
            
             public String getName() {
             return name;
             }
            
             public List<String> getNames() {
             return names;
             }
            
             public void setName(String name) {
             this.name = name;
             }
            
             public void setNames(List<String> names) {
             this.names = names;
             }
            
             //*No* Factory annotation since it's listed in the base class
            }
            
            <!-- With the @Factory annotation in the base class, nothing is ever listed here, even though "names" gets filled correctly... -->
            <h:dataTable value="#{names}" var="n">
             <h:column>
             #{n}
             </h:column>
            </h:dataTable>
            


            Is this a bug, a feature? Also, to get back to the original question, do you know of any future support for inherrited @DataModel annotations?

            Also, which other annotations did you try that worked?

            Thanks,
            - Cory

            • 3. Re: inherited annotations
              gavin.king

              Yes, a bad limitation in Seam is that Component does not scan superclasses for annotations.

              I will add this to JIRA.

              • 4. Re: inherited annotations
                gavin.king
                • 5. Re: inherited annotations
                  coryvirok

                  Sounds like a good addition.

                  Thanks,
                  - Cory