I’d like to ask about the root cause of the exception:
Caused by: java.lang.ClassCastException: java.lang.Class cannot be cast to
java.lang.reflect.ParameterizedType
which happens in Spring when we make Spring generate proxies for classes (i.e. setting proxy-target-class="true" on a transaction manager):
<tx:annotation-driven transaction-manager="transactionManager"
proxy-target-class="true"/>
and when the class to proxy is a parameterized class, i.e.
public class SomeDAOImpl<SomeEntity> implements SomeDAO ...
The full story can be, for example, read in this question: Abstract DAO pattern and Spring's "Proxy cannot be cast to …" problem!
Question: why can’t Spring proxy this class? Is it because it uses old code generation libraries? Because of type erasure? If the SomeDAOImpl was not a generic class, it would succeed (I checked that).
Please don’t answer like: “you should proxy interfaces, not classes”. I know that.
This looks like a Spring/CGLIB problem but the issue is actually in your constructor! I’m guessing you are trying to get the parameter type so that you can supply it to the entity manager (or whatever persistence framework you’re trying to use). I’m also guessing that to do that you are calling
getGenericSuperclass()and casting it to a ParameterizedType?The way that method behaves depends on the class. It turns out that not all Class objects implement the ParameterizedType interface (which I agree, is bizarre). The generated CGLIB proxies do not keep the generics information. It looks something like:
I don’t actually know why CGLIB proxies don’t keep the generics as the details of CGLIB proxies are very complex. It could be that it is simply impossible to do so. It could also be that doing so is not a priority to them.
Here is a simple experiment which takes Spring and CGLIB out of the picture but still gets that error.