From 3d93a260716babcc3633a5b0b5013d99cf44f1b1 Mon Sep 17 00:00:00 2001 From: Benjamin Graf Date: Fri, 12 Jun 2026 16:14:25 +0200 Subject: [PATCH] Add an option to disable recovery for a connection pool --- .../core/jdbc/GenericXADataSourceWrapper.java | 18 ++++---- .../AbstractXAConnectionFactoryWrapper.java | 14 +++--- .../GenericXAConnectionFactoryWrapper.java | 6 +-- .../jms/PooledXAConnectionFactoryWrapper.java | 8 ++-- .../core/properties/NarayanaProperties.java | 44 ++++++++++++++----- ...roperties.java => RecoveryProperties.java} | 25 ++++++++--- .../jdbc/GenericXADataSourceWrapperTests.java | 32 +++++++++----- ...enericXAConnectionFactoryWrapperTests.java | 32 +++++++++----- .../PooledXAConnectionFactoryWrapperTest.java | 38 ++++++++++------ 9 files changed, 146 insertions(+), 71 deletions(-) rename narayana-spring-boot-core/src/main/java/dev/snowdrop/boot/narayana/core/properties/{RecoveryCredentialsProperties.java => RecoveryProperties.java} (70%) diff --git a/narayana-spring-boot-core/src/main/java/dev/snowdrop/boot/narayana/core/jdbc/GenericXADataSourceWrapper.java b/narayana-spring-boot-core/src/main/java/dev/snowdrop/boot/narayana/core/jdbc/GenericXADataSourceWrapper.java index 23fca3c2..38985ab8 100644 --- a/narayana-spring-boot-core/src/main/java/dev/snowdrop/boot/narayana/core/jdbc/GenericXADataSourceWrapper.java +++ b/narayana-spring-boot-core/src/main/java/dev/snowdrop/boot/narayana/core/jdbc/GenericXADataSourceWrapper.java @@ -28,7 +28,7 @@ import com.arjuna.ats.internal.jdbc.drivers.modifiers.SupportsMultipleConnectionsModifier; import com.arjuna.ats.internal.jta.recovery.arjunacore.XARecoveryModule; import com.arjuna.ats.jta.recovery.XAResourceRecoveryHelper; -import dev.snowdrop.boot.narayana.core.properties.RecoveryCredentialsProperties; +import dev.snowdrop.boot.narayana.core.properties.RecoveryProperties; import dev.snowdrop.boot.narayana.core.properties.TransactionalDriverProperties; import org.springframework.boot.jdbc.DatabaseDriver; import org.springframework.boot.jdbc.XADataSourceWrapper; @@ -44,7 +44,7 @@ public class GenericXADataSourceWrapper implements XADataSourceWrapper { private final XARecoveryModule xaRecoveryModule; private final TransactionalDriverProperties transactionalDriverProperties; - private final RecoveryCredentialsProperties recoveryCredentials; + private final RecoveryProperties recoveryCredentials; /** * Create a new {@link GenericXADataSourceWrapper} instance. @@ -52,7 +52,7 @@ public class GenericXADataSourceWrapper implements XADataSourceWrapper { * @param xaRecoveryModule recovery module to register data source with. */ public GenericXADataSourceWrapper(XARecoveryModule xaRecoveryModule) { - this(xaRecoveryModule, RecoveryCredentialsProperties.DEFAULT); + this(xaRecoveryModule, RecoveryProperties.DEFAULT); } /** @@ -61,7 +61,7 @@ public GenericXADataSourceWrapper(XARecoveryModule xaRecoveryModule) { * @param xaRecoveryModule recovery module to register data source with. * @param recoveryCredentials credentials for recovery helper */ - public GenericXADataSourceWrapper(XARecoveryModule xaRecoveryModule, RecoveryCredentialsProperties recoveryCredentials) { + public GenericXADataSourceWrapper(XARecoveryModule xaRecoveryModule, RecoveryProperties recoveryCredentials) { this(xaRecoveryModule, new TransactionalDriverProperties(), recoveryCredentials); } @@ -72,7 +72,7 @@ public GenericXADataSourceWrapper(XARecoveryModule xaRecoveryModule, RecoveryCre * @param transactionalDriverProperties Transactional driver properties */ public GenericXADataSourceWrapper(XARecoveryModule xaRecoveryModule, TransactionalDriverProperties transactionalDriverProperties) { - this(xaRecoveryModule, transactionalDriverProperties, RecoveryCredentialsProperties.DEFAULT); + this(xaRecoveryModule, transactionalDriverProperties, RecoveryProperties.DEFAULT); } /** @@ -83,7 +83,7 @@ public GenericXADataSourceWrapper(XARecoveryModule xaRecoveryModule, Transaction * @param recoveryCredentials credentials for recovery helper */ public GenericXADataSourceWrapper(XARecoveryModule xaRecoveryModule, TransactionalDriverProperties transactionalDriverProperties, - RecoveryCredentialsProperties recoveryCredentials) { + RecoveryProperties recoveryCredentials) { this.xaRecoveryModule = xaRecoveryModule; this.transactionalDriverProperties = transactionalDriverProperties; this.recoveryCredentials = recoveryCredentials; @@ -98,8 +98,10 @@ public GenericXADataSourceWrapper(XARecoveryModule xaRecoveryModule, Transaction */ @Override public DataSource wrapDataSource(XADataSource dataSource) throws Exception { - XAResourceRecoveryHelper recoveryHelper = getRecoveryHelper(dataSource); - this.xaRecoveryModule.addXAResourceRecoveryHelper(recoveryHelper); + if (this.recoveryCredentials.isEnabled()) { + XAResourceRecoveryHelper recoveryHelper = getRecoveryHelper(dataSource); + this.xaRecoveryModule.addXAResourceRecoveryHelper(recoveryHelper); + } registerModifier(dataSource); return new NarayanaDataSource(dataSource, this.transactionalDriverProperties); } diff --git a/narayana-spring-boot-core/src/main/java/dev/snowdrop/boot/narayana/core/jms/AbstractXAConnectionFactoryWrapper.java b/narayana-spring-boot-core/src/main/java/dev/snowdrop/boot/narayana/core/jms/AbstractXAConnectionFactoryWrapper.java index 30eedded..8796831a 100644 --- a/narayana-spring-boot-core/src/main/java/dev/snowdrop/boot/narayana/core/jms/AbstractXAConnectionFactoryWrapper.java +++ b/narayana-spring-boot-core/src/main/java/dev/snowdrop/boot/narayana/core/jms/AbstractXAConnectionFactoryWrapper.java @@ -21,7 +21,7 @@ import com.arjuna.ats.internal.jta.recovery.arjunacore.XARecoveryModule; import com.arjuna.ats.jta.recovery.XAResourceRecoveryHelper; -import dev.snowdrop.boot.narayana.core.properties.RecoveryCredentialsProperties; +import dev.snowdrop.boot.narayana.core.properties.RecoveryProperties; import org.jboss.narayana.jta.jms.ConnectionFactoryProxy; import org.jboss.narayana.jta.jms.JmsXAResourceRecoveryHelper; import org.springframework.boot.jms.XAConnectionFactoryWrapper; @@ -35,9 +35,9 @@ public abstract class AbstractXAConnectionFactoryWrapper implements XAConnectionFactoryWrapper { private final XARecoveryModule xaRecoveryModule; - private final RecoveryCredentialsProperties recoveryCredentials; + private final RecoveryProperties recoveryCredentials; - protected AbstractXAConnectionFactoryWrapper(XARecoveryModule xaRecoveryModule, RecoveryCredentialsProperties recoveryCredentials) { + protected AbstractXAConnectionFactoryWrapper(XARecoveryModule xaRecoveryModule, RecoveryProperties recoveryCredentials) { this.xaRecoveryModule = xaRecoveryModule; this.recoveryCredentials = recoveryCredentials; } @@ -46,12 +46,14 @@ protected AbstractXAConnectionFactoryWrapper(XARecoveryModule xaRecoveryModule, @Override public ConnectionFactory wrapConnectionFactory(XAConnectionFactory xaConnectionFactory) throws Exception { - XAResourceRecoveryHelper recoveryHelper = getRecoveryHelper(xaConnectionFactory, this.recoveryCredentials); - this.xaRecoveryModule.addXAResourceRecoveryHelper(recoveryHelper); + if (this.recoveryCredentials.isEnabled()) { + XAResourceRecoveryHelper recoveryHelper = getRecoveryHelper(xaConnectionFactory, this.recoveryCredentials); + this.xaRecoveryModule.addXAResourceRecoveryHelper(recoveryHelper); + } return wrapConnectionFactoryInternal(xaConnectionFactory); } - protected XAResourceRecoveryHelper getRecoveryHelper(XAConnectionFactory xaConnectionFactory, RecoveryCredentialsProperties recoveryCredentials) { + protected XAResourceRecoveryHelper getRecoveryHelper(XAConnectionFactory xaConnectionFactory, RecoveryProperties recoveryCredentials) { if (recoveryCredentials.isValid()) { return new JmsXAResourceRecoveryHelper(xaConnectionFactory, recoveryCredentials.getUser(), recoveryCredentials.getPassword()); diff --git a/narayana-spring-boot-core/src/main/java/dev/snowdrop/boot/narayana/core/jms/GenericXAConnectionFactoryWrapper.java b/narayana-spring-boot-core/src/main/java/dev/snowdrop/boot/narayana/core/jms/GenericXAConnectionFactoryWrapper.java index f0ceb70b..556ee1d8 100644 --- a/narayana-spring-boot-core/src/main/java/dev/snowdrop/boot/narayana/core/jms/GenericXAConnectionFactoryWrapper.java +++ b/narayana-spring-boot-core/src/main/java/dev/snowdrop/boot/narayana/core/jms/GenericXAConnectionFactoryWrapper.java @@ -21,7 +21,7 @@ import jakarta.transaction.TransactionManager; import com.arjuna.ats.internal.jta.recovery.arjunacore.XARecoveryModule; -import dev.snowdrop.boot.narayana.core.properties.RecoveryCredentialsProperties; +import dev.snowdrop.boot.narayana.core.properties.RecoveryProperties; import org.jboss.narayana.jta.jms.ConnectionFactoryProxy; import org.jboss.narayana.jta.jms.TransactionHelperImpl; @@ -36,7 +36,7 @@ public class GenericXAConnectionFactoryWrapper extends AbstractXAConnectionFacto * @param xaRecoveryModule recovery module to register data source with. */ public GenericXAConnectionFactoryWrapper(TransactionManager transactionManager, XARecoveryModule xaRecoveryModule) { - this(transactionManager, xaRecoveryModule, RecoveryCredentialsProperties.DEFAULT); + this(transactionManager, xaRecoveryModule, RecoveryProperties.DEFAULT); } /** @@ -47,7 +47,7 @@ public GenericXAConnectionFactoryWrapper(TransactionManager transactionManager, * @param recoveryCredentials Credentials for recovery helper */ public GenericXAConnectionFactoryWrapper(TransactionManager transactionManager, XARecoveryModule xaRecoveryModule, - RecoveryCredentialsProperties recoveryCredentials) { + RecoveryProperties recoveryCredentials) { super(xaRecoveryModule, recoveryCredentials); this.transactionManager = transactionManager; } diff --git a/narayana-spring-boot-core/src/main/java/dev/snowdrop/boot/narayana/core/jms/PooledXAConnectionFactoryWrapper.java b/narayana-spring-boot-core/src/main/java/dev/snowdrop/boot/narayana/core/jms/PooledXAConnectionFactoryWrapper.java index 409f2b06..2dc066a6 100644 --- a/narayana-spring-boot-core/src/main/java/dev/snowdrop/boot/narayana/core/jms/PooledXAConnectionFactoryWrapper.java +++ b/narayana-spring-boot-core/src/main/java/dev/snowdrop/boot/narayana/core/jms/PooledXAConnectionFactoryWrapper.java @@ -25,7 +25,7 @@ import dev.snowdrop.boot.narayana.core.jms.pool.JmsPoolNarayanaConnectionFactory; import dev.snowdrop.boot.narayana.core.jms.pool.NamedJmsXAResourceRecoveryHelper; import dev.snowdrop.boot.narayana.core.properties.MessagingHubConnectionFactoryProperties; -import dev.snowdrop.boot.narayana.core.properties.RecoveryCredentialsProperties; +import dev.snowdrop.boot.narayana.core.properties.RecoveryProperties; public class PooledXAConnectionFactoryWrapper extends AbstractXAConnectionFactoryWrapper { @@ -41,7 +41,7 @@ public class PooledXAConnectionFactoryWrapper extends AbstractXAConnectionFactor */ public PooledXAConnectionFactoryWrapper(TransactionManager transactionManager, XARecoveryModule xaRecoveryModule, MessagingHubConnectionFactoryProperties properties) { - this(transactionManager, xaRecoveryModule, properties, RecoveryCredentialsProperties.DEFAULT); + this(transactionManager, xaRecoveryModule, properties, RecoveryProperties.DEFAULT); } /** @@ -53,7 +53,7 @@ public PooledXAConnectionFactoryWrapper(TransactionManager transactionManager, X * @param recoveryCredentials Credentials for recovery helper */ public PooledXAConnectionFactoryWrapper(TransactionManager transactionManager, XARecoveryModule xaRecoveryModule, - MessagingHubConnectionFactoryProperties properties, RecoveryCredentialsProperties recoveryCredentials) { + MessagingHubConnectionFactoryProperties properties, RecoveryProperties recoveryCredentials) { super(xaRecoveryModule, recoveryCredentials); this.properties = properties; this.transactionManager = transactionManager; @@ -82,7 +82,7 @@ protected ConnectionFactory wrapConnectionFactoryInternal(XAConnectionFactory xa } @Override - protected XAResourceRecoveryHelper getRecoveryHelper(XAConnectionFactory xaConnectionFactory, RecoveryCredentialsProperties recoveryCredentials) { + protected XAResourceRecoveryHelper getRecoveryHelper(XAConnectionFactory xaConnectionFactory, RecoveryProperties recoveryCredentials) { if (recoveryCredentials.isValid()) { return new NamedJmsXAResourceRecoveryHelper(xaConnectionFactory, recoveryCredentials.getUser(), recoveryCredentials.getPassword(), this.properties.getName()); diff --git a/narayana-spring-boot-core/src/main/java/dev/snowdrop/boot/narayana/core/properties/NarayanaProperties.java b/narayana-spring-boot-core/src/main/java/dev/snowdrop/boot/narayana/core/properties/NarayanaProperties.java index 5b00a404..47a079d8 100644 --- a/narayana-spring-boot-core/src/main/java/dev/snowdrop/boot/narayana/core/properties/NarayanaProperties.java +++ b/narayana-spring-boot-core/src/main/java/dev/snowdrop/boot/narayana/core/properties/NarayanaProperties.java @@ -76,14 +76,14 @@ public class NarayanaProperties { private int expiryScanInterval = 12; /** - * Database credentials to be used by recovery manager. + * Database recovery properties to be used by recovery manager. */ - private RecoveryCredentialsProperties recoveryDbCredentials = new RecoveryCredentialsProperties(); + private RecoveryProperties dbRecoveryProperties = new RecoveryProperties(); /** - * JMS credentials to be used by recovery manager. + * JMS recovery properties to be used by recovery manager. */ - private RecoveryCredentialsProperties recoveryJmsCredentials = new RecoveryCredentialsProperties(); + private RecoveryProperties jmsRecoveryProperties = new RecoveryProperties(); /** * Comma-separated list of orphan filters. @@ -253,20 +253,40 @@ public void setExpiryScanners(List expiryScanners) { this.expiryScanners = expiryScanners; } - public RecoveryCredentialsProperties getRecoveryDbCredentials() { - return this.recoveryDbCredentials; + @Deprecated(forRemoval = true) + public RecoveryProperties getRecoveryDbCredentials() { + return this.dbRecoveryProperties; } - public void setRecoveryDbCredentials(RecoveryCredentialsProperties recoveryDbCredentials) { - this.recoveryDbCredentials = recoveryDbCredentials; + @Deprecated(forRemoval = true) + public void setRecoveryDbCredentials(RecoveryProperties dbRecoveryProperties) { + this.dbRecoveryProperties = dbRecoveryProperties; } - public RecoveryCredentialsProperties getRecoveryJmsCredentials() { - return this.recoveryJmsCredentials; + @Deprecated(forRemoval = true) + public RecoveryProperties getRecoveryJmsCredentials() { + return this.jmsRecoveryProperties; } - public void setRecoveryJmsCredentials(RecoveryCredentialsProperties recoveryJmsCredentials) { - this.recoveryJmsCredentials = recoveryJmsCredentials; + @Deprecated(forRemoval = true) + public void setRecoveryJmsCredentials(RecoveryProperties jmsRecoveryProperties) { + this.jmsRecoveryProperties = jmsRecoveryProperties; + } + + public RecoveryProperties getDbRecoveryProperties() { + return this.dbRecoveryProperties; + } + + public void setDbRecoveryProperties(RecoveryProperties dbRecoveryProperties) { + this.dbRecoveryProperties = dbRecoveryProperties; + } + + public RecoveryProperties getJmsRecoveryProperties() { + return this.jmsRecoveryProperties; + } + + public void setJmsRecoveryProperties(RecoveryProperties jmsRecoveryProperties) { + this.jmsRecoveryProperties = jmsRecoveryProperties; } public TransactionalDriverProperties getTransactionalDriver() { diff --git a/narayana-spring-boot-core/src/main/java/dev/snowdrop/boot/narayana/core/properties/RecoveryCredentialsProperties.java b/narayana-spring-boot-core/src/main/java/dev/snowdrop/boot/narayana/core/properties/RecoveryProperties.java similarity index 70% rename from narayana-spring-boot-core/src/main/java/dev/snowdrop/boot/narayana/core/properties/RecoveryCredentialsProperties.java rename to narayana-spring-boot-core/src/main/java/dev/snowdrop/boot/narayana/core/properties/RecoveryProperties.java index df85da2f..d1492c12 100644 --- a/narayana-spring-boot-core/src/main/java/dev/snowdrop/boot/narayana/core/properties/RecoveryCredentialsProperties.java +++ b/narayana-spring-boot-core/src/main/java/dev/snowdrop/boot/narayana/core/properties/RecoveryProperties.java @@ -16,24 +16,31 @@ package dev.snowdrop.boot.narayana.core.properties; -public class RecoveryCredentialsProperties { +public class RecoveryProperties { /** * default instance for convenience. */ - public static final RecoveryCredentialsProperties DEFAULT; + public static final RecoveryProperties DEFAULT; + private boolean enabled; private String user; private String password; static { - DEFAULT = new RecoveryCredentialsProperties(); + DEFAULT = new RecoveryProperties(); } - public RecoveryCredentialsProperties() { + public RecoveryProperties() { + this(true); } - public RecoveryCredentialsProperties(String user, String password) { + public RecoveryProperties(boolean enabled) { + this.enabled = enabled; + } + + public RecoveryProperties(String user, String password) { + this(true); this.user = user; this.password = password; } @@ -42,6 +49,14 @@ public boolean isValid() { return !(this.user == null && this.password == null); } + public boolean isEnabled() { + return this.enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + public String getUser() { return this.user; } diff --git a/narayana-spring-boot-core/src/test/java/dev/snowdrop/boot/narayana/core/jdbc/GenericXADataSourceWrapperTests.java b/narayana-spring-boot-core/src/test/java/dev/snowdrop/boot/narayana/core/jdbc/GenericXADataSourceWrapperTests.java index 8cb716b2..0587ce6b 100644 --- a/narayana-spring-boot-core/src/test/java/dev/snowdrop/boot/narayana/core/jdbc/GenericXADataSourceWrapperTests.java +++ b/narayana-spring-boot-core/src/test/java/dev/snowdrop/boot/narayana/core/jdbc/GenericXADataSourceWrapperTests.java @@ -25,7 +25,7 @@ import javax.sql.XADataSource; import com.arjuna.ats.internal.jta.recovery.arjunacore.XARecoveryModule; -import dev.snowdrop.boot.narayana.core.properties.RecoveryCredentialsProperties; +import dev.snowdrop.boot.narayana.core.properties.RecoveryProperties; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -35,6 +35,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; /** @@ -61,7 +62,7 @@ class GenericXADataSourceWrapperTests { private XARecoveryModule mockXaRecoveryModule; @Mock - private RecoveryCredentialsProperties mockRecoveryCredentialsProperties; + private RecoveryProperties mockRecoveryProperties; private GenericXADataSourceWrapper wrapper; @@ -71,27 +72,38 @@ void before() throws SQLException { given(this.mockXaConnection.getConnection()).willReturn(this.mockConnection); given(this.mockConnection.getMetaData()).willReturn(this.mockDatabaseMetaData); given(this.mockDatabaseMetaData.getDatabaseProductName()).willReturn(""); - this.wrapper = new GenericXADataSourceWrapper(this.mockXaRecoveryModule, this.mockRecoveryCredentialsProperties); + given(this.mockRecoveryProperties.isEnabled()).willReturn(true); + this.wrapper = new GenericXADataSourceWrapper(this.mockXaRecoveryModule, this.mockRecoveryProperties); } @Test void wrap() throws Exception { - given(this.mockRecoveryCredentialsProperties.isValid()).willReturn(false); + given(this.mockRecoveryProperties.isValid()).willReturn(false); DataSource wrapped = this.wrapper.wrapDataSource(this.mockXaDataSource); assertThat(wrapped).isInstanceOf(NarayanaDataSource.class); + verify(this.mockRecoveryProperties).isValid(); verify(this.mockXaRecoveryModule).addXAResourceRecoveryHelper(any(DataSourceXAResourceRecoveryHelper.class)); - verify(this.mockRecoveryCredentialsProperties).isValid(); } @Test void wrapWithCredentials() throws Exception { - given(this.mockRecoveryCredentialsProperties.isValid()).willReturn(true); - given(this.mockRecoveryCredentialsProperties.getUser()).willReturn("userName"); - given(this.mockRecoveryCredentialsProperties.getPassword()).willReturn("password"); + given(this.mockRecoveryProperties.isValid()).willReturn(true); + given(this.mockRecoveryProperties.getUser()).willReturn("userName"); + given(this.mockRecoveryProperties.getPassword()).willReturn("password"); DataSource wrapped = this.wrapper.wrapDataSource(this.mockXaDataSource); assertThat(wrapped).isInstanceOf(NarayanaDataSource.class); + verify(this.mockRecoveryProperties).isValid(); + verify(this.mockRecoveryProperties).getUser(); + verify(this.mockRecoveryProperties).getPassword(); verify(this.mockXaRecoveryModule).addXAResourceRecoveryHelper(any(DataSourceXAResourceRecoveryHelper.class)); - verify(this.mockRecoveryCredentialsProperties).getUser(); - verify(this.mockRecoveryCredentialsProperties).getPassword(); + } + + @Test + void wrapWithRecoveryDisabled() throws Exception { + given(this.mockRecoveryProperties.isEnabled()).willReturn(false); + DataSource wrapped = this.wrapper.wrapDataSource(this.mockXaDataSource); + assertThat(wrapped).isInstanceOf(NarayanaDataSource.class); + verify(this.mockXaRecoveryModule, times(0)).addXAResourceRecoveryHelper(any(DataSourceXAResourceRecoveryHelper.class)); + verify(this.mockRecoveryProperties, times(0)).isValid(); } } diff --git a/narayana-spring-boot-core/src/test/java/dev/snowdrop/boot/narayana/core/jms/GenericXAConnectionFactoryWrapperTests.java b/narayana-spring-boot-core/src/test/java/dev/snowdrop/boot/narayana/core/jms/GenericXAConnectionFactoryWrapperTests.java index 1ab5dc89..916c0ad5 100644 --- a/narayana-spring-boot-core/src/test/java/dev/snowdrop/boot/narayana/core/jms/GenericXAConnectionFactoryWrapperTests.java +++ b/narayana-spring-boot-core/src/test/java/dev/snowdrop/boot/narayana/core/jms/GenericXAConnectionFactoryWrapperTests.java @@ -21,7 +21,7 @@ import jakarta.transaction.TransactionManager; import com.arjuna.ats.internal.jta.recovery.arjunacore.XARecoveryModule; -import dev.snowdrop.boot.narayana.core.properties.RecoveryCredentialsProperties; +import dev.snowdrop.boot.narayana.core.properties.RecoveryProperties; import org.jboss.narayana.jta.jms.ConnectionFactoryProxy; import org.jboss.narayana.jta.jms.JmsXAResourceRecoveryHelper; import org.junit.jupiter.api.BeforeEach; @@ -33,6 +33,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; /** @@ -53,34 +54,45 @@ class GenericXAConnectionFactoryWrapperTests { private XARecoveryModule mockXaRecoveryModule; @Mock - private RecoveryCredentialsProperties mockRecoveryCredentialsProperties; + private RecoveryProperties mockRecoveryProperties; private GenericXAConnectionFactoryWrapper wrapper; @BeforeEach void before() { + given(this.mockRecoveryProperties.isEnabled()).willReturn(true); this.wrapper = new GenericXAConnectionFactoryWrapper(this.mockTransactionManager, this.mockXaRecoveryModule, - this.mockRecoveryCredentialsProperties); + this.mockRecoveryProperties); } @Test void wrap() throws Exception { - given(this.mockRecoveryCredentialsProperties.isValid()).willReturn(false); + given(this.mockRecoveryProperties.isValid()).willReturn(false); ConnectionFactory wrapped = this.wrapper.wrapConnectionFactory(this.mockXaConnectionFactory); assertThat(wrapped).isInstanceOf(ConnectionFactoryProxy.class); + verify(this.mockRecoveryProperties).isValid(); verify(this.mockXaRecoveryModule).addXAResourceRecoveryHelper(any(JmsXAResourceRecoveryHelper.class)); - verify(this.mockRecoveryCredentialsProperties).isValid(); } @Test void wrapWithCredentials() throws Exception { - given(this.mockRecoveryCredentialsProperties.isValid()).willReturn(true); - given(this.mockRecoveryCredentialsProperties.getUser()).willReturn("userName"); - given(this.mockRecoveryCredentialsProperties.getPassword()).willReturn("password"); + given(this.mockRecoveryProperties.isValid()).willReturn(true); + given(this.mockRecoveryProperties.getUser()).willReturn("userName"); + given(this.mockRecoveryProperties.getPassword()).willReturn("password"); ConnectionFactory wrapped = this.wrapper.wrapConnectionFactory(this.mockXaConnectionFactory); assertThat(wrapped).isInstanceOf(ConnectionFactoryProxy.class); + verify(this.mockRecoveryProperties).isValid(); + verify(this.mockRecoveryProperties).getUser(); + verify(this.mockRecoveryProperties).getPassword(); verify(this.mockXaRecoveryModule).addXAResourceRecoveryHelper(any(JmsXAResourceRecoveryHelper.class)); - verify(this.mockRecoveryCredentialsProperties).getUser(); - verify(this.mockRecoveryCredentialsProperties).getPassword(); + } + + @Test + void wrapWithRecoveryDisabled() throws Exception { + given(this.mockRecoveryProperties.isEnabled()).willReturn(false); + ConnectionFactory wrapped = this.wrapper.wrapConnectionFactory(this.mockXaConnectionFactory); + assertThat(wrapped).isInstanceOf(ConnectionFactoryProxy.class); + verify(this.mockXaRecoveryModule, times(0)).addXAResourceRecoveryHelper(any(JmsXAResourceRecoveryHelper.class)); + verify(this.mockRecoveryProperties, times(0)).isValid(); } } diff --git a/narayana-spring-boot-core/src/test/java/dev/snowdrop/boot/narayana/core/jms/PooledXAConnectionFactoryWrapperTest.java b/narayana-spring-boot-core/src/test/java/dev/snowdrop/boot/narayana/core/jms/PooledXAConnectionFactoryWrapperTest.java index 540aaecb..44e9a7cb 100644 --- a/narayana-spring-boot-core/src/test/java/dev/snowdrop/boot/narayana/core/jms/PooledXAConnectionFactoryWrapperTest.java +++ b/narayana-spring-boot-core/src/test/java/dev/snowdrop/boot/narayana/core/jms/PooledXAConnectionFactoryWrapperTest.java @@ -29,7 +29,7 @@ import com.arjuna.ats.internal.jta.recovery.arjunacore.XARecoveryModule; import dev.snowdrop.boot.narayana.core.properties.MessagingHubConnectionFactoryProperties; -import dev.snowdrop.boot.narayana.core.properties.RecoveryCredentialsProperties; +import dev.snowdrop.boot.narayana.core.properties.RecoveryProperties; import org.jboss.narayana.jta.jms.JmsXAResourceRecoveryHelper; import org.jboss.tm.FirstResource; import org.jboss.tm.LastResource; @@ -47,6 +47,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @ExtendWith(MockitoExtension.class) @@ -61,46 +62,57 @@ class PooledXAConnectionFactoryWrapperTest { @Spy private MessagingHubConnectionFactoryProperties spyMessagingHubConnectionFactoryProperties; @Mock - private RecoveryCredentialsProperties mockRecoveryCredentialsProperties; + private RecoveryProperties mockRecoveryProperties; private PooledXAConnectionFactoryWrapper wrapper; @BeforeEach void before() { + given(this.mockRecoveryProperties.isEnabled()).willReturn(true); this.wrapper = new PooledXAConnectionFactoryWrapper(this.mockTransactionManager, this.mockXaRecoveryModule, - this.spyMessagingHubConnectionFactoryProperties, this.mockRecoveryCredentialsProperties); + this.spyMessagingHubConnectionFactoryProperties, this.mockRecoveryProperties); } @Test void wrap() throws Exception { - given(this.mockRecoveryCredentialsProperties.isValid()).willReturn(false); + given(this.mockRecoveryProperties.isValid()).willReturn(false); ConnectionFactory connectionFactory = this.wrapper.wrapConnectionFactory(this.mockXaConnectionFactory); assertThat(connectionFactory).isInstanceOf(JmsPoolXAConnectionFactory.class); JmsPoolXAConnectionFactory pooledConnectionFactory = (JmsPoolXAConnectionFactory) connectionFactory; assertThat(pooledConnectionFactory.getTransactionManager()).isEqualTo(this.mockTransactionManager); assertThat(pooledConnectionFactory.getConnectionFactory()).isEqualTo(this.mockXaConnectionFactory); + verify(this.mockRecoveryProperties).isValid(); verify(this.mockXaRecoveryModule).addXAResourceRecoveryHelper(any(JmsXAResourceRecoveryHelper.class)); - verify(this.mockRecoveryCredentialsProperties).isValid(); } @Test void wrapWithCredentials() throws Exception { - given(this.mockRecoveryCredentialsProperties.isValid()).willReturn(true); - given(this.mockRecoveryCredentialsProperties.getUser()).willReturn("userName"); - given(this.mockRecoveryCredentialsProperties.getPassword()).willReturn("password"); + given(this.mockRecoveryProperties.isValid()).willReturn(true); + given(this.mockRecoveryProperties.getUser()).willReturn("userName"); + given(this.mockRecoveryProperties.getPassword()).willReturn("password"); ConnectionFactory connectionFactory = this.wrapper.wrapConnectionFactory(this.mockXaConnectionFactory); assertThat(connectionFactory).isInstanceOf(JmsPoolXAConnectionFactory.class); JmsPoolXAConnectionFactory pooledConnectionFactory = (JmsPoolXAConnectionFactory) connectionFactory; assertThat(pooledConnectionFactory.getTransactionManager()).isEqualTo(this.mockTransactionManager); assertThat(pooledConnectionFactory.getConnectionFactory()).isEqualTo(this.mockXaConnectionFactory); + verify(this.mockRecoveryProperties).isValid(); + verify(this.mockRecoveryProperties).getUser(); + verify(this.mockRecoveryProperties).getPassword(); verify(this.mockXaRecoveryModule).addXAResourceRecoveryHelper(any(JmsXAResourceRecoveryHelper.class)); - verify(this.mockRecoveryCredentialsProperties).getUser(); - verify(this.mockRecoveryCredentialsProperties).getPassword(); + } + + @Test + void wrapWithRecoveryDisabled() throws Exception { + given(this.mockRecoveryProperties.isEnabled()).willReturn(false); + ConnectionFactory connectionFactory = this.wrapper.wrapConnectionFactory(this.mockXaConnectionFactory); + assertThat(connectionFactory).isInstanceOf(JmsPoolXAConnectionFactory.class); + verify(this.mockXaRecoveryModule, times(0)).addXAResourceRecoveryHelper(any(JmsXAResourceRecoveryHelper.class)); + verify(this.mockRecoveryProperties, times(0)).isValid(); } @Test void wrapWithFirstResource() throws Exception { given(this.spyMessagingHubConnectionFactoryProperties.isFirstResource()).willReturn(true); - given(this.mockRecoveryCredentialsProperties.isValid()).willReturn(false); + given(this.mockRecoveryProperties.isValid()).willReturn(false); ConnectionFactory connectionFactory = this.wrapper.wrapConnectionFactory(this.mockXaConnectionFactory); XAConnection mockXaConnection = mock(XAConnection.class); @@ -120,7 +132,7 @@ void wrapWithFirstResource() throws Exception { @Test void wrapWithLastResource() throws Exception { given(this.spyMessagingHubConnectionFactoryProperties.isLastResource()).willReturn(true); - given(this.mockRecoveryCredentialsProperties.isValid()).willReturn(false); + given(this.mockRecoveryProperties.isValid()).willReturn(false); ConnectionFactory connectionFactory = this.wrapper.wrapConnectionFactory(this.mockXaConnectionFactory); XAConnection mockXaConnection = mock(XAConnection.class); @@ -141,7 +153,7 @@ void wrapWithLastResource() throws Exception { void invalidFirstLastResourceConfiguration() throws Exception { given(this.spyMessagingHubConnectionFactoryProperties.isFirstResource()).willReturn(true); given(this.spyMessagingHubConnectionFactoryProperties.isLastResource()).willReturn(true); - given(this.mockRecoveryCredentialsProperties.isValid()).willReturn(false); + given(this.mockRecoveryProperties.isValid()).willReturn(false); assertThatThrownBy(() -> this.wrapper.wrapConnectionFactory(this.mockXaConnectionFactory)) .isInstanceOf(IllegalArgumentException.class) .hasMessage("Setting both firstResource and lastResource is not allowed");