Polish contribution

See gh-31248
This commit is contained in:
Sam Brannen 2023-09-26 13:49:03 +02:00
parent 6d2d8a36c2
commit d50ec68ad7
4 changed files with 69 additions and 70 deletions

View File

@ -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"); * 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.
@ -61,7 +61,7 @@ public abstract class AbstractRoutingDataSource extends AbstractDataSource imple
/** /**
* Specify the map of target DataSources, with the lookup key as key. * Specify the map of target DataSources, with the lookup key as key.
* The mapped value can either be a corresponding {@link javax.sql.DataSource} * <p>The mapped value can either be a corresponding {@link javax.sql.DataSource}
* instance or a data source name String (to be resolved via a * instance or a data source name String (to be resolved via a
* {@link #setDataSourceLookup DataSourceLookup}). * {@link #setDataSourceLookup DataSourceLookup}).
* <p>The key can be of arbitrary type; this class implements the * <p>The key can be of arbitrary type; this class implements the
@ -114,15 +114,23 @@ public abstract class AbstractRoutingDataSource extends AbstractDataSource imple
} }
/**
* Delegates to {@link #initialize()}.
*/
@Override @Override
public void afterPropertiesSet() { public void afterPropertiesSet() {
initialize(); initialize();
} }
/** /**
* Synchronizes targetDataSources to resolvedDataSources * Initialize the internal state of this {@code AbstractRoutingDataSource}
* and defaultTargetDataSource to resolvedDefaultDataSource. * by resolving the configured target DataSources.
* @throws IllegalArgumentException in case of targetDataSources is null * @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() { public void initialize() {
if (this.targetDataSources == null) { if (this.targetDataSources == null) {

View File

@ -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"); * 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 @@
package org.springframework.jdbc.datasource.lookup; package org.springframework.jdbc.datasource.lookup;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
import javax.sql.DataSource; import javax.sql.DataSource;
@ -28,7 +27,6 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.assertj.core.api.Assertions.assertThatIllegalStateException; import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
/** /**
* Tests for {@link AbstractRoutingDataSource}. * Tests for {@link AbstractRoutingDataSource}.
* *
@ -38,7 +36,7 @@ class AbstractRoutingDataSourceTests {
@Test @Test
void setTargetDataSources() { void setTargetDataSources() {
final ThreadLocal<String> lookupKey = new ThreadLocal<>(); ThreadLocal<String> lookupKey = new ThreadLocal<>();
AbstractRoutingDataSource routingDataSource = new AbstractRoutingDataSource() { AbstractRoutingDataSource routingDataSource = new AbstractRoutingDataSource() {
@Override @Override
protected Object determineCurrentLookupKey() { protected Object determineCurrentLookupKey() {
@ -50,14 +48,11 @@ class AbstractRoutingDataSourceTests {
MapDataSourceLookup dataSourceLookup = new MapDataSourceLookup(); MapDataSourceLookup dataSourceLookup = new MapDataSourceLookup();
dataSourceLookup.addDataSource("dataSource2", ds2); dataSourceLookup.addDataSource("dataSource2", ds2);
routingDataSource.setDataSourceLookup(dataSourceLookup); routingDataSource.setDataSourceLookup(dataSourceLookup);
routingDataSource.setTargetDataSources(Map.of("ds1", ds1, "ds2", "dataSource2"));
Map<Object, Object> targetDataSources = new HashMap<>();
targetDataSources.put("ds1", ds1);
targetDataSources.put("ds2", "dataSource2");
routingDataSource.setTargetDataSources(targetDataSources);
routingDataSource.afterPropertiesSet(); routingDataSource.afterPropertiesSet();
lookupKey.set("ds1"); lookupKey.set("ds1");
assertThat(routingDataSource.determineTargetDataSource()).isSameAs(ds1); assertThat(routingDataSource.determineTargetDataSource()).isSameAs(ds1);
lookupKey.set("ds2"); lookupKey.set("ds2");
@ -84,9 +79,7 @@ class AbstractRoutingDataSourceTests {
return null; return null;
} }
}; };
Map<Object, Object> targetDataSources = new HashMap<>(); routingDataSource.setTargetDataSources(Map.of("ds1", 1));
targetDataSources.put("ds1", 1);
routingDataSource.setTargetDataSources(targetDataSources);
assertThatIllegalArgumentException().isThrownBy(routingDataSource::afterPropertiesSet) assertThatIllegalArgumentException().isThrownBy(routingDataSource::afterPropertiesSet)
.withMessage("Illegal data source value - only [javax.sql.DataSource] and String supported: 1"); .withMessage("Illegal data source value - only [javax.sql.DataSource] and String supported: 1");
} }
@ -94,7 +87,7 @@ class AbstractRoutingDataSourceTests {
@Test @Test
void setDefaultTargetDataSource() { void setDefaultTargetDataSource() {
final ThreadLocal<String> lookupKey = new ThreadLocal<>(); ThreadLocal<String> lookupKey = new ThreadLocal<>();
AbstractRoutingDataSource routingDataSource = new AbstractRoutingDataSource() { AbstractRoutingDataSource routingDataSource = new AbstractRoutingDataSource() {
@Override @Override
protected Object determineCurrentLookupKey() { protected Object determineCurrentLookupKey() {
@ -102,7 +95,7 @@ class AbstractRoutingDataSourceTests {
} }
}; };
DataSource ds = new StubDataSource(); DataSource ds = new StubDataSource();
routingDataSource.setTargetDataSources(new HashMap<>()); routingDataSource.setTargetDataSources(Map.of());
routingDataSource.setDefaultTargetDataSource(ds); routingDataSource.setDefaultTargetDataSource(ds);
routingDataSource.afterPropertiesSet(); routingDataSource.afterPropertiesSet();
lookupKey.set("foo"); lookupKey.set("foo");
@ -111,7 +104,7 @@ class AbstractRoutingDataSourceTests {
@Test @Test
void setDefaultTargetDataSourceFallbackIsFalse() { void setDefaultTargetDataSourceFallbackIsFalse() {
final ThreadLocal<String> lookupKey = new ThreadLocal<>(); ThreadLocal<String> lookupKey = new ThreadLocal<>();
AbstractRoutingDataSource routingDataSource = new AbstractRoutingDataSource() { AbstractRoutingDataSource routingDataSource = new AbstractRoutingDataSource() {
@Override @Override
protected Object determineCurrentLookupKey() { protected Object determineCurrentLookupKey() {
@ -119,7 +112,7 @@ class AbstractRoutingDataSourceTests {
} }
}; };
DataSource ds = new StubDataSource(); DataSource ds = new StubDataSource();
routingDataSource.setTargetDataSources(new HashMap<>()); routingDataSource.setTargetDataSources(Map.of());
routingDataSource.setDefaultTargetDataSource(ds); routingDataSource.setDefaultTargetDataSource(ds);
routingDataSource.setLenientFallback(false); routingDataSource.setLenientFallback(false);
routingDataSource.afterPropertiesSet(); routingDataSource.afterPropertiesSet();
@ -130,7 +123,7 @@ class AbstractRoutingDataSourceTests {
@Test @Test
void setDefaultTargetDataSourceLookupKeyIsNullWhenFallbackIsFalse() { void setDefaultTargetDataSourceLookupKeyIsNullWhenFallbackIsFalse() {
final ThreadLocal<String> lookupKey = new ThreadLocal<>(); ThreadLocal<String> lookupKey = new ThreadLocal<>();
AbstractRoutingDataSource routingDataSource = new AbstractRoutingDataSource() { AbstractRoutingDataSource routingDataSource = new AbstractRoutingDataSource() {
@Override @Override
protected Object determineCurrentLookupKey() { protected Object determineCurrentLookupKey() {
@ -138,7 +131,7 @@ class AbstractRoutingDataSourceTests {
} }
}; };
DataSource ds = new StubDataSource(); DataSource ds = new StubDataSource();
routingDataSource.setTargetDataSources(new HashMap<>()); routingDataSource.setTargetDataSources(Map.of());
routingDataSource.setDefaultTargetDataSource(ds); routingDataSource.setDefaultTargetDataSource(ds);
routingDataSource.setLenientFallback(false); routingDataSource.setLenientFallback(false);
routingDataSource.afterPropertiesSet(); routingDataSource.afterPropertiesSet();
@ -147,7 +140,7 @@ class AbstractRoutingDataSourceTests {
} }
@Test @Test
void testInitialize_synchronizeTargetDataSourcesToResolvedDataSources() { void initializeSynchronizesTargetDataSourcesToResolvedDataSources() {
AbstractRoutingDataSource routingDataSource = new AbstractRoutingDataSource() { AbstractRoutingDataSource routingDataSource = new AbstractRoutingDataSource() {
@Override @Override
protected Object determineCurrentLookupKey() { protected Object determineCurrentLookupKey() {
@ -158,11 +151,7 @@ class AbstractRoutingDataSourceTests {
DataSource ds1 = new StubDataSource(); DataSource ds1 = new StubDataSource();
DataSource ds2 = new StubDataSource(); DataSource ds2 = new StubDataSource();
Map<Object, Object> targetDataSources = new HashMap<>(); routingDataSource.setTargetDataSources(Map.of("ds1", ds1, "ds2", ds2));
targetDataSources.put("ds1", ds1);
targetDataSources.put("ds2", ds2);
routingDataSource.setTargetDataSources(targetDataSources);
routingDataSource.initialize(); routingDataSource.initialize();
Map<Object, DataSource> resolvedDataSources = routingDataSource.getResolvedDataSources(); Map<Object, DataSource> resolvedDataSources = routingDataSource.getResolvedDataSources();

View File

@ -31,14 +31,14 @@ import org.springframework.util.CollectionUtils;
/** /**
* Abstract {@link ConnectionFactory} implementation that routes * Abstract {@link ConnectionFactory} implementation that routes
* {@link #create()} calls to one of various target * {@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 * The latter is typically (but not necessarily) determined from some
* subscriber context. * subscriber context.
* *
* <p> Allows to configure a {@link #setDefaultTargetConnectionFactory(Object) * <p>Allows to configure a default target {@link #setDefaultTargetConnectionFactory(Object)
* default ConnectionFactory} as fallback. * ConnectionFactory} as a fallback.
* *
* <p> Calls to {@link #getMetadata()} are routed to the * <p>Calls to {@link #getMetadata()} are routed to the
* {@link #setDefaultTargetConnectionFactory(Object) default ConnectionFactory} * {@link #setDefaultTargetConnectionFactory(Object) default ConnectionFactory}
* if configured. * if configured.
* *
@ -125,14 +125,22 @@ public abstract class AbstractRoutingConnectionFactory implements ConnectionFact
} }
/**
* Delegates to {@link #initialize()}.
*/
@Override @Override
public void afterPropertiesSet() { public void afterPropertiesSet() {
initialize(); initialize();
} }
/** /**
* Synchronizes targetConnectionFactories to resolvedConnectionFactories * Initialize the internal state of this {@code AbstractRoutingConnectionFactory}
* and defaultTargetConnectionFactory to resolvedDefaultConnectionFactory. * 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() { public void initialize() {
Assert.notNull(this.targetConnectionFactories, "Property 'targetConnectionFactories' must not be null"); Assert.notNull(this.targetConnectionFactories, "Property 'targetConnectionFactories' must not be null");

View File

@ -16,6 +16,8 @@
package org.springframework.r2dbc.connection.lookup; package org.springframework.r2dbc.connection.lookup;
import java.util.Map;
import io.r2dbc.spi.ConnectionFactory; import io.r2dbc.spi.ConnectionFactory;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -26,7 +28,7 @@ import reactor.core.publisher.Mono;
import reactor.test.StepVerifier; import reactor.test.StepVerifier;
import reactor.util.context.Context; 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; import static org.assertj.core.api.Assertions.assertThatThrownBy;
/** /**
@ -36,30 +38,28 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy;
* @author Jens Schauder * @author Jens Schauder
*/ */
@ExtendWith(MockitoExtension.class) @ExtendWith(MockitoExtension.class)
public class AbstractRoutingConnectionFactoryUnitTests { class AbstractRoutingConnectionFactoryUnitTests {
private static final String ROUTING_KEY = "routingKey"; private static final String ROUTING_KEY = "routingKey";
final DummyRoutingConnectionFactory connectionFactory = new DummyRoutingConnectionFactory();
@Mock @Mock
ConnectionFactory defaultConnectionFactory; ConnectionFactory defaultConnectionFactory;
@Mock @Mock
ConnectionFactory routedConnectionFactory; ConnectionFactory routedConnectionFactory;
DummyRoutingConnectionFactory connectionFactory;
@BeforeEach @BeforeEach
public void before() { void before() {
connectionFactory = new DummyRoutingConnectionFactory();
connectionFactory.setDefaultTargetConnectionFactory(defaultConnectionFactory); connectionFactory.setDefaultTargetConnectionFactory(defaultConnectionFactory);
} }
@Test @Test
public void shouldDetermineRoutedFactory() { void shouldDetermineRoutedFactory() {
connectionFactory.setTargetConnectionFactories( connectionFactory.setTargetConnectionFactories(Map.of("key", routedConnectionFactory));
singletonMap("key", routedConnectionFactory));
connectionFactory.setConnectionFactoryLookup(new MapConnectionFactoryLookup()); connectionFactory.setConnectionFactoryLookup(new MapConnectionFactoryLookup());
connectionFactory.afterPropertiesSet(); connectionFactory.afterPropertiesSet();
@ -71,9 +71,8 @@ public class AbstractRoutingConnectionFactoryUnitTests {
} }
@Test @Test
public void shouldFallbackToDefaultConnectionFactory() { void shouldFallbackToDefaultConnectionFactory() {
connectionFactory.setTargetConnectionFactories( connectionFactory.setTargetConnectionFactories(Map.of("key", routedConnectionFactory));
singletonMap("key", routedConnectionFactory));
connectionFactory.afterPropertiesSet(); connectionFactory.afterPropertiesSet();
connectionFactory.determineTargetConnectionFactory() connectionFactory.determineTargetConnectionFactory()
@ -83,29 +82,27 @@ public class AbstractRoutingConnectionFactoryUnitTests {
} }
@Test @Test
public void initializationShouldFailUnsupportedLookupKey() { void initializationShouldFailUnsupportedLookupKey() {
connectionFactory.setTargetConnectionFactories(singletonMap("key", new Object())); connectionFactory.setTargetConnectionFactories(Map.of("key", new Object()));
assertThatThrownBy(() -> connectionFactory.afterPropertiesSet()) assertThatIllegalArgumentException().isThrownBy(connectionFactory::initialize);
.isInstanceOf(IllegalArgumentException.class);
} }
@Test @Test
public void initializationShouldFailUnresolvableKey() { void initializationShouldFailUnresolvableKey() {
connectionFactory.setTargetConnectionFactories(singletonMap("key", "value")); connectionFactory.setTargetConnectionFactories(Map.of("key", "value"));
connectionFactory.setConnectionFactoryLookup(new MapConnectionFactoryLookup()); connectionFactory.setConnectionFactoryLookup(new MapConnectionFactoryLookup());
assertThatThrownBy(() -> connectionFactory.afterPropertiesSet()) assertThatThrownBy(connectionFactory::initialize)
.isInstanceOf(ConnectionFactoryLookupFailureException.class) .isInstanceOf(ConnectionFactoryLookupFailureException.class)
.hasMessageContaining("No ConnectionFactory with name 'value' registered"); .hasMessageContaining("No ConnectionFactory with name 'value' registered");
} }
@Test @Test
public void unresolvableConnectionFactoryRetrievalShouldFail() { void unresolvableConnectionFactoryRetrievalShouldFail() {
connectionFactory.setLenientFallback(false); connectionFactory.setLenientFallback(false);
connectionFactory.setConnectionFactoryLookup(new MapConnectionFactoryLookup()); connectionFactory.setConnectionFactoryLookup(new MapConnectionFactoryLookup());
connectionFactory.setTargetConnectionFactories( connectionFactory.setTargetConnectionFactories(Map.of("key", routedConnectionFactory));
singletonMap("key", routedConnectionFactory));
connectionFactory.afterPropertiesSet(); connectionFactory.afterPropertiesSet();
connectionFactory.determineTargetConnectionFactory() connectionFactory.determineTargetConnectionFactory()
@ -115,9 +112,8 @@ public class AbstractRoutingConnectionFactoryUnitTests {
} }
@Test @Test
public void connectionFactoryRetrievalWithUnknownLookupKeyShouldReturnDefaultConnectionFactory() { void connectionFactoryRetrievalWithUnknownLookupKeyShouldReturnDefaultConnectionFactory() {
connectionFactory.setTargetConnectionFactories( connectionFactory.setTargetConnectionFactories(Map.of("key", routedConnectionFactory));
singletonMap("key", routedConnectionFactory));
connectionFactory.setDefaultTargetConnectionFactory(defaultConnectionFactory); connectionFactory.setDefaultTargetConnectionFactory(defaultConnectionFactory);
connectionFactory.afterPropertiesSet(); connectionFactory.afterPropertiesSet();
@ -129,9 +125,8 @@ public class AbstractRoutingConnectionFactoryUnitTests {
} }
@Test @Test
public void connectionFactoryRetrievalWithoutLookupKeyShouldReturnDefaultConnectionFactory() { void connectionFactoryRetrievalWithoutLookupKeyShouldReturnDefaultConnectionFactory() {
connectionFactory.setTargetConnectionFactories( connectionFactory.setTargetConnectionFactories(Map.of("key", routedConnectionFactory));
singletonMap("key", routedConnectionFactory));
connectionFactory.setDefaultTargetConnectionFactory(defaultConnectionFactory); connectionFactory.setDefaultTargetConnectionFactory(defaultConnectionFactory);
connectionFactory.setLenientFallback(false); connectionFactory.setLenientFallback(false);
connectionFactory.afterPropertiesSet(); connectionFactory.afterPropertiesSet();
@ -143,12 +138,12 @@ public class AbstractRoutingConnectionFactoryUnitTests {
} }
@Test @Test
public void shouldLookupFromMap() { void shouldLookupFromMap() {
MapConnectionFactoryLookup lookup = MapConnectionFactoryLookup lookup =
new MapConnectionFactoryLookup("lookup-key", routedConnectionFactory); new MapConnectionFactoryLookup("lookup-key", routedConnectionFactory);
connectionFactory.setConnectionFactoryLookup(lookup); connectionFactory.setConnectionFactoryLookup(lookup);
connectionFactory.setTargetConnectionFactories(singletonMap("my-key", "lookup-key")); connectionFactory.setTargetConnectionFactories(Map.of("my-key", "lookup-key"));
connectionFactory.afterPropertiesSet(); connectionFactory.afterPropertiesSet();
connectionFactory.determineTargetConnectionFactory() connectionFactory.determineTargetConnectionFactory()
@ -159,7 +154,7 @@ public class AbstractRoutingConnectionFactoryUnitTests {
} }
@Test @Test
public void shouldAllowModificationsAfterInitialization() { void shouldAllowModificationsAfterInitialization() {
MapConnectionFactoryLookup lookup = new MapConnectionFactoryLookup(); MapConnectionFactoryLookup lookup = new MapConnectionFactoryLookup();
connectionFactory.setConnectionFactoryLookup(lookup); connectionFactory.setConnectionFactoryLookup(lookup);
@ -183,9 +178,8 @@ public class AbstractRoutingConnectionFactoryUnitTests {
} }
@Test @Test
void testInitialize_shouldDetermineRoutedFactory() { void initializeShouldDetermineRoutedFactory() {
connectionFactory.setTargetConnectionFactories( connectionFactory.setTargetConnectionFactories(Map.of("key", routedConnectionFactory));
singletonMap("key", routedConnectionFactory));
connectionFactory.setConnectionFactoryLookup(new MapConnectionFactoryLookup()); connectionFactory.setConnectionFactoryLookup(new MapConnectionFactoryLookup());
connectionFactory.initialize(); connectionFactory.initialize();