diff --git a/spring-boot-project/spring-boot-autoconfigure/build.gradle b/spring-boot-project/spring-boot-autoconfigure/build.gradle index fe176b12d48..0c84af5666d 100644 --- a/spring-boot-project/spring-boot-autoconfigure/build.gradle +++ b/spring-boot-project/spring-boot-autoconfigure/build.gradle @@ -12,8 +12,6 @@ description = "Spring Boot AutoConfigure" dependencies { api(project(":spring-boot-project:spring-boot")) - optional("com.atomikos:transactions-jdbc") - optional("com.atomikos:transactions-jta") optional("com.fasterxml.jackson.core:jackson-databind") optional("com.fasterxml.jackson.dataformat:jackson-dataformat-cbor") optional("com.fasterxml.jackson.dataformat:jackson-dataformat-xml") @@ -94,6 +92,7 @@ dependencies { optional("org.aspectj:aspectjweaver") optional("org.eclipse.jetty:jetty-webapp") { exclude group: "javax.servlet", module: "javax.servlet-api" + exclude(group: "org.eclipse.jetty", module: "jetty-jndi") } optional("org.eclipse.jetty:jetty-reactive-httpclient") optional("org.eclipse.jetty.websocket:javax-websocket-server-impl") { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/transaction/jta/AtomikosJtaConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/transaction/jta/AtomikosJtaConfiguration.java deleted file mode 100644 index 393494c0a23..00000000000 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/transaction/jta/AtomikosJtaConfiguration.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright 2012-2020 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 - * - * https://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.transaction.jta; - -import java.io.File; -import java.util.Properties; - -import javax.jms.Message; -import javax.transaction.TransactionManager; -import javax.transaction.UserTransaction; - -import com.atomikos.icatch.config.UserTransactionService; -import com.atomikos.icatch.config.UserTransactionServiceImp; -import com.atomikos.icatch.jta.UserTransactionManager; - -import org.springframework.beans.factory.ObjectProvider; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.autoconfigure.transaction.TransactionManagerCustomizers; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.boot.jdbc.XADataSourceWrapper; -import org.springframework.boot.jms.XAConnectionFactoryWrapper; -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.boot.system.ApplicationHome; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.transaction.jta.JtaTransactionManager; -import org.springframework.util.StringUtils; - -/** - * JTA Configuration for Atomikos. - * - * @author Josh Long - * @author Phillip Webb - * @author Andy Wilkinson - * @author Stephane Nicoll - * @author Kazuki Shimizu - */ -@Configuration(proxyBeanMethods = false) -@EnableConfigurationProperties({ AtomikosProperties.class, JtaProperties.class }) -@ConditionalOnClass({ JtaTransactionManager.class, UserTransactionManager.class }) -@ConditionalOnMissingBean(org.springframework.transaction.TransactionManager.class) -class AtomikosJtaConfiguration { - - @Bean(initMethod = "init", destroyMethod = "shutdownWait") - @ConditionalOnMissingBean(UserTransactionService.class) - UserTransactionServiceImp userTransactionService(AtomikosProperties atomikosProperties, - JtaProperties jtaProperties) { - Properties properties = new Properties(); - if (StringUtils.hasText(jtaProperties.getTransactionManagerId())) { - properties.setProperty("com.atomikos.icatch.tm_unique_name", jtaProperties.getTransactionManagerId()); - } - properties.setProperty("com.atomikos.icatch.log_base_dir", getLogBaseDir(jtaProperties)); - properties.putAll(atomikosProperties.asProperties()); - return new UserTransactionServiceImp(properties); - } - - private String getLogBaseDir(JtaProperties jtaProperties) { - if (StringUtils.hasLength(jtaProperties.getLogDir())) { - return jtaProperties.getLogDir(); - } - File home = new ApplicationHome().getDir(); - return new File(home, "transaction-logs").getAbsolutePath(); - } - - @Bean(initMethod = "init", destroyMethod = "close") - @ConditionalOnMissingBean(TransactionManager.class) - UserTransactionManager atomikosTransactionManager(UserTransactionService userTransactionService) throws Exception { - UserTransactionManager manager = new UserTransactionManager(); - manager.setStartupTransactionService(false); - manager.setForceShutdown(true); - return manager; - } - - @Bean - @ConditionalOnMissingBean(XADataSourceWrapper.class) - AtomikosXADataSourceWrapper xaDataSourceWrapper() { - return new AtomikosXADataSourceWrapper(); - } - - @Bean - @ConditionalOnMissingBean - static AtomikosDependsOnBeanFactoryPostProcessor atomikosDependsOnBeanFactoryPostProcessor() { - return new AtomikosDependsOnBeanFactoryPostProcessor(); - } - - @Bean - JtaTransactionManager transactionManager(UserTransaction userTransaction, TransactionManager transactionManager, - ObjectProvider transactionManagerCustomizers) { - JtaTransactionManager jtaTransactionManager = new JtaTransactionManager(userTransaction, transactionManager); - transactionManagerCustomizers.ifAvailable((customizers) -> customizers.customize(jtaTransactionManager)); - return jtaTransactionManager; - } - - @Configuration(proxyBeanMethods = false) - @ConditionalOnClass(Message.class) - static class AtomikosJtaJmsConfiguration { - - @Bean - @ConditionalOnMissingBean(XAConnectionFactoryWrapper.class) - AtomikosXAConnectionFactoryWrapper xaConnectionFactoryWrapper() { - return new AtomikosXAConnectionFactoryWrapper(); - } - - } - -} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/transaction/jta/JtaAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/transaction/jta/JtaAutoConfiguration.java index f4d62b49318..fadeabbd218 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/transaction/jta/JtaAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/transaction/jta/JtaAutoConfiguration.java @@ -40,7 +40,7 @@ import org.springframework.context.annotation.Import; @ConditionalOnProperty(prefix = "spring.jta", value = "enabled", matchIfMissing = true) @AutoConfigureBefore({ XADataSourceAutoConfiguration.class, ActiveMQAutoConfiguration.class, ArtemisAutoConfiguration.class, HibernateJpaAutoConfiguration.class }) -@Import({ JndiJtaConfiguration.class, AtomikosJtaConfiguration.class }) +@Import(JndiJtaConfiguration.class) public class JtaAutoConfiguration { } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/transaction/jta/JtaProperties.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/transaction/jta/JtaProperties.java deleted file mode 100644 index 0d8bc426126..00000000000 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/transaction/jta/JtaProperties.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2012-2019 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 - * - * https://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.transaction.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 - * @author Andy Wilkinson - * @since 1.2.0 - */ -@ConfigurationProperties(prefix = "spring.jta", ignoreUnknownFields = true) -public class JtaProperties { - - /** - * Transaction logs directory. - */ - private String logDir; - - /** - * Transaction manager unique identifier. - */ - private String transactionManagerId; - - public void setLogDir(String logDir) { - this.logDir = logDir; - } - - public String getLogDir() { - return this.logDir; - } - - public String getTransactionManagerId() { - return this.transactionManagerId; - } - - public void setTransactionManagerId(String transactionManagerId) { - this.transactionManagerId = transactionManagerId; - } - -} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfigurationTests.java index b526445c783..159327068a9 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfigurationTests.java @@ -75,6 +75,7 @@ import org.springframework.orm.jpa.JpaVendorAdapter; import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; +import org.springframework.transaction.jta.JtaTransactionManager; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatNoException; @@ -214,7 +215,7 @@ class HibernateJpaAutoConfigurationTests extends AbstractJpaAutoConfigurationTes @Test void jtaDefaultPlatform() { - contextRunner().withConfiguration(AutoConfigurations.of(JtaAutoConfiguration.class)) + contextRunner().withUserConfiguration(JtaTransactionManagerConfiguration.class) .run(assertJtaPlatform(SpringJtaPlatform.class)); } @@ -298,7 +299,7 @@ class HibernateJpaAutoConfigurationTests extends AbstractJpaAutoConfigurationTes @Test void providerDisablesAutoCommitIsNotConfiguredWithJta() { - contextRunner().withConfiguration(AutoConfigurations.of(JtaAutoConfiguration.class)) + contextRunner().withUserConfiguration(JtaTransactionManagerConfiguration.class) .withPropertyValues("spring.datasource.type:" + HikariDataSource.class.getName(), "spring.datasource.hikari.auto-commit:false") .run((context) -> { @@ -677,4 +678,17 @@ class HibernateJpaAutoConfigurationTests extends AbstractJpaAutoConfigurationTes } + @Configuration(proxyBeanMethods = false) + static class JtaTransactionManagerConfiguration { + + @Bean + JtaTransactionManager jtaTransactionManager() { + JtaTransactionManager jtaTransactionManager = new JtaTransactionManager(); + jtaTransactionManager.setUserTransaction(mock(UserTransaction.class)); + jtaTransactionManager.setTransactionManager(mock(TransactionManager.class)); + return jtaTransactionManager; + } + + } + } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/transaction/jta/JtaAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/transaction/jta/JtaAutoConfigurationTests.java index f25bcdcf70b..32b55b67f0b 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/transaction/jta/JtaAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/transaction/jta/JtaAutoConfigurationTests.java @@ -16,29 +16,16 @@ package org.springframework.boot.autoconfigure.transaction.jta; -import java.io.File; -import java.nio.file.Path; import java.util.Arrays; import java.util.List; import java.util.Properties; -import javax.jms.ConnectionFactory; -import javax.jms.TemporaryQueue; -import javax.jms.XAConnection; -import javax.jms.XAConnectionFactory; -import javax.jms.XASession; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; -import javax.sql.DataSource; -import javax.sql.XADataSource; import javax.transaction.TransactionManager; import javax.transaction.UserTransaction; -import javax.transaction.xa.XAResource; -import com.atomikos.icatch.config.UserTransactionService; -import com.atomikos.icatch.jta.UserTransactionManager; -import com.atomikos.jms.AtomikosConnectionFactoryBean; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.AfterEachCallback; @@ -49,21 +36,13 @@ import org.junit.jupiter.api.extension.ExtensionContext.Namespace; import org.junit.jupiter.api.extension.ParameterContext; import org.junit.jupiter.api.extension.ParameterResolutionException; import org.junit.jupiter.api.extension.ParameterResolver; -import org.junit.jupiter.api.io.TempDir; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import org.osjava.sj.loader.JndiLoader; import org.springframework.beans.factory.NoSuchBeanDefinitionException; -import org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration; -import org.springframework.boot.jdbc.XADataSourceWrapper; -import org.springframework.boot.jms.XAConnectionFactoryWrapper; -import org.springframework.boot.jta.atomikos.AtomikosDataSourceBean; -import org.springframework.boot.jta.atomikos.AtomikosDependsOnBeanFactoryPostProcessor; -import org.springframework.boot.jta.atomikos.AtomikosProperties; import org.springframework.boot.test.util.TestPropertyValues; -import org.springframework.boot.testsupport.BuildOutput; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -72,7 +51,6 @@ import org.springframework.transaction.jta.UserTransactionAdapter; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; -import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.mock; /** @@ -86,9 +64,6 @@ import static org.mockito.Mockito.mock; */ class JtaAutoConfigurationTests { - private final File atomikosLogs = new File(new BuildOutput(JtaAutoConfigurationTests.class).getRootLocation(), - "atomikos-logs"); - private AnnotationConfigApplicationContext context; @AfterEach @@ -132,81 +107,14 @@ class JtaAutoConfigurationTests { } @Test - void disableJtaSupport() { + @ExtendWith(JndiExtension.class) + void disableJtaSupport(InitialContext initialContext) throws NamingException { + new JndiEntry("java:comp/UserTransaction", UserTransaction.class).register(initialContext); this.context = new AnnotationConfigApplicationContext(); TestPropertyValues.of("spring.jta.enabled:false").applyTo(this.context); this.context.register(JtaAutoConfiguration.class); this.context.refresh(); assertThat(this.context.getBeansOfType(JtaTransactionManager.class)).isEmpty(); - assertThat(this.context.getBeansOfType(XADataSourceWrapper.class)).isEmpty(); - assertThat(this.context.getBeansOfType(XAConnectionFactoryWrapper.class)).isEmpty(); - } - - @Test - void atomikosSanityCheck() { - this.context = new AnnotationConfigApplicationContext(); - TestPropertyValues.of("spring.jta.log-dir:" + this.atomikosLogs).applyTo(this.context); - this.context.register(JtaProperties.class, AtomikosJtaConfiguration.class); - this.context.refresh(); - 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 - void defaultAtomikosTransactionManagerName(@TempDir Path dir) { - this.context = new AnnotationConfigApplicationContext(); - File logs = new File(dir.toFile(), "jta"); - TestPropertyValues.of("spring.jta.logDir:" + logs.getAbsolutePath()).applyTo(this.context); - this.context.register(AtomikosJtaConfiguration.class); - this.context.refresh(); - - File epochFile = new File(logs, "tmlog0.log"); - assertThat(epochFile.isFile()).isTrue(); - } - - @Test - void atomikosConnectionFactoryPoolConfiguration() { - this.context = new AnnotationConfigApplicationContext(); - TestPropertyValues.of("spring.jta.atomikos.connectionfactory.minPoolSize:5", - "spring.jta.atomikos.connectionfactory.maxPoolSize:10", "spring.jta.log-dir:" + this.atomikosLogs) - .applyTo(this.context); - this.context.register(AtomikosJtaConfiguration.class, PoolConfiguration.class); - this.context.refresh(); - AtomikosConnectionFactoryBean connectionFactory = this.context.getBean(AtomikosConnectionFactoryBean.class); - assertThat(connectionFactory.getMinPoolSize()).isEqualTo(5); - assertThat(connectionFactory.getMaxPoolSize()).isEqualTo(10); - } - - @Test - void atomikosDataSourcePoolConfiguration() { - this.context = new AnnotationConfigApplicationContext(); - TestPropertyValues.of("spring.jta.atomikos.datasource.minPoolSize:5", - "spring.jta.atomikos.datasource.maxPoolSize:10", "spring.jta.log-dir:" + this.atomikosLogs) - .applyTo(this.context); - this.context.register(AtomikosJtaConfiguration.class, PoolConfiguration.class); - this.context.refresh(); - AtomikosDataSourceBean dataSource = this.context.getBean(AtomikosDataSourceBean.class); - assertThat(dataSource.getMinPoolSize()).isEqualTo(5); - assertThat(dataSource.getMaxPoolSize()).isEqualTo(10); - } - - @Test - void atomikosCustomizeJtaTransactionManagerUsingProperties() { - this.context = new AnnotationConfigApplicationContext(); - TestPropertyValues.of("spring.transaction.default-timeout:30", - "spring.transaction.rollback-on-commit-failure:true", "spring.jta.log-dir:" + this.atomikosLogs) - .applyTo(this.context); - this.context.register(AtomikosJtaConfiguration.class, TransactionAutoConfiguration.class); - this.context.refresh(); - JtaTransactionManager transactionManager = this.context.getBean(JtaTransactionManager.class); - assertThat(transactionManager.getDefaultTimeout()).isEqualTo(30); - assertThat(transactionManager.isRollbackOnCommitFailure()).isTrue(); } @Configuration(proxyBeanMethods = false) @@ -219,31 +127,6 @@ class JtaAutoConfigurationTests { } - @Configuration(proxyBeanMethods = false) - static class PoolConfiguration { - - @Bean - ConnectionFactory pooledConnectionFactory(XAConnectionFactoryWrapper wrapper) throws Exception { - XAConnectionFactory connectionFactory = mock(XAConnectionFactory.class); - XAConnection connection = mock(XAConnection.class); - XASession session = mock(XASession.class); - TemporaryQueue queue = mock(TemporaryQueue.class); - XAResource resource = mock(XAResource.class); - given(connectionFactory.createXAConnection()).willReturn(connection); - given(connection.createXASession()).willReturn(session); - given(session.createTemporaryQueue()).willReturn(queue); - given(session.getXAResource()).willReturn(resource); - return wrapper.wrapConnectionFactory(connectionFactory); - } - - @Bean - DataSource pooledDataSource(XADataSourceWrapper wrapper) throws Exception { - XADataSource dataSource = mock(XADataSource.class); - return wrapper.wrapDataSource(dataSource); - } - - } - private static final class JndiEntry { private final String name; diff --git a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/anchor-rewrite.properties b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/anchor-rewrite.properties index f161d4ac33d..d91405888ca 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/anchor-rewrite.properties +++ b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/anchor-rewrite.properties @@ -793,10 +793,9 @@ features.caching.provider.caffeine=io.caching.provider.caffeine features.caching.provider.simple=io.caching.provider.simple features.caching.provider.none=io.caching.provider.none features.jta=io.jta -features.jta.atomikos=io.jta.atomikos -features.jta.javaee=io.jta.javaee +features.jta.javaee=io.jta.jakartaee features.jta.mixing-xa-and-non-xa-connections=io.jta.mixing-xa-and-non-xa-connections -features.jta.supporting-alternative-embedded-transaction-manager=io.jta.supporting-alternative-embedded-transaction-manager +features.jta.supporting-alternative-embedded-transaction-manager=io.jta.supporting-embedded-transaction-manager features.email=io.email features.quartz=io.quartz features.resttemplate=io.rest-client.resttemplate diff --git a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/io/jta.adoc b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/io/jta.adoc index 29cdc2779d7..0286712262e 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/io/jta.adoc +++ b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/io/jta.adoc @@ -1,7 +1,6 @@ [[io.jta]] == Distributed Transactions with JTA -Spring Boot supports distributed JTA transactions across multiple XA resources by using an https://www.atomikos.com/[Atomikos] embedded transaction manager. -JTA transactions are also supported when deploying to a suitable Java EE Application Server. +Spring Boot supports distributed JTA transactions across multiple XA resources by using a transaction manager retrieved from JNDI. When a JTA environment is detected, Spring's `JtaTransactionManager` is used to manage transactions. Auto-configured JMS, DataSource, and JPA beans are upgraded to support XA transactions. @@ -10,28 +9,11 @@ If you are within a JTA environment and still want to use local transactions, yo -[[io.jta.atomikos]] -=== Using an Atomikos Transaction Manager -https://www.atomikos.com/[Atomikos] is a popular open source transaction manager which can be embedded into your Spring Boot application. -You can use the `spring-boot-starter-jta-atomikos` starter to pull in the appropriate Atomikos libraries. -Spring Boot auto-configures Atomikos and ensures that appropriate `depends-on` settings are applied to your Spring beans for correct startup and shutdown ordering. - -By default, Atomikos transaction logs are written to a `transaction-logs` directory in your application's home directory (the directory in which your application jar file resides). -You can customize the location of this directory by setting a configprop:spring.jta.log-dir[] property in your `application.properties` file. -Properties starting with `spring.jta.atomikos.properties` can also be used to customize the Atomikos `UserTransactionServiceImp`. -See the {spring-boot-module-api}/jta/atomikos/AtomikosProperties.html[`AtomikosProperties` Javadoc] for complete details. - -NOTE: To ensure that multiple transaction managers can safely coordinate the same resource managers, each Atomikos instance must be configured with a unique ID. -By default, this ID is the IP address of the machine on which Atomikos is running. -To ensure uniqueness in production, you should configure the configprop:spring.jta.transaction-manager-id[] property with a different value for each instance of your application. - - - -[[io.jta.javaee]] -=== Using a Java EE Managed Transaction Manager -If you package your Spring Boot application as a `war` or `ear` file and deploy it to a Java EE application server, you can use your application server's built-in transaction manager. +[[io.jta.jakartaee]] +=== Using a Jakarta EE Managed Transaction Manager +If you package your Spring Boot application as a `war` or `ear` file and deploy it to a Jakarta EE application server, you can use your application server's built-in transaction manager. Spring Boot tries to auto-configure a transaction manager by looking at common JNDI locations (`java:comp/UserTransaction`, `java:comp/TransactionManager`, and so on). -If you use a transaction service provided by your application server, you generally also want to ensure that all resources are managed by the server and exposed over JNDI. +When using a transaction service provided by your application server, you generally also want to ensure that all resources are managed by the server and exposed over JNDI. Spring Boot tries to auto-configure JMS by looking for a `ConnectionFactory` at the JNDI path (`java:/JmsXA` or `java:/XAConnectionFactory`), and you can use the <> to configure your `DataSource`. @@ -65,10 +47,8 @@ include::{docs-java}/io/jta/mixingxaandnonxaconnections/xa/MyBean.java[tag=*] -[[io.jta.supporting-alternative-embedded-transaction-manager]] -=== Supporting an Alternative Embedded Transaction Manager -The {spring-boot-module-code}/jms/XAConnectionFactoryWrapper.java[`XAConnectionFactoryWrapper`] and {spring-boot-module-code}/jdbc/XADataSourceWrapper.java[`XADataSourceWrapper`] interfaces can be used to support alternative embedded transaction managers. +[[io.jta.supporting-embedded-transaction-manager]] +=== Supporting an Embedded Transaction Manager +The {spring-boot-module-code}/jms/XAConnectionFactoryWrapper.java[`XAConnectionFactoryWrapper`] and {spring-boot-module-code}/jdbc/XADataSourceWrapper.java[`XADataSourceWrapper`] interfaces can be used to support embedded transaction managers. The interfaces are responsible for wrapping `XAConnectionFactory` and `XADataSource` beans and exposing them as regular `ConnectionFactory` and `DataSource` beans, which transparently enroll in the distributed transaction. DataSource and JMS auto-configuration use JTA variants, provided you have a `JtaTransactionManager` bean and appropriate XA wrapper beans registered within your `ApplicationContext`. - -The {spring-boot-module-code}/jta/atomikos/AtomikosXAConnectionFactoryWrapper.java[AtomikosXAConnectionFactoryWrapper] and {spring-boot-module-code}/jta/atomikos/AtomikosXADataSourceWrapper.java[AtomikosXADataSourceWrapper] provide good examples of how to write XA wrappers. diff --git a/spring-boot-project/spring-boot-starters/spring-boot-starter-jta-atomikos/build.gradle b/spring-boot-project/spring-boot-starters/spring-boot-starter-jta-atomikos/build.gradle deleted file mode 100644 index cc9c208b503..00000000000 --- a/spring-boot-project/spring-boot-starters/spring-boot-starter-jta-atomikos/build.gradle +++ /dev/null @@ -1,13 +0,0 @@ -plugins { - id "org.springframework.boot.starter" -} - -description = "Starter for JTA transactions using Atomikos" - -dependencies { - api(project(":spring-boot-project:spring-boot-starters:spring-boot-starter")) - api("com.atomikos:transactions-jms") - api("com.atomikos:transactions-jta") - api("com.atomikos:transactions-jdbc") - api("jakarta.transaction:jakarta.transaction-api") -} diff --git a/spring-boot-project/spring-boot/build.gradle b/spring-boot-project/spring-boot/build.gradle index 05dcde61228..9d6750e254b 100644 --- a/spring-boot-project/spring-boot/build.gradle +++ b/spring-boot-project/spring-boot/build.gradle @@ -22,9 +22,6 @@ dependencies { api("org.springframework:spring-context") optional("ch.qos.logback:logback-classic") - optional("com.atomikos:transactions-jdbc") - optional("com.atomikos:transactions-jms") - optional("com.atomikos:transactions-jta") optional("com.fasterxml.jackson.core:jackson-databind") optional("com.h2database:h2") optional("com.google.code.gson:gson") diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jta/atomikos/AtomikosConnectionFactoryBean.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jta/atomikos/AtomikosConnectionFactoryBean.java deleted file mode 100644 index 829f80687f0..00000000000 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jta/atomikos/AtomikosConnectionFactoryBean.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2012-2019 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 - * - * https://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.jta.atomikos; - -import org.springframework.beans.factory.BeanNameAware; -import org.springframework.beans.factory.DisposableBean; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.util.StringUtils; - -/** - * Spring friendly version of {@link com.atomikos.jms.AtomikosConnectionFactoryBean}. - * - * @author Phillip Webb - * @author Andy Wilkinson - * @since 1.2.0 - */ -@SuppressWarnings("serial") -@ConfigurationProperties(prefix = "spring.jta.atomikos.connectionfactory") -public class AtomikosConnectionFactoryBean extends com.atomikos.jms.AtomikosConnectionFactoryBean - implements BeanNameAware, InitializingBean, DisposableBean { - - private String beanName; - - @Override - public void setBeanName(String name) { - this.beanName = name; - } - - @Override - public void afterPropertiesSet() throws Exception { - if (!StringUtils.hasLength(getUniqueResourceName())) { - setUniqueResourceName(this.beanName); - } - init(); - } - - @Override - public void destroy() throws Exception { - close(); - } - -} diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jta/atomikos/AtomikosDataSourceBean.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jta/atomikos/AtomikosDataSourceBean.java deleted file mode 100644 index ca483c0bb38..00000000000 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jta/atomikos/AtomikosDataSourceBean.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2012-2019 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 - * - * https://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.jta.atomikos; - -import org.springframework.beans.factory.BeanNameAware; -import org.springframework.beans.factory.DisposableBean; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.util.StringUtils; - -/** - * Spring friendly version of {@link com.atomikos.jdbc.AtomikosDataSourceBean}. - * - * @author Phillip Webb - * @author Andy Wilkinson - * @since 1.2.0 - */ -@SuppressWarnings("serial") -@ConfigurationProperties(prefix = "spring.jta.atomikos.datasource") -public class AtomikosDataSourceBean extends com.atomikos.jdbc.AtomikosDataSourceBean - implements BeanNameAware, InitializingBean, DisposableBean { - - private String beanName; - - @Override - public void setBeanName(String name) { - this.beanName = name; - } - - @Override - public void afterPropertiesSet() throws Exception { - if (!StringUtils.hasLength(getUniqueResourceName())) { - setUniqueResourceName(this.beanName); - } - init(); - } - - @Override - public void destroy() throws Exception { - close(); - } - -} diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jta/atomikos/AtomikosDependsOnBeanFactoryPostProcessor.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jta/atomikos/AtomikosDependsOnBeanFactoryPostProcessor.java deleted file mode 100644 index 996b50c1ba6..00000000000 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jta/atomikos/AtomikosDependsOnBeanFactoryPostProcessor.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright 2012-2019 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 - * - * https://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.jta.atomikos; - -import java.util.Arrays; -import java.util.Collections; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Set; - -import com.atomikos.icatch.jta.UserTransactionManager; - -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.config.BeanDefinition; -import org.springframework.beans.factory.config.BeanFactoryPostProcessor; -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.core.Ordered; -import org.springframework.util.StringUtils; - -/** - * {@link BeanFactoryPostProcessor} to automatically setup the recommended - * {@link BeanDefinition#setDependsOn(String[]) dependsOn} settings for - * correct Atomikos - * ordering. - * - * @author Phillip Webb - * @since 1.2.0 - */ -public class AtomikosDependsOnBeanFactoryPostProcessor implements BeanFactoryPostProcessor, Ordered { - - private static final String[] NO_BEANS = {}; - - private int order = Ordered.LOWEST_PRECEDENCE; - - @Override - public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { - String[] transactionManagers = beanFactory.getBeanNamesForType(UserTransactionManager.class, true, false); - for (String transactionManager : transactionManagers) { - addTransactionManagerDependencies(beanFactory, transactionManager); - } - addMessageDrivenContainerDependencies(beanFactory, transactionManagers); - } - - private void addTransactionManagerDependencies(ConfigurableListableBeanFactory beanFactory, - String transactionManager) { - BeanDefinition bean = beanFactory.getBeanDefinition(transactionManager); - Set dependsOn = new LinkedHashSet<>(asList(bean.getDependsOn())); - int initialSize = dependsOn.size(); - addDependencies(beanFactory, "javax.jms.ConnectionFactory", dependsOn); - addDependencies(beanFactory, "javax.sql.DataSource", dependsOn); - if (dependsOn.size() != initialSize) { - bean.setDependsOn(StringUtils.toStringArray(dependsOn)); - } - } - - private void addMessageDrivenContainerDependencies(ConfigurableListableBeanFactory beanFactory, - String[] transactionManagers) { - String[] messageDrivenContainers = getBeanNamesForType(beanFactory, - "com.atomikos.jms.extra.MessageDrivenContainer"); - for (String messageDrivenContainer : messageDrivenContainers) { - BeanDefinition bean = beanFactory.getBeanDefinition(messageDrivenContainer); - Set dependsOn = new LinkedHashSet<>(asList(bean.getDependsOn())); - dependsOn.addAll(asList(transactionManagers)); - bean.setDependsOn(StringUtils.toStringArray(dependsOn)); - } - } - - private void addDependencies(ConfigurableListableBeanFactory beanFactory, String type, Set dependsOn) { - dependsOn.addAll(asList(getBeanNamesForType(beanFactory, type))); - } - - private String[] getBeanNamesForType(ConfigurableListableBeanFactory beanFactory, String type) { - try { - return beanFactory.getBeanNamesForType(Class.forName(type), true, false); - } - catch (ClassNotFoundException | NoClassDefFoundError ex) { - // Ignore - } - return NO_BEANS; - } - - private List asList(String[] array) { - return (array != null) ? Arrays.asList(array) : Collections.emptyList(); - } - - @Override - public int getOrder() { - return this.order; - } - - public void setOrder(int order) { - this.order = order; - } - -} diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jta/atomikos/AtomikosProperties.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jta/atomikos/AtomikosProperties.java deleted file mode 100644 index 82189beba53..00000000000 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jta/atomikos/AtomikosProperties.java +++ /dev/null @@ -1,425 +0,0 @@ -/* - * Copyright 2012-2019 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 - * - * https://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.jta.atomikos; - -import java.time.Duration; -import java.util.Properties; - -import org.springframework.boot.context.properties.ConfigurationProperties; - -/** - * Bean friendly variant of - * Atomikos configuration - * properties. Allows for setter based configuration and is amiable to relaxed data - * binding. - * - * @author Phillip Webb - * @author Stephane Nicoll - * @since 1.2.0 - * @see #asProperties() - */ -@ConfigurationProperties(prefix = "spring.jta.atomikos.properties") -public class AtomikosProperties { - - /** - * Transaction manager implementation that should be started. - */ - private String service; - - /** - * Maximum timeout that can be allowed for transactions. - */ - private Duration maxTimeout = Duration.ofMillis(300000); - - /** - * Default timeout for JTA transactions. - */ - private Duration defaultJtaTimeout = Duration.ofMillis(10000); - - /** - * Maximum number of active transactions. - */ - private int maxActives = 50; - - /** - * Whether to enable disk logging. - */ - private boolean enableLogging = true; - - /** - * The transaction manager's unique name. Defaults to the machine's IP address. If you - * plan to run more than one transaction manager against one database you must set - * this property to a unique value. - */ - private String transactionManagerUniqueName; - - /** - * Whether sub-transactions should be joined when possible. - */ - private boolean serialJtaTransactions = true; - - /** - * Specify whether sub-transactions are allowed. - */ - private boolean allowSubTransactions = true; - - /** - * Whether a VM shutdown should trigger forced shutdown of the transaction core. - */ - private boolean forceShutdownOnVmExit; - - /** - * How long should normal shutdown (no-force) wait for transactions to complete. - */ - private long defaultMaxWaitTimeOnShutdown = Long.MAX_VALUE; - - /** - * Transactions log file base name. - */ - private String logBaseName = "tmlog"; - - /** - * Directory in which the log files should be stored. Defaults to the current working - * directory. - */ - private String logBaseDir; - - /** - * Interval between checkpoints, expressed as the number of log writes between two - * checkpoints. A checkpoint reduces the log file size at the expense of adding some - * overhead in the runtime. - */ - private long checkpointInterval = 500; - - /** - * Whether to use different (and concurrent) threads for two-phase commit on the - * participating resources. - */ - private boolean threadedTwoPhaseCommit; - - private final Recovery recovery = new Recovery(); - - /** - * Specifies the transaction manager implementation that should be started. There is - * no default value and this must be set. Generally, - * {@literal com.atomikos.icatch.standalone.UserTransactionServiceFactory} is the - * value you should set. - * @param service the service - */ - public void setService(String service) { - this.service = service; - } - - public String getService() { - return this.service; - } - - /** - * Specifies the maximum timeout that can be allowed for transactions. Defaults to - * {@literal 300000}. This means that calls to UserTransaction.setTransactionTimeout() - * with a value higher than configured here will be max'ed to this value. - * @param maxTimeout the max timeout - */ - public void setMaxTimeout(Duration maxTimeout) { - this.maxTimeout = maxTimeout; - } - - public Duration getMaxTimeout() { - return this.maxTimeout; - } - - /** - * The default timeout for JTA transactions (optional, defaults to {@literal 10000} - * ms). - * @param defaultJtaTimeout the default JTA timeout - */ - public void setDefaultJtaTimeout(Duration defaultJtaTimeout) { - this.defaultJtaTimeout = defaultJtaTimeout; - } - - public Duration getDefaultJtaTimeout() { - return this.defaultJtaTimeout; - } - - /** - * Specifies the maximum number of active transactions. Defaults to {@literal 50}. A - * negative value means infinite amount. You will get an {@code IllegalStateException} - * with error message "Max number of active transactions reached" if you call - * {@code UserTransaction.begin()} while there are already n concurrent transactions - * running, n being this value. - * @param maxActives the max activities - */ - public void setMaxActives(int maxActives) { - this.maxActives = maxActives; - } - - public int getMaxActives() { - return this.maxActives; - } - - /** - * Specifies if disk logging should be enabled or not. Defaults to true. It is useful - * for JUnit testing, or to profile code without seeing the transaction manager's - * activity as a hot spot but this should never be disabled on production or data - * integrity cannot be guaranteed. - * @param enableLogging if logging is enabled - */ - public void setEnableLogging(boolean enableLogging) { - this.enableLogging = enableLogging; - } - - public boolean isEnableLogging() { - return this.enableLogging; - } - - /** - * Specifies the transaction manager's unique name. Defaults to the machine's IP - * address. If you plan to run more than one transaction manager against one database - * you must set this property to a unique value or you might run into duplicate - * transaction ID (XID) problems that can be quite subtle (example: - * {@literal https://fogbugz.atomikos.com/default.asp?community.6.2225.7}). If - * multiple instances need to use the same properties file then the easiest way to - * ensure uniqueness for this property is by referencing a system property specified - * at VM startup. - * @param uniqueName the unique name - */ - public void setTransactionManagerUniqueName(String uniqueName) { - this.transactionManagerUniqueName = uniqueName; - } - - public String getTransactionManagerUniqueName() { - return this.transactionManagerUniqueName; - } - - /** - * Specifies if subtransactions should be joined when possible. Defaults to true. When - * false, no attempt to call {@code XAResource.start(TM_JOIN)} will be made for - * different but related subtransactions. This setting has no effect on resource - * access within one and the same transaction. If you don't use subtransactions then - * this setting can be ignored. - * @param serialJtaTransactions if serial JTA transactions are supported - */ - public void setSerialJtaTransactions(boolean serialJtaTransactions) { - this.serialJtaTransactions = serialJtaTransactions; - } - - public boolean isSerialJtaTransactions() { - return this.serialJtaTransactions; - } - - public void setAllowSubTransactions(boolean allowSubTransactions) { - this.allowSubTransactions = allowSubTransactions; - } - - public boolean isAllowSubTransactions() { - return this.allowSubTransactions; - } - - /** - * Specifies whether VM shutdown should trigger forced shutdown of the transaction - * core. Defaults to false. - * @param forceShutdownOnVmExit if VM shutdown should be forced - */ - public void setForceShutdownOnVmExit(boolean forceShutdownOnVmExit) { - this.forceShutdownOnVmExit = forceShutdownOnVmExit; - } - - public boolean isForceShutdownOnVmExit() { - return this.forceShutdownOnVmExit; - } - - /** - * Specifies how long should a normal shutdown (no-force) wait for transactions to - * complete. Defaults to {@literal Long.MAX_VALUE}. - * @param defaultMaxWaitTimeOnShutdown the default max wait time on shutdown - */ - public void setDefaultMaxWaitTimeOnShutdown(long defaultMaxWaitTimeOnShutdown) { - this.defaultMaxWaitTimeOnShutdown = defaultMaxWaitTimeOnShutdown; - } - - public long getDefaultMaxWaitTimeOnShutdown() { - return this.defaultMaxWaitTimeOnShutdown; - } - - /** - * Specifies the transactions log file base name. Defaults to {@literal tmlog}. The - * transactions logs are stored in files using this name appended with a number and - * the extension {@literal .log}. At checkpoint, a new transactions log file is - * created and the number is incremented. - * @param logBaseName the log base name - */ - public void setLogBaseName(String logBaseName) { - this.logBaseName = logBaseName; - } - - public String getLogBaseName() { - return this.logBaseName; - } - - /** - * Specifies the directory in which the log files should be stored. Defaults to the - * current working directory. This directory should be a stable storage like a SAN, - * RAID or at least backed up location. The transactions logs files are as important - * as the data themselves to guarantee consistency in case of failures. - * @param logBaseDir the log base dir - */ - public void setLogBaseDir(String logBaseDir) { - this.logBaseDir = logBaseDir; - } - - public String getLogBaseDir() { - return this.logBaseDir; - } - - /** - * Specifies the interval between checkpoints. A checkpoint reduces the log file size - * at the expense of adding some overhead in the runtime. Defaults to {@literal 500}. - * @param checkpointInterval the checkpoint interval - */ - public void setCheckpointInterval(long checkpointInterval) { - this.checkpointInterval = checkpointInterval; - } - - public long getCheckpointInterval() { - return this.checkpointInterval; - } - - /** - * Specifies whether or not to use different (and concurrent) threads for two-phase - * commit on the participating resources. Setting this to {@literal true} implies that - * the commit is more efficient since waiting for acknowledgements is done in - * parallel. Defaults to {@literal true}. If you set this to {@literal false}, then - * commits will happen in the order that resources are accessed within the - * transaction. - * @param threadedTwoPhaseCommit if threaded two phase commits should be used - */ - public void setThreadedTwoPhaseCommit(boolean threadedTwoPhaseCommit) { - this.threadedTwoPhaseCommit = threadedTwoPhaseCommit; - } - - public boolean isThreadedTwoPhaseCommit() { - return this.threadedTwoPhaseCommit; - } - - public Recovery getRecovery() { - return this.recovery; - } - - /** - * Returns the properties as a {@link Properties} object that can be used with - * Atomikos. - * @return the properties - */ - public Properties asProperties() { - Properties properties = new Properties(); - set(properties, "service", getService()); - set(properties, "max_timeout", getMaxTimeout()); - set(properties, "default_jta_timeout", getDefaultJtaTimeout()); - set(properties, "max_actives", getMaxActives()); - set(properties, "enable_logging", isEnableLogging()); - set(properties, "tm_unique_name", getTransactionManagerUniqueName()); - set(properties, "serial_jta_transactions", isSerialJtaTransactions()); - set(properties, "allow_subtransactions", isAllowSubTransactions()); - set(properties, "force_shutdown_on_vm_exit", isForceShutdownOnVmExit()); - set(properties, "default_max_wait_time_on_shutdown", getDefaultMaxWaitTimeOnShutdown()); - set(properties, "log_base_name", getLogBaseName()); - set(properties, "log_base_dir", getLogBaseDir()); - set(properties, "checkpoint_interval", getCheckpointInterval()); - set(properties, "threaded_2pc", isThreadedTwoPhaseCommit()); - Recovery recovery = getRecovery(); - set(properties, "forget_orphaned_log_entries_delay", recovery.getForgetOrphanedLogEntriesDelay()); - set(properties, "recovery_delay", recovery.getDelay()); - set(properties, "oltp_max_retries", recovery.getMaxRetries()); - set(properties, "oltp_retry_interval", recovery.getRetryInterval()); - return properties; - } - - private void set(Properties properties, String key, Object value) { - String id = "com.atomikos.icatch." + key; - if (value != null && !properties.containsKey(id)) { - properties.setProperty(id, asString(value)); - } - } - - private String asString(Object value) { - if (value instanceof Duration) { - return String.valueOf(((Duration) value).toMillis()); - } - return value.toString(); - } - - /** - * Recovery specific settings. - */ - public static class Recovery { - - /** - * Delay after which recovery can cleanup pending ('orphaned') log entries. - */ - private Duration forgetOrphanedLogEntriesDelay = Duration.ofMillis(86400000); - - /** - * Delay between two recovery scans. - */ - private Duration delay = Duration.ofMillis(10000); - - /** - * Number of retry attempts to commit the transaction before throwing an - * exception. - */ - private int maxRetries = 5; - - /** - * Delay between retry attempts. - */ - private Duration retryInterval = Duration.ofMillis(10000); - - public Duration getForgetOrphanedLogEntriesDelay() { - return this.forgetOrphanedLogEntriesDelay; - } - - public void setForgetOrphanedLogEntriesDelay(Duration forgetOrphanedLogEntriesDelay) { - this.forgetOrphanedLogEntriesDelay = forgetOrphanedLogEntriesDelay; - } - - public Duration getDelay() { - return this.delay; - } - - public void setDelay(Duration delay) { - this.delay = delay; - } - - public int getMaxRetries() { - return this.maxRetries; - } - - public void setMaxRetries(int maxRetries) { - this.maxRetries = maxRetries; - } - - public Duration getRetryInterval() { - return this.retryInterval; - } - - public void setRetryInterval(Duration retryInterval) { - this.retryInterval = retryInterval; - } - - } - -} diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jta/atomikos/AtomikosXAConnectionFactoryWrapper.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jta/atomikos/AtomikosXAConnectionFactoryWrapper.java deleted file mode 100644 index d0307e675c4..00000000000 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jta/atomikos/AtomikosXAConnectionFactoryWrapper.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2012-2019 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 - * - * https://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.jta.atomikos; - -import javax.jms.ConnectionFactory; -import javax.jms.XAConnectionFactory; - -import org.springframework.boot.jms.XAConnectionFactoryWrapper; - -/** - * {@link XAConnectionFactoryWrapper} that uses an {@link AtomikosConnectionFactoryBean} - * to wrap a {@link XAConnectionFactory}. - * - * @author Phillip Webb - * @since 1.2.0 - */ -public class AtomikosXAConnectionFactoryWrapper implements XAConnectionFactoryWrapper { - - @Override - public ConnectionFactory wrapConnectionFactory(XAConnectionFactory connectionFactory) { - AtomikosConnectionFactoryBean bean = new AtomikosConnectionFactoryBean(); - bean.setXaConnectionFactory(connectionFactory); - return bean; - } - -} diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jta/atomikos/AtomikosXADataSourceWrapper.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jta/atomikos/AtomikosXADataSourceWrapper.java deleted file mode 100644 index 3c5c5e3b13b..00000000000 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jta/atomikos/AtomikosXADataSourceWrapper.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2012-2019 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 - * - * https://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.jta.atomikos; - -import javax.sql.XADataSource; - -import org.springframework.boot.jdbc.XADataSourceWrapper; - -/** - * {@link XADataSourceWrapper} that uses an {@link AtomikosDataSourceBean} to wrap a - * {@link XADataSource}. - * - * @author Phillip Webb - * @since 1.2.0 - */ -public class AtomikosXADataSourceWrapper implements XADataSourceWrapper { - - @Override - public AtomikosDataSourceBean wrapDataSource(XADataSource dataSource) throws Exception { - AtomikosDataSourceBean bean = new AtomikosDataSourceBean(); - bean.setXaDataSource(dataSource); - return bean; - } - -} diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jta/atomikos/package-info.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jta/atomikos/package-info.java deleted file mode 100644 index 923e63b4a4e..00000000000 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jta/atomikos/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2012-2019 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 - * - * https://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. - */ - -/** - * Support classes for Atomikos JTA. - */ -package org.springframework.boot.jta.atomikos; diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jta/package-info.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jta/package-info.java deleted file mode 100644 index e574ee6000b..00000000000 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jta/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2012-2019 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 - * - * https://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. - */ - -/** - * Support for the Java Transaction API. - */ -package org.springframework.boot.jta; diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jta/atomikos/AtomikosConnectionFactoryBeanTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jta/atomikos/AtomikosConnectionFactoryBeanTests.java deleted file mode 100644 index 0f9d348416f..00000000000 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jta/atomikos/AtomikosConnectionFactoryBeanTests.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2012-2021 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 - * - * https://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.jta.atomikos; - -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.verify; - -/** - * Tests for {@link AtomikosConnectionFactoryBean}. - * - * @author Phillip Webb - */ -class AtomikosConnectionFactoryBeanTests { - - @Test - void beanMethods() throws Exception { - MockAtomikosConnectionFactoryBean bean = spy(new MockAtomikosConnectionFactoryBean()); - bean.setBeanName("bean"); - bean.afterPropertiesSet(); - assertThat(bean.getUniqueResourceName()).isEqualTo("bean"); - verify(bean).init(); - verify(bean, never()).close(); - bean.destroy(); - verify(bean).close(); - } - - static class MockAtomikosConnectionFactoryBean extends AtomikosConnectionFactoryBean { - - @Override - public synchronized void init() { - } - - @Override - public synchronized void close() { - } - - } - -} diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jta/atomikos/AtomikosDataSourceBeanTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jta/atomikos/AtomikosDataSourceBeanTests.java deleted file mode 100644 index b078d0012e1..00000000000 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jta/atomikos/AtomikosDataSourceBeanTests.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2012-2021 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 - * - * https://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.jta.atomikos; - -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.verify; - -/** - * Tests for {@link AtomikosDataSourceBean}. - * - * @author Phillip Webb - */ -class AtomikosDataSourceBeanTests { - - @Test - void beanMethods() throws Exception { - MockAtomikosDataSourceBean bean = spy(new MockAtomikosDataSourceBean()); - bean.setBeanName("bean"); - bean.afterPropertiesSet(); - assertThat(bean.getUniqueResourceName()).isEqualTo("bean"); - verify(bean).init(); - verify(bean, never()).close(); - bean.destroy(); - verify(bean).close(); - } - - static class MockAtomikosDataSourceBean extends AtomikosDataSourceBean { - - @Override - public synchronized void init() { - } - - @Override - public void close() { - } - - } - -} diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jta/atomikos/AtomikosDependsOnBeanFactoryPostProcessorTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jta/atomikos/AtomikosDependsOnBeanFactoryPostProcessorTests.java deleted file mode 100644 index 80f3c22ab43..00000000000 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jta/atomikos/AtomikosDependsOnBeanFactoryPostProcessorTests.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright 2012-2019 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 - * - * https://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.jta.atomikos; - -import java.util.Arrays; -import java.util.HashSet; - -import javax.jms.ConnectionFactory; -import javax.sql.DataSource; - -import com.atomikos.icatch.jta.UserTransactionManager; -import com.atomikos.jms.extra.MessageDrivenContainer; -import org.junit.jupiter.api.Test; - -import org.springframework.beans.factory.config.BeanDefinition; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; - -/** - * Tests for {@link AtomikosDependsOnBeanFactoryPostProcessor}. - * - * @author Phillip Webb - */ -class AtomikosDependsOnBeanFactoryPostProcessorTests { - - private AnnotationConfigApplicationContext context; - - @Test - void setsDependsOn() { - this.context = new AnnotationConfigApplicationContext(Config.class); - assertDependsOn("dataSource"); - assertDependsOn("connectionFactory"); - assertDependsOn("userTransactionManager", "dataSource", "connectionFactory"); - assertDependsOn("messageDrivenContainer", "userTransactionManager"); - this.context.close(); - } - - private void assertDependsOn(String bean, String... expected) { - BeanDefinition definition = this.context.getBeanDefinition(bean); - if (definition.getDependsOn() == null) { - assertThat(expected).as("No dependsOn expected for " + bean).isEmpty(); - return; - } - HashSet dependsOn = new HashSet<>(Arrays.asList(definition.getDependsOn())); - assertThat(dependsOn).isEqualTo(new HashSet<>(Arrays.asList(expected))); - } - - @Configuration(proxyBeanMethods = false) - static class Config { - - @Bean - DataSource dataSource() { - return mock(DataSource.class); - } - - @Bean - ConnectionFactory connectionFactory() { - return mock(ConnectionFactory.class); - } - - @Bean - UserTransactionManager userTransactionManager() { - return mock(UserTransactionManager.class); - } - - @Bean - MessageDrivenContainer messageDrivenContainer() { - return mock(MessageDrivenContainer.class); - } - - @Bean - static AtomikosDependsOnBeanFactoryPostProcessor atomikosPostProcessor() { - return new AtomikosDependsOnBeanFactoryPostProcessor(); - } - - } - -} diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jta/atomikos/AtomikosPropertiesTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jta/atomikos/AtomikosPropertiesTests.java deleted file mode 100644 index 830d25d5701..00000000000 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jta/atomikos/AtomikosPropertiesTests.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright 2012-2020 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 - * - * https://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.jta.atomikos; - -import java.time.Duration; -import java.util.Properties; - -import org.assertj.core.data.MapEntry; -import org.junit.jupiter.api.Test; - -import org.springframework.core.io.ClassPathResource; -import org.springframework.core.io.support.PropertiesLoaderUtils; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.entry; - -/** - * Tests for {@link AtomikosProperties}. - * - * @author Phillip Webb - * @author Stephane Nicoll - */ -class AtomikosPropertiesTests { - - private AtomikosProperties properties = new AtomikosProperties(); - - @Test - void testProperties() { - this.properties.setService("service"); - this.properties.setMaxTimeout(Duration.ofMillis(1)); - this.properties.setDefaultJtaTimeout(Duration.ofMillis(2)); - this.properties.setMaxActives(3); - this.properties.setEnableLogging(true); - this.properties.setTransactionManagerUniqueName("uniqueName"); - this.properties.setSerialJtaTransactions(true); - this.properties.setAllowSubTransactions(false); - this.properties.setForceShutdownOnVmExit(true); - this.properties.setDefaultMaxWaitTimeOnShutdown(20); - this.properties.setLogBaseName("logBaseName"); - this.properties.setLogBaseDir("logBaseDir"); - this.properties.setCheckpointInterval(4); - this.properties.setThreadedTwoPhaseCommit(true); - this.properties.getRecovery().setForgetOrphanedLogEntriesDelay(Duration.ofMillis(2000)); - this.properties.getRecovery().setDelay(Duration.ofMillis(3000)); - this.properties.getRecovery().setMaxRetries(10); - this.properties.getRecovery().setRetryInterval(Duration.ofMillis(4000)); - assertThat(this.properties.asProperties().size()).isEqualTo(18); - assertProperty("com.atomikos.icatch.service", "service"); - assertProperty("com.atomikos.icatch.max_timeout", "1"); - assertProperty("com.atomikos.icatch.default_jta_timeout", "2"); - assertProperty("com.atomikos.icatch.max_actives", "3"); - assertProperty("com.atomikos.icatch.enable_logging", "true"); - assertProperty("com.atomikos.icatch.tm_unique_name", "uniqueName"); - assertProperty("com.atomikos.icatch.serial_jta_transactions", "true"); - assertProperty("com.atomikos.icatch.allow_subtransactions", "false"); - assertProperty("com.atomikos.icatch.force_shutdown_on_vm_exit", "true"); - assertProperty("com.atomikos.icatch.default_max_wait_time_on_shutdown", "20"); - assertProperty("com.atomikos.icatch.log_base_name", "logBaseName"); - assertProperty("com.atomikos.icatch.log_base_dir", "logBaseDir"); - assertProperty("com.atomikos.icatch.checkpoint_interval", "4"); - assertProperty("com.atomikos.icatch.threaded_2pc", "true"); - assertProperty("com.atomikos.icatch.forget_orphaned_log_entries_delay", "2000"); - assertProperty("com.atomikos.icatch.recovery_delay", "3000"); - assertProperty("com.atomikos.icatch.oltp_max_retries", "10"); - assertProperty("com.atomikos.icatch.oltp_retry_interval", "4000"); - } - - @Test - void testDefaultProperties() { - Properties defaultSettings = loadDefaultSettings(); - Properties properties = this.properties.asProperties(); - assertThat(properties).contains(defaultOf(defaultSettings, "com.atomikos.icatch.max_timeout", - "com.atomikos.icatch.default_jta_timeout", "com.atomikos.icatch.max_actives", - "com.atomikos.icatch.enable_logging", "com.atomikos.icatch.serial_jta_transactions", - "com.atomikos.icatch.allow_subtransactions", "com.atomikos.icatch.force_shutdown_on_vm_exit", - "com.atomikos.icatch.default_max_wait_time_on_shutdown", "com.atomikos.icatch.log_base_name", - "com.atomikos.icatch.checkpoint_interval", "com.atomikos.icatch.threaded_2pc", - "com.atomikos.icatch.forget_orphaned_log_entries_delay", "com.atomikos.icatch.oltp_max_retries", - "com.atomikos.icatch.oltp_retry_interval")); - assertThat(properties).contains(entry("com.atomikos.icatch.recovery_delay", - defaultSettings.get("com.atomikos.icatch.default_jta_timeout"))); - assertThat(properties).hasSize(15); - } - - private MapEntry[] defaultOf(Properties defaultSettings, String... keys) { - MapEntry[] entries = new MapEntry[keys.length]; - for (int i = 0; i < keys.length; i++) { - String key = keys[i]; - entries[i] = entry(key, defaultSettings.get(key)); - } - return entries; - } - - private Properties loadDefaultSettings() { - try { - - return PropertiesLoaderUtils.loadProperties(new ClassPathResource("transactions-defaults.properties")); - } - catch (Exception ex) { - throw new IllegalStateException("Failed to get default from Atomikos", ex); - } - } - - private void assertProperty(String key, String value) { - assertThat(this.properties.asProperties().getProperty(key)).isEqualTo(value); - } - -} diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jta/atomikos/AtomikosXAConnectionFactoryWrapperTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jta/atomikos/AtomikosXAConnectionFactoryWrapperTests.java deleted file mode 100644 index 5cdd58b9cdb..00000000000 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jta/atomikos/AtomikosXAConnectionFactoryWrapperTests.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2012-2019 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 - * - * https://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.jta.atomikos; - -import javax.jms.ConnectionFactory; -import javax.jms.XAConnectionFactory; - -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; - -/** - * Tests for {@link AtomikosXAConnectionFactoryWrapper}. - * - * @author Phillip Webb - */ -class AtomikosXAConnectionFactoryWrapperTests { - - @Test - void wrap() { - XAConnectionFactory connectionFactory = mock(XAConnectionFactory.class); - AtomikosXAConnectionFactoryWrapper wrapper = new AtomikosXAConnectionFactoryWrapper(); - ConnectionFactory wrapped = wrapper.wrapConnectionFactory(connectionFactory); - assertThat(wrapped).isInstanceOf(AtomikosConnectionFactoryBean.class); - assertThat(((AtomikosConnectionFactoryBean) wrapped).getXaConnectionFactory()).isSameAs(connectionFactory); - } - -} diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jta/atomikos/AtomikosXADataSourceWrapperTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jta/atomikos/AtomikosXADataSourceWrapperTests.java deleted file mode 100644 index 6355c73c00a..00000000000 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jta/atomikos/AtomikosXADataSourceWrapperTests.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2012-2019 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 - * - * https://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.jta.atomikos; - -import javax.sql.DataSource; -import javax.sql.XADataSource; - -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; - -/** - * Tests for {@link AtomikosXADataSourceWrapper}. - * - * @author Phillip Webb - */ -class AtomikosXADataSourceWrapperTests { - - @Test - void wrap() throws Exception { - XADataSource dataSource = mock(XADataSource.class); - AtomikosXADataSourceWrapper wrapper = new AtomikosXADataSourceWrapper(); - DataSource wrapped = wrapper.wrapDataSource(dataSource); - assertThat(wrapped).isInstanceOf(AtomikosDataSourceBean.class); - assertThat(((AtomikosDataSourceBean) wrapped).getXaDataSource()).isSameAs(dataSource); - } - -} diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-jta-atomikos/build.gradle b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-jta-atomikos/build.gradle deleted file mode 100644 index 5f8555d5826..00000000000 --- a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-jta-atomikos/build.gradle +++ /dev/null @@ -1,27 +0,0 @@ -plugins { - id "java" - id "org.springframework.boot.conventions" -} - -description = "Spring Boot Atomikos JTA smoke test" - -dependencies { - implementation(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-artemis")) - implementation(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-data-jpa")) - implementation(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-jta-atomikos")) - implementation(project(":spring-boot-project:spring-boot-tools:spring-boot-test-support")) - if (JavaVersion.current().java9Compatible) { - implementation("jakarta.xml.bind:jakarta.xml.bind-api") - } - implementation("org.springframework:spring-jms") - - runtimeOnly("com.h2database:h2") - runtimeOnly("org.apache.activemq:artemis-jms-server") { - exclude group: "commons-logging", module: "commons-logging" - exclude group: "org.apache.geronimo.specs", module: "geronimo-jms_2.0_spec" - exclude group: "org.apache.geronimo.specs", module: "geronimo-json_1.0_spec" - exclude group: "org.apache.geronimo.specs", module: "geronimo-jta_1.1_spec" - } - - testImplementation(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-test")) -} diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-jta-atomikos/src/main/java/smoketest/atomikos/Account.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-jta-atomikos/src/main/java/smoketest/atomikos/Account.java deleted file mode 100644 index c73d1cfd1e2..00000000000 --- a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-jta-atomikos/src/main/java/smoketest/atomikos/Account.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2012-2019 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 - * - * https://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 smoketest.atomikos; - -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; - -@Entity -public class Account { - - @Id - @GeneratedValue - private Long id; - - private String username; - - Account() { - } - - public Account(String username) { - this.username = username; - } - - public String getUsername() { - return this.username; - } - -} diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-jta-atomikos/src/main/java/smoketest/atomikos/AccountRepository.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-jta-atomikos/src/main/java/smoketest/atomikos/AccountRepository.java deleted file mode 100644 index 99aed1784f0..00000000000 --- a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-jta-atomikos/src/main/java/smoketest/atomikos/AccountRepository.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2012-2019 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 - * - * https://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 smoketest.atomikos; - -import org.springframework.data.jpa.repository.JpaRepository; - -public interface AccountRepository extends JpaRepository { - -} diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-jta-atomikos/src/main/java/smoketest/atomikos/AccountService.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-jta-atomikos/src/main/java/smoketest/atomikos/AccountService.java deleted file mode 100644 index 7a0deade0f6..00000000000 --- a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-jta-atomikos/src/main/java/smoketest/atomikos/AccountService.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2012-2019 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 - * - * https://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 smoketest.atomikos; - -import javax.transaction.Transactional; - -import org.springframework.jms.core.JmsTemplate; -import org.springframework.stereotype.Service; - -@Service -@Transactional -public class AccountService { - - private final JmsTemplate jmsTemplate; - - private final AccountRepository accountRepository; - - public AccountService(JmsTemplate jmsTemplate, AccountRepository accountRepository) { - this.jmsTemplate = jmsTemplate; - this.accountRepository = accountRepository; - } - - public void createAccountAndNotify(String username) { - this.jmsTemplate.convertAndSend("accounts", username); - this.accountRepository.save(new Account(username)); - if ("error".equals(username)) { - throw new RuntimeException("Simulated error"); - } - } - -} diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-jta-atomikos/src/main/java/smoketest/atomikos/Messages.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-jta-atomikos/src/main/java/smoketest/atomikos/Messages.java deleted file mode 100644 index 1f0c90ad9c4..00000000000 --- a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-jta-atomikos/src/main/java/smoketest/atomikos/Messages.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2012-2019 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 - * - * https://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 smoketest.atomikos; - -import org.springframework.jms.annotation.JmsListener; -import org.springframework.stereotype.Component; - -@Component -public class Messages { - - @JmsListener(destination = "accounts") - public void onMessage(String content) { - System.out.println("----> " + content); - } - -} diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-jta-atomikos/src/main/java/smoketest/atomikos/SampleAtomikosApplication.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-jta-atomikos/src/main/java/smoketest/atomikos/SampleAtomikosApplication.java deleted file mode 100644 index eb028ae6ccd..00000000000 --- a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-jta-atomikos/src/main/java/smoketest/atomikos/SampleAtomikosApplication.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2012-2021 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 - * - * https://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 smoketest.atomikos; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.ConfigurableApplicationContext; - -@SpringBootApplication -public class SampleAtomikosApplication { - - public static void main(String[] args) throws Exception { - try (ConfigurableApplicationContext context = SpringApplication.run(SampleAtomikosApplication.class, args)) { - AccountService service = context.getBean(AccountService.class); - AccountRepository repository = context.getBean(AccountRepository.class); - service.createAccountAndNotify("josh"); - System.out.println("Count is " + repository.count()); - try { - service.createAccountAndNotify("error"); - } - catch (Exception ex) { - System.out.println(ex.getMessage()); - } - System.out.println("Count is " + repository.count()); - Thread.sleep(100); - } - } - -} diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-jta-atomikos/src/main/resources/application.properties b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-jta-atomikos/src/main/resources/application.properties deleted file mode 100644 index c2a36916165..00000000000 --- a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-jta-atomikos/src/main/resources/application.properties +++ /dev/null @@ -1,3 +0,0 @@ -logging.level.com.atomikos=WARN -spring.artemis.embedded.queues=accounts -spring.jpa.open-in-view=true diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-jta-atomikos/src/test/java/smoketest/atomikos/SampleAtomikosApplicationTests.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-jta-atomikos/src/test/java/smoketest/atomikos/SampleAtomikosApplicationTests.java deleted file mode 100644 index c65ae06d244..00000000000 --- a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-jta-atomikos/src/test/java/smoketest/atomikos/SampleAtomikosApplicationTests.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2012-2021 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 - * - * https://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 smoketest.atomikos; - -import java.io.File; -import java.util.function.Consumer; - -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; - -import org.springframework.boot.test.system.CapturedOutput; -import org.springframework.boot.test.system.OutputCaptureExtension; -import org.springframework.boot.testsupport.BuildOutput; -import org.springframework.util.StringUtils; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Basic integration tests for demo application. - * - * @author Phillip Webb - */ -@ExtendWith(OutputCaptureExtension.class) -class SampleAtomikosApplicationTests { - - @Test - void testTransactionRollback(CapturedOutput output) throws Exception { - File logDir = new File(new BuildOutput(getClass()).getRootLocation(), "atomikos-logs"); - SampleAtomikosApplication.main(new String[] { "--spring.jta.log-dir=" + logDir }); - assertThat(output).satisfies(numberOfOccurrences("---->", 1)); - assertThat(output).satisfies(numberOfOccurrences("----> josh", 1)); - assertThat(output).satisfies(numberOfOccurrences("Count is 1", 2)); - assertThat(output).satisfies(numberOfOccurrences("Simulated error", 1)); - } - - private Consumer numberOfOccurrences(String substring, int expectedCount) { - return (charSequence) -> { - int count = StringUtils.countOccurrencesOf(charSequence.toString(), substring); - assertThat(count).isEqualTo(expectedCount); - }; - } - -}