Remove bitronix support

See gh-24806
This commit is contained in:
Stephane Nicoll 2021-01-15 14:05:01 +01:00
parent 4b0d5c31de
commit a18f01addf
29 changed files with 142 additions and 1590 deletions

View File

@ -62,7 +62,6 @@ dependencies {
optional("org.apache.tomcat.embed:tomcat-embed-el")
optional("org.apache.tomcat.embed:tomcat-embed-websocket")
optional("org.apache.tomcat:tomcat-jdbc")
optional("org.codehaus.btm:btm")
optional("org.codehaus.groovy:groovy-templates")
optional("com.github.ben-manes.caffeine:caffeine")
optional("com.github.mxab.thymeleaf.extras:thymeleaf-extras-data-attribute")

View File

@ -1,121 +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 javax.jms.Message;
import javax.transaction.TransactionManager;
import javax.transaction.UserTransaction;
import bitronix.tm.BitronixTransactionManager;
import bitronix.tm.TransactionManagerServices;
import bitronix.tm.jndi.BitronixContext;
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.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.jdbc.XADataSourceWrapper;
import org.springframework.boot.jms.XAConnectionFactoryWrapper;
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 <A href="https://github.com/bitronix/btm">Bitronix</A>.
*
* @author Josh Long
* @author Phillip Webb
* @author Andy Wilkinson
* @author Kazuki Shimizu
* @deprecated since 2.3.0 as the Bitronix project is no longer being maintained
*/
@Deprecated
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(JtaProperties.class)
@ConditionalOnClass({ JtaTransactionManager.class, BitronixContext.class })
@ConditionalOnMissingBean(org.springframework.transaction.TransactionManager.class)
class BitronixJtaConfiguration {
@Bean
@ConditionalOnMissingBean
@ConfigurationProperties(prefix = "spring.jta.bitronix.properties")
bitronix.tm.Configuration bitronixConfiguration(JtaProperties jtaProperties) {
bitronix.tm.Configuration config = TransactionManagerServices.getConfiguration();
if (StringUtils.hasText(jtaProperties.getTransactionManagerId())) {
config.setServerId(jtaProperties.getTransactionManagerId());
}
File logBaseDir = getLogBaseDir(jtaProperties);
config.setLogPart1Filename(new File(logBaseDir, "part1.btm").getAbsolutePath());
config.setLogPart2Filename(new File(logBaseDir, "part2.btm").getAbsolutePath());
config.setDisableJmx(true);
return config;
}
private File getLogBaseDir(JtaProperties jtaProperties) {
if (StringUtils.hasLength(jtaProperties.getLogDir())) {
return new File(jtaProperties.getLogDir());
}
File home = new ApplicationHome().getDir();
return new File(home, "transaction-logs");
}
@Bean
@ConditionalOnMissingBean(TransactionManager.class)
BitronixTransactionManager bitronixTransactionManager(bitronix.tm.Configuration configuration) {
// Inject configuration to force ordering
return TransactionManagerServices.getTransactionManager();
}
@Bean
@ConditionalOnMissingBean(XADataSourceWrapper.class)
org.springframework.boot.jta.bitronix.BitronixXADataSourceWrapper xaDataSourceWrapper() {
return new org.springframework.boot.jta.bitronix.BitronixXADataSourceWrapper();
}
@Bean
@ConditionalOnMissingBean
static org.springframework.boot.jta.bitronix.BitronixDependentBeanFactoryPostProcessor bitronixDependentBeanFactoryPostProcessor() {
return new org.springframework.boot.jta.bitronix.BitronixDependentBeanFactoryPostProcessor();
}
@Bean
JtaTransactionManager transactionManager(UserTransaction userTransaction, TransactionManager transactionManager,
ObjectProvider<TransactionManagerCustomizers> transactionManagerCustomizers) {
JtaTransactionManager jtaTransactionManager = new JtaTransactionManager(userTransaction, transactionManager);
transactionManagerCustomizers.ifAvailable((customizers) -> customizers.customize(jtaTransactionManager));
return jtaTransactionManager;
}
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(Message.class)
static class BitronixJtaJmsConfiguration {
@Bean
@ConditionalOnMissingBean(XAConnectionFactoryWrapper.class)
org.springframework.boot.jta.bitronix.BitronixXAConnectionFactoryWrapper xaConnectionFactoryWrapper() {
return new org.springframework.boot.jta.bitronix.BitronixXAConnectionFactoryWrapper();
}
}
}

View File

@ -35,13 +35,12 @@ import org.springframework.context.annotation.Import;
* @author Nishant Raut
* @since 1.2.0
*/
@SuppressWarnings("deprecation")
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(javax.transaction.Transaction.class)
@ConditionalOnProperty(prefix = "spring.jta", value = "enabled", matchIfMissing = true)
@AutoConfigureBefore({ XADataSourceAutoConfiguration.class, ActiveMQAutoConfiguration.class,
ArtemisAutoConfiguration.class, HibernateJpaAutoConfiguration.class })
@Import({ JndiJtaConfiguration.class, BitronixJtaConfiguration.class, AtomikosJtaConfiguration.class })
@Import({ JndiJtaConfiguration.class, AtomikosJtaConfiguration.class })
public class JtaAutoConfiguration {
}

View File

@ -1041,119 +1041,6 @@
"name": "spring.jpa.open-in-view",
"defaultValue": true
},
{
"name": "spring.jta.bitronix.properties.allow-multiple-lrc",
"description": "Whether to allow multiple LRC resources to be enlisted into the same transaction.",
"defaultValue": false
},
{
"name": "spring.jta.bitronix.properties.asynchronous2-pc",
"description": "Whether to enable asynchronously execution of two phase commit.",
"defaultValue": false
},
{
"name": "spring.jta.bitronix.properties.background-recovery-interval",
"description": "Interval in minutes at which to run the recovery process in the background.",
"defaultValue": 1,
"deprecation": {
"replacement": "spring.jta.bitronix.properties.background-recovery-interval-seconds"
}
},
{
"name": "spring.jta.bitronix.properties.background-recovery-interval-seconds",
"description": "Interval in seconds at which to run the recovery process in the background.",
"defaultValue": 60
},
{
"name": "spring.jta.bitronix.properties.current-node-only-recovery",
"description": "Whether to recover only the current node. Should be enabled if you run multiple instances of the transaction manager on the same JMS and JDBC resources.",
"defaultValue": true
},
{
"name": "spring.jta.bitronix.properties.debug-zero-resource-transaction",
"description": "Whether to log the creation and commit call stacks of transactions executed without a single enlisted resource.",
"defaultValue": false
},
{
"name": "spring.jta.bitronix.properties.default-transaction-timeout",
"description": "Default transaction timeout, in seconds.",
"defaultValue": 60
},
{
"name": "spring.jta.bitronix.properties.disable-jmx",
"description": "Whether to enable JMX support.",
"defaultValue": false
},
{
"name": "spring.jta.bitronix.properties.exception-analyzer",
"description": "Set the fully qualified name of the exception analyzer implementation to use."
},
{
"name": "spring.jta.bitronix.properties.filter-log-status",
"description": "Whether to enable filtering of logs so that only mandatory logs are written.",
"defaultValue": false
},
{
"name": "spring.jta.bitronix.properties.force-batching-enabled",
"description": "Whether disk forces are batched.",
"defaultValue": true
},
{
"name": "spring.jta.bitronix.properties.forced-write-enabled",
"description": "Whether logs are forced to disk.",
"defaultValue": true
},
{
"name": "spring.jta.bitronix.properties.graceful-shutdown-interval",
"description": "Maximum amount of seconds the TM waits for transactions to get done before aborting them at shutdown time.",
"defaultValue": 60
},
{
"name": "spring.jta.bitronix.properties.jndi-transaction-synchronization-registry-name",
"description": "JNDI name of the TransactionSynchronizationRegistry."
},
{
"name": "spring.jta.bitronix.properties.jndi-user-transaction-name",
"description": "JNDI name of the UserTransaction."
},
{
"name": "spring.jta.bitronix.properties.journal",
"description": "Name of the journal. Can be 'disk', 'null', or a class name.",
"defaultValue": "disk"
},
{
"name": "spring.jta.bitronix.properties.log-part1-filename",
"description": "Name of the first fragment of the journal.",
"defaultValue": "btm1.tlog"
},
{
"name": "spring.jta.bitronix.properties.log-part2-filename",
"description": "Name of the second fragment of the journal.",
"defaultValue": "btm2.tlog"
},
{
"name": "spring.jta.bitronix.properties.max-log-size-in-mb",
"description": "Maximum size in megabytes of the journal fragments.",
"defaultValue": 2
},
{
"name": "spring.jta.bitronix.properties.resource-configuration-filename",
"description": "ResourceLoader configuration file name."
},
{
"name": "spring.jta.bitronix.properties.server-id",
"description": "ASCII ID that must uniquely identify this TM instance. Defaults to the machine's IP address."
},
{
"name": "spring.jta.bitronix.properties.skip-corrupted-logs",
"description": "Skip corrupted transactions log entries. Use only at last resort when all you have to recover is a pair of corrupted files.",
"defaultValue": false
},
{
"name": "spring.jta.bitronix.properties.warn-about-zero-resource-transaction",
"description": "Whether to log a warning for transactions executed without a single enlisted resource.",
"defaultValue": true
},
{
"name": "spring.jta.enabled",
"type": "java.lang.Boolean",

View File

@ -18,8 +18,6 @@ package org.springframework.boot.autoconfigure.transaction.jta;
import java.io.File;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.file.Path;
import javax.jms.ConnectionFactory;
@ -29,7 +27,6 @@ import javax.jms.XAConnectionFactory;
import javax.jms.XASession;
import javax.sql.DataSource;
import javax.sql.XADataSource;
import javax.transaction.TransactionManager;
import javax.transaction.UserTransaction;
import javax.transaction.xa.XAResource;
@ -67,7 +64,6 @@ import static org.mockito.Mockito.mock;
* @author Kazuki Shimizu
* @author Nishant Raut
*/
// @SuppressWarnings("deprecation")
class JtaAutoConfigurationTests {
private AnnotationConfigApplicationContext context;
@ -111,37 +107,6 @@ class JtaAutoConfigurationTests {
this.context.getBean(JtaTransactionManager.class);
}
@Test
@Deprecated
void bitronixSanityCheck() {
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(org.springframework.boot.jta.bitronix.BitronixDependentBeanFactoryPostProcessor.class);
this.context.getBean(JtaTransactionManager.class);
}
@Test
@Deprecated
void defaultBitronixServerId() throws UnknownHostException {
this.context = new AnnotationConfigApplicationContext(BitronixJtaConfiguration.class);
String serverId = this.context.getBean(bitronix.tm.Configuration.class).getServerId();
assertThat(serverId).isEqualTo(InetAddress.getLocalHost().getHostAddress());
}
@Test
@Deprecated
void customBitronixServerId() {
this.context = new AnnotationConfigApplicationContext();
TestPropertyValues.of("spring.jta.transactionManagerId:custom").applyTo(this.context);
this.context.register(BitronixJtaConfiguration.class);
this.context.refresh();
String serverId = this.context.getBean(bitronix.tm.Configuration.class).getServerId();
assertThat(serverId).isEqualTo("custom");
}
@Test
void defaultAtomikosTransactionManagerName(@TempDir Path dir) throws IOException {
this.context = new AnnotationConfigApplicationContext();
@ -166,20 +131,6 @@ class JtaAutoConfigurationTests {
assertThat(connectionFactory.getMaxPoolSize()).isEqualTo(10);
}
@Test
@Deprecated
void bitronixConnectionFactoryPoolConfiguration() {
this.context = new AnnotationConfigApplicationContext();
TestPropertyValues.of("spring.jta.bitronix.connectionfactory.minPoolSize:5",
"spring.jta.bitronix.connectionfactory.maxPoolSize:10").applyTo(this.context);
this.context.register(BitronixJtaConfiguration.class, PoolConfiguration.class);
this.context.refresh();
org.springframework.boot.jta.bitronix.PoolingConnectionFactoryBean connectionFactory = this.context
.getBean(org.springframework.boot.jta.bitronix.PoolingConnectionFactoryBean.class);
assertThat(connectionFactory.getMinPoolSize()).isEqualTo(5);
assertThat(connectionFactory.getMaxPoolSize()).isEqualTo(10);
}
@Test
void atomikosDataSourcePoolConfiguration() {
this.context = new AnnotationConfigApplicationContext();
@ -193,21 +144,6 @@ class JtaAutoConfigurationTests {
assertThat(dataSource.getMaxPoolSize()).isEqualTo(10);
}
@Test
@Deprecated
void bitronixDataSourcePoolConfiguration() {
this.context = new AnnotationConfigApplicationContext();
TestPropertyValues
.of("spring.jta.bitronix.datasource.minPoolSize:5", "spring.jta.bitronix.datasource.maxPoolSize:10")
.applyTo(this.context);
this.context.register(BitronixJtaConfiguration.class, PoolConfiguration.class);
this.context.refresh();
org.springframework.boot.jta.bitronix.PoolingDataSourceBean dataSource = this.context
.getBean(org.springframework.boot.jta.bitronix.PoolingDataSourceBean.class);
assertThat(dataSource.getMinPoolSize()).isEqualTo(5);
assertThat(dataSource.getMaxPoolSize()).isEqualTo(10);
}
@Test
void atomikosCustomizeJtaTransactionManagerUsingProperties() {
this.context = new AnnotationConfigApplicationContext();
@ -221,20 +157,6 @@ class JtaAutoConfigurationTests {
assertThat(transactionManager.isRollbackOnCommitFailure()).isTrue();
}
@Test
@Deprecated
void bitronixCustomizeJtaTransactionManagerUsingProperties() {
this.context = new AnnotationConfigApplicationContext();
TestPropertyValues
.of("spring.transaction.default-timeout:30", "spring.transaction.rollback-on-commit-failure:true")
.applyTo(this.context);
this.context.register(BitronixJtaConfiguration.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)
static class CustomTransactionManagerConfig {

View File

@ -128,13 +128,6 @@ bom {
]
}
}
library("Bitronix", "2.1.4") {
group("org.codehaus.btm") {
modules = [
"btm"
]
}
}
library("Build Helper Maven Plugin", "3.2.0") {
group("org.codehaus.mojo") {
plugins = [
@ -1421,7 +1414,6 @@ bom {
"spring-boot-starter-jooq",
"spring-boot-starter-json",
"spring-boot-starter-jta-atomikos",
"spring-boot-starter-jta-bitronix",
"spring-boot-starter-log4j2",
"spring-boot-starter-logging",
"spring-boot-starter-mail",

View File

@ -6472,7 +6472,6 @@ When a `jndi-name` is set, it takes precedence over all other Session-related se
[[boot-features-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.
Deprecated support for using a https://github.com/bitronix/btm[Bitronix] embedded transaction manager is also provided but it will be removed in a future release.
JTA transactions are also supported when deploying to a suitable Java EE Application Server.
When a JTA environment is detected, Spring's `JtaTransactionManager` is used to manage transactions.
@ -6499,24 +6498,6 @@ To ensure uniqueness in production, you should configure the configprop:spring.j
[[boot-features-jta-bitronix]]
=== Using a Bitronix Transaction Manager
NOTE: As of Spring Boot 2.3, support for Bitronix has been deprecated and will be removed in a future release.
You can use the `spring-boot-starter-jta-bitronix` starter to add the appropriate Bitronix dependencies to your project.
As with Atomikos, Spring Boot automatically configures Bitronix and post-processes your beans to ensure that startup and shutdown ordering is correct.
By default, Bitronix transaction log files (`part1.btm` and `part2.btm`) are written to a `transaction-logs` directory in your application home directory.
You can customize the location of this directory by setting the configprop:spring.jta.log-dir[] property.
Properties starting with `spring.jta.bitronix.properties` are also bound to the `bitronix.tm.Configuration` bean, allowing for complete customization.
See the https://github.com/bitronix/btm/wiki/Transaction-manager-configuration[Bitronix documentation] for details.
NOTE: To ensure that multiple transaction managers can safely coordinate the same resource managers, each Bitronix instance must be configured with a unique ID.
By default, this ID is the IP address of the machine on which Bitronix 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.
[[boot-features-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.

View File

@ -1,14 +0,0 @@
plugins {
id "org.springframework.boot.starter"
}
description = "Starter for JTA transactions using Bitronix. Deprecated since 2.3.0"
dependencies {
api(project(":spring-boot-project:spring-boot-starters:spring-boot-starter"))
api("jakarta.jms:jakarta.jms-api")
api("jakarta.transaction:jakarta.transaction-api")
api("org.codehaus.btm:btm") {
exclude group: "javax.transaction", module: "jta"
}
}

View File

@ -44,7 +44,6 @@ dependencies {
optional("org.apache.tomcat.embed:tomcat-embed-jasper")
optional("org.apache.tomcat:tomcat-jdbc")
optional("org.assertj:assertj-core")
optional("org.codehaus.btm:btm")
optional("org.codehaus.groovy:groovy")
optional("org.codehaus.groovy:groovy-xml")
optional("org.eclipse.jetty:jetty-servlets")

View File

@ -1,81 +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.bitronix;
import javax.transaction.TransactionManager;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.core.Ordered;
/**
* {@link BeanFactoryPostProcessor} to automatically register the recommended
* {@link ConfigurableListableBeanFactory#registerDependentBean(String, String)
* dependencies} for correct Bitronix shutdown ordering. With Bitronix it appears that
* ConnectionFactory and DataSource beans must be shutdown before the
* {@link TransactionManager}.
*
* @author Phillip Webb
* @since 1.2.0
* @deprecated since 2.3.0 as the Bitronix project is no longer being maintained
*/
@Deprecated
public class BitronixDependentBeanFactoryPostProcessor 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(TransactionManager.class, true, false);
for (String transactionManager : transactionManagers) {
addTransactionManagerDependencies(beanFactory, transactionManager);
}
}
private void addTransactionManagerDependencies(ConfigurableListableBeanFactory beanFactory,
String transactionManager) {
for (String dependentBeanName : getBeanNamesForType(beanFactory, "javax.jms.ConnectionFactory")) {
beanFactory.registerDependentBean(transactionManager, dependentBeanName);
}
for (String dependentBeanName : getBeanNamesForType(beanFactory, "javax.sql.DataSource")) {
beanFactory.registerDependentBean(transactionManager, dependentBeanName);
}
}
private String[] getBeanNamesForType(ConfigurableListableBeanFactory beanFactory, String type) {
try {
return beanFactory.getBeanNamesForType(Class.forName(type), true, false);
}
catch (ClassNotFoundException | NoClassDefFoundError ex) {
// Ignore
}
return NO_BEANS;
}
@Override
public int getOrder() {
return this.order;
}
public void setOrder(int order) {
this.order = order;
}
}

View File

@ -1,42 +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.bitronix;
import javax.jms.ConnectionFactory;
import javax.jms.XAConnectionFactory;
import org.springframework.boot.jms.XAConnectionFactoryWrapper;
/**
* {@link XAConnectionFactoryWrapper} that uses a Bitronix
* {@link PoolingConnectionFactoryBean} to wrap a {@link XAConnectionFactory}.
*
* @author Phillip Webb
* @since 1.2.0
* @deprecated since 2.3.0 as the Bitronix project is no longer being maintained
*/
@Deprecated
public class BitronixXAConnectionFactoryWrapper implements XAConnectionFactoryWrapper {
@Override
public ConnectionFactory wrapConnectionFactory(XAConnectionFactory connectionFactory) {
PoolingConnectionFactoryBean pool = new PoolingConnectionFactoryBean();
pool.setConnectionFactory(connectionFactory);
return pool;
}
}

View File

@ -1,41 +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.bitronix;
import javax.sql.XADataSource;
import org.springframework.boot.jdbc.XADataSourceWrapper;
/**
* {@link XADataSourceWrapper} that uses a Bitronix {@link PoolingDataSourceBean} to wrap
* a {@link XADataSource}.
*
* @author Phillip Webb
* @since 1.2.0
* @deprecated since 2.3.0 as the Bitronix project is no longer being maintained
*/
@Deprecated
public class BitronixXADataSourceWrapper implements XADataSourceWrapper {
@Override
public PoolingDataSourceBean wrapDataSource(XADataSource dataSource) throws Exception {
PoolingDataSourceBean pool = new PoolingDataSourceBean();
pool.setDataSource(dataSource);
return pool;
}
}

View File

@ -1,157 +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.bitronix;
import java.util.Properties;
import javax.jms.JMSException;
import javax.jms.XAConnection;
import javax.jms.XAConnectionFactory;
import javax.jms.XAJMSContext;
import bitronix.tm.resource.common.ResourceBean;
import bitronix.tm.resource.common.XAStatefulHolder;
import bitronix.tm.resource.jms.PoolingConnectionFactory;
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 PoolingConnectionFactory}. Provides sensible defaults
* and also supports direct wrapping of a {@link XAConnectionFactory} instance.
*
* @author Phillip Webb
* @author Josh Long
* @author Andy Wilkinson
* @since 1.2.0
* @deprecated since 2.3.0 as the Bitronix project is no longer being maintained
*/
@Deprecated
@SuppressWarnings("serial")
@ConfigurationProperties(prefix = "spring.jta.bitronix.connectionfactory")
public class PoolingConnectionFactoryBean extends PoolingConnectionFactory
implements BeanNameAware, InitializingBean, DisposableBean {
private static final ThreadLocal<PoolingConnectionFactoryBean> source = new ThreadLocal<>();
private String beanName;
private XAConnectionFactory connectionFactory;
public PoolingConnectionFactoryBean() {
setMaxPoolSize(10);
setTestConnections(true);
setAutomaticEnlistingEnabled(true);
setAllowLocalTransactions(true);
}
@Override
public synchronized void init() {
source.set(this);
try {
super.init();
}
finally {
source.remove();
}
}
@Override
public void setBeanName(String name) {
this.beanName = name;
}
@Override
public void afterPropertiesSet() throws Exception {
if (!StringUtils.hasLength(getUniqueName())) {
setUniqueName(this.beanName);
}
init();
}
@Override
public void destroy() throws Exception {
close();
}
/**
* Set the {@link XAConnectionFactory} directly, instead of calling
* {@link #setClassName(String)}.
* @param connectionFactory the connection factory to use
*/
public void setConnectionFactory(XAConnectionFactory connectionFactory) {
this.connectionFactory = connectionFactory;
setClassName(DirectXAConnectionFactory.class.getName());
setDriverProperties(new Properties());
}
protected final XAConnectionFactory getConnectionFactory() {
return this.connectionFactory;
}
@Override
public XAStatefulHolder createPooledConnection(Object xaFactory, ResourceBean bean) throws Exception {
if (xaFactory instanceof DirectXAConnectionFactory) {
xaFactory = ((DirectXAConnectionFactory) xaFactory).getConnectionFactory();
}
return super.createPooledConnection(xaFactory, bean);
}
/**
* A {@link XAConnectionFactory} implementation that delegates to the
* {@link ThreadLocal} {@link PoolingConnectionFactoryBean}.
*
* @see PoolingConnectionFactoryBean#setConnectionFactory(XAConnectionFactory)
*/
public static class DirectXAConnectionFactory implements XAConnectionFactory {
private final XAConnectionFactory connectionFactory;
public DirectXAConnectionFactory() {
this.connectionFactory = source.get().connectionFactory;
}
@Override
public XAConnection createXAConnection() throws JMSException {
return this.connectionFactory.createXAConnection();
}
@Override
public XAConnection createXAConnection(String userName, String password) throws JMSException {
return this.connectionFactory.createXAConnection(userName, password);
}
public XAConnectionFactory getConnectionFactory() {
return this.connectionFactory;
}
@Override
public XAJMSContext createXAContext() {
return this.connectionFactory.createXAContext();
}
@Override
public XAJMSContext createXAContext(String username, String password) {
return this.connectionFactory.createXAContext(username, password);
}
}
}

View File

@ -1,179 +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.bitronix;
import java.io.PrintWriter;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.Properties;
import java.util.logging.Logger;
import javax.sql.XAConnection;
import javax.sql.XADataSource;
import bitronix.tm.resource.common.ResourceBean;
import bitronix.tm.resource.common.XAStatefulHolder;
import bitronix.tm.resource.jdbc.PoolingDataSource;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.util.StringUtils;
/**
* Spring friendly version of {@link PoolingDataSource}. Provides sensible defaults and
* also supports direct wrapping of a {@link XADataSource} instance.
*
* @author Phillip Webb
* @author Josh Long
* @author Andy Wilkinson
* @since 1.2.0
* @deprecated since 2.3.0 as the Bitronix project is no longer being maintained
*/
@Deprecated
@SuppressWarnings("serial")
@ConfigurationProperties(prefix = "spring.jta.bitronix.datasource")
public class PoolingDataSourceBean extends PoolingDataSource implements BeanNameAware, InitializingBean {
private static final ThreadLocal<PoolingDataSourceBean> source = new ThreadLocal<>();
private XADataSource dataSource;
private String beanName;
public PoolingDataSourceBean() {
setMaxPoolSize(10);
setAllowLocalTransactions(true);
setEnableJdbc4ConnectionTest(true);
}
@Override
public synchronized void init() {
source.set(this);
try {
super.init();
}
finally {
source.remove();
}
}
@Override
public void setBeanName(String name) {
this.beanName = name;
}
@Override
public void afterPropertiesSet() throws Exception {
if (!StringUtils.hasLength(getUniqueName())) {
setUniqueName(this.beanName);
}
}
/**
* Set the {@link XADataSource} directly, instead of calling
* {@link #setClassName(String)}.
* @param dataSource the data source to use
*/
public void setDataSource(XADataSource dataSource) {
this.dataSource = dataSource;
setClassName(DirectXADataSource.class.getName());
setDriverProperties(new Properties());
}
protected final XADataSource getDataSource() {
return this.dataSource;
}
@Override
public XAStatefulHolder createPooledConnection(Object xaFactory, ResourceBean bean) throws Exception {
if (xaFactory instanceof DirectXADataSource) {
xaFactory = ((DirectXADataSource) xaFactory).getDataSource();
}
return super.createPooledConnection(xaFactory, bean);
}
@Override
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
XADataSource dataSource = this.dataSource;
if (dataSource != null) {
try {
return dataSource.getParentLogger();
}
catch (Exception ex) {
// Swallow and continue
}
}
return Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
}
/**
* A {@link XADataSource} implementation that delegates to the {@link ThreadLocal}
* {@link PoolingDataSourceBean}.
*
* @see PoolingDataSourceBean#setDataSource(XADataSource)
*/
public static class DirectXADataSource implements XADataSource {
private final XADataSource dataSource;
public DirectXADataSource() {
this.dataSource = source.get().dataSource;
}
@Override
public PrintWriter getLogWriter() throws SQLException {
return this.dataSource.getLogWriter();
}
@Override
public XAConnection getXAConnection() throws SQLException {
return this.dataSource.getXAConnection();
}
@Override
public XAConnection getXAConnection(String user, String password) throws SQLException {
return this.dataSource.getXAConnection(user, password);
}
@Override
public void setLogWriter(PrintWriter out) throws SQLException {
this.dataSource.setLogWriter(out);
}
@Override
public void setLoginTimeout(int seconds) throws SQLException {
this.dataSource.setLoginTimeout(seconds);
}
@Override
public int getLoginTimeout() throws SQLException {
return this.dataSource.getLoginTimeout();
}
@Override
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
return this.dataSource.getParentLogger();
}
public XADataSource getDataSource() {
return this.dataSource;
}
}
}

View File

@ -1,21 +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.
*/
/**
* Support classes for Bitronix JTA.
* @deprecated since 2.3.0 as the Bitronix project is no longer being maintained
*/
package org.springframework.boot.jta.bitronix;

View File

@ -469,273 +469,331 @@
{
"name": "spring.jta.bitronix.connectionfactory.acquire-increment",
"type": "java.lang.Integer",
"description": "Number of connections to create when growing the pool.",
"defaultValue": 1
"deprecation": {
"level": "error"
}
},
{
"name": "spring.jta.bitronix.connectionfactory.acquisition-interval",
"type": "java.lang.Integer",
"description": "Time, in seconds, to wait before trying to acquire a connection again after an invalid connection was acquired.",
"defaultValue": 1
"deprecation": {
"level": "error"
}
},
{
"name": "spring.jta.bitronix.connectionfactory.acquisition-timeout",
"type": "java.lang.Integer",
"description": "Timeout, in seconds, for acquiring connections from the pool.",
"defaultValue": 30
"deprecation": {
"level": "error"
}
},
{
"name": "spring.jta.bitronix.connectionfactory.allow-local-transactions",
"type": "java.lang.Boolean",
"description": "Whether the transaction manager should allow mixing XA and non-XA transactions.",
"defaultValue": false
"deprecation": {
"level": "error"
}
},
{
"name": "spring.jta.bitronix.connectionfactory.apply-transaction-timeout",
"type": "java.lang.Boolean",
"description": "Whether the transaction timeout should be set on the XAResource when it is enlisted.",
"defaultValue": false
"deprecation": {
"level": "error"
}
},
{
"name": "spring.jta.bitronix.connectionfactory.automatic-enlisting-enabled",
"type": "java.lang.Boolean",
"description": "Whether resources should be enlisted and delisted automatically.",
"defaultValue": true
"deprecation": {
"level": "error"
}
},
{
"name": "spring.jta.bitronix.connectionfactory.cache-producers-consumers",
"type": "java.lang.Boolean",
"description": "Whether producers and consumers should be cached.",
"defaultValue": true
"deprecation": {
"level": "error"
}
},
{
"name": "spring.jta.bitronix.connectionfactory.class-name",
"type": "java.lang.String",
"description": "Underlying implementation class name of the XA resource."
"deprecation": {
"level": "error"
}
},
{
"name": "spring.jta.bitronix.connectionfactory.defer-connection-release",
"type": "java.lang.Boolean",
"description": "Whether the provider can run many transactions on the same connection and supports transaction interleaving.",
"defaultValue": true
"deprecation": {
"level": "error"
}
},
{
"name": "spring.jta.bitronix.connectionfactory.disabled",
"type": "java.lang.Boolean",
"description": "Whether this resource is disabled, meaning it's temporarily forbidden to acquire a connection from its pool.",
"defaultValue": false
"deprecation": {
"level": "error"
}
},
{
"name": "spring.jta.bitronix.connectionfactory.driver-properties",
"type": "java.util.Properties",
"description": "Properties that should be set on the underlying implementation."
"deprecation": {
"level": "error"
}
},
{
"name": "spring.jta.bitronix.connectionfactory.ignore-recovery-failures",
"type": "java.lang.Boolean",
"description": "Whether recovery failures should be ignored.",
"defaultValue": false
"deprecation": {
"level": "error"
}
},
{
"name": "spring.jta.bitronix.connectionfactory.max-idle-time",
"type": "java.lang.Integer",
"description": "Time, in seconds, after which connections are cleaned up from the pool.",
"defaultValue": 60
"deprecation": {
"level": "error"
}
},
{
"name": "spring.jta.bitronix.connectionfactory.max-pool-size",
"type": "java.lang.Integer",
"description": "Maximum size of the pool. 0 denotes no limit.",
"defaultValue": 0
"deprecation": {
"level": "error"
}
},
{
"name": "spring.jta.bitronix.connectionfactory.min-pool-size",
"type": "java.lang.Integer",
"description": "Minimum size of the pool.",
"defaultValue": 0
"deprecation": {
"level": "error"
}
},
{
"name": "spring.jta.bitronix.connectionfactory.password",
"type": "java.lang.String",
"description": "Password to use to connect to the JMS provider."
"deprecation": {
"level": "error"
}
},
{
"name": "spring.jta.bitronix.connectionfactory.share-transaction-connections",
"type": "java.lang.Boolean",
"description": "Whether connections in the ACCESSIBLE state can be shared within the context of a transaction.",
"defaultValue": false
"deprecation": {
"level": "error"
}
},
{
"name": "spring.jta.bitronix.connectionfactory.test-connections",
"type": "java.lang.Boolean",
"description": "Whether connections should be tested when acquired from the pool.",
"defaultValue": false
"deprecation": {
"level": "error"
}
},
{
"name": "spring.jta.bitronix.connectionfactory.two-pc-ordering-position",
"type": "java.lang.Integer",
"description": "Position that this resource should take during two-phase commit (always first is Integer.MIN_VALUE, always last is Integer.MAX_VALUE).",
"defaultValue": 1
"deprecation": {
"level": "error"
}
},
{
"name": "spring.jta.bitronix.connectionfactory.unique-name",
"type": "java.lang.String",
"description": "Unique name used to identify the resource during recovery.",
"defaultValue": "jmsConnectionFactory"
"deprecation": {
"level": "error"
}
},
{
"name": "spring.jta.bitronix.connectionfactory.use-tm-join",
"type": "java.lang.Boolean",
"description": "Whether TMJOIN should be used when starting XAResources.",
"defaultValue": true
"deprecation": {
"level": "error"
}
},
{
"name": "spring.jta.bitronix.connectionfactory.user",
"type": "java.lang.String",
"description": "User to use to connect to the JMS provider."
"deprecation": {
"level": "error"
}
},
{
"name": "spring.jta.bitronix.datasource.acquire-increment",
"type": "java.lang.Integer",
"description": "Number of connections to create when growing the pool.",
"defaultValue": 1
"deprecation": {
"level": "error"
}
},
{
"name": "spring.jta.bitronix.datasource.acquisition-interval",
"type": "java.lang.Integer",
"description": "Time, in seconds, to wait before trying to acquire a connection again after an invalid connection was acquired.",
"defaultValue": 1
"deprecation": {
"level": "error"
}
},
{
"name": "spring.jta.bitronix.datasource.acquisition-timeout",
"type": "java.lang.Integer",
"description": "Timeout, in seconds, for acquiring connections from the pool.",
"defaultValue": 30
"deprecation": {
"level": "error"
}
},
{
"name": "spring.jta.bitronix.datasource.allow-local-transactions",
"type": "java.lang.Boolean",
"description": "Whether the transaction manager should allow mixing XA and non-XA transactions.",
"defaultValue": false
"deprecation": {
"level": "error"
}
},
{
"name": "spring.jta.bitronix.datasource.apply-transaction-timeout",
"type": "java.lang.Boolean",
"description": "Whether the transaction timeout should be set on the XAResource when it is enlisted.",
"defaultValue": "false"
"deprecation": {
"level": "error"
}
},
{
"name": "spring.jta.bitronix.datasource.automatic-enlisting-enabled",
"type": "java.lang.Boolean",
"description": "Whether resources should be enlisted and delisted automatically.",
"defaultValue": true
"deprecation": {
"level": "error"
}
},
{
"name": "spring.jta.bitronix.datasource.class-name",
"type": "java.lang.String",
"description": "Underlying implementation class name of the XA resource."
"deprecation": {
"level": "error"
}
},
{
"name": "spring.jta.bitronix.datasource.cursor-holdability",
"type": "java.lang.String",
"description": "Default cursor holdability for connections."
"deprecation": {
"level": "error"
}
},
{
"name": "spring.jta.bitronix.datasource.defer-connection-release",
"type": "java.lang.Boolean",
"description": "Whether the database can run many transactions on the same connection and supports transaction interleaving.",
"defaultValue": true
"deprecation": {
"level": "error"
}
},
{
"name": "spring.jta.bitronix.datasource.disabled",
"type": "java.lang.Boolean",
"description": "Whether this resource is disabled, meaning it's temporarily forbidden to acquire a connection from its pool.",
"defaultValue": false
"deprecation": {
"level": "error"
}
},
{
"name": "spring.jta.bitronix.datasource.driver-properties",
"type": "java.util.Properties",
"description": "Properties that should be set on the underlying implementation."
"deprecation": {
"level": "error"
}
},
{
"name": "spring.jta.bitronix.datasource.enable-jdbc4-connection-test",
"type": "java.lang.Boolean",
"description": "Whether Connection.isValid() is called when acquiring a connection from the pool.",
"defaultValue": false
"deprecation": {
"level": "error"
}
},
{
"name": "spring.jta.bitronix.datasource.ignore-recovery-failures",
"type": "java.lang.Boolean",
"description": "Whether recovery failures should be ignored.",
"defaultValue": false
"deprecation": {
"level": "error"
}
},
{
"name": "spring.jta.bitronix.datasource.isolation-level",
"type": "java.lang.String",
"description": "Default isolation level for connections."
"deprecation": {
"level": "error"
}
},
{
"name": "spring.jta.bitronix.datasource.local-auto-commit",
"type": "java.lang.String",
"description": "Default auto-commit mode for local transactions."
"deprecation": {
"level": "error"
}
},
{
"name": "spring.jta.bitronix.datasource.login-timeout",
"type": "java.lang.Integer",
"description": "Timeout, in seconds, for establishing a database connection."
"deprecation": {
"level": "error"
}
},
{
"name": "spring.jta.bitronix.datasource.max-idle-time",
"type": "java.lang.Integer",
"description": "Time, in seconds, after which connections are cleaned up from the pool.",
"defaultValue": 60
"deprecation": {
"level": "error"
}
},
{
"name": "spring.jta.bitronix.datasource.max-pool-size",
"type": "java.lang.Integer",
"description": "Maximum size of the pool. 0 denotes no limit.",
"defaultValue": 0
"deprecation": {
"level": "error"
}
},
{
"name": "spring.jta.bitronix.datasource.min-pool-size",
"type": "java.lang.Integer",
"description": "Minimum size of the pool.",
"defaultValue": 0
"deprecation": {
"level": "error"
}
},
{
"name": "spring.jta.bitronix.datasource.prepared-statement-cache-size",
"type": "java.lang.Integer",
"description": "Target size of the prepared statement cache. 0 disables the cache.",
"defaultValue": 0
"deprecation": {
"level": "error"
}
},
{
"name": "spring.jta.bitronix.datasource.share-transaction-connections",
"type": "java.lang.Boolean",
"description": "Whether connections in the ACCESSIBLE state can be shared within the context of a transaction.",
"defaultValue": false
"deprecation": {
"level": "error"
}
},
{
"name": "spring.jta.bitronix.datasource.test-query",
"type": "java.lang.String",
"description": "SQL query or statement used to validate a connection before returning it."
"deprecation": {
"level": "error"
}
},
{
"name": "spring.jta.bitronix.datasource.two-pc-ordering-position",
"type": "java.lang.Integer",
"description": "Position that this resource should take during two-phase commit (always first is Integer.MIN_VALUE, and always last is Integer.MAX_VALUE).",
"defaultValue": 1
"deprecation": {
"level": "error"
}
},
{
"name": "spring.jta.bitronix.datasource.unique-name",
"type": "java.lang.String",
"description": "Unique name used to identify the resource during recovery.",
"defaultValue": "dataSource"
"deprecation": {
"level": "error"
}
},
{
"name": "spring.jta.bitronix.datasource.use-tm-join",
"type": "java.lang.Boolean",
"description": "Whether TMJOIN should be used when starting XAResources.",
"defaultValue": true
"deprecation": {
"level": "error"
}
},
{
"name": "spring.main.allow-bean-definition-overriding",

View File

@ -1,81 +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.bitronix;
import javax.jms.ConnectionFactory;
import javax.sql.DataSource;
import bitronix.tm.BitronixTransactionManager;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
/**
* Tests for {@link BitronixDependentBeanFactoryPostProcessor}.
*
* @author Phillip Webb
*/
@Deprecated
class BitronixDependentBeanFactoryPostProcessorTests {
private AnnotationConfigApplicationContext context;
@Test
void setsDependsOn() {
DefaultListableBeanFactory beanFactory = spy(new DefaultListableBeanFactory());
this.context = new AnnotationConfigApplicationContext(beanFactory);
this.context.register(Config.class);
this.context.refresh();
String name = "bitronixTransactionManager";
verify(beanFactory).registerDependentBean(name, "dataSource");
verify(beanFactory).registerDependentBean(name, "connectionFactory");
this.context.close();
}
@Configuration(proxyBeanMethods = false)
static class Config {
@Bean
DataSource dataSource() {
return mock(DataSource.class);
}
@Bean
ConnectionFactory connectionFactory() {
return mock(ConnectionFactory.class);
}
@Bean
BitronixTransactionManager bitronixTransactionManager() {
return mock(BitronixTransactionManager.class);
}
@Bean
static BitronixDependentBeanFactoryPostProcessor bitronixPostProcessor() {
return new BitronixDependentBeanFactoryPostProcessor();
}
}
}

View File

@ -1,44 +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.bitronix;
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 BitronixXAConnectionFactoryWrapper}.
*
* @author Phillip Webb
*/
@Deprecated
class BitronixXAConnectionFactoryWrapperTests {
@Test
void wrap() {
XAConnectionFactory connectionFactory = mock(XAConnectionFactory.class);
BitronixXAConnectionFactoryWrapper wrapper = new BitronixXAConnectionFactoryWrapper();
ConnectionFactory wrapped = wrapper.wrapConnectionFactory(connectionFactory);
assertThat(wrapped).isInstanceOf(PoolingConnectionFactoryBean.class);
assertThat(((PoolingConnectionFactoryBean) wrapped).getConnectionFactory()).isSameAs(connectionFactory);
}
}

View File

@ -1,44 +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.bitronix;
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 BitronixXADataSourceWrapper}.
*
* @author Phillip Webb
*/
@Deprecated
class BitronixXADataSourceWrapperTests {
@Test
void wrap() throws Exception {
XADataSource dataSource = mock(XADataSource.class);
BitronixXADataSourceWrapper wrapper = new BitronixXADataSourceWrapper();
DataSource wrapped = wrapper.wrapDataSource(dataSource);
assertThat(wrapped).isInstanceOf(PoolingDataSourceBean.class);
assertThat(((PoolingDataSourceBean) wrapped).getDataSource()).isSameAs(dataSource);
}
}

View File

@ -1,77 +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.bitronix;
import javax.jms.XAConnectionFactory;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
/**
* Tests for {@link PoolingConnectionFactoryBean}.
*
* @author Phillip Webb
*/
@Deprecated
class PoolingConnectionFactoryBeanTests {
@SuppressWarnings("serial")
private PoolingConnectionFactoryBean bean = new PoolingConnectionFactoryBean() {
@Override
public synchronized void init() {
// Stub out for the tests
}
};
@Test
void sensibleDefaults() {
assertThat(this.bean.getMaxPoolSize()).isEqualTo(10);
assertThat(this.bean.getTestConnections()).isTrue();
assertThat(this.bean.getAutomaticEnlistingEnabled()).isTrue();
assertThat(this.bean.getAllowLocalTransactions()).isTrue();
}
@Test
void setsUniqueNameIfNull() throws Exception {
this.bean.setBeanName("beanName");
this.bean.afterPropertiesSet();
assertThat(this.bean.getUniqueName()).isEqualTo("beanName");
}
@Test
void doesNotSetUniqueNameIfNotNull() throws Exception {
this.bean.setBeanName("beanName");
this.bean.setUniqueName("un");
this.bean.afterPropertiesSet();
assertThat(this.bean.getUniqueName()).isEqualTo("un");
}
@Test
void setConnectionFactory() throws Exception {
XAConnectionFactory factory = mock(XAConnectionFactory.class);
this.bean.setConnectionFactory(factory);
this.bean.setBeanName("beanName");
this.bean.afterPropertiesSet();
this.bean.init();
this.bean.createPooledConnection(factory, this.bean);
verify(factory).createXAConnection();
}
}

View File

@ -1,104 +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.bitronix;
import java.sql.Connection;
import java.sql.SQLFeatureNotSupportedException;
import java.util.logging.Logger;
import javax.sql.XAConnection;
import javax.sql.XADataSource;
import bitronix.tm.TransactionManagerServices;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
/**
* Tests for {@link PoolingDataSourceBean}.
*
* @author Phillip Webb
*/
@Deprecated
class PoolingDataSourceBeanTests {
private PoolingDataSourceBean bean = new PoolingDataSourceBean();
@Test
void sensibleDefaults() {
assertThat(this.bean.getMaxPoolSize()).isEqualTo(10);
assertThat(this.bean.getAutomaticEnlistingEnabled()).isTrue();
assertThat(this.bean.isEnableJdbc4ConnectionTest()).isTrue();
}
@Test
void setsUniqueNameIfNull() throws Exception {
this.bean.setBeanName("beanName");
this.bean.afterPropertiesSet();
assertThat(this.bean.getUniqueName()).isEqualTo("beanName");
}
@Test
void doesNotSetUniqueNameIfNotNull() throws Exception {
this.bean.setBeanName("beanName");
this.bean.setUniqueName("un");
this.bean.afterPropertiesSet();
assertThat(this.bean.getUniqueName()).isEqualTo("un");
}
@Test
void shouldReturnGlobalLoggerWhenDataSourceIsAbsent() throws SQLFeatureNotSupportedException {
assertThat(this.bean.getParentLogger()).isSameAs(Logger.getLogger(Logger.GLOBAL_LOGGER_NAME));
}
@Test
void shouldReturnGlobalLoggerWhenDataSourceThrowsException() throws SQLFeatureNotSupportedException {
XADataSource dataSource = mock(XADataSource.class);
given(dataSource.getParentLogger()).willThrow(new SQLFeatureNotSupportedException());
this.bean.setDataSource(dataSource);
assertThat(this.bean.getParentLogger()).isSameAs(Logger.getLogger(Logger.GLOBAL_LOGGER_NAME));
}
@Test
void shouldReturnParentLoggerFromDataSource() throws SQLFeatureNotSupportedException {
Logger logger = Logger.getLogger("test");
XADataSource dataSource = mock(XADataSource.class);
given(dataSource.getParentLogger()).willReturn(logger);
this.bean.setDataSource(dataSource);
assertThat(this.bean.getParentLogger()).isSameAs(logger);
}
@Test
void setDataSource() throws Exception {
XADataSource dataSource = mock(XADataSource.class);
XAConnection xaConnection = mock(XAConnection.class);
Connection connection = mock(Connection.class);
given(dataSource.getXAConnection()).willReturn(xaConnection);
given(xaConnection.getConnection()).willReturn(connection);
this.bean.setDataSource(dataSource);
this.bean.setBeanName("beanName");
this.bean.afterPropertiesSet();
this.bean.init();
this.bean.createPooledConnection(dataSource, this.bean);
verify(dataSource).getXAConnection();
TransactionManagerServices.getTaskScheduler().shutdown();
}
}

View File

@ -1,23 +0,0 @@
plugins {
id "java"
id "org.springframework.boot.conventions"
}
description = "Spring Boot Bitronix 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-bitronix"))
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: "org.apache.geronimo.specs", module: "geronimo-jms_2.0_spec"
}
testImplementation(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-test"))
}

View File

@ -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.bitronix;
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;
}
}

View File

@ -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.bitronix;
import org.springframework.data.jpa.repository.JpaRepository;
public interface AccountRepository extends JpaRepository<Account, Long> {
}

View File

@ -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.bitronix;
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");
}
}
}

