5 Replies Latest reply on Aug 22, 2006 11:16 PM by gavin.king

    Eliminating code redundancy + suggestion for DataModel and D

    jbmadair

      Preface: I'm quite certain that my usage patterns in Seam are not advanced yet, so I might be looking at the problem of code redundancy in Seam components completely wrong, so comments highly welcome.

      I'm trying to work through strategies to eliminate repetitive code in a large project, and common features such as entity search pages and components are an example of an easy win since the combination of Hibernate + Seam makes much of the code generic. It looks to me that even with a modest project its easy to eliminate 10k lines of code just for that one feature alone on all the entities that need searchability.

      My approach at this point is to create an abstract class that holds most of the standard functionality and use Generics to handle typing provided by the subclasses. It's not fully tested yet, but so far appears good.

      For instance, the signature of the (untested) abstract superclass is:

      public abstract class StatelessSearchBean<T> implements Search <T> {
      
      ...
      
      }
      


      The code currently has some less than safe typecasts, due to erasure, but I'm not so worried about that at this point.

      A subclass looks like this:

      @Name("someEntityFinder")
      @Stateful
      @Scope(ScopeType.SESSION)
      @Interceptors(SeamInterceptor.class)
      public class SomeEntitySearchBean extends StatelessSearchBean<SomeEntity> {
      
       private static final long serialVersionUID = 1L;
      
       @DataModel
       private List<SomeEntity> someEntityList;
      
       @DataModelSelection
       private SomeEntity selectedSomeEntity;
      
       public SomeEntitySearchBean() throws IllegalAccessException,
       InstantiationException {
       }
      
       public SomeEntity getSelected() {
       return this.selectedSomeEntity;
       }
      
       public void setList(List<SomeEntity> list) {
       this.someEntityList = list;
       }
      
       public List<SomeEntity> getList() {
       return this.someEntityList;
       }
      
      }
      


      The constructor is currently resolving Generics instantiation issues as well, but it's just a placeholder for better handling that I will add later.

      The @DataModel and @DataModelSelection are both set here instead of the superclass, since the default "value" parameter in the superclass would name-clash with other components. For instance, it wouldn't work to have multiple lists on a page named "list". But since it's annotations that set the DataModel* naming, I can't use non-constant values, such as getName() results to fix the problem. (The accessors and mutators are also there to allow access internally in the abstract superclass.)

      1. It appears that with a minor modification to @DataModel and @DataModelSelection default value settings in Seam code, it would be possible to turn the above into:

      @Name("someEntityFinder")
      @Stateful
      @Scope(ScopeType.SESSION)
      @Interceptors(SeamInterceptor.class)
      public class SomeEntitySearchBean extends StatelessSearchBean<SomeEntity> {
      
       private static final long serialVersionUID = 1L;
      
      }
      


      I suggest that perhaps an optional setting @DataModel and @DataModelSelection, to change the naming strategy in the "value" parameter, would fix the issue of all that repetitive code. For instance, a parameter like "qualifyDefaultValue" could prefix the class name so that a default of "list" becomes "someEntityList" in the above example.

      Of course, it's been a long night, and I might just be missing other obvious ways to refactor this. In which case... >> cringe << while i wait for a flaming ;-)

      2. What am I missing here? What are other people experiencing? Just like most of Java, it looks like there's a lot of repetitive code laying around (no fault of Seam's), so I'm just trying to cut down several 10's of thousands of lines of code from my project and I want to work out the best strategies for doing so. This is just one example of a common use case that I'm trying to genericize.

      I'd really rather not opt for a code generator, instead preferring to eliminate redundancy (plus, the Hibernate Utils Seam template code is rather attrocious anyway ;-D, so I'd have to resort to homegrown tools).

      Thanks!