• Home
  • RSS Feed
  • Log in


Accessing generic types at runtime in Java
Posted by Arjan Blokzijl mid-morning: February 7th, 2009

I was writing my n-th Dao implementation, this time using JPA.
I (and probably a whole lot of others) usually create a DAO per entity, parameterizing the entity type.
Specific DAO instances for entities implement the generic DAO using their entity type as type parameter. One generic DAO implementation exists, containing common operations like findById, persist, remove, etc. This generic DAO uses the class type specified by the implementing DAO classes (e.g. a Person) to manipulate or query the entity specified by this type. The (slightly) annoying problem for me has always been to instantiate that entity type in the generic DAO superclass. I’ve always done this by just creating a constructor in the generic DAO which takes a class argument containing the required Class of the entity. However, there’s a better way, which I’ll show in this post.

To start with an example, the generic DAO interface looks like this:

public interface GenericEntityDao {

   T findById(Serializable id);

   List findAll();

   ... more methods omitted
}

And its generic DAO implementation class looks something like this:

public abstract class GenericJpaDao implements GenericDao {

  private Class entityBeanType;

  @PersistenceContext
  private EntityManager entityManager;

  public T findById(Serializable id) {
     return entityManager.find(getEntityBeanType(), id);
  }

  public List findAll() {
      return entityManager.createQuery("from " + getEntityBeanType().getName() )
                          .getResultList();
  }

  protected Class getEntityBeanType() {
      return entityBeanType;
  }
  ... more methods omitted

}

The question is, how do we obtain the parametized type of T for the entityBeanType field to use in our queries? Earlier, I used to just instantiate this type in the constructor, like so:

public GenericJpaDao(Class entityBeanType) {
     this.entityBeanType = entityBeanType;
}

public JpaPersonDao extends GenericJpaEntityDao implements PersonDao {
   public PersonDao() {
      super(Person.class);
   }
}

But this is a bit silly, since we already know from the type parameter that the entity we’re interested in has type Person.
However, there is an easier way out: we can use Java’s ParameterizedType class to obtain information about the declared generic type. As stated in the javadoc:

