3

How can I fix my test Spring configuration for Atomikos JTA and Hibernate?

Exception stack trace:

2017-02-06 16:03:22.944 [TRACE] [main] [org.hibernate.service.internal.AbstractServiceRegistryImpl:224] Initializing service [role=org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform]
2017-02-06 16:03:22.953 [WARN] [main] [org.springframework.context.support.GenericApplicationContext:549] Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'hudsonTradeController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.opessoftware.platinum.oms.webservice.TradeService com.opessoftware.platinum.oms.controller.HudsonTradeController.tradeService; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'tradeServiceImpl': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.opessoftware.platinum.oms.db.OrderManagementSystemDao com.opessoftware.platinum.oms.webservice.TradeServiceImpl.orderDao; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'orderManagementSystemDaoJpa': Injection of persistence dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in com.opessoftware.platinum.oms.configuration.PersistenceConfiguration: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory
2017-02-06 16:03:22.964 [ERROR] [main] [org.springframework.test.context.TestContextManager:231] Caught exception while allowing TestExecutionListener [org.springframework.test.context.support.DependencyInjectionTestExecutionListener@a96d56c] to prepare test instance [com.opessoftware.platinum.oms.controller.CancelServiceImplTest@6ab4a5b]
java.lang.IllegalStateException: Failed to load ApplicationContext
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124)
    at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83)
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117)
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83)
    at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:228)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:230)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:289)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:291)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:249)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:89)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:193)
    at org.apache.maven.surefire.junit4.JUnit4TestSet.execute(JUnit4TestSet.java:53)
    at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:123)
    at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:104)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:164)
    at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:110)
    at org.apache.maven.surefire.booter.SurefireStarter.invokeProvider(SurefireStarter.java:175)
    at org.apache.maven.surefire.booter.SurefireStarter.runSuitesInProcessWhenForked(SurefireStarter.java:107)
    at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:68)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'hudsonTradeController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.opessoftware.platinum.oms.webservice.TradeService com.opessoftware.platinum.oms.controller.HudsonTradeController.tradeService; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'tradeServiceImpl': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.opessoftware.platinum.oms.db.OrderManagementSystemDao com.opessoftware.platinum.oms.webservice.TradeServiceImpl.orderDao; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'orderManagementSystemDaoJpa': Injection of persistence dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in com.opessoftware.platinum.oms.configuration.PersistenceConfiguration: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1219)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:551)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:778)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:843)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:541)
    at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:125)
    at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:60)
    at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.delegateLoading(AbstractDelegatingSmartContextLoader.java:109)
    at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.loadContext(AbstractDelegatingSmartContextLoader.java:261)
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98)
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116)
    ... 31 common frames omitted
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.opessoftware.platinum.oms.webservice.TradeService com.opessoftware.platinum.oms.controller.HudsonTradeController.tradeService; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'tradeServiceImpl': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.opessoftware.platinum.oms.db.OrderManagementSystemDao com.opessoftware.platinum.oms.webservice.TradeServiceImpl.orderDao; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'orderManagementSystemDaoJpa': Injection of persistence dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in com.opessoftware.platinum.oms.configuration.PersistenceConfiguration: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:573)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331)
    ... 47 common frames omitted
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'tradeServiceImpl': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.opessoftware.platinum.oms.db.OrderManagementSystemDao com.opessoftware.platinum.oms.webservice.TradeServiceImpl.orderDao; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'orderManagementSystemDaoJpa': Injection of persistence dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in com.opessoftware.platinum.oms.configuration.PersistenceConfiguration: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1219)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:551)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:1199)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1123)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1021)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:545)
    ... 49 common frames omitted
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.opessoftware.platinum.oms.db.OrderManagementSystemDao com.opessoftware.platinum.oms.webservice.TradeServiceImpl.orderDao; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'orderManagementSystemDaoJpa': Injection of persistence dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in com.opessoftware.platinum.oms.configuration.PersistenceConfiguration: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:573)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331)
    ... 60 common frames omitted
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'orderManagementSystemDaoJpa': Injection of persistence dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in com.opessoftware.platinum.oms.configuration.PersistenceConfiguration: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory
    at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.postProcessPropertyValues(PersistenceAnnotationBeanPostProcessor.java:357)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1219)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:551)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:1199)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1123)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1021)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:545)
    ... 62 common frames omitted
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in com.opessoftware.platinum.oms.configuration.PersistenceConfiguration: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1583)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
    at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.findDefaultEntityManagerFactory(PersistenceAnnotationBeanPostProcessor.java:575)
    at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.findEntityManagerFactory(PersistenceAnnotationBeanPostProcessor.java:541)
    at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor$PersistenceElement.resolveEntityManager(PersistenceAnnotationBeanPostProcessor.java:707)
    at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor$PersistenceElement.getResourceToInject(PersistenceAnnotationBeanPostProcessor.java:680)
    at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:169)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
    at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.postProcessPropertyValues(PersistenceAnnotationBeanPostProcessor.java:354)
    ... 73 common frames omitted
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.persistenceException(EntityManagerFactoryBuilderImpl.java:953)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:883)
    at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60)
    at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:340)
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:319)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1642)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1579)
    ... 86 common frames omitted
