1

most people should be familiar with making a Generic DAO for Spring + hibernate. The reference is from here http://www.ibm.com/developerworks/java/library/j-genericdao/index.html but there is an improvement to it on Single DAO & generic CRUD methods (JPA/Hibernate + Spring)

This improvement is the detection of the type as it is part of the superclass, instead of using the constructor to tell which class it is

public GenericDaoJpaImpl() {
    ParameterizedType genericSuperclass = (ParameterizedType) getClass()
         .getGenericSuperclass();
    this.entityClass = (Class<T>) genericSuperclass
         .getActualTypeArguments()[0];
}

HOWEVER, this cast will fail with Guice. To be injected, the interface and the class need to be binded in a module like this

bind(TestDao.class).to(TestDaoImpl.class);

And by doing so the constructor trick for our GenericDAO won't work because of the following:

getClass().getGenericSuperclass() = java.lang.Class
getClass().getName() = com.gwtplatform.samples.basic.server.dao.TestDaoImpl$$EnhancerByGuice$$5fe0d6fd

contrary to what a Spring + Hibernate returns

getClass().getGenericSuperclass() = sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl
getClass().getName() =  com.gwtplatform.samples.basic.server.dao.TestDaoImpl

I'm just using a super constructor in my extended DAOs now, but still would like to obtain the type instead of providing it, any ideas?

Community
  • 1
  • 1
javaNoober
  • 1,338
  • 2
  • 17
  • 43

3 Answers3

5

The "guicy" way is to let Guice inject a TypeLiteral into your code.

bind(new TypeLiteral<Dao<Foo>>(){}).to(GenericDAO.class);

and then….

class GenericDao implements Dao<T>
  @Inject
  GenericDao(TypeLiteral<T> type) {
    this.whatever = type;
  }
}

Guice knows the type of T and is happy to tell you. TypeLiteral has accessors to get the raw underlying type.

The guice docs have precious little information on this technique, but this blog post is helpful: http://blog.publicobject.com/2008/11/guice-punches-erasure-in-face.html

Darren Gilroy
  • 2,071
  • 11
  • 6
  • I'm marking this as answer as this was a way to obtain the type, but for me, at the end this is just a lot of code, compared providing the type myself – javaNoober Jan 11 '12 at 04:22
1

These kind of generic tricks make my head hurt and if I'm there I often question if I should be, perhaps there is a better solution, but I think you can do this by using a Provider in Guice, so you are passing the actual class, instead of letting Guice create it. So

public class DAOProvider implements Provider<TestDaoImpl> {/*etc*/}

bind(TestDao.class).toProvider(new DAOProvider());
Yishai
  • 90,445
  • 31
  • 189
  • 263
0

You can get underlying class from Guice proxy with this code:

Class<?> clazz = getClass();

if (clazz.getName().contains("EnhancerByGuice")) {
  clazz = clazz.getSuperclass();
}
Yuppy
  • 1