Add Atomikos and Bitronix JTA auto-configuration
Add auto-configuration for the Atomikos and Bitronix JTA libraries. See gh-947
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright 2012-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.jta;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.transaction.TransactionManager;
|
||||
import javax.transaction.UserTransaction;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.ApplicationHome;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.jta.XAConnectionFactoryWrapper;
|
||||
import org.springframework.boot.jta.XADataSourceWrapper;
|
||||
import org.springframework.boot.jta.atomikos.AtomikosDependsOnBeanFactoryPostProcessor;
|
||||
import org.springframework.boot.jta.atomikos.AtomikosProperties;
|
||||
import org.springframework.boot.jta.atomikos.AtomikosXAConnectionFactoryWrapper;
|
||||
import org.springframework.boot.jta.atomikos.AtomikosXADataSourceWrapper;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.jta.JtaTransactionManager;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.atomikos.icatch.config.UserTransactionService;
|
||||
import com.atomikos.icatch.config.UserTransactionServiceImp;
|
||||
import com.atomikos.icatch.jta.UserTransactionManager;
|
||||
|
||||
/**
|
||||
* JTA Configuration for <A href="http://www.atomikos.com/">Atomikos</a>.
|
||||
*
|
||||
* @author Josh Long
|
||||
* @author Phillip Webb
|
||||
* @since 1.2.0
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnClass(UserTransactionManager.class)
|
||||
@ConditionalOnMissingBean(PlatformTransactionManager.class)
|
||||
class AtomikosJtaConfiguration {
|
||||
|
||||
@Autowired
|
||||
private JtaProperties jtaProperties;
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@ConfigurationProperties(prefix = JtaProperties.PREFIX)
|
||||
public AtomikosProperties atomikosProperties() {
|
||||
return new AtomikosProperties();
|
||||
}
|
||||
|
||||
@Bean(initMethod = "init", destroyMethod = "shutdownForce")
|
||||
@ConditionalOnMissingBean
|
||||
public UserTransactionService userTransactionService(
|
||||
AtomikosProperties atomikosProperties) {
|
||||
Properties properties = new Properties();
|
||||
properties.setProperty("com.atomikos.icatch.log_base_dir", getLogBaseDir());
|
||||
properties.putAll(atomikosProperties.asProperties());
|
||||
return new UserTransactionServiceImp(properties);
|
||||
}
|
||||
|
||||
private String getLogBaseDir() {
|
||||
if (StringUtils.hasLength(this.jtaProperties.getLogDir())) {
|
||||
return this.jtaProperties.getLogDir();
|
||||
}
|
||||
File home = new ApplicationHome().getDir();
|
||||
return new File(home, "transaction-logs").getAbsolutePath();
|
||||
}
|
||||
|
||||
@Bean(initMethod = "init", destroyMethod = "close")
|
||||
@ConditionalOnMissingBean
|
||||
public UserTransactionManager atomikosTransactionManager(
|
||||
UserTransactionService userTransactionService) throws Exception {
|
||||
UserTransactionManager manager = new UserTransactionManager();
|
||||
manager.setStartupTransactionService(false);
|
||||
manager.setForceShutdown(true);
|
||||
return manager;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public XADataSourceWrapper xaDataSourceWrapper() {
|
||||
return new AtomikosXADataSourceWrapper();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public XAConnectionFactoryWrapper xaConnectionFactoryWrapper() {
|
||||
return new AtomikosXAConnectionFactoryWrapper();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public static AtomikosDependsOnBeanFactoryPostProcessor atomikosDependsOnBeanFactoryPostProcessor() {
|
||||
return new AtomikosDependsOnBeanFactoryPostProcessor();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public JtaTransactionManager transactionManager(UserTransaction userTransaction,
|
||||
TransactionManager transactionManager) {
|
||||
return new JtaTransactionManager(userTransaction, transactionManager);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright 2012-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.jta;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import javax.transaction.TransactionManager;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.ApplicationHome;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.jta.XAConnectionFactoryWrapper;
|
||||
import org.springframework.boot.jta.XADataSourceWrapper;
|
||||
import org.springframework.boot.jta.bitronix.BitronixDependentBeanFactoryPostProcessor;
|
||||
import org.springframework.boot.jta.bitronix.BitronixXAConnectionFactoryWrapper;
|
||||
import org.springframework.boot.jta.bitronix.BitronixXADataSourceWrapper;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.jta.JtaTransactionManager;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import bitronix.tm.TransactionManagerServices;
|
||||
import bitronix.tm.jndi.BitronixContext;
|
||||
|
||||
/**
|
||||
* JTA Configuration for <A href="http://docs.codehaus.org/display/BTM/Home">Bitronix</A>.
|
||||
*
|
||||
* @author Josh Long
|
||||
* @author Phillip Webb
|
||||
* @since 1.2.0
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnClass(BitronixContext.class)
|
||||
@ConditionalOnMissingBean(PlatformTransactionManager.class)
|
||||
class BitronixJtaConfiguration {
|
||||
|
||||
@Autowired
|
||||
private JtaProperties jtaProperties;
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@ConfigurationProperties(prefix = JtaProperties.PREFIX)
|
||||
public bitronix.tm.Configuration bitronixConfiguration(JtaProperties xxx) {
|
||||
bitronix.tm.Configuration config = TransactionManagerServices.getConfiguration();
|
||||
config.setServerId("spring-boot-jta-bitronix");
|
||||
File logBaseDir = getLogBaseDir();
|
||||
config.setLogPart1Filename(new File(logBaseDir, "part1.btm").getAbsolutePath());
|
||||
config.setLogPart2Filename(new File(logBaseDir, "part2.btm").getAbsolutePath());
|
||||
config.setDisableJmx(true);
|
||||
return config;
|
||||
}
|
||||
|
||||
private File getLogBaseDir() {
|
||||
if (StringUtils.hasLength(this.jtaProperties.getLogDir())) {
|
||||
return new File(this.jtaProperties.getLogDir());
|
||||
}
|
||||
File home = new ApplicationHome().getDir();
|
||||
return new File(home, "transaction-logs");
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public TransactionManager bitronixTransactionManager(
|
||||
bitronix.tm.Configuration configuration) {
|
||||
// Inject configuration to force ordering
|
||||
return TransactionManagerServices.getTransactionManager();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public XADataSourceWrapper xaDataSourceWrapper() {
|
||||
return new BitronixXADataSourceWrapper();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public XAConnectionFactoryWrapper xaConnectionFactoryWrapper() {
|
||||
return new BitronixXAConnectionFactoryWrapper();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public static BitronixDependentBeanFactoryPostProcessor atomikosDependsOnBeanFactoryPostProcessor() {
|
||||
return new BitronixDependentBeanFactoryPostProcessor();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public JtaTransactionManager transactionManager(TransactionManager transactionManager) {
|
||||
return new JtaTransactionManager(transactionManager);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2012-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.jta;
|
||||
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
/**
|
||||
* {@link EnableAutoConfiguration Auto-configuration} for JTA.
|
||||
*
|
||||
* @author Josh Long
|
||||
* @author Phillip Webb
|
||||
* @since 1.2.0
|
||||
*/
|
||||
@ConditionalOnClass(javax.transaction.Transaction.class)
|
||||
@Import({ BitronixJtaConfiguration.class, AtomikosJtaConfiguration.class })
|
||||
@EnableConfigurationProperties(JtaProperties.class)
|
||||
public class JtaAutoConfiguration {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2012-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.jta;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.transaction.jta.JtaTransactionManager;
|
||||
|
||||
/**
|
||||
* External configuration properties for a {@link JtaTransactionManager} created by
|
||||
* Spring. All {@literal spring.jta.} properties are also applied to the appropriate
|
||||
* vendor specific configuration.
|
||||
*
|
||||
* @author Josh Long
|
||||
* @author Phillip Webb
|
||||
* @since 1.2.0
|
||||
*/
|
||||
@ConfigurationProperties(prefix = JtaProperties.PREFIX, ignoreUnknownFields = true)
|
||||
public class JtaProperties {
|
||||
|
||||
public static final String PREFIX = "spring.jta";
|
||||
|
||||
private String logDir;
|
||||
|
||||
public void setLogDir(String logDir) {
|
||||
this.logDir = logDir;
|
||||
}
|
||||
|
||||
public String getLogDir() {
|
||||
return this.logDir;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -25,6 +25,7 @@ org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration,\
|
||||
org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration,\
|
||||
org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration,\
|
||||
org.springframework.boot.autoconfigure.jms.hornetq.HornetQAutoConfiguration,\
|
||||
org.springframework.boot.autoconfigure.jta.JtaAutoConfiguration,\
|
||||
org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchAutoConfiguration,\
|
||||
org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchDataAutoConfiguration,\
|
||||
org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright 2012-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.jta;
|
||||
|
||||
import javax.transaction.TransactionManager;
|
||||
import javax.transaction.UserTransaction;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.boot.jta.XAConnectionFactoryWrapper;
|
||||
import org.springframework.boot.jta.XADataSourceWrapper;
|
||||
import org.springframework.boot.jta.atomikos.AtomikosDependsOnBeanFactoryPostProcessor;
|
||||
import org.springframework.boot.jta.atomikos.AtomikosProperties;
|
||||
import org.springframework.boot.jta.bitronix.BitronixDependentBeanFactoryPostProcessor;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.jta.JtaTransactionManager;
|
||||
|
||||
import com.atomikos.icatch.config.UserTransactionService;
|
||||
import com.atomikos.icatch.jta.UserTransactionManager;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* Tests for {@link JtaAutoConfiguration}.
|
||||
*
|
||||
* @author Josh Long
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class JtaAutoConfigurationTests {
|
||||
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
private AnnotationConfigApplicationContext context;
|
||||
|
||||
@After
|
||||
public void closeContext() {
|
||||
if (this.context != null) {
|
||||
this.context.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customPatformTransactionManager() throws Exception {
|
||||
this.context = new AnnotationConfigApplicationContext(
|
||||
CustomTransactionManagerConfig.class, JtaAutoConfiguration.class);
|
||||
this.thrown.expect(NoSuchBeanDefinitionException.class);
|
||||
this.context.getBean(JtaTransactionManager.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void atomikosSanityCheck() throws Exception {
|
||||
this.context = new AnnotationConfigApplicationContext(JtaProperties.class,
|
||||
AtomikosJtaConfiguration.class);
|
||||
this.context.getBean(AtomikosProperties.class);
|
||||
this.context.getBean(UserTransactionService.class);
|
||||
this.context.getBean(UserTransactionManager.class);
|
||||
this.context.getBean(UserTransaction.class);
|
||||
this.context.getBean(XADataSourceWrapper.class);
|
||||
this.context.getBean(XAConnectionFactoryWrapper.class);
|
||||
this.context.getBean(AtomikosDependsOnBeanFactoryPostProcessor.class);
|
||||
this.context.getBean(JtaTransactionManager.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bitronixSanityCheck() throws Exception {
|
||||
this.context = new AnnotationConfigApplicationContext(JtaProperties.class,
|
||||
BitronixJtaConfiguration.class);
|
||||
this.context.getBean(bitronix.tm.Configuration.class);
|
||||
this.context.getBean(TransactionManager.class);
|
||||
this.context.getBean(XADataSourceWrapper.class);
|
||||
this.context.getBean(XAConnectionFactoryWrapper.class);
|
||||
this.context.getBean(BitronixDependentBeanFactoryPostProcessor.class);
|
||||
this.context.getBean(JtaTransactionManager.class);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
public static class CustomTransactionManagerConfig {
|
||||
|
||||
@Bean
|
||||
public PlatformTransactionManager transactionManager() {
|
||||
return mock(PlatformTransactionManager.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -17,11 +17,12 @@
|
||||
package org.springframework.boot.autoconfigure.orm.jpa;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform;
|
||||
import org.junit.After;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
@@ -228,8 +229,10 @@ public abstract class AbstractJpaAutoConfigurationTests {
|
||||
factoryBean.setJpaVendorAdapter(adapter);
|
||||
factoryBean.setDataSource(dataSource);
|
||||
factoryBean.setPersistenceUnitName("manually-configured");
|
||||
factoryBean.setJpaPropertyMap(Collections.singletonMap("configured",
|
||||
"manually"));
|
||||
Map<String, Object> properties = new HashMap<String, Object>();
|
||||
properties.put("configured", "manually");
|
||||
properties.put("hibernate.transaction.jta.platform", NoJtaPlatform.INSTANCE);
|
||||
factoryBean.setJpaPropertyMap(properties);
|
||||
return factoryBean;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user