Caused by: java.lang.NullPointerException: null
    at org.hibernate.resource.transaction.backend.jta.internal.DdlTransactionIsolatorJtaImpl.<init>(DdlTransactionIsolatorJtaImpl.java:34)
    at org.hibernate.tool.schema.internal.Helper.buildDefaultDdlTransactionIsolator(Helper.java:145)
    at org.hibernate.tool.schema.internal.HibernateSchemaManagementTool.getDdlTransactionIsolator(HibernateSchemaManagementTool.java:162)
    at org.hibernate.tool.schema.internal.HibernateSchemaManagementTool.buildGenerationTargets(HibernateSchemaManagementTool.java:122)
    at org.hibernate.tool.schema.internal.SchemaDropperImpl.doDrop(SchemaDropperImpl.java:109)
    at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.performDatabaseAction(SchemaManagementToolCoordinator.java:137)
    at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.process(SchemaManagementToolCoordinator.java:65)
    at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:459)
    at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:465)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:880)
    ... 91 common frames omitted

Atomikos JTA configuration:

@Configuration
@EnableTransactionManagement
public class AtomikosJtaTransactionManagerConfiguration {

    @Autowired
    private ApplicationEnvironmentProperties applicationProperties;

    @Bean
    public UserTransaction userTransaction() throws Throwable {
        final UserTransactionImp userTransaction = new UserTransactionImp();
        userTransaction.setTransactionTimeout(1000);

        AtomikosJtaPlatform.transaction = userTransaction;

        return userTransaction;
    }

    @Bean(initMethod = "init", destroyMethod = "close")
    public TransactionManager transactionManager() throws Throwable {
        final UserTransactionManager userTransactionManager = new UserTransactionManager();
        userTransactionManager.setForceShutdown(false);

        AtomikosJtaPlatform.transactionManager = userTransactionManager;

        return userTransactionManager;
    }

    @Bean
    public PlatformTransactionManager platformTransactionManager(TransactionManager transactionManager,
            UserTransaction userTransaction) throws Throwable {
        return new JtaTransactionManager(userTransaction, transactionManager);
    }

    @Bean
    public XAConnectionFactory xaConnectionFactory(RedeliveryPolicy redeliveryPolicy) {
        final ActiveMQXAConnectionFactory xaConnectionFactory = new ActiveMQXAConnectionFactory();
        xaConnectionFactory.setBrokerURL(this.applicationProperties.getJmsBrokerUrl());
        xaConnectionFactory.setPassword(this.applicationProperties.getJmsBrokerPassword());
        xaConnectionFactory.setRedeliveryPolicy(redeliveryPolicy);
        xaConnectionFactory.setTrustAllPackages(true);
        xaConnectionFactory.setUserName(this.applicationProperties.getJmsBrokerUserName());
        return xaConnectionFactory;
    }

    @Bean(initMethod = "init", destroyMethod = "close")
    public ConnectionFactory connectionFactory(XAConnectionFactory xaConnectionFactory) {
        final AtomikosConnectionFactoryBean atomikosConnectionFactory = new AtomikosConnectionFactoryBean();
        atomikosConnectionFactory.setUniqueResourceName("xamq");
        atomikosConnectionFactory.setLocalTransactionMode(false);
        atomikosConnectionFactory.setXaConnectionFactory(xaConnectionFactory);

        final PooledConnectionFactory pooledConnectionFactory = new PooledConnectionFactory();
        pooledConnectionFactory.setMaxConnections(3);
        pooledConnectionFactory.setConnectionFactory(new CachingConnectionFactory(atomikosConnectionFactory));
        return atomikosConnectionFactory;
    }
}

