diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/lookup/AbstractRoutingDataSource.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/lookup/AbstractRoutingDataSource.java index 81aee2588bf6..d444fe5617e6 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/lookup/AbstractRoutingDataSource.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/lookup/AbstractRoutingDataSource.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2023 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. @@ -61,7 +61,7 @@ public abstract class AbstractRoutingDataSource extends AbstractDataSource imple /** * Specify the map of target DataSources, with the lookup key as key. - * The mapped value can either be a corresponding {@link javax.sql.DataSource} + *

The mapped value can either be a corresponding {@link javax.sql.DataSource} * instance or a data source name String (to be resolved via a * {@link #setDataSourceLookup DataSourceLookup}). *

The key can be of arbitrary type; this class implements the @@ -114,15 +114,23 @@ public void setDataSourceLookup(@Nullable DataSourceLookup dataSourceLookup) { } + /** + * Delegates to {@link #initialize()}. + */ @Override public void afterPropertiesSet() { initialize(); } /** - * Synchronizes targetDataSources to resolvedDataSources - * and defaultTargetDataSource to resolvedDefaultDataSource. - * @throws IllegalArgumentException in case of targetDataSources is null + * Initialize the internal state of this {@code AbstractRoutingDataSource} + * by resolving the configured target DataSources. + * @throws IllegalArgumentException if the target DataSources have not been configured + * @since 6.1 + * @see #setTargetDataSources(Map) + * @see #setDefaultTargetDataSource(Object) + * @see #getResolvedDataSources() + * @see #getResolvedDefaultDataSource() */ public void initialize() { if (this.targetDataSources == null) { diff --git a/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/lookup/AbstractRoutingDataSourceTests.java b/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/lookup/AbstractRoutingDataSourceTests.java index bdb8e5939314..6ec95a438c6e 100644 --- a/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/lookup/AbstractRoutingDataSourceTests.java +++ b/spring-jdbc/src/test/java/org/springframework/jdbc/datasource/lookup/AbstractRoutingDataSourceTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2023 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. @@ -17,7 +17,6 @@ package org.springframework.jdbc.datasource.lookup; -import java.util.HashMap; import java.util.Map; import javax.sql.DataSource; @@ -28,7 +27,6 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; import static org.assertj.core.api.Assertions.assertThatIllegalStateException; - /** * Tests for {@link AbstractRoutingDataSource}. * @@ -38,7 +36,7 @@ class AbstractRoutingDataSourceTests { @Test void setTargetDataSources() { - final ThreadLocal lookupKey = new ThreadLocal<>(); + ThreadLocal lookupKey = new ThreadLocal<>(); AbstractRoutingDataSource routingDataSource = new AbstractRoutingDataSource() { @Override protected Object determineCurrentLookupKey() { @@ -50,14 +48,11 @@ protected Object determineCurrentLookupKey() { MapDataSourceLookup dataSourceLookup = new MapDataSourceLookup(); dataSourceLookup.addDataSource("dataSource2", ds2); - routingDataSource.setDataSourceLookup(dataSourceLookup); - - Map targetDataSources = new HashMap<>(); - targetDataSources.put("ds1", ds1); - targetDataSources.put("ds2", "dataSource2"); - routingDataSource.setTargetDataSources(targetDataSources); + routingDataSource.setDataSourceLookup(dataSourceLookup); + routingDataSource.setTargetDataSources(Map.of("ds1", ds1, "ds2", "dataSource2")); routingDataSource.afterPropertiesSet(); + lookupKey.set("ds1"); assertThat(routingDataSource.determineTargetDataSource()).isSameAs(ds1); lookupKey.set("ds2"); @@ -84,9 +79,7 @@ protected Object determineCurrentLookupKey() { return null; } }; - Map targetDataSources = new HashMap<>(); - targetDataSources.put("ds1", 1); - routingDataSource.setTargetDataSources(targetDataSources); + routingDataSource.setTargetDataSources(Map.of("ds1", 1)); assertThatIllegalArgumentException().isThrownBy(routingDataSource::afterPropertiesSet) .withMessage("Illegal data source value - only [javax.sql.DataSource] and String supported: 1"); } @@ -94,7 +87,7 @@ protected Object determineCurrentLookupKey() { @Test void setDefaultTargetDataSource() { - final ThreadLocal lookupKey = new ThreadLocal<>(); + ThreadLocal lookupKey = new ThreadLocal<>(); AbstractRoutingDataSource routingDataSource = new AbstractRoutingDataSource() { @Override protected Object determineCurrentLookupKey() { @@ -102,7 +95,7 @@ protected Object determineCurrentLookupKey() { } }; DataSource ds = new StubDataSource(); - routingDataSource.setTargetDataSources(new HashMap<>()); + routingDataSource.setTargetDataSources(Map.of()); routingDataSource.setDefaultTargetDataSource(ds); routingDataSource.afterPropertiesSet(); lookupKey.set("foo"); @@ -111,7 +104,7 @@ protected Object determineCurrentLookupKey() { @Test void setDefaultTargetDataSourceFallbackIsFalse() { - final ThreadLocal lookupKey = new ThreadLocal<>(); + ThreadLocal lookupKey = new ThreadLocal<>(); AbstractRoutingDataSource routingDataSource = new AbstractRoutingDataSource() { @Override protected Object determineCurrentLookupKey() { @@ -119,7 +112,7 @@ protected Object determineCurrentLookupKey() { } }; DataSource ds = new StubDataSource(); - routingDataSource.setTargetDataSources(new HashMap<>()); + routingDataSource.setTargetDataSources(Map.of()); routingDataSource.setDefaultTargetDataSource(ds); routingDataSource.setLenientFallback(false); routingDataSource.afterPropertiesSet(); @@ -130,7 +123,7 @@ protected Object determineCurrentLookupKey() { @Test void setDefaultTargetDataSourceLookupKeyIsNullWhenFallbackIsFalse() { - final ThreadLocal lookupKey = new ThreadLocal<>(); + ThreadLocal lookupKey = new ThreadLocal<>(); AbstractRoutingDataSource routingDataSource = new AbstractRoutingDataSource() { @Override protected Object determineCurrentLookupKey() { @@ -138,7 +131,7 @@ protected Object determineCurrentLookupKey() { } }; DataSource ds = new StubDataSource(); - routingDataSource.setTargetDataSources(new HashMap<>()); + routingDataSource.setTargetDataSources(Map.of()); routingDataSource.setDefaultTargetDataSource(ds); routingDataSource.setLenientFallback(false); routingDataSource.afterPropertiesSet(); @@ -147,7 +140,7 @@ protected Object determineCurrentLookupKey() { } @Test - void testInitialize_synchronizeTargetDataSourcesToResolvedDataSources() { + void initializeSynchronizesTargetDataSourcesToResolvedDataSources() { AbstractRoutingDataSource routingDataSource = new AbstractRoutingDataSource() { @Override protected Object determineCurrentLookupKey() { @@ -158,11 +151,7 @@ protected Object determineCurrentLookupKey() { DataSource ds1 = new StubDataSource(); DataSource ds2 = new StubDataSource(); - Map targetDataSources = new HashMap<>(); - targetDataSources.put("ds1", ds1); - targetDataSources.put("ds2", ds2); - routingDataSource.setTargetDataSources(targetDataSources); - + routingDataSource.setTargetDataSources(Map.of("ds1", ds1, "ds2", ds2)); routingDataSource.initialize(); Map resolvedDataSources = routingDataSource.getResolvedDataSources(); diff --git a/spring-r2dbc/src/main/java/org/springframework/r2dbc/connection/lookup/AbstractRoutingConnectionFactory.java b/spring-r2dbc/src/main/java/org/springframework/r2dbc/connection/lookup/AbstractRoutingConnectionFactory.java index 9d55d01edfaf..f02703476d93 100644 --- a/spring-r2dbc/src/main/java/org/springframework/r2dbc/connection/lookup/AbstractRoutingConnectionFactory.java +++ b/spring-r2dbc/src/main/java/org/springframework/r2dbc/connection/lookup/AbstractRoutingConnectionFactory.java @@ -31,14 +31,14 @@ /** * Abstract {@link ConnectionFactory} implementation that routes * {@link #create()} calls to one of various target - * {@link ConnectionFactory factories} based on a lookup key. + * {@linkplain ConnectionFactory factories} based on a lookup key. * The latter is typically (but not necessarily) determined from some * subscriber context. * - *

Allows to configure a {@link #setDefaultTargetConnectionFactory(Object) - * default ConnectionFactory} as fallback. + *

Allows to configure a default target {@link #setDefaultTargetConnectionFactory(Object) + * ConnectionFactory} as a fallback. * - *

Calls to {@link #getMetadata()} are routed to the + *

Calls to {@link #getMetadata()} are routed to the * {@link #setDefaultTargetConnectionFactory(Object) default ConnectionFactory} * if configured. * @@ -125,14 +125,22 @@ public void setConnectionFactoryLookup(ConnectionFactoryLookup connectionFactory } + /** + * Delegates to {@link #initialize()}. + */ @Override public void afterPropertiesSet() { initialize(); } /** - * Synchronizes targetConnectionFactories to resolvedConnectionFactories - * and defaultTargetConnectionFactory to resolvedDefaultConnectionFactory. + * Initialize the internal state of this {@code AbstractRoutingConnectionFactory} + * by resolving the configured target ConnectionFactories. + * @throws IllegalArgumentException if the target ConnectionFactories have not + * been configured + * @since 6.1 + * @see #setTargetConnectionFactories(Map) + * @see #setDefaultTargetConnectionFactory(Object) */ public void initialize() { Assert.notNull(this.targetConnectionFactories, "Property 'targetConnectionFactories' must not be null"); diff --git a/spring-r2dbc/src/test/java/org/springframework/r2dbc/connection/lookup/AbstractRoutingConnectionFactoryUnitTests.java b/spring-r2dbc/src/test/java/org/springframework/r2dbc/connection/lookup/AbstractRoutingConnectionFactoryUnitTests.java index 0b7009b7fb58..f07a9fc8a74d 100644 --- a/spring-r2dbc/src/test/java/org/springframework/r2dbc/connection/lookup/AbstractRoutingConnectionFactoryUnitTests.java +++ b/spring-r2dbc/src/test/java/org/springframework/r2dbc/connection/lookup/AbstractRoutingConnectionFactoryUnitTests.java @@ -16,6 +16,8 @@ package org.springframework.r2dbc.connection.lookup; +import java.util.Map; + import io.r2dbc.spi.ConnectionFactory; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -26,7 +28,7 @@ import reactor.test.StepVerifier; import reactor.util.context.Context; -import static java.util.Collections.singletonMap; +import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; import static org.assertj.core.api.Assertions.assertThatThrownBy; /** @@ -36,30 +38,28 @@ * @author Jens Schauder */ @ExtendWith(MockitoExtension.class) -public class AbstractRoutingConnectionFactoryUnitTests { +class AbstractRoutingConnectionFactoryUnitTests { private static final String ROUTING_KEY = "routingKey"; + final DummyRoutingConnectionFactory connectionFactory = new DummyRoutingConnectionFactory(); + @Mock ConnectionFactory defaultConnectionFactory; @Mock ConnectionFactory routedConnectionFactory; - DummyRoutingConnectionFactory connectionFactory; - @BeforeEach - public void before() { - connectionFactory = new DummyRoutingConnectionFactory(); + void before() { connectionFactory.setDefaultTargetConnectionFactory(defaultConnectionFactory); } @Test - public void shouldDetermineRoutedFactory() { - connectionFactory.setTargetConnectionFactories( - singletonMap("key", routedConnectionFactory)); + void shouldDetermineRoutedFactory() { + connectionFactory.setTargetConnectionFactories(Map.of("key", routedConnectionFactory)); connectionFactory.setConnectionFactoryLookup(new MapConnectionFactoryLookup()); connectionFactory.afterPropertiesSet(); @@ -71,9 +71,8 @@ public void shouldDetermineRoutedFactory() { } @Test - public void shouldFallbackToDefaultConnectionFactory() { - connectionFactory.setTargetConnectionFactories( - singletonMap("key", routedConnectionFactory)); + void shouldFallbackToDefaultConnectionFactory() { + connectionFactory.setTargetConnectionFactories(Map.of("key", routedConnectionFactory)); connectionFactory.afterPropertiesSet(); connectionFactory.determineTargetConnectionFactory() @@ -83,29 +82,27 @@ public void shouldFallbackToDefaultConnectionFactory() { } @Test - public void initializationShouldFailUnsupportedLookupKey() { - connectionFactory.setTargetConnectionFactories(singletonMap("key", new Object())); + void initializationShouldFailUnsupportedLookupKey() { + connectionFactory.setTargetConnectionFactories(Map.of("key", new Object())); - assertThatThrownBy(() -> connectionFactory.afterPropertiesSet()) - .isInstanceOf(IllegalArgumentException.class); + assertThatIllegalArgumentException().isThrownBy(connectionFactory::initialize); } @Test - public void initializationShouldFailUnresolvableKey() { - connectionFactory.setTargetConnectionFactories(singletonMap("key", "value")); + void initializationShouldFailUnresolvableKey() { + connectionFactory.setTargetConnectionFactories(Map.of("key", "value")); connectionFactory.setConnectionFactoryLookup(new MapConnectionFactoryLookup()); - assertThatThrownBy(() -> connectionFactory.afterPropertiesSet()) + assertThatThrownBy(connectionFactory::initialize) .isInstanceOf(ConnectionFactoryLookupFailureException.class) .hasMessageContaining("No ConnectionFactory with name 'value' registered"); } @Test - public void unresolvableConnectionFactoryRetrievalShouldFail() { + void unresolvableConnectionFactoryRetrievalShouldFail() { connectionFactory.setLenientFallback(false); connectionFactory.setConnectionFactoryLookup(new MapConnectionFactoryLookup()); - connectionFactory.setTargetConnectionFactories( - singletonMap("key", routedConnectionFactory)); + connectionFactory.setTargetConnectionFactories(Map.of("key", routedConnectionFactory)); connectionFactory.afterPropertiesSet(); connectionFactory.determineTargetConnectionFactory() @@ -115,9 +112,8 @@ public void unresolvableConnectionFactoryRetrievalShouldFail() { } @Test - public void connectionFactoryRetrievalWithUnknownLookupKeyShouldReturnDefaultConnectionFactory() { - connectionFactory.setTargetConnectionFactories( - singletonMap("key", routedConnectionFactory)); + void connectionFactoryRetrievalWithUnknownLookupKeyShouldReturnDefaultConnectionFactory() { + connectionFactory.setTargetConnectionFactories(Map.of("key", routedConnectionFactory)); connectionFactory.setDefaultTargetConnectionFactory(defaultConnectionFactory); connectionFactory.afterPropertiesSet(); @@ -129,9 +125,8 @@ public void connectionFactoryRetrievalWithUnknownLookupKeyShouldReturnDefaultCon } @Test - public void connectionFactoryRetrievalWithoutLookupKeyShouldReturnDefaultConnectionFactory() { - connectionFactory.setTargetConnectionFactories( - singletonMap("key", routedConnectionFactory)); + void connectionFactoryRetrievalWithoutLookupKeyShouldReturnDefaultConnectionFactory() { + connectionFactory.setTargetConnectionFactories(Map.of("key", routedConnectionFactory)); connectionFactory.setDefaultTargetConnectionFactory(defaultConnectionFactory); connectionFactory.setLenientFallback(false); connectionFactory.afterPropertiesSet(); @@ -143,12 +138,12 @@ public void connectionFactoryRetrievalWithoutLookupKeyShouldReturnDefaultConnect } @Test - public void shouldLookupFromMap() { + void shouldLookupFromMap() { MapConnectionFactoryLookup lookup = new MapConnectionFactoryLookup("lookup-key", routedConnectionFactory); connectionFactory.setConnectionFactoryLookup(lookup); - connectionFactory.setTargetConnectionFactories(singletonMap("my-key", "lookup-key")); + connectionFactory.setTargetConnectionFactories(Map.of("my-key", "lookup-key")); connectionFactory.afterPropertiesSet(); connectionFactory.determineTargetConnectionFactory() @@ -159,7 +154,7 @@ public void shouldLookupFromMap() { } @Test - public void shouldAllowModificationsAfterInitialization() { + void shouldAllowModificationsAfterInitialization() { MapConnectionFactoryLookup lookup = new MapConnectionFactoryLookup(); connectionFactory.setConnectionFactoryLookup(lookup); @@ -183,9 +178,8 @@ public void shouldAllowModificationsAfterInitialization() { } @Test - void testInitialize_shouldDetermineRoutedFactory() { - connectionFactory.setTargetConnectionFactories( - singletonMap("key", routedConnectionFactory)); + void initializeShouldDetermineRoutedFactory() { + connectionFactory.setTargetConnectionFactories(Map.of("key", routedConnectionFactory)); connectionFactory.setConnectionFactoryLookup(new MapConnectionFactoryLookup()); connectionFactory.initialize();