JaVers + Spring Boot 3 + JTA + Atomikos

289 Views Asked by At

After upgrading an existing Java project from Spring Boot 2.7 to 3.1, everything is working except JaVers. Whenever JaVers needs to do something - like validate the schema on app startup or commit a new audit record - it throws a SQL exception saying the connection is already closed.

The versions in use are:

  • Java 17
  • Spring Boot 3.1.4
  • JaVers 7.3.3
  • Hibernate 6.2.9-Final
  • Atomikos 6.0.0

I have stepped through the code in debug mode and everything looks correct, such as:

  1. JaVers being assigned the correct JTA transaction manager.
  2. Javers receives a valid ConnectionProvider, specifically Hibernate JPA.
  3. Javers gets a PostgreSQL connection from the connection pool.

The only thing that I see that is odd is when I look at the properties of the database connection, it says closed=true, and I cannot seem to figure out why.

Update: I have created a brand new project using only Spring Boot, JaVers, and Atomikos, with a simple Controller-Service-Repository pattern and a single entity. I have also not added any custom beans, i.e. everything is default as included in the JaVers and Atomikos starters.

The results are as follows:

  1. With only JaVers enabled and not Atomikos, auditing works correctly.
  2. With only Atomikos enabled and not JaVers, transactions work correctly.
  3. With both JaVers and Atomikos enabled, the application fails to start with the following stack trace:
    org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'JaversFromStarter' defined in class path resource [org/javers/spring/boot/sql/JaversSqlAutoConfiguration.class]: [METADATA_EXTRACTION_ERROR] Failed to obtain metadata from connection.
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1770) ~[spring-beans-6.0.12.jar:6.0.12]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:598) ~[spring-beans-6.0.12.jar:6.0.12]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:520) ~[spring-beans-6.0.12.jar:6.0.12]
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:325) ~[spring-beans-6.0.12.jar:6.0.12]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.0.12.jar:6.0.12]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:323) ~[spring-beans-6.0.12.jar:6.0.12]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[spring-beans-6.0.12.jar:6.0.12]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:973) ~[spring-beans-6.0.12.jar:6.0.12]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:942) ~[spring-context-6.0.12.jar:6.0.12]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:608) ~[spring-context-6.0.12.jar:6.0.12]
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) ~[spring-boot-3.1.4.jar:3.1.4]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:737) ~[spring-boot-3.1.4.jar:3.1.4]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:439) ~[spring-boot-3.1.4.jar:3.1.4]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) ~[spring-boot-3.1.4.jar:3.1.4]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1309) ~[spring-boot-3.1.4.jar:3.1.4]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1298) ~[spring-boot-3.1.4.jar:3.1.4]
    at com.example.springjtaatomikos.SpringJtaAtomikosApplication.main(SpringJtaAtomikosApplication.java:12) ~[classes/:na]
Caused by: org.polyjdbc.core.exception.SchemaInspectionException: [METADATA_EXTRACTION_ERROR] Failed to obtain metadata from connection.
    at org.polyjdbc.core.schema.SchemaInspectorImpl.extractMetadata(SchemaInspectorImpl.java:69) ~[polyjdbc-0.7.6.jar:na]
    at org.polyjdbc.core.schema.SchemaInspectorImpl.<init>(SchemaInspectorImpl.java:60) ~[polyjdbc-0.7.6.jar:na]
    at org.polyjdbc.core.schema.SchemaInspectorImpl.<init>(SchemaInspectorImpl.java:52) ~[polyjdbc-0.7.6.jar:na]
    at org.polyjdbc.core.schema.SchemaManagerFactory.createInspector(SchemaManagerFactory.java:44) ~[polyjdbc-0.7.6.jar:na]
    at org.polyjdbc.core.DefaultPolyJDBC.schemaInspector(DefaultPolyJDBC.java:78) ~[polyjdbc-0.7.6.jar:na]
    at org.javers.repository.sql.schema.JaversSchemaManager.ensureSchema(JaversSchemaManager.java:43) ~[javers-persistence-sql-7.3.3.jar:na]
    at org.javers.repository.sql.JaversSqlRepository.ensureSchema(JaversSqlRepository.java:186) ~[javers-persistence-sql-7.3.3.jar:na]
    at org.javers.spring.jpa.JaversTransactionalJpaDecorator$1.doInTransactionWithoutResult(JaversTransactionalJpaDecorator.java:64) ~[javers-spring-jpa-7.3.3.jar:na]
    at org.springframework.transaction.support.TransactionCallbackWithoutResult.doInTransaction(TransactionCallbackWithoutResult.java:36) ~[spring-tx-6.0.12.jar:6.0.12]
    at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140) ~[spring-tx-6.0.12.jar:6.0.12]
    at org.javers.spring.jpa.JaversTransactionalJpaDecorator.ensureSchema(JaversTransactionalJpaDecorator.java:61) ~[javers-spring-jpa-7.3.3.jar:na]
    at org.javers.spring.jpa.JaversTransactionalJpaDecorator.afterPropertiesSet(JaversTransactionalJpaDecorator.java:55) ~[javers-spring-jpa-7.3.3.jar:na]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1817) ~[spring-beans-6.0.12.jar:6.0.12]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1766) ~[spring-beans-6.0.12.jar:6.0.12]
    ... 16 common frames omitted
Caused by: com.atomikos.jdbc.internal.AtomikosSQLException: Connection was already closed - calling getMetaData is no longer allowed!
    at com.atomikos.jdbc.internal.AtomikosSQLException.throwAtomikosSQLException(AtomikosSQLException.java:29) ~[transactions-jdbc-6.0.0-jakarta.jar:na]
    at com.atomikos.jdbc.internal.AtomikosSQLException.throwAtomikosSQLException(AtomikosSQLException.java:40) ~[transactions-jdbc-6.0.0-jakarta.jar:na]
    at com.atomikos.jdbc.internal.AbstractJdbcConnectionProxy.throwInvocationAfterClose(AbstractJdbcConnectionProxy.java:240) ~[transactions-jdbc-6.0.0-jakarta.jar:na]
    at com.atomikos.util.DynamicProxySupport.invoke(DynamicProxySupport.java:114) ~[atomikos-util-6.0.0.jar:na]
    at jdk.proxy2/jdk.proxy2.$Proxy72.getMetaData(Unknown Source) ~[na:na]
    at org.polyjdbc.core.schema.SchemaInspectorImpl.extractMetadata(SchemaInspectorImpl.java:66) ~[polyjdbc-0.7.6.jar:na]
    ... 29 common frames omitted

As such, I suspect it is a compatibility issue between the two dependencies - perhaps the underlying org.polyjdbc dependency that JaVers uses, which is very outdated?

0

There are 0 best solutions below