Hello, I have a complex auto wiring scenario that seems to be only happening in production.
Affected versions:
- Spring Core 5.3.27
- Spring Batch 4.3.8
- Spring ORM 5.3.27
- Hibernate 5.4.33
- Note I am not using Spring Boot at all.
In particular, I have a transactionManager bean that is a HibernateTransactionManager and another transactionManagerTarget bean that is of type DataSourceTransactionManager. The doGetTransaction() method is failing at runtime because of a ClassCastException.
While I am not able to reproduce the issue to send as a sample project (I tried), I wanted to offer this small rewrite. It is 100% backwards compatible and simply routes into the else block instead of throwing a ClassCastException at runtime. I would greatly appreciate if it could be considered in an upcoming release!
instanceofcheck automatically handles the!= nullcase- rewriting cast to avoid potential ClassCastException scenarios
- specifically avoiding runtime
java.lang.ClassCastException: org.springframework.orm.jpa.EntityManagerHolder cannot be cast to org.springframework.orm.hibernate5.SessionHolder
Lastly, here is the original stack trace. Thank you!
Caused by: java.lang.ClassCastException: org.springframework.orm.jpa.EntityManagerHolder cannot be cast to org.springframework.orm.hibernate5.SessionHolder
at org.springframework.orm.hibernate5.HibernateTransactionManager.doGetTransaction(HibernateTransactionManager.java:425)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:347)
at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:595)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:382)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:241)
at com.sun.proxy.$Proxy74.updateExecutionContext(Unknown Source)~[?:?]
at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:452)
... 14 more
Comment From: snicoll
Unfortunately, that would be hiding the actual issue rather than fixing it. Without a test that demonstrates why this is legit to be lenient like that, this PR isn't actionable. And we wouldn't make such a change in 5.3.x at this point either.
Chatting with @jhoeller, it looks like you have a case with a nested transaction and incompatible resource management, which must be fixed in your application. Perhaps the outer transaction is using JPATransactionManager that ends up delegating to an inner transaction using HibernateTransactionManager, pointing to the same Hibernate SessionFactory instance?
Comment From: NaanProphet
Hi! Thanks for your reply. No problem, it sense that you need a true RCA to consider the PR, so I will keep trying to recreate a test to present.
I appreciate the tip about the nested transaction scenario - I will look into that more closely!