public class AtomikosJtaPlatform extends AbstractJtaPlatform {

    private static final long serialVersionUID = 7364400174741027431L;

    static UserTransaction transaction;

    static TransactionManager transactionManager;

    @Override
    protected TransactionManager locateTransactionManager() {
        return transactionManager;
    }

    @Override
    protected UserTransaction locateUserTransaction() {
        return transaction;
    }
}

JPA configuration:

@Configuration
@Import({CommonConfiguration.class})
public class PersistenceConfiguration {

    @Autowired
    private ApplicationEnvironmentProperties applicationProperties;

    @Autowired
    private HibernateProperties hibernateProperties;

    @Bean
    public DataSource derbyDataSource() {
        final BasicDataSource dataSource = new BasicDataSource();
        dataSource.setDriverClassName("org.apache.derby.jdbc.EmbeddedDriver");
        dataSource.setPassword(this.applicationProperties.getJdbcConnectionPassword());
        dataSource.setUsername(this.applicationProperties.getJdbcConnectionUserName());
        dataSource.setUrl(this.applicationProperties.getJdbcConnectionUrl());
        return dataSource;
    }

    @Bean
    public AbstractEntityManagerFactoryBean entityManagerFactory(DataSource dataSource,
            JpaVendorAdapter jpaVendorAdapter) {
        final LocalContainerEntityManagerFactoryBean entityManagerFactory = new LocalContainerEntityManagerFactoryBean();
        entityManagerFactory.setDataSource(dataSource);
        entityManagerFactory.setJpaVendorAdapter(jpaVendorAdapter);
        entityManagerFactory.setPackagesToScan("com.opessoftware.platinum.model");
        entityManagerFactory.setJpaProperties(this.hibernateProperties.getProperties());
        return entityManagerFactory;
    }

    @Bean
    public JpaVendorAdapter hibernateJpaVendorAdapter() {
        final HibernateJpaVendorAdapter jpaAdapter = new HibernateJpaVendorAdapter();
        jpaAdapter.setShowSql(true);
        jpaAdapter.setGenerateDdl(true);
        return jpaAdapter;
    }

    @Bean
    public OrderManagementSystemDao orderManagementSystemDaoJpa() {
        return new OrderManagementSystemDaoJpa();
    }
}

Hibernate configuration (properties) for Atomikos:

public class AtomikosJtaHibernateConfiguration {
    @Bean
    public HibernateProperties hibernateProperties() {
        return new AtomikosJtaHibernateProperties(new DefaultHibernateProperties());
    }
}

Hibernate properties:

public class AtomikosJtaHibernateProperties implements HibernateProperties {

        private final HibernateProperties hibernateProperties;

        public AtomikosJtaHibernateProperties(HibernateProperties defaultHibernateProperties) {
            this.hibernateProperties = defaultHibernateProperties;
            this.hibernateProperties.getProperties().setProperty("hibernate.transaction.jta.platform",
                    AtomikosJtaPlatform.class.getName());
            this.hibernateProperties.getProperties().setProperty("javax.persistence.transactionType", "JTA");
            this.hibernateProperties.getProperties().setProperty("hibernate.transaction.factory_class",
                    "org.hibernate.transaction.JTATransactionFactory");
            this.hibernateProperties.getProperties().setProperty("hibernate.transaction.manager_lookup_class",
                    "com.atomikos.icatch.jta.hibernate3.TransactionManagerLookup");
        }

        @Override
        public Properties getProperties() {
            return this.hibernateProperties.getProperties();
        }
    }

public class DefaultHibernateProperties implements HibernateProperties {

    private final Properties hibernateProperties;

    public DefaultHibernateProperties() {
        this.hibernateProperties = new Properties();
        this.hibernateProperties.setProperty("hibernate.dialect", "org.hibernate.dialect.DerbyDialect");
        this.hibernateProperties.setProperty("hibernate.format_sql", "true");
        this.hibernateProperties.setProperty("hibernate.jdbc.fetch_size", "50");
        this.hibernateProperties.setProperty("hibernate.hbm2ddl.auto", "create");
    }

