Defensively unwrap CacheConnectionFactory
This commit refines the optimization introduced in gh-39816 to only unwrap our own caching connection factory. The more advanced unwrap algorithm is still available, but opt-in only. Unwrapping more aggressively may break use cases where the wrapped ConnectionFactory is required, i.e. for transactional purposes. Closes gh-43277
This commit is contained in:
@@ -33,6 +33,23 @@ public final class ConnectionFactoryUnwrapper {
|
||||
private ConnectionFactoryUnwrapper() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the native {@link ConnectionFactory} by unwrapping ot from a
|
||||
* {@link CachingConnectionFactory}. Return the given {@link ConnectionFactory} if no
|
||||
* {@link CachingConnectionFactory} wrapper has been detected.
|
||||
* @param connectionFactory a connection factory
|
||||
* @return the native connection factory that a {@link CachingConnectionFactory}
|
||||
* wraps, if any
|
||||
* @since 3.4.1
|
||||
*/
|
||||
public static ConnectionFactory unwrapCaching(ConnectionFactory connectionFactory) {
|
||||
if (connectionFactory instanceof CachingConnectionFactory cachingConnectionFactory) {
|
||||
ConnectionFactory unwrapedConnectionFactory = cachingConnectionFactory.getTargetConnectionFactory();
|
||||
return (unwrapedConnectionFactory != null) ? unwrapCaching(unwrapedConnectionFactory) : connectionFactory;
|
||||
}
|
||||
return connectionFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the native {@link ConnectionFactory} by unwrapping it from a cache or pool
|
||||
* connection factory. Return the given {@link ConnectionFactory} if no caching
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.springframework.boot.jms;
|
||||
|
||||
import jakarta.jms.ConnectionFactory;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.messaginghub.pooled.jms.JmsPoolConnectionFactory;
|
||||
|
||||
@@ -35,59 +36,110 @@ import static org.mockito.Mockito.mock;
|
||||
*/
|
||||
class ConnectionFactoryUnwrapperTests {
|
||||
|
||||
@Test
|
||||
void unwrapWithSingleConnectionFactory() {
|
||||
ConnectionFactory connectionFactory = new SingleConnectionFactory();
|
||||
assertThat(ConnectionFactoryUnwrapper.unwrap(connectionFactory)).isSameAs(connectionFactory);
|
||||
@Nested
|
||||
class UnwrapCaching {
|
||||
|
||||
@Test
|
||||
void unwrapWithSingleConnectionFactory() {
|
||||
ConnectionFactory connectionFactory = new SingleConnectionFactory();
|
||||
assertThat(unwrapCaching(connectionFactory)).isSameAs(connectionFactory);
|
||||
}
|
||||
|
||||
@Test
|
||||
void unwrapWithConnectionFactory() {
|
||||
ConnectionFactory connectionFactory = mock(ConnectionFactory.class);
|
||||
assertThat(unwrapCaching(connectionFactory)).isSameAs(connectionFactory);
|
||||
}
|
||||
|
||||
@Test
|
||||
void unwrapWithCachingConnectionFactory() {
|
||||
ConnectionFactory connectionFactory = mock(ConnectionFactory.class);
|
||||
assertThat(unwrapCaching(new CachingConnectionFactory(connectionFactory))).isSameAs(connectionFactory);
|
||||
}
|
||||
|
||||
@Test
|
||||
void unwrapWithNestedCachingConnectionFactories() {
|
||||
ConnectionFactory connectionFactory = mock(ConnectionFactory.class);
|
||||
CachingConnectionFactory firstCachingConnectionFactory = new CachingConnectionFactory(connectionFactory);
|
||||
CachingConnectionFactory secondCachingConnectionFactory = new CachingConnectionFactory(
|
||||
firstCachingConnectionFactory);
|
||||
assertThat(unwrapCaching(secondCachingConnectionFactory)).isSameAs(connectionFactory);
|
||||
}
|
||||
|
||||
@Test
|
||||
void unwrapWithJmsPoolConnectionFactory() {
|
||||
ConnectionFactory connectionFactory = mock(ConnectionFactory.class);
|
||||
JmsPoolConnectionFactory poolConnectionFactory = new JmsPoolConnectionFactory();
|
||||
poolConnectionFactory.setConnectionFactory(connectionFactory);
|
||||
assertThat(unwrapCaching(poolConnectionFactory)).isSameAs(poolConnectionFactory);
|
||||
}
|
||||
|
||||
private ConnectionFactory unwrapCaching(ConnectionFactory connectionFactory) {
|
||||
return ConnectionFactoryUnwrapper.unwrapCaching(connectionFactory);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
void unwrapWithConnectionFactory() {
|
||||
ConnectionFactory connectionFactory = mock(ConnectionFactory.class);
|
||||
assertThat(ConnectionFactoryUnwrapper.unwrap(connectionFactory)).isSameAs(connectionFactory);
|
||||
}
|
||||
@Nested
|
||||
class Unwrap {
|
||||
|
||||
@Test
|
||||
void unwrapWithCachingConnectionFactory() {
|
||||
ConnectionFactory connectionFactory = mock(ConnectionFactory.class);
|
||||
assertThat(ConnectionFactoryUnwrapper.unwrap(new CachingConnectionFactory(connectionFactory)))
|
||||
.isSameAs(connectionFactory);
|
||||
}
|
||||
@Test
|
||||
void unwrapWithSingleConnectionFactory() {
|
||||
ConnectionFactory connectionFactory = new SingleConnectionFactory();
|
||||
assertThat(unwrap(connectionFactory)).isSameAs(connectionFactory);
|
||||
}
|
||||
|
||||
@Test
|
||||
void unwrapWithNestedCachingConnectionFactories() {
|
||||
ConnectionFactory connectionFactory = mock(ConnectionFactory.class);
|
||||
CachingConnectionFactory firstCachingConnectionFactory = new CachingConnectionFactory(connectionFactory);
|
||||
CachingConnectionFactory secondCachingConnectionFactory = new CachingConnectionFactory(
|
||||
firstCachingConnectionFactory);
|
||||
assertThat(ConnectionFactoryUnwrapper.unwrap(secondCachingConnectionFactory)).isSameAs(connectionFactory);
|
||||
}
|
||||
@Test
|
||||
void unwrapWithConnectionFactory() {
|
||||
ConnectionFactory connectionFactory = mock(ConnectionFactory.class);
|
||||
assertThat(unwrap(connectionFactory)).isSameAs(connectionFactory);
|
||||
}
|
||||
|
||||
@Test
|
||||
void unwrapWithJmsPoolConnectionFactory() {
|
||||
ConnectionFactory connectionFactory = mock(ConnectionFactory.class);
|
||||
JmsPoolConnectionFactory poolConnectionFactory = new JmsPoolConnectionFactory();
|
||||
poolConnectionFactory.setConnectionFactory(connectionFactory);
|
||||
assertThat(ConnectionFactoryUnwrapper.unwrap(poolConnectionFactory)).isSameAs(connectionFactory);
|
||||
}
|
||||
@Test
|
||||
void unwrapWithCachingConnectionFactory() {
|
||||
ConnectionFactory connectionFactory = mock(ConnectionFactory.class);
|
||||
assertThat(unwrap(new CachingConnectionFactory(connectionFactory))).isSameAs(connectionFactory);
|
||||
}
|
||||
|
||||
@Test
|
||||
void unwrapWithNestedJmsPoolConnectionFactories() {
|
||||
ConnectionFactory connectionFactory = mock(ConnectionFactory.class);
|
||||
JmsPoolConnectionFactory firstPooledConnectionFactory = new JmsPoolConnectionFactory();
|
||||
firstPooledConnectionFactory.setConnectionFactory(connectionFactory);
|
||||
JmsPoolConnectionFactory secondPooledConnectionFactory = new JmsPoolConnectionFactory();
|
||||
secondPooledConnectionFactory.setConnectionFactory(firstPooledConnectionFactory);
|
||||
assertThat(ConnectionFactoryUnwrapper.unwrap(secondPooledConnectionFactory)).isSameAs(connectionFactory);
|
||||
}
|
||||
@Test
|
||||
void unwrapWithNestedCachingConnectionFactories() {
|
||||
ConnectionFactory connectionFactory = mock(ConnectionFactory.class);
|
||||
CachingConnectionFactory firstCachingConnectionFactory = new CachingConnectionFactory(connectionFactory);
|
||||
CachingConnectionFactory secondCachingConnectionFactory = new CachingConnectionFactory(
|
||||
firstCachingConnectionFactory);
|
||||
assertThat(unwrap(secondCachingConnectionFactory)).isSameAs(connectionFactory);
|
||||
}
|
||||
|
||||
@Test
|
||||
void unwrapWithJmsPoolConnectionFactory() {
|
||||
ConnectionFactory connectionFactory = mock(ConnectionFactory.class);
|
||||
JmsPoolConnectionFactory poolConnectionFactory = new JmsPoolConnectionFactory();
|
||||
poolConnectionFactory.setConnectionFactory(connectionFactory);
|
||||
assertThat(unwrap(poolConnectionFactory)).isSameAs(connectionFactory);
|
||||
}
|
||||
|
||||
@Test
|
||||
void unwrapWithNestedJmsPoolConnectionFactories() {
|
||||
ConnectionFactory connectionFactory = mock(ConnectionFactory.class);
|
||||
JmsPoolConnectionFactory firstPooledConnectionFactory = new JmsPoolConnectionFactory();
|
||||
firstPooledConnectionFactory.setConnectionFactory(connectionFactory);
|
||||
JmsPoolConnectionFactory secondPooledConnectionFactory = new JmsPoolConnectionFactory();
|
||||
secondPooledConnectionFactory.setConnectionFactory(firstPooledConnectionFactory);
|
||||
assertThat(unwrap(secondPooledConnectionFactory)).isSameAs(connectionFactory);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ClassPathExclusions("pooled-jms-*")
|
||||
void unwrapWithoutJmsPoolOnClasspath() {
|
||||
assertThat(ClassUtils.isPresent("org.messaginghub.pooled.jms.JmsPoolConnectionFactory", null)).isFalse();
|
||||
ConnectionFactory connectionFactory = mock(ConnectionFactory.class);
|
||||
assertThat(unwrap(new CachingConnectionFactory(connectionFactory))).isSameAs(connectionFactory);
|
||||
}
|
||||
|
||||
private ConnectionFactory unwrap(ConnectionFactory connectionFactory) {
|
||||
return ConnectionFactoryUnwrapper.unwrap(connectionFactory);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ClassPathExclusions("pooled-jms-*")
|
||||
void unwrapWithoutJmsPoolOnClasspath() {
|
||||
assertThat(ClassUtils.isPresent("org.messaginghub.pooled.jms.JmsPoolConnectionFactory", null)).isFalse();
|
||||
ConnectionFactory connectionFactory = mock(ConnectionFactory.class);
|
||||
assertThat(ConnectionFactoryUnwrapper.unwrap(new CachingConnectionFactory(connectionFactory)))
|
||||
.isSameAs(connectionFactory);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user