Commit 48800f18 authored by Phillip Webb's avatar Phillip Webb

Polish contribution

parent a2adc5a1
/* /*
* Copyright 2012-2015 the original author or authors. * Copyright 2012-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -22,7 +22,6 @@ import javax.transaction.UserTransaction; ...@@ -22,7 +22,6 @@ import javax.transaction.UserTransaction;
import com.arjuna.ats.jbossatx.jta.RecoveryManagerService; import com.arjuna.ats.jbossatx.jta.RecoveryManagerService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.jta.XAConnectionFactoryWrapper; import org.springframework.boot.jta.XAConnectionFactoryWrapper;
...@@ -42,15 +41,20 @@ import org.springframework.transaction.jta.JtaTransactionManager; ...@@ -42,15 +41,20 @@ import org.springframework.transaction.jta.JtaTransactionManager;
/** /**
* JTA Configuration for <a href="http://narayana.io/">Narayana</a>. * JTA Configuration for <a href="http://narayana.io/">Narayana</a>.
* *
* @author <a href="mailto:gytis@redhat.com">Gytis Trikleris</a> * @author Gytis Trikleris
* @since 1.4.0
*/ */
@Configuration @Configuration
@ConditionalOnClass({ JtaTransactionManager.class, com.arjuna.ats.jta.UserTransaction.class }) @ConditionalOnClass({ JtaTransactionManager.class,
com.arjuna.ats.jta.UserTransaction.class })
@ConditionalOnMissingBean(PlatformTransactionManager.class) @ConditionalOnMissingBean(PlatformTransactionManager.class)
public class NarayanaJtaConfiguration { public class NarayanaJtaConfiguration {
@Autowired private final JtaProperties jtaProperties;
private JtaProperties jtaProperties;
public NarayanaJtaConfiguration(JtaProperties jtaProperties) {
this.jtaProperties = jtaProperties;
}
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
...@@ -60,53 +64,57 @@ public class NarayanaJtaConfiguration { ...@@ -60,53 +64,57 @@ public class NarayanaJtaConfiguration {
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
public NarayanaConfigurationBean narayanaConfigurationBean(NarayanaProperties narayanaProperties) { public NarayanaConfigurationBean narayanaConfiguration(
NarayanaProperties properties) {
if (this.jtaProperties.getLogDir() != null) { if (this.jtaProperties.getLogDir() != null) {
narayanaProperties.setLogDir(this.jtaProperties.getLogDir()); properties.setLogDir(this.jtaProperties.getLogDir());
} }
if (this.jtaProperties.getTransactionManagerId() != null) { if (this.jtaProperties.getTransactionManagerId() != null) {
narayanaProperties.setTransactionManagerId(this.jtaProperties.getTransactionManagerId()); properties.setTransactionManagerId(
this.jtaProperties.getTransactionManagerId());
} }
return new NarayanaConfigurationBean(properties);
return new NarayanaConfigurationBean(narayanaProperties);
} }
@Bean @Bean
@DependsOn("narayanaConfigurationBean") @DependsOn("narayanaConfiguration")
@ConditionalOnMissingBean @ConditionalOnMissingBean
public UserTransaction narayanaUserTransaction() { public UserTransaction narayanaUserTransaction() {
return com.arjuna.ats.jta.UserTransaction.userTransaction(); return com.arjuna.ats.jta.UserTransaction.userTransaction();
} }
@Bean @Bean
@DependsOn("narayanaConfigurationBean") @DependsOn("narayanaConfiguration")
@ConditionalOnMissingBean @ConditionalOnMissingBean
public TransactionManager narayanaTransactionManager() { public TransactionManager narayanaTransactionManager() {
return com.arjuna.ats.jta.TransactionManager.transactionManager(); return com.arjuna.ats.jta.TransactionManager.transactionManager();
} }
@Bean @Bean
@DependsOn("narayanaConfigurationBean") @DependsOn("narayanaConfiguration")
public RecoveryManagerService narayanaRecoveryManagerService() { public RecoveryManagerService narayanaRecoveryManagerService() {
return new RecoveryManagerService(); return new RecoveryManagerService();
} }
@Bean @Bean
public NarayanaRecoveryManagerBean narayanaRecoveryManagerBean(RecoveryManagerService recoveryManagerService) { public NarayanaRecoveryManagerBean narayanaRecoveryManager(
RecoveryManagerService recoveryManagerService) {
return new NarayanaRecoveryManagerBean(recoveryManagerService); return new NarayanaRecoveryManagerBean(recoveryManagerService);
} }
@Bean @Bean
public JtaTransactionManager transactionManager(UserTransaction userTransaction, TransactionManager transactionManager) { public JtaTransactionManager transactionManager(UserTransaction userTransaction,
TransactionManager transactionManager) {
return new JtaTransactionManager(userTransaction, transactionManager); return new JtaTransactionManager(userTransaction, transactionManager);
} }
@Bean @Bean
@ConditionalOnMissingBean(XADataSourceWrapper.class) @ConditionalOnMissingBean(XADataSourceWrapper.class)
public XADataSourceWrapper xaDataSourceWrapper(NarayanaRecoveryManagerBean narayanaRecoveryManagerBean, public XADataSourceWrapper xaDataSourceWrapper(
NarayanaRecoveryManagerBean narayanaRecoveryManagerBean,
NarayanaProperties narayanaProperties) { NarayanaProperties narayanaProperties) {
return new NarayanaXADataSourceWrapper(narayanaRecoveryManagerBean, narayanaProperties); return new NarayanaXADataSourceWrapper(narayanaRecoveryManagerBean,
narayanaProperties);
} }
@Bean @Bean
...@@ -121,9 +129,12 @@ public class NarayanaJtaConfiguration { ...@@ -121,9 +129,12 @@ public class NarayanaJtaConfiguration {
@Bean @Bean
@ConditionalOnMissingBean(XAConnectionFactoryWrapper.class) @ConditionalOnMissingBean(XAConnectionFactoryWrapper.class)
public NarayanaXAConnectionFactoryWrapper xaConnectionFactoryWrapper(TransactionManager transactionManager, public NarayanaXAConnectionFactoryWrapper xaConnectionFactoryWrapper(
NarayanaRecoveryManagerBean narayanaRecoveryManagerBean, NarayanaProperties narayanaProperties) { TransactionManager transactionManager,
return new NarayanaXAConnectionFactoryWrapper(transactionManager, narayanaRecoveryManagerBean, narayanaProperties); NarayanaRecoveryManagerBean narayanaRecoveryManagerBean,
NarayanaProperties narayanaProperties) {
return new NarayanaXAConnectionFactoryWrapper(transactionManager,
narayanaRecoveryManagerBean, narayanaProperties);
} }
} }
......
...@@ -100,6 +100,7 @@ ...@@ -100,6 +100,7 @@
<jaxen.version>1.1.6</jaxen.version> <jaxen.version>1.1.6</jaxen.version>
<jaybird.version>2.2.10</jaybird.version> <jaybird.version>2.2.10</jaybird.version>
<jboss-logging.version>3.3.0.Final</jboss-logging.version> <jboss-logging.version>3.3.0.Final</jboss-logging.version>
<jboss-transaction-spi.version>7.3.0.Final</jboss-transaction-spi.version>
<jdom2.version>2.0.6</jdom2.version> <jdom2.version>2.0.6</jdom2.version>
<jedis.version>2.8.1</jedis.version> <jedis.version>2.8.1</jedis.version>
<jersey.version>2.22.2</jersey.version> <jersey.version>2.22.2</jersey.version>
...@@ -124,6 +125,7 @@ ...@@ -124,6 +125,7 @@
<mockito.version>1.10.19</mockito.version> <mockito.version>1.10.19</mockito.version>
<mongodb.version>2.14.2</mongodb.version> <mongodb.version>2.14.2</mongodb.version>
<mysql.version>5.1.38</mysql.version> <mysql.version>5.1.38</mysql.version>
<narayana.version>5.3.2.Final</narayana.version>
<nekohtml.version>1.9.22</nekohtml.version> <nekohtml.version>1.9.22</nekohtml.version>
<neo4j-ogm.version>2.0.0</neo4j-ogm.version> <neo4j-ogm.version>2.0.0</neo4j-ogm.version>
<postgresql.version>9.4.1208.jre7</postgresql.version> <postgresql.version>9.4.1208.jre7</postgresql.version>
...@@ -174,8 +176,6 @@ ...@@ -174,8 +176,6 @@
<webjars-hal-browser.version>9f96c74</webjars-hal-browser.version> <webjars-hal-browser.version>9f96c74</webjars-hal-browser.version>
<webjars-locator.version>0.30</webjars-locator.version> <webjars-locator.version>0.30</webjars-locator.version>
<wsdl4j.version>1.6.3</wsdl4j.version> <wsdl4j.version>1.6.3</wsdl4j.version>
<narayana.version>5.3.2.Final</narayana.version>
<jboss-transaction-spi.version>7.3.0.Final</jboss-transaction-spi.version>
</properties> </properties>
<prerequisites> <prerequisites>
<maven>3.2.1</maven> <maven>3.2.1</maven>
...@@ -401,11 +401,6 @@ ...@@ -401,11 +401,6 @@
<artifactId>spring-boot-starter-jta-bitronix</artifactId> <artifactId>spring-boot-starter-jta-bitronix</artifactId>
<version>1.4.0.BUILD-SNAPSHOT</version> <version>1.4.0.BUILD-SNAPSHOT</version>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jta-narayana</artifactId>
<version>1.4.0.BUILD-SNAPSHOT</version>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId> <artifactId>spring-boot-starter-undertow</artifactId>
...@@ -436,6 +431,11 @@ ...@@ -436,6 +431,11 @@
<artifactId>spring-boot-starter-mustache</artifactId> <artifactId>spring-boot-starter-mustache</artifactId>
<version>1.4.0.BUILD-SNAPSHOT</version> <version>1.4.0.BUILD-SNAPSHOT</version>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jta-narayana</artifactId>
<version>1.4.0.BUILD-SNAPSHOT</version>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-remote-shell</artifactId> <artifactId>spring-boot-starter-remote-shell</artifactId>
...@@ -1740,11 +1740,36 @@ ...@@ -1740,11 +1740,36 @@
<artifactId>javassist</artifactId> <artifactId>javassist</artifactId>
<version>${javassist.version}</version> <version>${javassist.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.jboss</groupId>
<artifactId>jboss-transaction-spi</artifactId>
<version>${jboss-transaction-spi.version}</version>
</dependency>
<dependency> <dependency>
<groupId>org.jboss.logging</groupId> <groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId> <artifactId>jboss-logging</artifactId>
<version>${jboss-logging.version}</version> <version>${jboss-logging.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.jboss.narayana.jta</groupId>
<artifactId>jdbc</artifactId>
<version>${narayana.version}</version>
</dependency>
<dependency>
<groupId>org.jboss.narayana.jta</groupId>
<artifactId>jms</artifactId>
<version>${narayana.version}</version>
</dependency>
<dependency>
<groupId>org.jboss.narayana.jta</groupId>
<artifactId>jta</artifactId>
<version>${narayana.version}</version>
</dependency>
<dependency>
<groupId>org.jboss.narayana.jts</groupId>
<artifactId>narayana-jts-integration</artifactId>
<version>${narayana.version}</version>
</dependency>
<dependency> <dependency>
<groupId>org.jdom</groupId> <groupId>org.jdom</groupId>
<artifactId>jdom2</artifactId> <artifactId>jdom2</artifactId>
...@@ -2219,31 +2244,6 @@ ...@@ -2219,31 +2244,6 @@
<artifactId>wsdl4j</artifactId> <artifactId>wsdl4j</artifactId>
<version>${wsdl4j.version}</version> <version>${wsdl4j.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.jboss.narayana.jta</groupId>
<artifactId>jta</artifactId>
<version>${narayana.version}</version>
</dependency>
<dependency>
<groupId>org.jboss.narayana.jta</groupId>
<artifactId>jdbc</artifactId>
<version>${narayana.version}</version>
</dependency>
<dependency>
<groupId>org.jboss.narayana.jta</groupId>
<artifactId>jms</artifactId>
<version>${narayana.version}</version>
</dependency>
<dependency>
<groupId>org.jboss.narayana.jts</groupId>
<artifactId>narayana-jts-integration</artifactId>
<version>${narayana.version}</version>
</dependency>
<dependency>
<groupId>org.jboss</groupId>
<artifactId>jboss-transaction-spi</artifactId>
<version>${jboss-transaction-spi.version}</version>
</dependency>
</dependencies> </dependencies>
</dependencyManagement> </dependencyManagement>
<build> <build>
......
...@@ -716,17 +716,17 @@ content into your application; rather pick only the properties that you need. ...@@ -716,17 +716,17 @@ content into your application; rather pick only the properties that you need.
spring.jta.bitronix.properties.warn-about-zero-resource-transaction=true # Log a warning for transactions executed without a single enlisted resource. spring.jta.bitronix.properties.warn-about-zero-resource-transaction=true # Log a warning for transactions executed without a single enlisted resource.
# NARAYANA # NARAYANA
spring.jta.narayana.one-phase-commit=true # Enable or disable one phase commit optimisation
spring.jta.narayana.default-timeout=60 # Set default transaction timeout in seconds spring.jta.narayana.default-timeout=60 # Set default transaction timeout in seconds
spring.jta.narayana.expiry-scanners=com.arjuna.ats.internal.arjuna.recovery.ExpiredTransactionStatusManagerScanner # List of ExpiryScanner implementations
spring.jta.narayana.one-phase-commit=true # Enable or disable one phase commit optimisation
spring.jta.narayana.periodic-recovery-period=120 # Set interval in which periodic recovery scans are performed in seconds spring.jta.narayana.periodic-recovery-period=120 # Set interval in which periodic recovery scans are performed in seconds
spring.jta.narayana.recovery-backoff-period=10 # Set back off period between first and second phases of the recovery scan in seconds spring.jta.narayana.recovery-backoff-period=10 # Set back off period between first and second phases of the recovery scan in seconds
spring.jta.narayana.xa-resource-orphan-filters=com.arjuna.ats.internal.jta.recovery.arjunacore.JTATransactionLogXAResourceOrphanFilter,com.arjuna.ats.internal.jta.recovery.arjunacore.JTANodeNameXAResourceOrphanFilter # List of XAResourceOrphanFilter implementations
spring.jta.narayana.recovery-modules=com.arjuna.ats.internal.arjuna.recovery.AtomicActionRecoveryModule,com.arjuna.ats.internal.jta.recovery.arjunacore.XARecoveryModule # List of RecoveryModule implementations
spring.jta.narayana.expiry-scanners=com.arjuna.ats.internal.arjuna.recovery.ExpiredTransactionStatusManagerScanner # List of ExpiryScanner implementations
spring.jta.narayana.recovery-db-user= # Database username to be used by recovery manager spring.jta.narayana.recovery-db-user= # Database username to be used by recovery manager
spring.jta.narayana.recovery-db-pass= # Database password to be used by recovery manager spring.jta.narayana.recovery-db-pass= # Database password to be used by recovery manager
spring.jta.narayana.recovery-jms-user= # JMS username to be used by recovery manager spring.jta.narayana.recovery-jms-user= # JMS username to be used by recovery manager
spring.jta.narayana.recovery-jms-pass= # JMS password to be used by recovery manager spring.jta.narayana.recovery-jms-pass= # JMS password to be used by recovery manager
spring.jta.narayana.recovery-modules=com.arjuna.ats.internal.arjuna.recovery.AtomicActionRecoveryModule,com.arjuna.ats.internal.jta.recovery.arjunacore.XARecoveryModule # List of RecoveryModule implementations
spring.jta.narayana.xa-resource-orphan-filters=com.arjuna.ats.internal.jta.recovery.arjunacore.JTATransactionLogXAResourceOrphanFilter,com.arjuna.ats.internal.jta.recovery.arjunacore.JTANodeNameXAResourceOrphanFilter # List of XAResourceOrphanFilter implementations
# EMBEDDED MONGODB ({sc-spring-boot-autoconfigure}/mongo/embedded/EmbeddedMongoProperties.{sc-ext}[EmbeddedMongoProperties]) # EMBEDDED MONGODB ({sc-spring-boot-autoconfigure}/mongo/embedded/EmbeddedMongoProperties.{sc-ext}[EmbeddedMongoProperties])
spring.mongodb.embedded.features=SYNC_DELAY # Comma-separated list of features to enable. spring.mongodb.embedded.features=SYNC_DELAY # Comma-separated list of features to enable.
......
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion>
<modelVersion>4.0.0</modelVersion> <parent>
<parent> <artifactId>spring-boot-samples</artifactId>
<artifactId>spring-boot-samples</artifactId> <groupId>org.springframework.boot</groupId>
<groupId>org.springframework.boot</groupId> <version>1.4.0.BUILD-SNAPSHOT</version>
<version>1.4.0.BUILD-SNAPSHOT</version> </parent>
</parent> <artifactId>spring-boot-sample-jta-narayana</artifactId>
<artifactId>spring-boot-sample-jta-narayana</artifactId> <name>Spring Boot Narayana JTA Sample</name>
<name>Spring Boot Narayana JTA Sample</name> <description>Spring Boot Narayana JTA Sample</description>
<description>Spring Boot Narayana JTA Sample</description> <url>http://projects.spring.io/spring-boot/</url>
<url>http://projects.spring.io/spring-boot/</url> <properties>
<properties> <main.basedir>${basedir}/../..</main.basedir>
<main.basedir>${basedir}/../..</main.basedir> </properties>
</properties> <dependencies>
<dependencies> <dependency>
<dependency> <groupId>org.springframework</groupId>
<groupId>org.springframework</groupId> <artifactId>spring-jms</artifactId>
<artifactId>spring-jms</artifactId> </dependency>
</dependency> <dependency>
<dependency> <groupId>org.springframework.boot</groupId>
<groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId>
<artifactId>spring-boot-starter-data-jpa</artifactId> </dependency>
</dependency> <dependency>
<dependency> <groupId>org.springframework.boot</groupId>
<groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jta-narayana</artifactId>
<artifactId>spring-boot-starter-jta-narayana</artifactId> </dependency>
</dependency> <dependency>
<dependency> <groupId>org.springframework.boot</groupId>
<groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-hornetq</artifactId>
<artifactId>spring-boot-starter-hornetq</artifactId> </dependency>
</dependency> <dependency>
<dependency> <groupId>org.hornetq</groupId>
<groupId>org.hornetq</groupId> <artifactId>hornetq-jms-server</artifactId>
<artifactId>hornetq-jms-server</artifactId> </dependency>
</dependency> <dependency>
<dependency> <groupId>com.h2database</groupId>
<groupId>com.h2database</groupId> <artifactId>h2</artifactId>
<artifactId>h2</artifactId> </dependency>
</dependency> <dependency>
<dependency> <groupId>org.springframework.boot</groupId>
<groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId>
<artifactId>spring-boot-starter-test</artifactId> <scope>test</scope>
<scope>test</scope> </dependency>
</dependency> </dependencies>
</dependencies> <build>
<build> <plugins>
<plugins> <plugin>
<plugin> <groupId>org.springframework.boot</groupId>
<groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId>
<artifactId>spring-boot-maven-plugin</artifactId> </plugin>
</plugin> </plugins>
</plugins> </build>
</build> </project>
</project>
\ No newline at end of file
/* /*
* Copyright 2012-2014 the original author or authors. * Copyright 2012-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
......
/* /*
* Copyright 2012-2014 the original author or authors. * Copyright 2012-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
......
/* /*
* Copyright 2012-2014 the original author or authors. * Copyright 2012-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
......
/* /*
* Copyright 2012-2014 the original author or authors. * Copyright 2012-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
......
/* /*
* Copyright 2012-2014 the original author or authors. * Copyright 2012-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -26,7 +26,8 @@ import org.springframework.context.ApplicationContext; ...@@ -26,7 +26,8 @@ import org.springframework.context.ApplicationContext;
public class SampleNarayanaApplication { public class SampleNarayanaApplication {
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
ApplicationContext context = SpringApplication.run(SampleNarayanaApplication.class, args); ApplicationContext context = SpringApplication
.run(SampleNarayanaApplication.class, args);
AccountService service = context.getBean(AccountService.class); AccountService service = context.getBean(AccountService.class);
AccountRepository repository = context.getBean(AccountRepository.class); AccountRepository repository = context.getBean(AccountRepository.class);
service.createAccountAndNotify("josh"); service.createAccountAndNotify("josh");
...@@ -34,7 +35,8 @@ public class SampleNarayanaApplication { ...@@ -34,7 +35,8 @@ public class SampleNarayanaApplication {
try { try {
// Using username "error" will cause service to throw SampleRuntimeException // Using username "error" will cause service to throw SampleRuntimeException
service.createAccountAndNotify("error"); service.createAccountAndNotify("error");
} catch (SampleRuntimeException ex) { }
catch (SampleRuntimeException ex) {
// Log message to let test case know that exception was thrown // Log message to let test case know that exception was thrown
System.out.println(ex.getMessage()); System.out.println(ex.getMessage());
} }
......
/*
* Copyright 2012-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package sample.narayana; package sample.narayana;
/**
* @author <a href="mailto:gytis@redhat.com">Gytis Trikleris</a>
*/
public class SampleRuntimeException extends RuntimeException { public class SampleRuntimeException extends RuntimeException {
public SampleRuntimeException(String message) { public SampleRuntimeException(String message) {
......
/* /*
* Copyright 2012-2014 the original author or authors. * Copyright 2012-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -16,16 +16,18 @@ ...@@ -16,16 +16,18 @@
package sample.narayana; package sample.narayana;
import org.hamcrest.Matcher; import org.assertj.core.api.Condition;
import org.hamcrest.core.SubstringMatcher;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.springframework.boot.test.OutputCapture;
import static org.junit.Assert.assertThat; import org.springframework.boot.test.rule.OutputCapture;
import static org.assertj.core.api.Assertions.assertThat;
/** /**
* @author <a href="mailto:gytis@redhat.com">Gytis Trikleris</a> * Basic integration tests for demo application.
*
* @author Gytis Trikleris
*/ */
public class SampleNarayanaApplicationTests { public class SampleNarayanaApplicationTests {
...@@ -36,25 +38,22 @@ public class SampleNarayanaApplicationTests { ...@@ -36,25 +38,22 @@ public class SampleNarayanaApplicationTests {
public void testTransactionRollback() throws Exception { public void testTransactionRollback() throws Exception {
SampleNarayanaApplication.main(new String[] {}); SampleNarayanaApplication.main(new String[] {});
String output = this.outputCapture.toString(); String output = this.outputCapture.toString();
assertThat(output, containsString(1, "---->")); assertThat(output).has(substring(1, "---->"));
assertThat(output, containsString(1, "----> josh")); assertThat(output).has(substring(1, "----> josh"));
assertThat(output, containsString(2, "Count is 1")); assertThat(output).has(substring(2, "Count is 1"));
assertThat(output, containsString(1, "Simulated error")); assertThat(output).has(substring(1, "Simulated error"));
} }
private Matcher<? super String> containsString(final int times, String s) { private Condition<String> substring(final int times, final String substring) {
return new SubstringMatcher(s) { return new Condition<String>(
"containing '" + substring + "' " + times + " times") {
@Override
protected String relationship() {
return "containing " + times + " times";
}
@Override @Override
protected boolean evalSubstringOf(String s) { public boolean matches(String value) {
int i = 0; int i = 0;
while (s.contains(this.substring)) { while (value.contains(substring)) {
s = s.substring(s.indexOf(this.substring) + this.substring.length()); int beginIndex = value.indexOf(substring) + substring.length();
value = value.substring(beginIndex);
i++; i++;
} }
return i == times; return i == times;
......
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion>
<modelVersion>4.0.0</modelVersion> <parent>
<parent> <artifactId>spring-boot-starters</artifactId>
<artifactId>spring-boot-starters</artifactId> <groupId>org.springframework.boot</groupId>
<groupId>org.springframework.boot</groupId> <version>1.4.0.BUILD-SNAPSHOT</version>
<version>1.4.0.BUILD-SNAPSHOT</version> </parent>
</parent> <artifactId>spring-boot-starter-jta-narayana</artifactId>
<artifactId>spring-boot-starter-jta-narayana</artifactId> <name>Spring Boot Narayana JTA Starter</name>
<name>Spring Boot Narayana JTA Starter</name> <description>Spring Boot Narayana JTA Starter</description>
<description>Spring Boot Narayana JTA Starter</description> <url>http://projects.spring.io/spring-boot/</url>
<url>http://projects.spring.io/spring-boot/</url> <properties>
<properties> <main.basedir>${basedir}/../..</main.basedir>
<main.basedir>${basedir}/../..</main.basedir> </properties>
</properties> <dependencies>
<dependencies> <dependency>
<dependency> <groupId>org.springframework.boot</groupId>
<groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId>
<artifactId>spring-boot-starter</artifactId> </dependency>
</dependency> <dependency>
<dependency> <groupId>org.jboss</groupId>
<groupId>org.jboss.narayana.jta</groupId> <artifactId>jboss-transaction-spi</artifactId>
<artifactId>jta</artifactId> </dependency>
</dependency> <dependency>
<dependency> <groupId>org.jboss.narayana.jta</groupId>
<groupId>org.jboss.narayana.jta</groupId> <artifactId>jdbc</artifactId>
<artifactId>jdbc</artifactId> </dependency>
</dependency> <dependency>
<dependency> <groupId>org.jboss.narayana.jta</groupId>
<groupId>org.jboss.narayana.jta</groupId> <artifactId>jms</artifactId>
<artifactId>jms</artifactId> </dependency>
</dependency> <dependency>
<dependency> <groupId>org.jboss.narayana.jta</groupId>
<groupId>org.jboss.narayana.jts</groupId> <artifactId>jta</artifactId>
<artifactId>narayana-jts-integration</artifactId> </dependency>
</dependency> <dependency>
<dependency> <groupId>org.jboss.narayana.jts</groupId>
<groupId>org.jboss</groupId> <artifactId>narayana-jts-integration</artifactId>
<artifactId>jboss-transaction-spi</artifactId> </dependency>
</dependency> <dependency>
<dependency> <groupId>javax.transaction</groupId>
<groupId>javax.transaction</groupId> <artifactId>javax.transaction-api</artifactId>
<artifactId>javax.transaction-api</artifactId> </dependency>
</dependency> </dependencies>
</dependencies> </project>
</project>
\ No newline at end of file
/* /*
* Copyright 2012-2015 the original author or authors. * Copyright 2012-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -17,8 +17,6 @@ ...@@ -17,8 +17,6 @@
package org.springframework.boot.jta.narayana; package org.springframework.boot.jta.narayana;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.sql.XAConnection; import javax.sql.XAConnection;
import javax.sql.XADataSource; import javax.sql.XADataSource;
...@@ -27,34 +25,56 @@ import javax.transaction.xa.XAResource; ...@@ -27,34 +25,56 @@ import javax.transaction.xa.XAResource;
import javax.transaction.xa.Xid; import javax.transaction.xa.Xid;
import com.arjuna.ats.jta.recovery.XAResourceRecoveryHelper; import com.arjuna.ats.jta.recovery.XAResourceRecoveryHelper;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.Assert;
/** /**
* XAResourceRecoveryHelper implementation which gets Xids, which needs to be recovered, from the database. * XAResourceRecoveryHelper implementation which gets XIDs, which needs to be recovered,
* from the database.
* *
* @author <a href="mailto:gytis@redhat.com">Gytis Trikleris</a> * @author Gytis Trikleris
* @since 1.4.0
*/ */
public class DataSourceXAResourceRecoveryHelper implements XAResourceRecoveryHelper, XAResource { public class DataSourceXAResourceRecoveryHelper
implements XAResourceRecoveryHelper, XAResource {
private static final XAResource[] NO_XA_RESOURCES = {};
private static final Logger LOGGER = Logger.getLogger(DataSourceXAResourceRecoveryHelper.class.getName()); private static final Log logger = LogFactory
.getLog(DataSourceXAResourceRecoveryHelper.class);
private final XADataSource xaDataSource; private final XADataSource xaDataSource;
private final String user; private final String user;
private final String pass; private final String password;
private XAConnection xaConnection; private XAConnection xaConnection;
private XAResource delegate; private XAResource delegate;
/**
* Create a new {@link DataSourceXAResourceRecoveryHelper} instance.
* @param xaDataSource the XA data source
*/
public DataSourceXAResourceRecoveryHelper(XADataSource xaDataSource) { public DataSourceXAResourceRecoveryHelper(XADataSource xaDataSource) {
this(xaDataSource, null, null); this(xaDataSource, null, null);
} }
public DataSourceXAResourceRecoveryHelper(XADataSource xaDataSource, String user, String pass) { /**
* Create a new {@link DataSourceXAResourceRecoveryHelper} instance.
* @param xaDataSource the XA data source
* @param user the database user or {@code null}
* @param password the database password or {@code null}
*/
public DataSourceXAResourceRecoveryHelper(XADataSource xaDataSource, String user,
String password) {
Assert.notNull(xaDataSource, "XADataSource must not be null");
this.xaDataSource = xaDataSource; this.xaDataSource = xaDataSource;
this.user = user; this.user = user;
this.pass = pass; this.password = password;
} }
@Override @Override
...@@ -67,103 +87,104 @@ public class DataSourceXAResourceRecoveryHelper implements XAResourceRecoveryHel ...@@ -67,103 +87,104 @@ public class DataSourceXAResourceRecoveryHelper implements XAResourceRecoveryHel
if (connect()) { if (connect()) {
return new XAResource[] { this }; return new XAResource[] { this };
} }
return NO_XA_RESOURCES;
}
return new XAResource[0]; private boolean connect() {
if (this.delegate == null) {
try {
this.xaConnection = getXaConnection();
this.delegate = this.xaConnection.getXAResource();
}
catch (SQLException ex) {
logger.warn("Failed to create connection", ex);
return false;
}
}
return true;
}
private XAConnection getXaConnection() throws SQLException {
if (this.user == null && this.password == null) {
return this.xaDataSource.getXAConnection();
}
return this.xaDataSource.getXAConnection(this.user, this.password);
} }
@Override @Override
public Xid[] recover(int i) throws XAException { public Xid[] recover(int flag) throws XAException {
try { try {
return this.delegate.recover(i); return getDelegate(true).recover(flag);
} }
finally { finally {
if (i == XAResource.TMENDRSCAN) { if (flag == XAResource.TMENDRSCAN) {
disconnect(); disconnect();
} }
} }
} }
private void disconnect() throws XAException {
try {
this.xaConnection.close();
}
catch (SQLException e) {
logger.warn("Failed to close connection", e);
}
finally {
this.xaConnection = null;
this.delegate = null;
}
}
@Override @Override
public void start(Xid xid, int i) throws XAException { public void start(Xid xid, int flags) throws XAException {
this.delegate.start(xid, i); getDelegate(true).start(xid, flags);
} }
@Override @Override
public void end(Xid xid, int i) throws XAException { public void end(Xid xid, int flags) throws XAException {
this.delegate.end(xid, i); getDelegate(true).end(xid, flags);
} }
@Override @Override
public int prepare(Xid xid) throws XAException { public int prepare(Xid xid) throws XAException {
return this.delegate.prepare(xid); return getDelegate(true).prepare(xid);
} }
@Override @Override
public void commit(Xid xid, boolean b) throws XAException { public void commit(Xid xid, boolean onePhase) throws XAException {
this.delegate.commit(xid, b); getDelegate(true).commit(xid, onePhase);
} }
@Override @Override
public void rollback(Xid xid) throws XAException { public void rollback(Xid xid) throws XAException {
this.delegate.rollback(xid); getDelegate(true).rollback(xid);
} }
@Override @Override
public boolean isSameRM(XAResource xaResource) throws XAException { public boolean isSameRM(XAResource xaResource) throws XAException {
return this.delegate.isSameRM(xaResource); return getDelegate(true).isSameRM(xaResource);
} }
@Override @Override
public void forget(Xid xid) throws XAException { public void forget(Xid xid) throws XAException {
this.delegate.forget(xid); getDelegate(true).forget(xid);
} }
@Override @Override
public int getTransactionTimeout() throws XAException { public int getTransactionTimeout() throws XAException {
return this.delegate.getTransactionTimeout(); return getDelegate(true).getTransactionTimeout();
} }
@Override @Override
public boolean setTransactionTimeout(int i) throws XAException { public boolean setTransactionTimeout(int seconds) throws XAException {
return this.delegate.setTransactionTimeout(i); return getDelegate(true).setTransactionTimeout(seconds);
}
private boolean connect() {
if (this.delegate != null) {
return true;
}
try {
this.xaConnection = getXaConnection();
this.delegate = this.xaConnection.getXAResource();
}
catch (SQLException e) {
LOGGER.log(Level.WARNING, "Failed to create connection", e);
return false;
}
return true;
}
private void disconnect() throws XAException {
try {
this.xaConnection.close();
}
catch (SQLException e) {
LOGGER.log(Level.WARNING, "Failed to close connection", e);
}
finally {
this.xaConnection = null;
this.delegate = null;
}
} }
private XAConnection getXaConnection() throws SQLException { private XAResource getDelegate(boolean required) {
if (this.user == null && this.pass == null) { Assert.state(this.delegate != null || !required,
return this.xaDataSource.getXAConnection(); "Connection has not been opened");
} return this.delegate;
return this.xaDataSource.getXAConnection(this.user, this.pass);
} }
} }
/* /*
* Copyright 2012-2015 the original author or authors. * Copyright 2012-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -26,44 +26,54 @@ import org.springframework.core.Ordered; ...@@ -26,44 +26,54 @@ import org.springframework.core.Ordered;
/** /**
* {@link BeanFactoryPostProcessor} to automatically setup correct beans ordering. * {@link BeanFactoryPostProcessor} to automatically setup correct beans ordering.
* *
* @author <a href="mailto:gytis@redhat.com">Gytis Trikleris</a> * @author Gytis Trikleris
* @since 1.4.0
*/ */
public class NarayanaBeanFactoryPostProcessor implements BeanFactoryPostProcessor, Ordered { public class NarayanaBeanFactoryPostProcessor
implements BeanFactoryPostProcessor, Ordered {
private static final String[] NO_BEANS = {}; private static final String[] NO_BEANS = {};
private static final int ORDER = Ordered.LOWEST_PRECEDENCE; private static final int ORDER = Ordered.LOWEST_PRECEDENCE;
@Override @Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
String[] transactionManagers = beanFactory.getBeanNamesForType(TransactionManager.class, true, false); throws BeansException {
String[] recoveryManagers = beanFactory.getBeanNamesForType(NarayanaRecoveryManagerBean.class, true, false); String[] transactionManagers = beanFactory
.getBeanNamesForType(TransactionManager.class, true, false);
String[] recoveryManagers = beanFactory
.getBeanNamesForType(NarayanaRecoveryManagerBean.class, true, false);
addBeanDependencies(beanFactory, transactionManagers, "javax.sql.DataSource"); addBeanDependencies(beanFactory, transactionManagers, "javax.sql.DataSource");
addBeanDependencies(beanFactory, recoveryManagers, "javax.sql.DataSource"); addBeanDependencies(beanFactory, recoveryManagers, "javax.sql.DataSource");
addBeanDependencies(beanFactory, transactionManagers, "javax.jms.ConnectionFactory"); addBeanDependencies(beanFactory, transactionManagers,
"javax.jms.ConnectionFactory");
addBeanDependencies(beanFactory, recoveryManagers, "javax.jms.ConnectionFactory"); addBeanDependencies(beanFactory, recoveryManagers, "javax.jms.ConnectionFactory");
} }
private void addBeanDependencies(ConfigurableListableBeanFactory beanFactory, String[] beanNames, String dependencyType) { private void addBeanDependencies(ConfigurableListableBeanFactory beanFactory,
String[] beanNames, String dependencyType) {
for (String beanName : beanNames) { for (String beanName : beanNames) {
addBeanDependencies(beanFactory, beanName, dependencyType); addBeanDependencies(beanFactory, beanName, dependencyType);
} }
} }
private void addBeanDependencies(ConfigurableListableBeanFactory beanFactory, String beanName, String dependencyType) { private void addBeanDependencies(ConfigurableListableBeanFactory beanFactory,
for (String dependentBeanName : getBeanNamesForType(beanFactory, dependencyType)) { String beanName, String dependencyType) {
for (String dependentBeanName : getBeanNamesForType(beanFactory,
dependencyType)) {
beanFactory.registerDependentBean(beanName, dependentBeanName); beanFactory.registerDependentBean(beanName, dependentBeanName);
} }
} }
private String[] getBeanNamesForType(ConfigurableListableBeanFactory beanFactory, String type) { private String[] getBeanNamesForType(ConfigurableListableBeanFactory beanFactory,
String type) {
try { try {
return beanFactory.getBeanNamesForType(Class.forName(type), true, false); return beanFactory.getBeanNamesForType(Class.forName(type), true, false);
} }
catch (ClassNotFoundException ex) { catch (ClassNotFoundException ex) {
// Ignore // Ignore
} catch (NoClassDefFoundError ex) { }
catch (NoClassDefFoundError ex) {
// Ignore // Ignore
} }
return NO_BEANS; return NO_BEANS;
......
/* /*
* Copyright 2012-2015 the original author or authors. * Copyright 2012-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -31,16 +31,17 @@ import org.springframework.beans.factory.InitializingBean; ...@@ -31,16 +31,17 @@ import org.springframework.beans.factory.InitializingBean;
/** /**
* Bean that configures Narayana transaction manager. * Bean that configures Narayana transaction manager.
* *
* @author <a href="mailto:gytis@redhat.com">Gytis Trikleris</a> * @author Gytis Trikleris
* @since 1.4.0
*/ */
public class NarayanaConfigurationBean implements InitializingBean { public class NarayanaConfigurationBean implements InitializingBean {
private static final String JBOSSTS_PROPERTIES_FILE_NAME = "jbossts-properties.xml"; private static final String JBOSSTS_PROPERTIES_FILE_NAME = "jbossts-properties.xml";
private final NarayanaProperties narayanaProperties; private final NarayanaProperties properties;
public NarayanaConfigurationBean(NarayanaProperties narayanaProperties) { public NarayanaConfigurationBean(NarayanaProperties narayanaProperties) {
this.narayanaProperties = narayanaProperties; this.properties = narayanaProperties;
} }
@Override @Override
...@@ -48,59 +49,75 @@ public class NarayanaConfigurationBean implements InitializingBean { ...@@ -48,59 +49,75 @@ public class NarayanaConfigurationBean implements InitializingBean {
if (isPropertiesFileAvailable()) { if (isPropertiesFileAvailable()) {
return; return;
} }
setNodeIdentifier(this.properties.getTransactionManagerId());
setNodeIdentifier(this.narayanaProperties.getTransactionManagerId()); setObjectStoreDir(this.properties.getLogDir());
setObjectStoreDir(this.narayanaProperties.getLogDir()); setCommitOnePhase(this.properties.isOnePhaseCommit());
setCommitOnePhase(this.narayanaProperties.isOnePhaseCommit()); setDefaultTimeout(this.properties.getDefaultTimeout());
setDefaultTimeout(this.narayanaProperties.getDefaultTimeout()); setPeriodicRecoveryPeriod(this.properties.getPeriodicRecoveryPeriod());
setPeriodicRecoveryPeriod(this.narayanaProperties.getPeriodicRecoveryPeriod()); setRecoveryBackoffPeriod(this.properties.getRecoveryBackoffPeriod());
setRecoveryBackoffPeriod(this.narayanaProperties.getRecoveryBackoffPeriod()); setXaResourceOrphanFilters(this.properties.getXaResourceOrphanFilters());
setXaResourceOrphanFilters(this.narayanaProperties.getXaResourceOrphanFilters()); setRecoveryModules(this.properties.getRecoveryModules());
setRecoveryModules(this.narayanaProperties.getRecoveryModules()); setExpiryScanners(this.properties.getExpiryScanners());
setExpiryScanners(this.narayanaProperties.getExpiryScanners());
} }
private boolean isPropertiesFileAvailable() { private boolean isPropertiesFileAvailable() {
return Thread.currentThread().getContextClassLoader().getResource(JBOSSTS_PROPERTIES_FILE_NAME) != null; return Thread.currentThread().getContextClassLoader()
.getResource(JBOSSTS_PROPERTIES_FILE_NAME) != null;
} }
private void setNodeIdentifier(String nodeIdentifier) throws CoreEnvironmentBeanException { private void setNodeIdentifier(String nodeIdentifier)
BeanPopulator.getDefaultInstance(CoreEnvironmentBean.class).setNodeIdentifier(nodeIdentifier); throws CoreEnvironmentBeanException {
getPopulator(CoreEnvironmentBean.class).setNodeIdentifier(nodeIdentifier);
} }
private void setObjectStoreDir(String objectStoreDir) { private void setObjectStoreDir(String objectStoreDir) {
BeanPopulator.getDefaultInstance(ObjectStoreEnvironmentBean.class).setObjectStoreDir(objectStoreDir); getPopulator(ObjectStoreEnvironmentBean.class).setObjectStoreDir(objectStoreDir);
BeanPopulator.getNamedInstance(ObjectStoreEnvironmentBean.class, "communicationStore") getPopulator(ObjectStoreEnvironmentBean.class, "communicationStore")
.setObjectStoreDir(objectStoreDir);
getPopulator(ObjectStoreEnvironmentBean.class, "stateStore")
.setObjectStoreDir(objectStoreDir); .setObjectStoreDir(objectStoreDir);
BeanPopulator.getNamedInstance(ObjectStoreEnvironmentBean.class, "stateStore").setObjectStoreDir(objectStoreDir);
} }
private void setCommitOnePhase(boolean isCommitOnePhase) { private void setCommitOnePhase(boolean isCommitOnePhase) {
BeanPopulator.getDefaultInstance(CoordinatorEnvironmentBean.class).setCommitOnePhase(isCommitOnePhase); getPopulator(CoordinatorEnvironmentBean.class)
.setCommitOnePhase(isCommitOnePhase);
} }
private void setDefaultTimeout(int defaultTimeout) { private void setDefaultTimeout(int defaultTimeout) {
BeanPopulator.getDefaultInstance(CoordinatorEnvironmentBean.class).setDefaultTimeout(defaultTimeout); getPopulator(CoordinatorEnvironmentBean.class).setDefaultTimeout(defaultTimeout);
} }
private void setPeriodicRecoveryPeriod(int periodicRecoveryPeriod) { private void setPeriodicRecoveryPeriod(int periodicRecoveryPeriod) {
BeanPopulator.getDefaultInstance(RecoveryEnvironmentBean.class).setPeriodicRecoveryPeriod(periodicRecoveryPeriod); getPopulator(RecoveryEnvironmentBean.class)
.setPeriodicRecoveryPeriod(periodicRecoveryPeriod);
} }
private void setRecoveryBackoffPeriod(int recoveryBackoffPeriod) { private void setRecoveryBackoffPeriod(int recoveryBackoffPeriod) {
BeanPopulator.getDefaultInstance(RecoveryEnvironmentBean.class).setRecoveryBackoffPeriod(recoveryBackoffPeriod); getPopulator(RecoveryEnvironmentBean.class)
.setRecoveryBackoffPeriod(recoveryBackoffPeriod);
} }
private void setXaResourceOrphanFilters(List<String> xaResourceOrphanFilters) { private void setXaResourceOrphanFilters(List<String> xaResourceOrphanFilters) {
BeanPopulator.getDefaultInstance(JTAEnvironmentBean.class).setXaResourceOrphanFilterClassNames(xaResourceOrphanFilters); getPopulator(JTAEnvironmentBean.class)
.setXaResourceOrphanFilterClassNames(xaResourceOrphanFilters);
} }
private void setRecoveryModules(List<String> recoveryModules) { private void setRecoveryModules(List<String> recoveryModules) {
BeanPopulator.getDefaultInstance(RecoveryEnvironmentBean.class).setRecoveryModuleClassNames(recoveryModules); getPopulator(RecoveryEnvironmentBean.class)
.setRecoveryModuleClassNames(recoveryModules);
} }
private void setExpiryScanners(List<String> expiryScanners) { private void setExpiryScanners(List<String> expiryScanners) {
BeanPopulator.getDefaultInstance(RecoveryEnvironmentBean.class).setExpiryScannerClassNames(expiryScanners); getPopulator(RecoveryEnvironmentBean.class)
.setExpiryScannerClassNames(expiryScanners);
}
private <T> T getPopulator(Class<T> beanClass) {
return BeanPopulator.getDefaultInstance(beanClass);
}
private <T> T getPopulator(Class<T> beanClass, String name) {
return BeanPopulator.getNamedInstance(beanClass, name);
} }
} }
/* /*
* Copyright 2012-2015 the original author or authors. * Copyright 2012-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -29,16 +29,26 @@ import javax.sql.XADataSource; ...@@ -29,16 +29,26 @@ import javax.sql.XADataSource;
import com.arjuna.ats.internal.jdbc.ConnectionManager; import com.arjuna.ats.internal.jdbc.ConnectionManager;
import com.arjuna.ats.jdbc.TransactionalDriver; import com.arjuna.ats.jdbc.TransactionalDriver;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
/** /**
* {@link DataSource} implementation wrapping {@link XADataSource} and using {@link ConnectionManager} to acquire connections. * {@link DataSource} implementation wrapping {@link XADataSource} and using
* {@link ConnectionManager} to acquire connections.
* *
* @author <a href="mailto:gytis@redhat.com">Gytis Trikleris</a> * @author Gytis Trikleris
* @since 1.4.0
*/ */
public class NarayanaDataSourceBean implements DataSource { public class NarayanaDataSourceBean implements DataSource {
private final XADataSource xaDataSource; private final XADataSource xaDataSource;
/**
* Create a new {@link NarayanaDataSourceBean} instance.
* @param xaDataSource the XA DataSource
*/
public NarayanaDataSourceBean(XADataSource xaDataSource) { public NarayanaDataSourceBean(XADataSource xaDataSource) {
Assert.notNull(xaDataSource, "XADataSource must not be null");
this.xaDataSource = xaDataSource; this.xaDataSource = xaDataSource;
} }
...@@ -46,17 +56,16 @@ public class NarayanaDataSourceBean implements DataSource { ...@@ -46,17 +56,16 @@ public class NarayanaDataSourceBean implements DataSource {
public Connection getConnection() throws SQLException { public Connection getConnection() throws SQLException {
Properties properties = new Properties(); Properties properties = new Properties();
properties.put(TransactionalDriver.XADataSource, this.xaDataSource); properties.put(TransactionalDriver.XADataSource, this.xaDataSource);
return ConnectionManager.create(null, properties); return ConnectionManager.create(null, properties);
} }
@Override @Override
public Connection getConnection(String username, String password) throws SQLException { public Connection getConnection(String username, String password)
throws SQLException {
Properties properties = new Properties(); Properties properties = new Properties();
properties.put(TransactionalDriver.XADataSource, this.xaDataSource); properties.put(TransactionalDriver.XADataSource, this.xaDataSource);
properties.put(TransactionalDriver.userName, username); properties.put(TransactionalDriver.userName, username);
properties.put(TransactionalDriver.password, password); properties.put(TransactionalDriver.password, password);
return ConnectionManager.create(null, properties); return ConnectionManager.create(null, properties);
} }
...@@ -91,20 +100,15 @@ public class NarayanaDataSourceBean implements DataSource { ...@@ -91,20 +100,15 @@ public class NarayanaDataSourceBean implements DataSource {
if (isWrapperFor(iface)) { if (isWrapperFor(iface)) {
return (T) this; return (T) this;
} }
else if (isWrapperFor(iface, this.xaDataSource.getClass())) { if (ClassUtils.isAssignableValue(iface, this.xaDataSource)) {
return (T) this.xaDataSource; return (T) this.xaDataSource;
} }
throw new SQLException(getClass() + " is not a wrapper for " + iface); throw new SQLException(getClass() + " is not a wrapper for " + iface);
} }
@Override @Override
public boolean isWrapperFor(Class<?> iface) throws SQLException { public boolean isWrapperFor(Class<?> iface) throws SQLException {
return isWrapperFor(iface, getClass()); return iface.isAssignableFrom(getClass());
}
private boolean isWrapperFor(Class<?> iface, Class<?> wrapperIface) {
return iface.isAssignableFrom(wrapperIface);
} }
} }
/* /*
* Copyright 2012-2015 the original author or authors. * Copyright 2012-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -22,10 +22,11 @@ import java.util.List; ...@@ -22,10 +22,11 @@ import java.util.List;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
/** /**
* Subset of Narayana properties which can be configured via Spring configuration. Use jbossts-properties.xml for complete * Subset of Narayana properties which can be configured via Spring configuration. Use
* configuration. * jbossts-properties.xml for complete configuration.
* *
* @author <a href="mailto:gytis@redhat.com">Gytis Trikleris</a> * @author Gytis Trikleris
* @since 1.4.0
*/ */
@ConfigurationProperties(prefix = NarayanaProperties.PROPERTIES_PREFIX) @ConfigurationProperties(prefix = NarayanaProperties.PROPERTIES_PREFIX)
public class NarayanaProperties { public class NarayanaProperties {
...@@ -56,12 +57,14 @@ public class NarayanaProperties { ...@@ -56,12 +57,14 @@ public class NarayanaProperties {
private int defaultTimeout = 60; private int defaultTimeout = 60;
/** /**
* Interval in which periodic recovery scans are performed in seconds. Default: <code>120</code> * Interval in which periodic recovery scans are performed in seconds. Default:
* <code>120</code>
*/ */
private int periodicRecoveryPeriod = 120; private int periodicRecoveryPeriod = 120;
/** /**
* Back off period between first and second phases of the recovery scan in seconds. Default: <code>10</code> * Back off period between first and second phases of the recovery scan in seconds.
* Default: <code>10</code>
*/ */
private int recoveryBackoffPeriod = 10; private int recoveryBackoffPeriod = 10;
...@@ -88,8 +91,11 @@ public class NarayanaProperties { ...@@ -88,8 +91,11 @@ public class NarayanaProperties {
/** /**
* List of orphan filters. Default: * List of orphan filters. Default:
* <ul> * <ul>
* <li>com.arjuna.ats.internal.jta.recovery.arjunacore.JTATransactionLogXAResourceOrphanFilter</li> * <li>com.arjuna.ats.internal.jta.recovery.arjunacore.
* <li>com.arjuna.ats.internal.jta.recovery.arjunacore.JTANodeNameXAResourceOrphanFilter</li> * JTATransactionLogXAResourceOrphanFilter</li>
* <li>
* com.arjuna.ats.internal.jta.recovery.arjunacore.JTANodeNameXAResourceOrphanFilter
* </li>
* </ul> * </ul>
*/ */
private List<String> xaResourceOrphanFilters = Arrays.asList( private List<String> xaResourceOrphanFilters = Arrays.asList(
...@@ -103,17 +109,19 @@ public class NarayanaProperties { ...@@ -103,17 +109,19 @@ public class NarayanaProperties {
* <li>com.arjuna.ats.internal.jta.recovery.arjunacore.XARecoveryModule</li> * <li>com.arjuna.ats.internal.jta.recovery.arjunacore.XARecoveryModule</li>
* </ul> * </ul>
*/ */
private List<String> recoveryModules = Arrays.asList("com.arjuna.ats.internal.arjuna.recovery.AtomicActionRecoveryModule", private List<String> recoveryModules = Arrays.asList(
"com.arjuna.ats.internal.arjuna.recovery.AtomicActionRecoveryModule",
"com.arjuna.ats.internal.jta.recovery.arjunacore.XARecoveryModule"); "com.arjuna.ats.internal.jta.recovery.arjunacore.XARecoveryModule");
/** /**
* List of expiry scanners. Default: * List of expiry scanners. Default:
* <ul> * <ul>
* <li>com.arjuna.ats.internal.arjuna.recovery.ExpiredTransactionStatusManagerScanner</li> * <li>com.arjuna.ats.internal.arjuna.recovery.ExpiredTransactionStatusManagerScanner
* </li>
* </ul> * </ul>
*/ */
private List<String> expiryScanners = Arrays private List<String> expiryScanners = Arrays.asList(
.asList("com.arjuna.ats.internal.arjuna.recovery.ExpiredTransactionStatusManagerScanner"); "com.arjuna.ats.internal.arjuna.recovery.ExpiredTransactionStatusManagerScanner");
public String getLogDir() { public String getLogDir() {
return this.logDir; return this.logDir;
...@@ -218,4 +226,5 @@ public class NarayanaProperties { ...@@ -218,4 +226,5 @@ public class NarayanaProperties {
public void setRecoveryJmsPass(String recoveryJmsPass) { public void setRecoveryJmsPass(String recoveryJmsPass) {
this.recoveryJmsPass = recoveryJmsPass; this.recoveryJmsPass = recoveryJmsPass;
} }
} }
/* /*
* Copyright 2012-2015 the original author or authors. * Copyright 2012-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -24,17 +24,20 @@ import com.arjuna.ats.jta.recovery.XAResourceRecoveryHelper; ...@@ -24,17 +24,20 @@ import com.arjuna.ats.jta.recovery.XAResourceRecoveryHelper;
import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
/** /**
* Bean to set up Narayana recovery manager. * Bean to set up Narayana recovery manager.
* *
* @author <a href="mailto:gytis@redhat.com">Gytis Trikleris</a> * @author Gytis Trikleris
* @since 1.4.0
*/ */
public class NarayanaRecoveryManagerBean implements InitializingBean, DisposableBean { public class NarayanaRecoveryManagerBean implements InitializingBean, DisposableBean {
private final RecoveryManagerService recoveryManagerService; private final RecoveryManagerService recoveryManagerService;
public NarayanaRecoveryManagerBean(RecoveryManagerService recoveryManagerService) { public NarayanaRecoveryManagerBean(RecoveryManagerService recoveryManagerService) {
Assert.notNull(recoveryManagerService, "RecoveryManagerService must not be null");
this.recoveryManagerService = recoveryManagerService; this.recoveryManagerService = recoveryManagerService;
} }
...@@ -50,8 +53,10 @@ public class NarayanaRecoveryManagerBean implements InitializingBean, Disposable ...@@ -50,8 +53,10 @@ public class NarayanaRecoveryManagerBean implements InitializingBean, Disposable
this.recoveryManagerService.destroy(); this.recoveryManagerService.destroy();
} }
void registerXAResourceRecoveryHelper(XAResourceRecoveryHelper xaResourceRecoveryHelper) { void registerXAResourceRecoveryHelper(
getXARecoveryModule(RecoveryManager.manager()).addXAResourceRecoveryHelper(xaResourceRecoveryHelper); XAResourceRecoveryHelper xaResourceRecoveryHelper) {
getXARecoveryModule(RecoveryManager.manager())
.addXAResourceRecoveryHelper(xaResourceRecoveryHelper);
} }
private XARecoveryModule getXARecoveryModule(RecoveryManager recoveryManager) { private XARecoveryModule getXARecoveryModule(RecoveryManager recoveryManager) {
...@@ -60,8 +65,8 @@ public class NarayanaRecoveryManagerBean implements InitializingBean, Disposable ...@@ -60,8 +65,8 @@ public class NarayanaRecoveryManagerBean implements InitializingBean, Disposable
return (XARecoveryModule) recoveryModule; return (XARecoveryModule) recoveryModule;
} }
} }
throw new IllegalStateException(
throw new IllegalStateException("XARecoveryModule is not registered with recovery manager"); "XARecoveryModule is not registered with recovery manager");
} }
} }
/* /*
* Copyright 2012-2014 the original author or authors. * Copyright 2012-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -26,41 +26,57 @@ import org.jboss.narayana.jta.jms.JmsXAResourceRecoveryHelper; ...@@ -26,41 +26,57 @@ import org.jboss.narayana.jta.jms.JmsXAResourceRecoveryHelper;
import org.jboss.narayana.jta.jms.TransactionHelperImpl; import org.jboss.narayana.jta.jms.TransactionHelperImpl;
import org.springframework.boot.jta.XAConnectionFactoryWrapper; import org.springframework.boot.jta.XAConnectionFactoryWrapper;
import org.springframework.util.Assert;
/** /**
* {@link XAConnectionFactoryWrapper} that uses {@link ConnectionFactoryProxy} to wrap an {@link XAConnectionFactory}. * {@link XAConnectionFactoryWrapper} that uses {@link ConnectionFactoryProxy} to wrap an
* {@link XAConnectionFactory}.
* *
* @author <a href="mailto:gytis@redhat.com">Gytis Trikleris</a> * @author Gytis Trikleris
* @since 1.4.0
*/ */
public class NarayanaXAConnectionFactoryWrapper implements XAConnectionFactoryWrapper { public class NarayanaXAConnectionFactoryWrapper implements XAConnectionFactoryWrapper {
private final TransactionManager transactionManager; private final TransactionManager transactionManager;
private final NarayanaRecoveryManagerBean narayanaRecoveryManagerBean; private final NarayanaRecoveryManagerBean recoveryManager;
private final NarayanaProperties narayanaProperties; private final NarayanaProperties properties;
/**
* Create a new {@link NarayanaXAConnectionFactoryWrapper} instance.
* @param transactionManager the underlying transaction manager
* @param recoveryManager the underlying recovery manager
* @param properties the Narayana properties
*/
public NarayanaXAConnectionFactoryWrapper(TransactionManager transactionManager, public NarayanaXAConnectionFactoryWrapper(TransactionManager transactionManager,
NarayanaRecoveryManagerBean narayanaRecoveryManagerBean, NarayanaProperties narayanaProperties) { NarayanaRecoveryManagerBean recoveryManager, NarayanaProperties properties) {
Assert.notNull(transactionManager, "TransactionManager must not be null");
Assert.notNull(recoveryManager, "RecoveryManager must not be null");
Assert.notNull(properties, "Properties must not be null");
this.transactionManager = transactionManager; this.transactionManager = transactionManager;
this.narayanaRecoveryManagerBean = narayanaRecoveryManagerBean; this.recoveryManager = recoveryManager;
this.narayanaProperties = narayanaProperties; this.properties = properties;
} }
@Override @Override
public ConnectionFactory wrapConnectionFactory(XAConnectionFactory xaConnectionFactory) { public ConnectionFactory wrapConnectionFactory(
this.narayanaRecoveryManagerBean.registerXAResourceRecoveryHelper(getRecoveryHelper(xaConnectionFactory)); XAConnectionFactory xaConnectionFactory) {
XAResourceRecoveryHelper recoveryHelper = getRecoveryHelper(xaConnectionFactory);
return new ConnectionFactoryProxy(xaConnectionFactory, new TransactionHelperImpl(this.transactionManager)); this.recoveryManager.registerXAResourceRecoveryHelper(recoveryHelper);
return new ConnectionFactoryProxy(xaConnectionFactory,
new TransactionHelperImpl(this.transactionManager));
} }
private XAResourceRecoveryHelper getRecoveryHelper(XAConnectionFactory xaConnectionFactory) { private XAResourceRecoveryHelper getRecoveryHelper(
if (this.narayanaProperties.getRecoveryJmsUser() == null && this.narayanaProperties.getRecoveryJmsPass() == null) { XAConnectionFactory xaConnectionFactory) {
if (this.properties.getRecoveryJmsUser() == null
&& this.properties.getRecoveryJmsPass() == null) {
return new JmsXAResourceRecoveryHelper(xaConnectionFactory); return new JmsXAResourceRecoveryHelper(xaConnectionFactory);
} }
return new JmsXAResourceRecoveryHelper(xaConnectionFactory,
return new JmsXAResourceRecoveryHelper(xaConnectionFactory, this.narayanaProperties.getRecoveryJmsUser(), this.properties.getRecoveryJmsUser(),
this.narayanaProperties.getRecoveryJmsPass()); this.properties.getRecoveryJmsPass());
} }
} }
/* /*
* Copyright 2012-2015 the original author or authors. * Copyright 2012-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -22,38 +22,48 @@ import javax.sql.XADataSource; ...@@ -22,38 +22,48 @@ import javax.sql.XADataSource;
import com.arjuna.ats.jta.recovery.XAResourceRecoveryHelper; import com.arjuna.ats.jta.recovery.XAResourceRecoveryHelper;
import org.springframework.boot.jta.XADataSourceWrapper; import org.springframework.boot.jta.XADataSourceWrapper;
import org.springframework.util.Assert;
/** /**
* {@link XADataSourceWrapper} that uses {@link NarayanaDataSourceBean} to wrap an {@link XADataSource}. * {@link XADataSourceWrapper} that uses {@link NarayanaDataSourceBean} to wrap an
* {@link XADataSource}.
* *
* @author <a href="mailto:gytis@redhat.com">Gytis Trikleris</a> * @author Gytis Trikleris
* @since 1.4.0
*/ */
public class NarayanaXADataSourceWrapper implements XADataSourceWrapper { public class NarayanaXADataSourceWrapper implements XADataSourceWrapper {
private final NarayanaRecoveryManagerBean narayanaRecoveryManagerBean; private final NarayanaRecoveryManagerBean recoveryManager;
private final NarayanaProperties narayanaProperties; private final NarayanaProperties properties;
public NarayanaXADataSourceWrapper(NarayanaRecoveryManagerBean narayanaRecoveryManagerBean, /**
NarayanaProperties narayanaProperties) { * Create a new {@link NarayanaXADataSourceWrapper} instance.
this.narayanaRecoveryManagerBean = narayanaRecoveryManagerBean; * @param recoveryManager the underlying recovery manager
this.narayanaProperties = narayanaProperties; * @param properties the Narayana properties
*/
public NarayanaXADataSourceWrapper(NarayanaRecoveryManagerBean recoveryManager,
NarayanaProperties properties) {
Assert.notNull(recoveryManager, "RecoveryManager must not be null");
Assert.notNull(properties, "Properties must not be null");
this.recoveryManager = recoveryManager;
this.properties = properties;
} }
@Override @Override
public DataSource wrapDataSource(XADataSource dataSource) { public DataSource wrapDataSource(XADataSource dataSource) {
this.narayanaRecoveryManagerBean.registerXAResourceRecoveryHelper(getRecoveryHelper(dataSource)); XAResourceRecoveryHelper recoveryHelper = getRecoveryHelper(dataSource);
this.recoveryManager.registerXAResourceRecoveryHelper(recoveryHelper);
return new NarayanaDataSourceBean(dataSource); return new NarayanaDataSourceBean(dataSource);
} }
private XAResourceRecoveryHelper getRecoveryHelper(XADataSource dataSource) { private XAResourceRecoveryHelper getRecoveryHelper(XADataSource dataSource) {
if (this.narayanaProperties.getRecoveryDbUser() == null && this.narayanaProperties.getRecoveryDbPass() == null) { if (this.properties.getRecoveryDbUser() == null
&& this.properties.getRecoveryDbPass() == null) {
return new DataSourceXAResourceRecoveryHelper(dataSource); return new DataSourceXAResourceRecoveryHelper(dataSource);
} }
return new DataSourceXAResourceRecoveryHelper(dataSource,
return new DataSourceXAResourceRecoveryHelper(dataSource, this.narayanaProperties.getRecoveryDbUser(), this.properties.getRecoveryDbUser(), this.properties.getRecoveryDbPass());
this.narayanaProperties.getRecoveryDbPass());
} }
} }
/* /*
* Copyright 2012-2014 the original author or authors. * Copyright 2012-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -27,14 +27,16 @@ import org.junit.Before; ...@@ -27,14 +27,16 @@ import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.mock; import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.times;
import static org.mockito.BDDMockito.verify;
import static org.mockito.BDDMockito.when;
import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
/** /**
* @author <a href="mailto:gytis@redhat.com">Gytis Trikleris</a> * Tests for {@link DataSourceXAResourceRecoveryHelper}.
*
* @author Gytis Trikleris
*/ */
public class DataSourceXAResourceRecoveryHelperTests { public class DataSourceXAResourceRecoveryHelperTests {
...@@ -53,8 +55,8 @@ public class DataSourceXAResourceRecoveryHelperTests { ...@@ -53,8 +55,8 @@ public class DataSourceXAResourceRecoveryHelperTests {
this.xaResource = mock(XAResource.class); this.xaResource = mock(XAResource.class);
this.recoveryHelper = new DataSourceXAResourceRecoveryHelper(this.xaDataSource); this.recoveryHelper = new DataSourceXAResourceRecoveryHelper(this.xaDataSource);
when(this.xaDataSource.getXAConnection()).thenReturn(this.xaConnection); given(this.xaDataSource.getXAConnection()).willReturn(this.xaConnection);
when(this.xaConnection.getXAResource()).thenReturn(this.xaResource); given(this.xaConnection.getXAResource()).willReturn(this.xaResource);
} }
@Test @Test
...@@ -67,10 +69,12 @@ public class DataSourceXAResourceRecoveryHelperTests { ...@@ -67,10 +69,12 @@ public class DataSourceXAResourceRecoveryHelperTests {
} }
@Test @Test
public void shouldCreateConnectionWithCredentialsAndGetXAResource() throws SQLException { public void shouldCreateConnectionWithCredentialsAndGetXAResource()
when(this.xaDataSource.getXAConnection(anyString(), anyString())).thenReturn(this.xaConnection); throws SQLException {
this.recoveryHelper = new DataSourceXAResourceRecoveryHelper(this.xaDataSource, "username", "password"); given(this.xaDataSource.getXAConnection(anyString(), anyString()))
.willReturn(this.xaConnection);
this.recoveryHelper = new DataSourceXAResourceRecoveryHelper(this.xaDataSource,
"username", "password");
XAResource[] xaResources = this.recoveryHelper.getXAResources(); XAResource[] xaResources = this.recoveryHelper.getXAResources();
assertThat(xaResources.length).isEqualTo(1); assertThat(xaResources.length).isEqualTo(1);
assertThat(xaResources[0]).isSameAs(this.recoveryHelper); assertThat(xaResources[0]).isSameAs(this.recoveryHelper);
...@@ -80,10 +84,9 @@ public class DataSourceXAResourceRecoveryHelperTests { ...@@ -80,10 +84,9 @@ public class DataSourceXAResourceRecoveryHelperTests {
@Test @Test
public void shouldFailToCreateConnectionAndNotGetXAResource() throws SQLException { public void shouldFailToCreateConnectionAndNotGetXAResource() throws SQLException {
when(this.xaDataSource.getXAConnection()).thenThrow(new SQLException("Test exception")); given(this.xaDataSource.getXAConnection())
.willThrow(new SQLException("Test exception"));
XAResource[] xaResources = this.recoveryHelper.getXAResources(); XAResource[] xaResources = this.recoveryHelper.getXAResources();
assertThat(xaResources.length).isEqualTo(0); assertThat(xaResources.length).isEqualTo(0);
verify(this.xaDataSource, times(1)).getXAConnection(); verify(this.xaDataSource, times(1)).getXAConnection();
verify(this.xaConnection, times(0)).getXAResource(); verify(this.xaConnection, times(0)).getXAResource();
...@@ -93,15 +96,14 @@ public class DataSourceXAResourceRecoveryHelperTests { ...@@ -93,15 +96,14 @@ public class DataSourceXAResourceRecoveryHelperTests {
public void shouldDelegateRecoverCall() throws XAException { public void shouldDelegateRecoverCall() throws XAException {
this.recoveryHelper.getXAResources(); this.recoveryHelper.getXAResources();
this.recoveryHelper.recover(XAResource.TMSTARTRSCAN); this.recoveryHelper.recover(XAResource.TMSTARTRSCAN);
verify(this.xaResource, times(1)).recover(XAResource.TMSTARTRSCAN); verify(this.xaResource, times(1)).recover(XAResource.TMSTARTRSCAN);
} }
@Test @Test
public void shouldDelegateRecoverCallAndCloseConnection() throws XAException, SQLException { public void shouldDelegateRecoverCallAndCloseConnection()
throws XAException, SQLException {
this.recoveryHelper.getXAResources(); this.recoveryHelper.getXAResources();
this.recoveryHelper.recover(XAResource.TMENDRSCAN); this.recoveryHelper.recover(XAResource.TMENDRSCAN);
verify(this.xaResource, times(1)).recover(XAResource.TMENDRSCAN); verify(this.xaResource, times(1)).recover(XAResource.TMENDRSCAN);
verify(this.xaConnection, times(1)).close(); verify(this.xaConnection, times(1)).close();
} }
...@@ -110,7 +112,6 @@ public class DataSourceXAResourceRecoveryHelperTests { ...@@ -110,7 +112,6 @@ public class DataSourceXAResourceRecoveryHelperTests {
public void shouldDelegateStartCall() throws XAException { public void shouldDelegateStartCall() throws XAException {
this.recoveryHelper.getXAResources(); this.recoveryHelper.getXAResources();
this.recoveryHelper.start(null, 0); this.recoveryHelper.start(null, 0);
verify(this.xaResource, times(1)).start(null, 0); verify(this.xaResource, times(1)).start(null, 0);
} }
...@@ -118,7 +119,6 @@ public class DataSourceXAResourceRecoveryHelperTests { ...@@ -118,7 +119,6 @@ public class DataSourceXAResourceRecoveryHelperTests {
public void shouldDelegateEndCall() throws XAException { public void shouldDelegateEndCall() throws XAException {
this.recoveryHelper.getXAResources(); this.recoveryHelper.getXAResources();
this.recoveryHelper.end(null, 0); this.recoveryHelper.end(null, 0);
verify(this.xaResource, times(1)).end(null, 0); verify(this.xaResource, times(1)).end(null, 0);
} }
...@@ -126,7 +126,6 @@ public class DataSourceXAResourceRecoveryHelperTests { ...@@ -126,7 +126,6 @@ public class DataSourceXAResourceRecoveryHelperTests {
public void shouldDelegatePrepareCall() throws XAException { public void shouldDelegatePrepareCall() throws XAException {
this.recoveryHelper.getXAResources(); this.recoveryHelper.getXAResources();
this.recoveryHelper.prepare(null); this.recoveryHelper.prepare(null);
verify(this.xaResource, times(1)).prepare(null); verify(this.xaResource, times(1)).prepare(null);
} }
...@@ -134,7 +133,6 @@ public class DataSourceXAResourceRecoveryHelperTests { ...@@ -134,7 +133,6 @@ public class DataSourceXAResourceRecoveryHelperTests {
public void shouldDelegateCommitCall() throws XAException { public void shouldDelegateCommitCall() throws XAException {
this.recoveryHelper.getXAResources(); this.recoveryHelper.getXAResources();
this.recoveryHelper.commit(null, true); this.recoveryHelper.commit(null, true);
verify(this.xaResource, times(1)).commit(null, true); verify(this.xaResource, times(1)).commit(null, true);
} }
...@@ -142,7 +140,6 @@ public class DataSourceXAResourceRecoveryHelperTests { ...@@ -142,7 +140,6 @@ public class DataSourceXAResourceRecoveryHelperTests {
public void shouldDelegateRollbackCall() throws XAException { public void shouldDelegateRollbackCall() throws XAException {
this.recoveryHelper.getXAResources(); this.recoveryHelper.getXAResources();
this.recoveryHelper.rollback(null); this.recoveryHelper.rollback(null);
verify(this.xaResource, times(1)).rollback(null); verify(this.xaResource, times(1)).rollback(null);
} }
...@@ -150,7 +147,6 @@ public class DataSourceXAResourceRecoveryHelperTests { ...@@ -150,7 +147,6 @@ public class DataSourceXAResourceRecoveryHelperTests {
public void shouldDelegateIsSameRMCall() throws XAException { public void shouldDelegateIsSameRMCall() throws XAException {
this.recoveryHelper.getXAResources(); this.recoveryHelper.getXAResources();
this.recoveryHelper.isSameRM(null); this.recoveryHelper.isSameRM(null);
verify(this.xaResource, times(1)).isSameRM(null); verify(this.xaResource, times(1)).isSameRM(null);
} }
...@@ -158,7 +154,6 @@ public class DataSourceXAResourceRecoveryHelperTests { ...@@ -158,7 +154,6 @@ public class DataSourceXAResourceRecoveryHelperTests {
public void shouldDelegateForgetCall() throws XAException { public void shouldDelegateForgetCall() throws XAException {
this.recoveryHelper.getXAResources(); this.recoveryHelper.getXAResources();
this.recoveryHelper.forget(null); this.recoveryHelper.forget(null);
verify(this.xaResource, times(1)).forget(null); verify(this.xaResource, times(1)).forget(null);
} }
...@@ -166,7 +161,6 @@ public class DataSourceXAResourceRecoveryHelperTests { ...@@ -166,7 +161,6 @@ public class DataSourceXAResourceRecoveryHelperTests {
public void shouldDelegateGetTransactionTimeoutCall() throws XAException { public void shouldDelegateGetTransactionTimeoutCall() throws XAException {
this.recoveryHelper.getXAResources(); this.recoveryHelper.getXAResources();
this.recoveryHelper.getTransactionTimeout(); this.recoveryHelper.getTransactionTimeout();
verify(this.xaResource, times(1)).getTransactionTimeout(); verify(this.xaResource, times(1)).getTransactionTimeout();
} }
...@@ -174,9 +168,7 @@ public class DataSourceXAResourceRecoveryHelperTests { ...@@ -174,9 +168,7 @@ public class DataSourceXAResourceRecoveryHelperTests {
public void shouldDelegateSetTransactionTimeoutCall() throws XAException { public void shouldDelegateSetTransactionTimeoutCall() throws XAException {
this.recoveryHelper.getXAResources(); this.recoveryHelper.getXAResources();
this.recoveryHelper.setTransactionTimeout(0); this.recoveryHelper.setTransactionTimeout(0);
verify(this.xaResource, times(1)).setTransactionTimeout(0); verify(this.xaResource, times(1)).setTransactionTimeout(0);
} }
} }
/* /*
* Copyright 2012-2015 the original author or authors. * Copyright 2012-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -27,12 +27,14 @@ import org.springframework.context.annotation.AnnotationConfigApplicationContext ...@@ -27,12 +27,14 @@ import org.springframework.context.annotation.AnnotationConfigApplicationContext
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import static org.mockito.BDDMockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.BDDMockito.spy; import static org.mockito.Mockito.spy;
import static org.mockito.BDDMockito.verify; import static org.mockito.Mockito.verify;
/** /**
* @author <a href="mailto:gytis@redhat.com">Gytis Trikleris</a> * Tests for {@link NarayanaBeanFactoryPostProcessor}.
*
* @author Gytis Trikleris
*/ */
public class NarayanaBeanFactoryPostProcessorTests { public class NarayanaBeanFactoryPostProcessorTests {
...@@ -41,16 +43,17 @@ public class NarayanaBeanFactoryPostProcessorTests { ...@@ -41,16 +43,17 @@ public class NarayanaBeanFactoryPostProcessorTests {
@Test @Test
public void setsDependsOn() { public void setsDependsOn() {
DefaultListableBeanFactory beanFactory = spy(new DefaultListableBeanFactory()); DefaultListableBeanFactory beanFactory = spy(new DefaultListableBeanFactory());
this.context = new AnnotationConfigApplicationContext(beanFactory); this.context = new AnnotationConfigApplicationContext(beanFactory);
this.context.register(Config.class); this.context.register(Config.class);
this.context.refresh(); this.context.refresh();
verify(beanFactory).registerDependentBean("narayanaTransactionManager",
verify(beanFactory).registerDependentBean("narayanaTransactionManager", "dataSource"); "dataSource");
verify(beanFactory).registerDependentBean("narayanaTransactionManager", "connectionFactory"); verify(beanFactory).registerDependentBean("narayanaTransactionManager",
verify(beanFactory).registerDependentBean("narayanaRecoveryManagerBean", "dataSource"); "connectionFactory");
verify(beanFactory).registerDependentBean("narayanaRecoveryManagerBean", "connectionFactory"); verify(beanFactory).registerDependentBean("narayanaRecoveryManagerBean",
"dataSource");
verify(beanFactory).registerDependentBean("narayanaRecoveryManagerBean",
"connectionFactory");
this.context.close(); this.context.close();
} }
......
/* /*
* Copyright 2012-2014 the original author or authors. * Copyright 2012-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -25,52 +25,63 @@ import com.arjuna.ats.arjuna.common.ObjectStoreEnvironmentBean; ...@@ -25,52 +25,63 @@ import com.arjuna.ats.arjuna.common.ObjectStoreEnvironmentBean;
import com.arjuna.ats.arjuna.common.RecoveryEnvironmentBean; import com.arjuna.ats.arjuna.common.RecoveryEnvironmentBean;
import com.arjuna.ats.jta.common.JTAEnvironmentBean; import com.arjuna.ats.jta.common.JTAEnvironmentBean;
import com.arjuna.common.internal.util.propertyservice.BeanPopulator; import com.arjuna.common.internal.util.propertyservice.BeanPopulator;
import org.junit.Test; import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
/** /**
* @author <a href="mailto:gytis@redhat.com">Gytis Trikleris</a> * Tests for {@link NarayanaConfigurationBean}.
*
* @author Gytis Trikleris
*/ */
public class NarayanaConfigurationBeanTests { public class NarayanaConfigurationBeanTests {
@Test @Test
public void shouldSetDefaultProperties() throws Exception { public void shouldSetDefaultProperties() throws Exception {
NarayanaProperties narayanaProperties = new NarayanaProperties(); NarayanaProperties narayanaProperties = new NarayanaProperties();
NarayanaConfigurationBean narayanaConfigurationBean = new NarayanaConfigurationBean(narayanaProperties); NarayanaConfigurationBean narayanaConfigurationBean = new NarayanaConfigurationBean(
narayanaProperties);
narayanaConfigurationBean.afterPropertiesSet(); narayanaConfigurationBean.afterPropertiesSet();
assertThat(BeanPopulator.getDefaultInstance(CoreEnvironmentBean.class).getNodeIdentifier()).isEqualTo("1"); assertThat(BeanPopulator.getDefaultInstance(CoreEnvironmentBean.class)
assertThat(BeanPopulator.getDefaultInstance(ObjectStoreEnvironmentBean.class).getObjectStoreDir()) .getNodeIdentifier()).isEqualTo("1");
.isEqualTo("target/tx-object-store"); assertThat(BeanPopulator.getDefaultInstance(ObjectStoreEnvironmentBean.class)
assertThat(BeanPopulator.getNamedInstance(ObjectStoreEnvironmentBean.class, "communicationStore").getObjectStoreDir()) .getObjectStoreDir()).isEqualTo("target/tx-object-store");
.isEqualTo("target/tx-object-store"); assertThat(BeanPopulator
assertThat(BeanPopulator.getNamedInstance(ObjectStoreEnvironmentBean.class, "stateStore").getObjectStoreDir()) .getNamedInstance(ObjectStoreEnvironmentBean.class, "communicationStore")
.isEqualTo("target/tx-object-store"); .getObjectStoreDir()).isEqualTo("target/tx-object-store");
assertThat(BeanPopulator.getDefaultInstance(CoordinatorEnvironmentBean.class).isCommitOnePhase()).isTrue(); assertThat(BeanPopulator
assertThat(BeanPopulator.getDefaultInstance(CoordinatorEnvironmentBean.class).getDefaultTimeout()).isEqualTo(60); .getNamedInstance(ObjectStoreEnvironmentBean.class, "stateStore")
assertThat(BeanPopulator.getDefaultInstance(RecoveryEnvironmentBean.class).getPeriodicRecoveryPeriod()).isEqualTo(120); .getObjectStoreDir()).isEqualTo("target/tx-object-store");
assertThat(BeanPopulator.getDefaultInstance(RecoveryEnvironmentBean.class).getRecoveryBackoffPeriod()).isEqualTo(10); assertThat(BeanPopulator.getDefaultInstance(CoordinatorEnvironmentBean.class)
.isCommitOnePhase()).isTrue();
assertThat(BeanPopulator.getDefaultInstance(CoordinatorEnvironmentBean.class)
.getDefaultTimeout()).isEqualTo(60);
assertThat(BeanPopulator.getDefaultInstance(RecoveryEnvironmentBean.class)
.getPeriodicRecoveryPeriod()).isEqualTo(120);
assertThat(BeanPopulator.getDefaultInstance(RecoveryEnvironmentBean.class)
.getRecoveryBackoffPeriod()).isEqualTo(10);
List<String> xaResourceOrphanFilters = Arrays.asList( List<String> xaResourceOrphanFilters = Arrays.asList(
"com.arjuna.ats.internal.jta.recovery.arjunacore.JTATransactionLogXAResourceOrphanFilter", "com.arjuna.ats.internal.jta.recovery.arjunacore.JTATransactionLogXAResourceOrphanFilter",
"com.arjuna.ats.internal.jta.recovery.arjunacore.JTANodeNameXAResourceOrphanFilter"); "com.arjuna.ats.internal.jta.recovery.arjunacore.JTANodeNameXAResourceOrphanFilter");
assertThat(BeanPopulator.getDefaultInstance(JTAEnvironmentBean.class).getXaResourceOrphanFilterClassNames()) assertThat(BeanPopulator.getDefaultInstance(JTAEnvironmentBean.class)
.isEqualTo(xaResourceOrphanFilters); .getXaResourceOrphanFilterClassNames())
.isEqualTo(xaResourceOrphanFilters);
List<String> recoveryModules = Arrays.asList("com.arjuna.ats.internal.arjuna.recovery.AtomicActionRecoveryModule", List<String> recoveryModules = Arrays.asList(
"com.arjuna.ats.internal.arjuna.recovery.AtomicActionRecoveryModule",
"com.arjuna.ats.internal.jta.recovery.arjunacore.XARecoveryModule"); "com.arjuna.ats.internal.jta.recovery.arjunacore.XARecoveryModule");
assertThat(BeanPopulator.getDefaultInstance(RecoveryEnvironmentBean.class).getRecoveryModuleClassNames()) assertThat(BeanPopulator.getDefaultInstance(RecoveryEnvironmentBean.class)
.isEqualTo(recoveryModules); .getRecoveryModuleClassNames()).isEqualTo(recoveryModules);
List<String> expiryScanners = Arrays List<String> expiryScanners = Arrays.asList(
.asList("com.arjuna.ats.internal.arjuna.recovery.ExpiredTransactionStatusManagerScanner"); "com.arjuna.ats.internal.arjuna.recovery.ExpiredTransactionStatusManagerScanner");
assertThat(BeanPopulator.getDefaultInstance(RecoveryEnvironmentBean.class).getExpiryScannerClassNames()) assertThat(BeanPopulator.getDefaultInstance(RecoveryEnvironmentBean.class)
.isEqualTo(expiryScanners); .getExpiryScannerClassNames()).isEqualTo(expiryScanners);
assertThat(BeanPopulator.getDefaultInstance(JTAEnvironmentBean.class).getXaResourceRecoveryClassNames()).isEmpty(); assertThat(BeanPopulator.getDefaultInstance(JTAEnvironmentBean.class)
.getXaResourceRecoveryClassNames()).isEmpty();
} }
@Test @Test
...@@ -82,30 +93,44 @@ public class NarayanaConfigurationBeanTests { ...@@ -82,30 +93,44 @@ public class NarayanaConfigurationBeanTests {
narayanaProperties.setPeriodicRecoveryPeriod(2); narayanaProperties.setPeriodicRecoveryPeriod(2);
narayanaProperties.setRecoveryBackoffPeriod(3); narayanaProperties.setRecoveryBackoffPeriod(3);
narayanaProperties.setOnePhaseCommit(false); narayanaProperties.setOnePhaseCommit(false);
narayanaProperties.setXaResourceOrphanFilters(Arrays.asList("test-filter-1", "test-filter-2")); narayanaProperties.setXaResourceOrphanFilters(
narayanaProperties.setRecoveryModules(Arrays.asList("test-module-1", "test-module-2")); Arrays.asList("test-filter-1", "test-filter-2"));
narayanaProperties.setExpiryScanners(Arrays.asList("test-scanner-1", "test-scanner-2")); narayanaProperties
.setRecoveryModules(Arrays.asList("test-module-1", "test-module-2"));
NarayanaConfigurationBean narayanaConfigurationBean = new NarayanaConfigurationBean(narayanaProperties); narayanaProperties
.setExpiryScanners(Arrays.asList("test-scanner-1", "test-scanner-2"));
NarayanaConfigurationBean narayanaConfigurationBean = new NarayanaConfigurationBean(
narayanaProperties);
narayanaConfigurationBean.afterPropertiesSet(); narayanaConfigurationBean.afterPropertiesSet();
assertThat(BeanPopulator.getDefaultInstance(CoreEnvironmentBean.class).getNodeIdentifier()).isEqualTo("test-id"); assertThat(BeanPopulator.getDefaultInstance(CoreEnvironmentBean.class)
assertThat(BeanPopulator.getDefaultInstance(ObjectStoreEnvironmentBean.class).getObjectStoreDir()) .getNodeIdentifier()).isEqualTo("test-id");
.isEqualTo("test-dir"); assertThat(BeanPopulator.getDefaultInstance(ObjectStoreEnvironmentBean.class)
assertThat(BeanPopulator.getNamedInstance(ObjectStoreEnvironmentBean.class, "communicationStore").getObjectStoreDir()) .getObjectStoreDir()).isEqualTo("test-dir");
.isEqualTo("test-dir"); assertThat(BeanPopulator
assertThat(BeanPopulator.getNamedInstance(ObjectStoreEnvironmentBean.class, "stateStore").getObjectStoreDir()) .getNamedInstance(ObjectStoreEnvironmentBean.class, "communicationStore")
.isEqualTo("test-dir"); .getObjectStoreDir()).isEqualTo("test-dir");
assertThat(BeanPopulator.getDefaultInstance(CoordinatorEnvironmentBean.class).isCommitOnePhase()).isFalse(); assertThat(BeanPopulator
assertThat(BeanPopulator.getDefaultInstance(CoordinatorEnvironmentBean.class).getDefaultTimeout()).isEqualTo(1); .getNamedInstance(ObjectStoreEnvironmentBean.class, "stateStore")
assertThat(BeanPopulator.getDefaultInstance(RecoveryEnvironmentBean.class).getPeriodicRecoveryPeriod()).isEqualTo(2); .getObjectStoreDir()).isEqualTo("test-dir");
assertThat(BeanPopulator.getDefaultInstance(RecoveryEnvironmentBean.class).getRecoveryBackoffPeriod()).isEqualTo(3); assertThat(BeanPopulator.getDefaultInstance(CoordinatorEnvironmentBean.class)
assertThat(BeanPopulator.getDefaultInstance(JTAEnvironmentBean.class).getXaResourceOrphanFilterClassNames()) .isCommitOnePhase()).isFalse();
.isEqualTo(Arrays.asList("test-filter-1", "test-filter-2")); assertThat(BeanPopulator.getDefaultInstance(CoordinatorEnvironmentBean.class)
assertThat(BeanPopulator.getDefaultInstance(RecoveryEnvironmentBean.class).getRecoveryModuleClassNames()) .getDefaultTimeout()).isEqualTo(1);
.isEqualTo(Arrays.asList("test-module-1", "test-module-2")); assertThat(BeanPopulator.getDefaultInstance(RecoveryEnvironmentBean.class)
assertThat(BeanPopulator.getDefaultInstance(RecoveryEnvironmentBean.class).getExpiryScannerClassNames()) .getPeriodicRecoveryPeriod()).isEqualTo(2);
.isEqualTo(Arrays.asList("test-scanner-1", "test-scanner-2")); assertThat(BeanPopulator.getDefaultInstance(RecoveryEnvironmentBean.class)
.getRecoveryBackoffPeriod()).isEqualTo(3);
assertThat(BeanPopulator.getDefaultInstance(JTAEnvironmentBean.class)
.getXaResourceOrphanFilterClassNames())
.isEqualTo(Arrays.asList("test-filter-1", "test-filter-2"));
assertThat(BeanPopulator.getDefaultInstance(RecoveryEnvironmentBean.class)
.getRecoveryModuleClassNames())
.isEqualTo(Arrays.asList("test-module-1", "test-module-2"));
assertThat(BeanPopulator.getDefaultInstance(RecoveryEnvironmentBean.class)
.getExpiryScannerClassNames())
.isEqualTo(Arrays.asList("test-scanner-1", "test-scanner-2"));
} }
} }
/* /*
* Copyright 2012-2014 the original author or authors. * Copyright 2012-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -30,24 +30,26 @@ import org.junit.Before; ...@@ -30,24 +30,26 @@ import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.mock; import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.times; import static org.mockito.Mockito.mock;
import static org.mockito.BDDMockito.verify; import static org.mockito.Mockito.times;
import static org.mockito.BDDMockito.when; import static org.mockito.Mockito.verify;
/** /**
* @author <a href="mailto:gytis@redhat.com">Gytis Trikleris</a> * Tests for {@link NarayanaDataSourceBean}.
*
* @author Gytis Trikleris
*/ */
public class NarayanaDataSourceBeanTests { public class NarayanaDataSourceBeanTests {
private XADataSource mockDataSource; private XADataSource dataSource;
private NarayanaDataSourceBean dataSourceBean; private NarayanaDataSourceBean dataSourceBean;
@Before @Before
public void before() { public void before() {
this.mockDataSource = mock(XADataSource.class); this.dataSource = mock(XADataSource.class);
this.dataSourceBean = new NarayanaDataSourceBean(this.mockDataSource); this.dataSourceBean = new NarayanaDataSourceBean(this.dataSource);
} }
@Test @Test
...@@ -62,32 +64,36 @@ public class NarayanaDataSourceBeanTests { ...@@ -62,32 +64,36 @@ public class NarayanaDataSourceBeanTests {
@Test @Test
public void shouldUnwrapDataSource() throws SQLException { public void shouldUnwrapDataSource() throws SQLException {
assertThat(this.dataSourceBean.unwrap(DataSource.class)).isInstanceOf(DataSource.class); assertThat(this.dataSourceBean.unwrap(DataSource.class))
assertThat(this.dataSourceBean.unwrap(DataSource.class)).isSameAs(this.dataSourceBean); .isInstanceOf(DataSource.class);
assertThat(this.dataSourceBean.unwrap(DataSource.class))
.isSameAs(this.dataSourceBean);
} }
@Test @Test
public void shouldUnwrapXaDataSource() throws SQLException { public void shouldUnwrapXaDataSource() throws SQLException {
assertThat(this.dataSourceBean.unwrap(XADataSource.class)).isInstanceOf(XADataSource.class); assertThat(this.dataSourceBean.unwrap(XADataSource.class))
assertThat(this.dataSourceBean.unwrap(XADataSource.class)).isSameAs(this.mockDataSource); .isInstanceOf(XADataSource.class);
assertThat(this.dataSourceBean.unwrap(XADataSource.class))
.isSameAs(this.dataSource);
} }
@Test @Test
public void shouldGetConnectionAndCommit() throws SQLException { public void shouldGetConnectionAndCommit() throws SQLException {
Connection mockConnection = mock(Connection.class); Connection mockConnection = mock(Connection.class);
XAConnection mockXaConnection = mock(XAConnection.class); XAConnection mockXaConnection = mock(XAConnection.class);
when(mockXaConnection.getConnection()).thenReturn(mockConnection); given(mockXaConnection.getConnection()).willReturn(mockConnection);
when(this.mockDataSource.getXAConnection()).thenReturn(mockXaConnection); given(this.dataSource.getXAConnection()).willReturn(mockXaConnection);
Properties properties = new Properties(); Properties properties = new Properties();
properties.put(TransactionalDriver.XADataSource, this.mockDataSource); properties.put(TransactionalDriver.XADataSource, this.dataSource);
Connection connection = this.dataSourceBean.getConnection(); Connection connection = this.dataSourceBean.getConnection();
assertThat(connection).isInstanceOf(ConnectionImple.class); assertThat(connection).isInstanceOf(ConnectionImple.class);
connection.commit(); connection.commit();
verify(this.mockDataSource, times(1)).getXAConnection(); verify(this.dataSource, times(1)).getXAConnection();
verify(mockXaConnection, times(1)).getConnection(); verify(mockXaConnection, times(1)).getConnection();
verify(mockConnection, times(1)).commit(); verify(mockConnection, times(1)).commit();
} }
...@@ -98,11 +104,12 @@ public class NarayanaDataSourceBeanTests { ...@@ -98,11 +104,12 @@ public class NarayanaDataSourceBeanTests {
String password = "testPassword"; String password = "testPassword";
Connection mockConnection = mock(Connection.class); Connection mockConnection = mock(Connection.class);
XAConnection mockXaConnection = mock(XAConnection.class); XAConnection mockXaConnection = mock(XAConnection.class);
when(mockXaConnection.getConnection()).thenReturn(mockConnection); given(mockXaConnection.getConnection()).willReturn(mockConnection);
when(this.mockDataSource.getXAConnection(username, password)).thenReturn(mockXaConnection); given(this.dataSource.getXAConnection(username, password))
.willReturn(mockXaConnection);
Properties properties = new Properties(); Properties properties = new Properties();
properties.put(TransactionalDriver.XADataSource, this.mockDataSource); properties.put(TransactionalDriver.XADataSource, this.dataSource);
properties.put(TransactionalDriver.userName, username); properties.put(TransactionalDriver.userName, username);
properties.put(TransactionalDriver.password, password); properties.put(TransactionalDriver.password, password);
...@@ -111,7 +118,7 @@ public class NarayanaDataSourceBeanTests { ...@@ -111,7 +118,7 @@ public class NarayanaDataSourceBeanTests {
connection.commit(); connection.commit();
verify(this.mockDataSource, times(1)).getXAConnection(username, password); verify(this.dataSource, times(1)).getXAConnection(username, password);
verify(mockXaConnection, times(1)).getConnection(); verify(mockXaConnection, times(1)).getConnection();
verify(mockConnection, times(1)).commit(); verify(mockConnection, times(1)).commit();
} }
......
/* /*
* Copyright 2012-2014 the original author or authors. * Copyright 2012-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -17,7 +17,6 @@ ...@@ -17,7 +17,6 @@
package org.springframework.boot.jta.narayana; package org.springframework.boot.jta.narayana;
import com.arjuna.ats.jbossatx.jta.RecoveryManagerService; import com.arjuna.ats.jbossatx.jta.RecoveryManagerService;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
...@@ -26,34 +25,34 @@ import static org.mockito.Mockito.times; ...@@ -26,34 +25,34 @@ import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
/** /**
* @author <a href="mailto:gytis@redhat.com">Gytis Trikleris</a> * Tests for {@link NarayanaRecoveryManagerBean}.
*
* @author Gytis Trikleris
*/ */
public class NarayanaRecoveryManagerBeanTests { public class NarayanaRecoveryManagerBeanTests {
private RecoveryManagerService recoveryManagerService; private RecoveryManagerService service;
private NarayanaRecoveryManagerBean narayanaRecoveryManagerBean; private NarayanaRecoveryManagerBean recoveryManager;
@Before @Before
public void before() { public void before() {
this.recoveryManagerService = mock(RecoveryManagerService.class); this.service = mock(RecoveryManagerService.class);
this.narayanaRecoveryManagerBean = new NarayanaRecoveryManagerBean(this.recoveryManagerService); this.recoveryManager = new NarayanaRecoveryManagerBean(this.service);
} }
@Test @Test
public void shouldCreateAndStartRecoveryManagerService() throws Exception { public void shouldCreateAndStartRecoveryManagerService() throws Exception {
this.narayanaRecoveryManagerBean.afterPropertiesSet(); this.recoveryManager.afterPropertiesSet();
verify(this.service, times(1)).create();
verify(this.recoveryManagerService, times(1)).create(); verify(this.service, times(1)).start();
verify(this.recoveryManagerService, times(1)).start();
} }
@Test @Test
public void shouldStopAndDestroyRecoveryManagerService() throws Exception { public void shouldStopAndDestroyRecoveryManagerService() throws Exception {
this.narayanaRecoveryManagerBean.destroy(); this.recoveryManager.destroy();
verify(this.service, times(1)).stop();
verify(this.recoveryManagerService, times(1)).stop(); verify(this.service, times(1)).destroy();
verify(this.recoveryManagerService, times(1)).destroy();
} }
} }
/* /*
* Copyright 2012-2014 the original author or authors. * Copyright 2012-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -25,14 +25,16 @@ import org.jboss.narayana.jta.jms.JmsXAResourceRecoveryHelper; ...@@ -25,14 +25,16 @@ import org.jboss.narayana.jta.jms.JmsXAResourceRecoveryHelper;
import org.junit.Test; import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.mock; import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.times;
import static org.mockito.BDDMockito.verify;
import static org.mockito.BDDMockito.when;
import static org.mockito.Matchers.any; import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
/** /**
* @author <a href="mailto:gytis@redhat.com">Gytis Trikleris</a> * Tests for {@link NarayanaXAConnectionFactoryWrapper}.
*
* @author Gytis Trikleris
*/ */
public class NarayanaXAConnectionFactoryWrapperTests { public class NarayanaXAConnectionFactoryWrapperTests {
...@@ -40,34 +42,36 @@ public class NarayanaXAConnectionFactoryWrapperTests { ...@@ -40,34 +42,36 @@ public class NarayanaXAConnectionFactoryWrapperTests {
private TransactionManager transactionManager = mock(TransactionManager.class); private TransactionManager transactionManager = mock(TransactionManager.class);
private NarayanaRecoveryManagerBean narayanaRecoveryManagerBean = mock(NarayanaRecoveryManagerBean.class); private NarayanaRecoveryManagerBean recoveryManager = mock(
NarayanaRecoveryManagerBean.class);
private NarayanaProperties narayanaProperties = mock(NarayanaProperties.class); private NarayanaProperties properties = mock(NarayanaProperties.class);
private NarayanaXAConnectionFactoryWrapper wrapper = new NarayanaXAConnectionFactoryWrapper(this.transactionManager, private NarayanaXAConnectionFactoryWrapper wrapper = new NarayanaXAConnectionFactoryWrapper(
this.narayanaRecoveryManagerBean, this.narayanaProperties); this.transactionManager, this.recoveryManager, this.properties);
@Test @Test
public void wrap() { public void wrap() {
ConnectionFactory wrapped = this.wrapper.wrapConnectionFactory(this.connectionFactory); ConnectionFactory wrapped = this.wrapper
.wrapConnectionFactory(this.connectionFactory);
assertThat(wrapped).isInstanceOf(ConnectionFactoryProxy.class); assertThat(wrapped).isInstanceOf(ConnectionFactoryProxy.class);
verify(this.narayanaRecoveryManagerBean, times(1)) verify(this.recoveryManager, times(1))
.registerXAResourceRecoveryHelper(any(JmsXAResourceRecoveryHelper.class)); .registerXAResourceRecoveryHelper(any(JmsXAResourceRecoveryHelper.class));
verify(this.narayanaProperties, times(1)).getRecoveryJmsUser(); verify(this.properties, times(1)).getRecoveryJmsUser();
verify(this.narayanaProperties, times(1)).getRecoveryJmsPass(); verify(this.properties, times(1)).getRecoveryJmsPass();
} }
@Test @Test
public void wrapWithCredentials() { public void wrapWithCredentials() {
when(this.narayanaProperties.getRecoveryJmsUser()).thenReturn("userName"); given(this.properties.getRecoveryJmsUser()).willReturn("userName");
when(this.narayanaProperties.getRecoveryJmsPass()).thenReturn("password"); given(this.properties.getRecoveryJmsPass()).willReturn("password");
ConnectionFactory wrapped = this.wrapper.wrapConnectionFactory(this.connectionFactory); ConnectionFactory wrapped = this.wrapper
.wrapConnectionFactory(this.connectionFactory);
assertThat(wrapped).isInstanceOf(ConnectionFactoryProxy.class); assertThat(wrapped).isInstanceOf(ConnectionFactoryProxy.class);
verify(this.narayanaRecoveryManagerBean, times(1)) verify(this.recoveryManager, times(1))
.registerXAResourceRecoveryHelper(any(JmsXAResourceRecoveryHelper.class)); .registerXAResourceRecoveryHelper(any(JmsXAResourceRecoveryHelper.class));
verify(this.narayanaProperties, times(2)).getRecoveryJmsUser(); verify(this.properties, times(2)).getRecoveryJmsUser();
verify(this.narayanaProperties, times(1)).getRecoveryJmsPass(); verify(this.properties, times(1)).getRecoveryJmsPass();
} }
} }
/* /*
* Copyright 2012-2014 the original author or authors. * Copyright 2012-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -22,48 +22,49 @@ import javax.sql.XADataSource; ...@@ -22,48 +22,49 @@ import javax.sql.XADataSource;
import org.junit.Test; import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.mock; import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.times;
import static org.mockito.BDDMockito.verify;
import static org.mockito.BDDMockito.when;
import static org.mockito.Matchers.any; import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
/** /**
* @author <a href="mailto:gytis@redhat.com">Gytis Trikleris</a> * Tests for {@link NarayanaXADataSourceWrapper}.
*
* @author Gytis Trikleris
*/ */
public class NarayanaXADataSourceWrapperTests { public class NarayanaXADataSourceWrapperTests {
private XADataSource dataSource = mock(XADataSource.class); private XADataSource dataSource = mock(XADataSource.class);
private NarayanaRecoveryManagerBean narayanaRecoveryManagerBean = mock(NarayanaRecoveryManagerBean.class); private NarayanaRecoveryManagerBean recoveryManager = mock(
NarayanaRecoveryManagerBean.class);
private NarayanaProperties narayanaProperties = mock(NarayanaProperties.class); private NarayanaProperties properties = mock(NarayanaProperties.class);
private NarayanaXADataSourceWrapper wrapper = new NarayanaXADataSourceWrapper(this.narayanaRecoveryManagerBean, private NarayanaXADataSourceWrapper wrapper = new NarayanaXADataSourceWrapper(
this.narayanaProperties); this.recoveryManager, this.properties);
@Test @Test
public void wrap() { public void wrap() {
DataSource wrapped = this.wrapper.wrapDataSource(this.dataSource); DataSource wrapped = this.wrapper.wrapDataSource(this.dataSource);
assertThat(wrapped).isInstanceOf(NarayanaDataSourceBean.class); assertThat(wrapped).isInstanceOf(NarayanaDataSourceBean.class);
verify(this.narayanaRecoveryManagerBean, times(1)) verify(this.recoveryManager, times(1)).registerXAResourceRecoveryHelper(
.registerXAResourceRecoveryHelper(any(DataSourceXAResourceRecoveryHelper.class)); any(DataSourceXAResourceRecoveryHelper.class));
verify(this.narayanaProperties, times(1)).getRecoveryDbUser(); verify(this.properties, times(1)).getRecoveryDbUser();
verify(this.narayanaProperties, times(1)).getRecoveryDbPass(); verify(this.properties, times(1)).getRecoveryDbPass();
} }
@Test @Test
public void wrapWithCredentials() { public void wrapWithCredentials() {
when(this.narayanaProperties.getRecoveryDbUser()).thenReturn("userName"); given(this.properties.getRecoveryDbUser()).willReturn("userName");
when(this.narayanaProperties.getRecoveryDbPass()).thenReturn("password"); given(this.properties.getRecoveryDbPass()).willReturn("password");
DataSource wrapped = this.wrapper.wrapDataSource(this.dataSource); DataSource wrapped = this.wrapper.wrapDataSource(this.dataSource);
assertThat(wrapped).isInstanceOf(NarayanaDataSourceBean.class); assertThat(wrapped).isInstanceOf(NarayanaDataSourceBean.class);
verify(this.narayanaRecoveryManagerBean, times(1)) verify(this.recoveryManager, times(1)).registerXAResourceRecoveryHelper(
.registerXAResourceRecoveryHelper(any(DataSourceXAResourceRecoveryHelper.class)); any(DataSourceXAResourceRecoveryHelper.class));
verify(this.narayanaProperties, times(2)).getRecoveryDbUser(); verify(this.properties, times(2)).getRecoveryDbUser();
verify(this.narayanaProperties, times(1)).getRecoveryDbPass(); verify(this.properties, times(1)).getRecoveryDbPass();
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment