Since I didn't find any article explaining how to use the auto configuration to configure Atomikos on SpringBoot, I decided to write this post. I hope it can be useful to someone. ;)
Dependencies
Assuming you are developing a web application and want to use Atomikos to provide distributed transactions over multiple datasources, you will need only two dependencies:
def springBootVersion = 'YOUR_SPRING_BOOT_VERSION_HERE'
compile group: 'org.springframework.boot', name: 'spring-boot-starter-jta-atomikos', version: springBootVersion
compile group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: springBootVersion
The application.yml
If you are using SpringBoot, you need to have an application.properties or an application.yml. I find YAML much easier to read than a properties file, so, that's why I'm using it in here.
spring:
profiles:
active: prod
jta:
enabled: true
service: com.atomikos.icatch.standalone.UserTransactionServiceFactory
max-actives: 200
enable-logging: false
atomikos:
datasource:
one:
unique-resource-name: dataSourceOne
max-pool-size: 5
min-pool-size: 1
max-life-time: 20000
borrow-connection-timeout: 10000
xa-data-source-class-name: org.h2.jdbcx.JdbcDataSource
xa-properties:
user: sa
password:
URL: jdbc:h2:mem:one;DB_CLOSE_DELAY=-1
two:
unique-resource-name: dataSourceTwo
max-pool-size: 5
min-pool-size: 1
max-life-time: 20000
borrow-connection-timeout: 10000
xa-data-source-class-name: org.h2.jdbcx.JdbcDataSource
xa-properties:
user: sa
password:
URL: jdbc:h2:mem:two;DB_CLOSE_DELAY=-1
three:
unique-resource-name: dataSourceThree
max-pool-size: 5
min-pool-size: 1
max-life-time: 20000
borrow-connection-timeout: 10000
xa-data-source-class-name: org.h2.jdbcx.JdbcDataSource
xa-properties:
user: sa
password:
URL: jdbc:h2:mem:three;DB_CLOSE_DELAY=-1
The Configuration class
After you have configured the application.yml, you need to create three beans: the datasources. We need to create each of them based on each datasource that you configured in the application.yml properties.
@Configuration
@EnableConfigurationProperties
@EnableAutoConfiguration
public class SpringContext {
@Bean
@ConfigurationProperties(prefix = "spring.jta.atomikos.datasource.one")
public DataSource dataSourceOne() {
return new AtomikosDataSourceBean();
}
@Bean
@ConfigurationProperties(prefix = "spring.jta.atomikos.datasource.two")
public DataSource dataSourceTwo() {
return new AtomikosDataSourceBean();
}
@Bean
@ConfigurationProperties(prefix = "spring.jta.atomikos.datasource.three")
public DataSource dataSourceThree() {
return new AtomikosDataSourceBean();
}
}
That could be all, but, unfortunately, when you use the @EnableAutoConfiguration annotation, all auto configurations are enabled, and so are the configurations that awaits only one datasource. So, if you run this, probably you will get this exception:
(...) Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [javax.sql.DataSource] is defined: expected single matching bean but found 3: dataSourceOne,dataSourceTwo,dataSourceThree. (...)
The Spring doc says you need to set a @Primary datasource for resolving this issue, but, if you don't have a primary datasource, there is no sense in doing it at all.
So, if you want to use multiple datasources and you still don't want to set a primary datasource, you need to disable every auto configuration that uses a default datasource. So, I came up with this to resolve the problem:
@Configuration
@EnableConfigurationProperties
@EnableAutoConfiguration(exclude = {
DataSourceAutoConfiguration.class,
HibernateJpaAutoConfiguration.class, //if you are using Hibernate
DataSourceTransactionManagerAutoConfiguration.class
})
public class SpringContext {
(...)
}
So, after that you can run your SpringBoot application using JTA provided by Atomikos. ;)
Any question? Please, leave a message.
[]'S