This post looks at how to make service and persistence layers re-usable by another application – even if the application extends your original domain model. Lets take a simple example…

public class Article {
  public String title;
}

public class TravelArticle extends Article {
  public String destination;
}

// We CAN'T do
// TravelArticle ta = articleService.findByTitle(myTitle);
public class ArticleService {
  public Article findByTitle(String title) {return null;}
}

Making it generic

We can make it generic at the method level like so…

public class ArticleService {
  public <T extends ArticleImpl> T findByTitle(String t) {
    return null;
  }
}

or at the class level

public class ArticleService<T extends ArticleImpl> {
  public T findByTitle(String title) {return null;}
}

Taking it further

If we need to instantiate domain classes from within ArticleService we need a bit extra - we can put it in a base class something like the one below. The domain class is infered from the type parameter but it can also be specified explicitly (in case the parameter type is an interface, for example).

public class BaseService<T> {
  private Class<T> domainClass;
   
  public Class<T> getDomainClass() {
    if (domainClass == null) {
      domainClass = (Class<T> ) ((ParameterizedType) getClass()
          .getGenericSuperclass()).getActualTypeArguments()[0];
    }
    return domainClass;
  }

  public T newDomainInstance() {
    try {
      return (T) getDomainClass().newInstance();
    } catch (InstantiationException e) {
      throw new RuntimeException(e);
    } catch (IllegalAccessException e) {
      throw new RuntimeException(e);
    }
  }

  public void setDomainClass(Class<?> domainClass) {
    this.domainClass = (Class<T> ) domainClass;
  }
}

// Generified
public class ArticleService<T extends ArticleImpl>
    extends BaseService<T> {
  public T findByTitle(String title) {
    return newDomainInstance();
  }
}

Of course, if you have logic specific to the TravelArticle subclass then you have to subclass ArticleService.

Leave a Reply