/**
* ParameterizedType represents a parameterized type such as
* Collection<String>.
*
* A parameterized type is created the first time it is needed by a
* reflective method, as specified in this package. When a
* parameterized type p is created, the generic type declaration that
* p instantiates is resolved, and all type arguments of p are created
* recursively.


Thus, it seems that ParameterizedType contains the information that we want. How do we obtain an instance of it? The answer lies in Java’s getGenericSuperclass method, defined on the Class object. This returns a Type representing the superclass of this Class. The Javadoc of the method states the following:

* If the superclass is a parameterized type, the Type
* object returned must accurately reflect the actual type
* parameters used in the source code. The parameterized type
* representing the superclass is created if it had not been
* created before.



The Type interface itself is just a marker interface, containing no methods. Depending on the case at hand, an Type extending the Type interface will be returned. In our case, we’ll use the getGenericSuperclass method on a class extending our GenericJpaDao class. Thus, the superclass is JpaGenericDao, which is a parameterized type. In this case, the actual the Type object returned by getGenericSuperClass will be a ParameterizedType instance. This class contains a method getActualTypeArguments, which returns an array containing all generic type parameters used in the source code.

This is precisely what we desire, so in our GenericJpaDao class constructor, can get rid of the Class argument, and instead do the following:

  @SuppressWarnings("unchecked")
  public GenericJpaDao() {
    this.entityBeanType = ((Class) ((ParameterizedType) getClass()
        .getGenericSuperclass()).getActualTypeArguments()[0]);
  }

We know there’s precisely one type argument in our class, so we can take the first element of the array that is returned, which provides the Class of our entity. Thus we can get rid of all the annoying constructors with Class arguments, and handle determination of the entity type in just one place.

This may not provide the highest amount of code reduction you have ever experienced, but it’s a neat trick in any case.

Share

Tags: generics, Java, JPA
Filed under Java | 11 Comments »



11 Responses to “Accessing generic types at runtime in Java”



    Maarten Winkels Says:
    Posted at: February 7, 2009 at 2:50 pm

    Hi Arjan,

    A neat trick indeed. I found it here, the first time I ever heard about it. The code itself though is just plain nasty, with all the explicit casting and using hardcoded array indexing. Also, it only works when you implement a generic interface or a generic superclass (I think?).

    Anyways, good to have it on the Xebia blog, so I know where to find that nasty line of code when I need it… ;)

    -Maarten

    Reply


    Andrew Phillips Says:
    Posted at: March 5, 2009 at 12:33 pm

    A nice trick, indeed. But something to bear in mind here: this only works if

    • the type information is in a superclass and, thus,
    • the class that needs the type information inherits from the type-defining class.

    If you are class Foo<V> and you need access to the runtime type of V this unfortunately won’t work. Neither if you are FooUtils and get passed an instance of Foo.

    I’ll hopefully get round to writing a post about some of these issues soon…

    Reply


    A general-purpose utility to retrieve Java generic type values | Xebia Blog Says:
    Posted at: March 12, 2009 at 2:28 pm

    [...] by Andrew Phillips in the early afternoon: March 12, 2009 In a recent post, Arjan Blokzijl discussed how Class.getGenericSuperclass can be used to access generic type [...]

    Reply


    JPA implementation patterns: Data access objects | Xebia Blog Says:
    Posted at: March 29, 2009 at 5:52 pm

    [...] with the shared functionality and then subclass from that for each specific DAO. There are a lot of blogs out there about such a type-safe generic DAO pattern and you can even download some code from [...]

    Reply


    Rob Says:
    Posted at: June 12, 2009 at 7:54 pm

    Thank you so much!! Saved me ours of javadoc reading :)

    I had the same feelings than you about redundancy by passing in the class. ParameterizedType is the solution!

    Reply


    feng Says:
    Posted at: August 28, 2009 at 2:14 am

    Excellent article.

    I modified the code for the constructor as below so that it can handle multiple level inheritance.

    [edited to correct formatting]

    Class< ?> cls = getClass();
    while (!(cls.getSuperclass() == null
        || cls.getSuperclass().equals(AbstractExpression.class))) {
      cls = cls.getSuperclass();
    }
    
    if (cls.getSuperclass() == null)
      throw new RuntimeException(”Unexpected exception occurred.”);
    
    this.entityBeanType = ((Class) ((ParameterizedType)
      cls.getGenericSuperclass()).getActualTypeArguments()[0]);
    
    Reply


    Luis Daniel Mesa Velásquez Says:
    Posted at: November 5, 2009 at 2:00 am

    Useful for when you have a subclass of a generic, in which case you don’t really need it, cuz you know the generic type and it saves you, perhaps, 2 lines of code per subclass…

    completely useless if you don’t have a subclass. I tried creating a “generic helper” to let me create a subclass and get around the block… It works, but i didn’t like not having an elegant solution either.

    Reply


    Jelmer Says:
    Posted at: February 5, 2010 at 11:08 am

    Yes this is a useful trick. The exact same piece of code has been part of the caveat emptor sample applicatication for the Java Persistence with Hibernate for quite some time. As has been pointed out in the comments. This code doesn’t work in all cases.

    If you use spring3 you could use

    this.entityBeanType = GenericTypeResolver.resolveTypeArgument(getClass(), GenericDao.class)

    as a more elegant and robust solution

    Reply


    Myšlenky dne otce Fura » Blog Archive » Oříšek v reflexní analýze generik Says:
    Posted at: March 19, 2010 at 8:23 am

    [...] Tohle je tak trošku předskokan prvně uvedeného článku – s tímhle bych doporučoval zač… [...]

    Reply


    Thomas Says:
    Posted at: September 8, 2010 at 10:22 am

    Good read indeed.

    For those who are interested, here’s an extension:

    We’re using a similar approach with our DAOs having more than one type parameter due to our architecture.

    Additionally, we have a hierarchy of abstract generic DAOs, so there’s the problem of getting information on the actual parameter types for the most basic DAOs.

    Consider the following:

    [edited to correct formatting] ProjectSpecificUserDAO -> AbstractUserDAO<OtherParameter, UserEntity> -> AbstractBaseDAO<UserEntity>

    When reading the actual type of UserEntity in AbstractBaseDAO you’ll get into trouble since when using the first actual type parameter you’d get the class for OtherParameter instead of UserEntity.

    Additionally, Java reflection doesn’t make it easy to go down and get the actual parameter for AbstractBaseDAO, since all you get easily in that case is the name ‘UserEntity’.

    However, here’s a solution that we’re using now: http://www.artima.com/weblogs/viewpost.jsp?thread=208860

    Reply


    Andrew Phillips Says:
    Posted at: September 10, 2010 at 8:25 am

    @Thomas: Looks like what you’ve come up with is very similar to what is discussed in this post. Might be interesting for you to have a look!

    Reply


Leave a Reply

Click here to cancel reply.


Xebia Sites

  • Xebia Corporate
  • Xebia France
  • Xebia India
  • Xebia Sweden

Categories

  • Java (311)
  • Agile (181)
  • General (136)
  • Scrum (67)
  • Architecture (64)
  • Testing (59)
  • Performance (46)
  • Middleware (56)
    • Deployment (38)
  • Xebia Labs (39)
  • SOA (31)
  • Podcast (31)
  • Project Management (28)
  • Tools (26)
  • Uncategorized (20)
  • lean architecture (20)
  • Quality Assurance (17)
  • Articles (13)
  • Requirements Management (13)
  • Virtualization (19)

Tag Cloud

    Javascript Architecture Eclipse lean architecture Flex Grails Lean Scrum TDD XML lean architectuur Ajax Hibernate Xebia Scala Java Moving to India Frameworks JPA implementation patterns SOA JPA ACT Maven Spring Agile product owner Oracle Groovy Concurrency Control agile architectuur

Archives

  • February 2012
  • January 2012
  • December 2011
  • November 2011
  • October 2011
  • September 2011
  • August 2011
  • July 2011
  • June 2011
  • May 2011
  • April 2011
  • March 2011
Avatars by Sterling Adventures