java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType

java, spring

Solution

Remove `@Repository` annotation from `AbstractGenericDAO` and make it `abstract`:

public abstract class AbstractGenericDAO<T extends Serializable, ID extends Serializable> 
   implements GenericDAO<T, ID>

Your problem occurs because `@Repository` is a specialization of `@Component`, which means that Spring will try to create `AbstractGenericDAO` instances for injection. Since `AbstractGenericDAO` superclass (`Object`) is not generic, you will not be able to downcast its `Type` to `ParameterizedType`, and so this line of code will fail (in the same way that it would if you tried to instantiate it manually with `new AbstractGenericDAO()`):

this.persistentClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];

The specialized class `ShlkActiveWorkflowDAOImpl` should still be annotated with `@Repository`. When spring tries to create a instance of this class a implicit call to `AbstractGenericDAO` constructor will occur, but this time the line of code mentioned above will run as expected. This happens because `getClass()` returns `ShlkActiveWorkflowDAOImpl.class` which is a subclass of the generic `AbstractGenericDAO` (so the downcast to `ParameterizedType` works).

Since `ShlkActiveWorkflowDAOImpl` `extends` `AbstractGenericDAO<ShlkActiveWorkflow, Serializable>` the actual type `ShlkActiveWorkflow` will be correctly reflected at runtime. This is a known workaround to avoid passing a `Class<T>` reference to the `AbstractGenericDAO` constructor.

If you are worried about the `@Autowired` annotation at `AbstractGenericDAO`, don't be. Spring will correctly wire everything up when you inject a instance of one of its subclasses.

Problem

I am stuck with this issue for a long time. I searched for this issue for sometime but none of solution worked. Structure: ``` public interface GenericDAO<T extends Serializable, ID extends Serializable> @Repository public class AbstractGenericDAO<T extends Serializable, ID extends Serializable> implements GenericDAO<T, ID> { private Class<T> persistentClass; @Autowired private SessionFactory sessionFactory; static Logger LOGGER = Logger.getLogger(AbstractGenericDAO.class); @SuppressWarnings("unchecked") public AbstractGenericDAO() { this.persistentClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]; } /** * @param entity * @return T * @throws DBException */ @SuppressWarnings("unchecked") public T saveEntity(T entity) throws DBException { return saveEntity(entity, false); } /** * @param entity * @param explicitFlush * @return T * @throws DBException */ @SuppressWarnings("unchecked") public T saveEntity(T entity, boolean explicitFlush) throws DBException { Session session = getSessionFactory().getCurrentSession(); try { session.save(entity); if(explicitFlush) { session.flush(); session.refresh(entity); } } catch (HibernateException he) { String errorMsg = "Could not save entity. Reason: " + he.getMessage(); LOGGER.error(errorMsg, he); throw new DBException(errorMsg, he); } return entity; } /* (non-Javadoc) * @see com.amazon.fc.receive.dbaccess.dao.GenericDAO#getPersistentClass() */ @SuppressWarnings("unchecked") public Class<T> getPersistentClass() { return persistentClass; } /** * @return the sessionFactory */ public SessionFactory getSessionFactory() { return this.sessionFactory; } /** * @param sessionFactory the sessionFactory to set */ @Autowired public void setSessionFactory(SessionFactory sessionFactory) { this.sessionFactory = sessionFactory; } } public interface ShlkActiveWorkflowDAO extends GenericDAO<ShlkActiveWorkflow, Serializable> @Repository public class ShlkActiveWorkflowDAOImpl extends AbstractGenericDAO<ShlkActiveWorkflow, Serializable> implements ShlkActiveWorkflowDAO ``` I am also using `<context:component-scan>` in my `application-config.xml` `+ <tx:annotation-driven />` in my `application-config.xml`. Please provide some information about how to fix this issue. ``` Exception: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'abstractGenericDAO' Constructor threw exception; nested exception is java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:946) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:890) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:479) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:450) at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:290) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:287) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:189) at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:557) at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:842) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:416) at com.coral.spring.Launcher.<init>(Launcher.java:95) at com.coral.spring.Launcher.main(Launcher.java:56) Caused by: org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [com.workflow.dao.AbstractGenericDAO]: Constructor threw exception; nested exception is java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:141) at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:72) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:938) ... 12 more Caused by: java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType at com.workflow.dao.AbstractGenericDAO.<init>(AbstractGenericDAO.java:43) at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27) at java.lang.reflect.Constructor.newInstance(Constructor.java:513) at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:126) ... 14 more ```

Original source