    @Override
    public Properties getProperties() {
        return this.hibernateProperties;
    }
}

JDBC connection properties:

jdbc.ConnectionDatabaseName=testdb
jdbc.ConnectionPassword=
jdbc.ConnectionPortNumber=0
jdbc.ConnectionServerName=memory
jdbc.ConnectionUrl=jdbc:derby:memory:testdb;create=true
jdbc.ConnectionUserName=sa

Software configuration:

  • Atomikos 4.0.4
  • Hibernate 5.1.3.Final
  • Spring 4.2.9.RELEASE
  • OpenJDK 1.8.0_121

References:

Derek Mahar
  • 27,608
  • 43
  • 124
  • 174
  • Really hard to say what's wrong, but I am pretty sure that `AtomikosJtaPlatform` should be a bean and I could not see where you create it. – Strelok Feb 07 '17 at 04:31
  • Members of `AtomikosJtaPlatform` are `public static`. – Derek Mahar Feb 07 '17 at 04:34
  • not sure how that's relevant, the line of code that's failing for you seems to be [here](https://github.com/hibernate/hibernate-orm/blob/5.1.3/hibernate-core/src/main/java/org/hibernate/resource/transaction/backend/jta/internal/DdlTransactionIsolatorJtaImpl.java#L34) and probably happens when `getService(JtaPlatform.class)` returns null. You can breakpoint on that line and know exactly which part is null. – Strelok Feb 07 '17 at 05:01
  • Comparing your code with [my working app](https://github.com/manish-in-java/spring-data-jta/blob/master/src/main/resources/springContext.xml), I find that you are using `UserTransactionImp` instead of `J2eeUserTransaction` and calling `setDataSource` instead of `setJtaDataSource` on `LocalContainerEntityManagerFactoryBean`. – manish Feb 07 '17 at 05:44
  • @manish, yes because your application must run inside a Java application container while mine is standalone Java application. – Derek Mahar Feb 07 '17 at 07:38
  • @Strelok, I see your point. Even a static class instance needs a bean instance in the application context. – Derek Mahar Feb 07 '17 at 08:05
  • @Derek, no, my sample app runs on Tomcat, which is not a full J2EE container. It can be easily converted into a fat JAR as well. Try running the app as `mvn tomcat7:run`. – manish Feb 07 '17 at 08:12
  • @manish, I followed the example in https://github.com/gn715364/spring3-jpa-jta-hibernate4-annotation/tree/5d2fcafd3400d86223971566b65e4d8a49833ce4/src/main/java/com/gn/sub/config. Granted, these examples may be incorrect, but I think I found several similar to this configuration. – Derek Mahar Feb 07 '17 at 15:35
  • @Strelok, do you see any good reason why the members of class `AtomikosJtaPlatform` must or even should be static? If they are instance variables and `AtomikosJtaPlatform` is a bean, by default, Spring should just create one instance. – Derek Mahar Feb 07 '17 at 15:52
  • @Strelok, it seems that the author of the example intended for `AtomikosJtaPlatform` to be a singleton. However, I think it's better for the Spring application context to enforce this property. – Derek Mahar Feb 07 '17 at 16:01
  • @Strelok, after setting breakpoints on the bean methods, I discovered that Spring didn't invoke *any* of the Atomikos configuration beans because there is no direct dependency between the JPA beans and the JTA beans. – Derek Mahar Feb 07 '17 at 16:40
  • @manish, according to https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/orm/jpa/LocalContainerEntityManagerFactoryBean.html#setDataSource-javax.sql.DataSource- `setDataSource` should also work with a JTA data source. – Derek Mahar Feb 08 '17 at 19:37
  • @Derek, from the linked documentation - `a DataSource passed in here will be used as "nonJtaDataSource" on the PersistenceUnitInfo` (emphasis on **nonJtaDataSource**); and, `this variant typically works for JTA transaction management as well; if it does not, consider using the explicit setJtaDataSource` (emphasis on **if it does not** - which it doesn't with most JPA providers, including Hibernate). – manish Feb 09 '17 at 03:21
  • @manish, what would happen if I were to set both `setDataSource` and `setJtaDataSource` for any data source? The idea would be to create a single `EntityManagerFactory` bean for any data source. – Derek Mahar Feb 09 '17 at 09:20
  • @Derek, please ask only one question per post. For your latest question, refer to the source code of the `LocalContainerEntityManagerFactoryBean` (available on Github). – manish Feb 09 '17 at 11:00
  • @manish, I raised question http://stackoverflow.com/questions/42140966/how-does-hibernate-behave-if-set-both-non-jta-and-jta-data-source-in-instance-of. I guess my point is that one shouldn't have to set both data source properties because this defeats the polymorphic nature of the `DataSource` interface which has multiple implementations, which should include JTA implementations. – Derek Mahar Feb 09 '17 at 15:46
  • @manish, source code for `LocalContainerEntityManagerFactoryBean` (https://github.com/spring-projects/spring-framework/blob/master/spring-orm/src/main/java/org/springframework/orm/jpa/LocalContainerEntityManagerFactoryBean.java) and `DefaultPeristenceUnitManager` (https://github.com/spring-projects/spring-framework/blob/master/spring-orm/src/main/java/org/springframework/orm/jpa/persistenceunit/DefaultPersistenceUnitManager.java) give no direct clues as to how a JPA provider behaves when an application sets both non-JTA and JTA data sources. – Derek Mahar Feb 09 '17 at 15:49
  • In any case, I have resolved the exception that I reported in my question. The problem was that Spring was not creating the Atomikos transaction manager beans because there was no direct dependency between the JPA beans and the transaction manager beans. Fixed the problem by adding a `@DependsOn` annotation for the transaction manager configuration to the JPA configuration. I'll post an answer after I get Atomikos Transaction Essentials working. – Derek Mahar Feb 09 '17 at 15:59

2 Answers2

1

After quite a bit of research and experimentation with an example project that I created called spring-jpa-atomikos-hibernate-activemq, I finally managed to configure Spring JPA, Atomikos JTA, Hibernate, and an embedded HSQLDB server. Note that in version 1.0.0, unit test PersonRepositoryAndMessengerTest introduces a TransactionTemplate that requires a PlatformTransactionManager, so the JPA configuration did not require an @DependsOn annotation for the transaction manager bean as I had stated earlier. However, I did have to add @DependsOn({"brokerService"}) in order to force Spring to create the embedded ActiveMQ broker:

@Configuration
@Import({AtomikosJtaHsqlDatabaseConfiguration.class, AtomikosJtaTransactionManagerConfiguration.class,
    CommonConfiguration.class, JpaConfiguration.class, MessageBrokerConfiguration.class, ServiceConfiguration.class,
    TransactionTemplateConfiguration.class})
@DependsOn({"brokerService"})
public class GlobalTransactionManagerConfiguration {
}

Note that the instance of EntityManagerFactory in the JPA configuration sets the non-JTA data source and not the JTA data source which confirms my suggestion (and contradicts manish's observation), at least in this case, that one can still use setDataSource instead of setJtaDataSource:

@Bean
    public AbstractEntityManagerFactoryBean entityManagerFactory(DataSource dataSource,
            JpaVendorAdapter jpaVendorAdapter) {
        final LocalContainerEntityManagerFactoryBean entityManagerFactory = new LocalContainerEntityManagerFactoryBean();
        entityManagerFactory.setDataSource(dataSource);
        entityManagerFactory.setJpaVendorAdapter(jpaVendorAdapter);
        entityManagerFactory.setPackagesToScan("me.derekmahar.example.spring.model");
        entityManagerFactory.setJpaProperties(this.hibernateProperties.getProperties());
        return entityManagerFactory;
    }

While just warnings, each unit test generates annoying TransportDisposedIOException exceptions which I do not yet know how to eliminate:

org.apache.activemq.transport.TransportDisposedIOException: peer (vm://test#3) stopped.
Community
  • 1
  • 1
Derek Mahar
  • 27,608
  • 43
  • 124
  • 174
1

This was needed for hibernate3:

this.hibernateProperties.getProperties().setProperty("hibernate.transaction.manager_lookup_class","com.atomikos.icatch.jta.hibernate3.TransactionManagerLookup");

For hibernate5 (or 4) (works for me):

this.hibernateProperties.getProperties().setProperty("hibernate.transaction.jta.platform", "AtomikosJtaPlatform"); 

From:

How to use Atomikos Transaction Essentials with Hibernate >= 4.3