View File

@ -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.bitronix;
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);
}
}

View File

@ -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.bitronix;
import java.io.Closeable;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
@SpringBootApplication
public class SampleBitronixApplication {
public static void main(String[] args) throws Exception {
ApplicationContext context = SpringApplication.run(SampleBitronixApplication.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);
((Closeable) context).close();
}
}

View File

@ -1,2 +0,0 @@
spring.artemis.embedded.queues=accounts
spring.jpa.open-in-view=true

View File

@ -1,68 +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.bitronix;
import java.util.function.Consumer;
import bitronix.tm.resource.jms.PoolingConnectionFactory;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.test.system.CapturedOutput;
import org.springframework.boot.test.system.OutputCaptureExtension;
import org.springframework.context.ApplicationContext;
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 SampleBitronixApplicationTests {
@Test
void testTransactionRollback(CapturedOutput output) throws Exception {
SampleBitronixApplication.main(new String[] {});
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));
}
@Test
void testExposesXaAndNonXa() {
ApplicationContext context = SpringApplication.run(SampleBitronixApplication.class);
Object jmsConnectionFactory = context.getBean("jmsConnectionFactory");
Object xaJmsConnectionFactory = context.getBean("xaJmsConnectionFactory");
Object nonXaJmsConnectionFactory = context.getBean("nonXaJmsConnectionFactory");
assertThat(jmsConnectionFactory).isSameAs(xaJmsConnectionFactory);
assertThat(jmsConnectionFactory).isInstanceOf(PoolingConnectionFactory.class);
assertThat(nonXaJmsConnectionFactory).isNotInstanceOf(PoolingConnectionFactory.class);
}
private <T extends CharSequence> Consumer<T> numberOfOccurrences(String substring, int expectedCount) {
return (charSequence) -> {
int count = StringUtils.countOccurrencesOf(charSequence.toString(), substring);
assertThat(count).isEqualTo(expectedCount);
};
}
}