Search code examples
javaspringservicesharingtransactional

Spring - Can 2 applications use the same @Transactional service at once?


I am working on 2 Spring projects, one web app and one standalone backend service. Both use Hibernate and the same underlying database. Since both projects were using their own copies of most of the Service and Repository classes, i had a lot of duplicate code and this was becoming a nightmare to manage on my own at over 47 000 lines of code in total. I therefore decided to create a third project which i'm essentially using as a class library. It stores the entity classes, service classes and repository classes and it's added as a Maven dependency to each project. Everything worked flawlessly before i made this major change.

The web app works perfectly but the service will not start at all. This is the stack trace :

Exception in thread "Test Legacy Orders Server Init Thread" Exception in thread "Test Legacy Formulary Server Init Thread" org.springframework.transaction.CannotCreateTransactionException: Could not open Hibernate Session for transaction; nested exception is java.lang.IllegalStateException: EntityManagerFactory is closed
at org.springframework.orm.hibernate5.HibernateTransactionManager.doBegin(HibernateTransactionManager.java:564)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:378)
at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:474)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:289)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
at com.sun.proxy.$Proxy79.logInfo(Unknown Source)
at com.mdenis.mdhis_service.connectivity.HL7TestServer.start(HL7TestServer.java:69)
at com.mdenis.mdhis_service.core.MDHIS_Service$7.run(MDHIS_Service.java:311)

Caused by: java.lang.IllegalStateException: EntityManagerFactory is closed
at org.hibernate.internal.SessionFactoryImpl.validateNotClosed(SessionFactoryImpl.java:498)
at org.hibernate.internal.SessionFactoryImpl.getCache(SessionFactoryImpl.java:769)
at org.hibernate.internal.AbstractSharedSessionContract.<init>(AbstractSharedSessionContract.java:142)
at org.hibernate.internal.AbstractSessionImpl.<init>(AbstractSessionImpl.java:29)
at org.hibernate.internal.SessionImpl.<init>(SessionImpl.java:252)
at org.hibernate.internal.SessionFactoryImpl$SessionBuilderImpl.openSession(SessionFactoryImpl.java:1229)
at org.hibernate.internal.SessionFactoryImpl.openSession(SessionFactoryImpl.java:449)
at org.springframework.orm.hibernate5.HibernateTransactionManager.doBegin(HibernateTransactionManager.java:456)
... 9 more

The only thing i changed in my HibernateUtil class is this line :

sessionFactory.setPackagesToScan(new String[] {"com.mdenis.mdhis_common.entity"});

which is the new package containing the entities in the shared jar file. I know for a fact Hibernate is initializing correctly with the new settings since there are transactions going through the database successfully from this very service. One thing I am noticing is that the main thread appears to be fine. This application is heavily multithreaded and only the child threads appear to be suffering this issue.

Before my massive refactoring, each project had its own local @Transactional service class to work with and everything was working perfectly. Is what i'm doing not allowed? Is there a way to have 2 projects use the same @Transactional service?

Thanks!


Solution

  • Wow, figured this one out. The entity manager WAS closed, the main thread was erroring out due to a missing bean. I fixed that and everything is working, enough coding for today!