Refactor ContainerConnectionDetailsFactory classes

Update `ContainerConnectionDetailsFactory` so that they consistently
extend `ContainerConnectionDetails`. The container is also no longer
accessible from the `ContainerConnectionSource` and is never used
during the construction of `ConnectionDetails` instances.

See gh-35168
This commit is contained in:
Phillip Webb 2023-04-29 13:36:07 -07:00
parent 403481ff96
commit d1084ee6db
20 changed files with 97 additions and 135 deletions

View File

@ -34,7 +34,7 @@ import org.springframework.util.ObjectUtils;
* {@link ConnectionDetails} from a {@link ContainerConnectionSource}.
*
* @param <D> the connection details type
* @param <C> the generic container type
* @param <C> the container type
* @author Moritz Halbritter
* @author Andy Wilkinson
* @author Phillip Webb
@ -110,23 +110,30 @@ public abstract class ContainerConnectionDetailsFactory<D extends ConnectionDeta
/**
* Convenient base class for {@link ConnectionDetails} results that are backed by a
* {@link ContainerConnectionSource}.
*
* @param <C> the container type
*/
protected static class ContainerConnectionDetails implements ConnectionDetails, OriginProvider {
protected static class ContainerConnectionDetails<C extends Container<?>>
implements ConnectionDetails, OriginProvider {
private final Origin origin;
private final ContainerConnectionSource<C> source;
/**
* Create a new {@link ContainerConnectionDetails} instance.
* @param source the source {@link ContainerConnectionSource}
*/
protected ContainerConnectionDetails(ContainerConnectionSource<?> source) {
protected ContainerConnectionDetails(ContainerConnectionSource<C> source) {
Assert.notNull(source, "Source must not be null");
this.origin = source.getOrigin();
this.source = source;
}
protected final C getContainer() {
return this.source.getContainer();
}
@Override
public Origin getOrigin() {
return this.origin;
return this.source.getOrigin();
}
}

View File

@ -118,11 +118,7 @@ public final class ContainerConnectionSource<C extends Container<?>> implements
return this.origin;
}
/**
* Return the {@link Container} that implements the service being connected to.
* @return the {@link Container} providing the service
*/
public C getContainer() {
C getContainer() {
return this.container;
}

View File

@ -47,29 +47,26 @@ class RabbitContainerConnectionDetailsFactory
/**
* {@link RabbitConnectionDetails} backed by a {@link ContainerConnectionSource}.
*/
private static final class RabbitMqContainerConnectionDetails extends ContainerConnectionDetails
private static final class RabbitMqContainerConnectionDetails extends ContainerConnectionDetails<RabbitMQContainer>
implements RabbitConnectionDetails {
private final RabbitMQContainer container;
private RabbitMqContainerConnectionDetails(ContainerConnectionSource<RabbitMQContainer> source) {
super(source);
this.container = source.getContainer();
}
@Override
public String getUsername() {
return this.container.getAdminUsername();
return getContainer().getAdminUsername();
}
@Override
public String getPassword() {
return this.container.getAdminPassword();
return getContainer().getAdminPassword();
}
@Override
public List<Address> getAddresses() {
URI uri = URI.create(this.container.getAmqpUrl());
URI uri = URI.create(getContainer().getAmqpUrl());
return List.of(new Address(uri.getHost(), uri.getPort()));
}

View File

@ -16,6 +16,7 @@
package org.springframework.boot.testcontainers.service.connection.cassandra;
import java.net.InetSocketAddress;
import java.util.List;
import org.testcontainers.containers.CassandraContainer;
@ -46,35 +47,32 @@ class CassandraContainerConnectionDetailsFactory
/**
* {@link CassandraConnectionDetails} backed by a {@link ContainerConnectionSource}.
*/
private static final class CassandraContainerConnectionDetails extends ContainerConnectionDetails
implements CassandraConnectionDetails {
private final CassandraContainer<?> container;
private static final class CassandraContainerConnectionDetails
extends ContainerConnectionDetails<CassandraContainer<?>> implements CassandraConnectionDetails {
private CassandraContainerConnectionDetails(ContainerConnectionSource<CassandraContainer<?>> source) {
super(source);
this.container = source.getContainer();
}
@Override
public List<Node> getContactPoints() {
return List.of(new Node(this.container.getContactPoint().getHostString(),
this.container.getContactPoint().getPort()));
InetSocketAddress contactPoint = getContainer().getContactPoint();
return List.of(new Node(contactPoint.getHostString(), contactPoint.getPort()));
}
@Override
public String getUsername() {
return this.container.getUsername();
return getContainer().getUsername();
}
@Override
public String getPassword() {
return this.container.getPassword();
return getContainer().getPassword();
}
@Override
public String getLocalDatacenter() {
return this.container.getLocalDatacenter();
return getContainer().getLocalDatacenter();
}
}

View File

@ -44,29 +44,26 @@ class CouchbaseContainerConnectionDetailsFactory
/**
* {@link CouchbaseConnectionDetails} backed by a {@link ContainerConnectionSource}.
*/
private static final class CouchbaseContainerConnectionDetails extends ContainerConnectionDetails
implements CouchbaseConnectionDetails {
private final CouchbaseContainer container;
private static final class CouchbaseContainerConnectionDetails
extends ContainerConnectionDetails<CouchbaseContainer> implements CouchbaseConnectionDetails {
private CouchbaseContainerConnectionDetails(ContainerConnectionSource<CouchbaseContainer> source) {
super(source);
this.container = source.getContainer();
}
@Override
public String getUsername() {
return this.container.getUsername();
return getContainer().getUsername();
}
@Override
public String getPassword() {
return this.container.getPassword();
return getContainer().getPassword();
}
@Override
public String getConnectionString() {
return this.container.getConnectionString();
return getContainer().getConnectionString();
}
}

View File

@ -50,20 +50,18 @@ class ElasticsearchContainerConnectionDetailsFactory
* {@link ElasticsearchConnectionDetails} backed by a
* {@link ContainerConnectionSource}.
*/
private static final class ElasticsearchContainerConnectionDetails extends ContainerConnectionDetails
implements ElasticsearchConnectionDetails {
private final List<Node> nodes;
private static final class ElasticsearchContainerConnectionDetails
extends ContainerConnectionDetails<ElasticsearchContainer> implements ElasticsearchConnectionDetails {
private ElasticsearchContainerConnectionDetails(ContainerConnectionSource<ElasticsearchContainer> source) {
super(source);
this.nodes = List.of(new Node(source.getContainer().getHost(),
source.getContainer().getMappedPort(DEFAULT_PORT), Protocol.HTTP, null, null));
}
@Override
public List<Node> getNodes() {
return this.nodes;
String host = getContainer().getHost();
Integer port = getContainer().getMappedPort(DEFAULT_PORT);
return List.of(new Node(host, port, Protocol.HTTP, null, null));
}
}

View File

@ -42,34 +42,31 @@ class FlywayContainerConnectionDetailsFactory
/**
* {@link FlywayConnectionDetails} backed by a {@link JdbcDatabaseContainer}.
*/
private static final class FlywayContainerConnectionDetails extends ContainerConnectionDetails
implements FlywayConnectionDetails {
private final JdbcDatabaseContainer<?> container;
private static final class FlywayContainerConnectionDetails
extends ContainerConnectionDetails<JdbcDatabaseContainer<?>> implements FlywayConnectionDetails {
private FlywayContainerConnectionDetails(ContainerConnectionSource<JdbcDatabaseContainer<?>> source) {
super(source);
this.container = source.getContainer();
}
@Override
public String getUsername() {
return this.container.getUsername();
return getContainer().getUsername();
}
@Override
public String getPassword() {
return this.container.getPassword();
return getContainer().getPassword();
}
@Override
public String getJdbcUrl() {
return this.container.getJdbcUrl();
return getContainer().getJdbcUrl();
}
@Override
public String getDriverClassName() {
return this.container.getDriverClassName();
return getContainer().getDriverClassName();
}
}

View File

@ -43,34 +43,31 @@ class JdbcContainerConnectionDetailsFactory
/**
* {@link JdbcConnectionDetails} backed by a {@link ContainerConnectionSource}.
*/
private static final class JdbcContainerConnectionDetails extends ContainerConnectionDetails
implements JdbcConnectionDetails {
private final JdbcDatabaseContainer<?> container;
private static final class JdbcContainerConnectionDetails
extends ContainerConnectionDetails<JdbcDatabaseContainer<?>> implements JdbcConnectionDetails {
private JdbcContainerConnectionDetails(ContainerConnectionSource<JdbcDatabaseContainer<?>> source) {
super(source);
this.container = source.getContainer();
}
@Override
public String getUsername() {
return this.container.getUsername();
return getContainer().getUsername();
}
@Override
public String getPassword() {
return this.container.getPassword();
return getContainer().getPassword();
}
@Override
public String getJdbcUrl() {
return this.container.getJdbcUrl();
return getContainer().getJdbcUrl();
}
@Override
public String getDriverClassName() {
return this.container.getDriverClassName();
return getContainer().getDriverClassName();
}
}

View File

@ -45,19 +45,16 @@ class KafkaContainerConnectionDetailsFactory
/**
* {@link KafkaConnectionDetails} backed by a {@link ContainerConnectionSource}.
*/
private static final class KafkaContainerConnectionDetails extends ContainerConnectionDetails
private static final class KafkaContainerConnectionDetails extends ContainerConnectionDetails<KafkaContainer>
implements KafkaConnectionDetails {
private final KafkaContainer container;
private KafkaContainerConnectionDetails(ContainerConnectionSource<KafkaContainer> source) {
super(source);
this.container = source.getContainer();
}
@Override
public List<Node> getBootstrapNodes() {
URI uri = URI.create(this.container.getBootstrapServers());
URI uri = URI.create(getContainer().getBootstrapServers());
return List.of(new Node(uri.getHost(), uri.getPort()));
}

View File

@ -42,34 +42,31 @@ class LiquibaseContainerConnectionDetailsFactory
/**
* {@link LiquibaseConnectionDetails} backed by a {@link JdbcDatabaseContainer}.
*/
private static final class LiquibaseContainerConnectionDetails extends ContainerConnectionDetails
implements LiquibaseConnectionDetails {
private final JdbcDatabaseContainer<?> container;
private static final class LiquibaseContainerConnectionDetails
extends ContainerConnectionDetails<JdbcDatabaseContainer<?>> implements LiquibaseConnectionDetails {
private LiquibaseContainerConnectionDetails(ContainerConnectionSource<JdbcDatabaseContainer<?>> source) {
super(source);
this.container = source.getContainer();
}
@Override
public String getUsername() {
return this.container.getUsername();
return getContainer().getUsername();
}
@Override
public String getPassword() {
return this.container.getPassword();
return getContainer().getPassword();
}
@Override
public String getJdbcUrl() {
return this.container.getJdbcUrl();
return getContainer().getJdbcUrl();
}
@Override
public String getDriverClassName() {
return this.container.getDriverClassName();
return getContainer().getDriverClassName();
}
}

View File

@ -47,19 +47,16 @@ class MongoContainerConnectionDetailsFactory
/**
* {@link MongoConnectionDetails} backed by a {@link ContainerConnectionSource}.
*/
private static final class MongoContainerConnectionDetails extends ContainerConnectionDetails
private static final class MongoContainerConnectionDetails extends ContainerConnectionDetails<MongoDBContainer>
implements MongoConnectionDetails {
private final ConnectionString connectionString;
private MongoContainerConnectionDetails(ContainerConnectionSource<MongoDBContainer> source) {
super(source);
this.connectionString = new ConnectionString(source.getContainer().getReplicaSetUrl());
}
@Override
public ConnectionString getConnectionString() {
return this.connectionString;
return new ConnectionString(getContainer().getReplicaSetUrl());
}
}

View File

@ -51,24 +51,21 @@ class Neo4jContainerConnectionDetailsFactory
/**
* {@link Neo4jConnectionDetails} backed by a {@link ContainerConnectionSource}.
*/
private static final class Neo4jContainerConnectionDetails extends ContainerConnectionDetails
private static final class Neo4jContainerConnectionDetails extends ContainerConnectionDetails<Neo4jContainer<?>>
implements Neo4jConnectionDetails {
private final Neo4jContainer<?> container;
private Neo4jContainerConnectionDetails(ContainerConnectionSource<Neo4jContainer<?>> source) {
super(source);
this.container = source.getContainer();
}
@Override
public URI getUri() {
return URI.create(this.container.getBoltUrl());
return URI.create(getContainer().getBoltUrl());
}
@Override
public AuthToken getAuthToken() {
String password = this.container.getAdminPassword();
String password = getContainer().getAdminPassword();
return (password != null) ? AuthTokens.basic("neo4j", password) : AuthTokens.none();
}

View File

@ -42,23 +42,22 @@ class MariaDbR2dbcContainerConnectionDetailsFactory
@Override
public R2dbcConnectionDetails getContainerConnectionDetails(ContainerConnectionSource<MariaDBContainer<?>> source) {
return new R2dbcDatabaseContainerConnectionDetails(source.getContainer());
return new MariaDbR2dbcDatabaseContainerConnectionDetails(source);
}
/**
* {@link R2dbcConnectionDetails} backed by a {@link ContainerConnectionSource}.
*/
private static final class R2dbcDatabaseContainerConnectionDetails implements R2dbcConnectionDetails {
private static final class MariaDbR2dbcDatabaseContainerConnectionDetails
extends ContainerConnectionDetails<MariaDBContainer<?>> implements R2dbcConnectionDetails {
private final MariaDBContainer<?> container;
private R2dbcDatabaseContainerConnectionDetails(MariaDBContainer<?> container) {
this.container = container;
private MariaDbR2dbcDatabaseContainerConnectionDetails(ContainerConnectionSource<MariaDBContainer<?>> source) {
super(source);
}
@Override
public ConnectionFactoryOptions getConnectionFactoryOptions() {
return MariaDBR2DBCDatabaseContainer.getOptions(this.container);
return MariaDBR2DBCDatabaseContainer.getOptions(getContainer());
}
}

View File

@ -42,23 +42,22 @@ class MySqlR2dbcContainerConnectionDetailsFactory
@Override
public R2dbcConnectionDetails getContainerConnectionDetails(ContainerConnectionSource<MySQLContainer<?>> source) {
return new R2dbcDatabaseContainerConnectionDetails(source.getContainer());
return new MySqlR2dbcDatabaseContainerConnectionDetails(source);
}
/**
* {@link R2dbcConnectionDetails} backed by a {@link ContainerConnectionSource}.
*/
private static final class R2dbcDatabaseContainerConnectionDetails implements R2dbcConnectionDetails {
private static final class MySqlR2dbcDatabaseContainerConnectionDetails
extends ContainerConnectionDetails<MySQLContainer<?>> implements R2dbcConnectionDetails {
private final MySQLContainer<?> container;
private R2dbcDatabaseContainerConnectionDetails(MySQLContainer<?> container) {
this.container = container;
private MySqlR2dbcDatabaseContainerConnectionDetails(ContainerConnectionSource<MySQLContainer<?>> source) {
super(source);
}
@Override
public ConnectionFactoryOptions getConnectionFactoryOptions() {
return MySQLR2DBCDatabaseContainer.getOptions(this.container);
return MySQLR2DBCDatabaseContainer.getOptions(getContainer());
}
}

View File

@ -46,19 +46,16 @@ class OracleR2dbcContainerConnectionDetailsFactory
/**
* {@link R2dbcConnectionDetails} backed by a {@link ContainerConnectionSource}.
*/
private static final class R2dbcDatabaseContainerConnectionDetails extends ContainerConnectionDetails
implements R2dbcConnectionDetails {
private final OracleContainer container;
private static final class R2dbcDatabaseContainerConnectionDetails
extends ContainerConnectionDetails<OracleContainer> implements R2dbcConnectionDetails {
private R2dbcDatabaseContainerConnectionDetails(ContainerConnectionSource<OracleContainer> source) {
super(source);
this.container = source.getContainer();
}
@Override
public ConnectionFactoryOptions getConnectionFactoryOptions() {
return OracleR2DBCDatabaseContainer.getOptions(this.container);
return OracleR2DBCDatabaseContainer.getOptions(getContainer());
}
}

View File

@ -43,23 +43,22 @@ class PostgresR2dbcContainerConnectionDetailsFactory
@Override
public R2dbcConnectionDetails getContainerConnectionDetails(
ContainerConnectionSource<PostgreSQLContainer<?>> source) {
return new R2dbcDatabaseContainerConnectionDetails(source.getContainer());
return new PostgresR2dbcDatabaseContainerConnectionDetails(source);
}
/**
* {@link R2dbcConnectionDetails} backed by a {@link ContainerConnectionSource}.
*/
private static final class R2dbcDatabaseContainerConnectionDetails implements R2dbcConnectionDetails {
private static final class PostgresR2dbcDatabaseContainerConnectionDetails
extends ContainerConnectionDetails<PostgreSQLContainer<?>> implements R2dbcConnectionDetails {
private final PostgreSQLContainer<?> container;
private R2dbcDatabaseContainerConnectionDetails(PostgreSQLContainer<?> container) {
this.container = container;
PostgresR2dbcDatabaseContainerConnectionDetails(ContainerConnectionSource<PostgreSQLContainer<?>> source) {
super(source);
}
@Override
public ConnectionFactoryOptions getConnectionFactoryOptions() {
return PostgreSQLR2DBCDatabaseContainer.getOptions(this.container);
return PostgreSQLR2DBCDatabaseContainer.getOptions(getContainer());
}
}

View File

@ -43,23 +43,23 @@ class SqlServerR2dbcContainerConnectionDetailsFactory
@Override
public R2dbcConnectionDetails getContainerConnectionDetails(
ContainerConnectionSource<MSSQLServerContainer<?>> source) {
return new R2dbcDatabaseContainerConnectionDetails(source.getContainer());
return new MsSqlServerR2dbcDatabaseContainerConnectionDetails(source);
}
/**
* {@link R2dbcConnectionDetails} backed by a {@link ContainerConnectionSource}.
*/
private static final class R2dbcDatabaseContainerConnectionDetails implements R2dbcConnectionDetails {
private static final class MsSqlServerR2dbcDatabaseContainerConnectionDetails
extends ContainerConnectionDetails<MSSQLServerContainer<?>> implements R2dbcConnectionDetails {
private final MSSQLServerContainer<?> container;
private R2dbcDatabaseContainerConnectionDetails(MSSQLServerContainer<?> container) {
this.container = container;
private MsSqlServerR2dbcDatabaseContainerConnectionDetails(
ContainerConnectionSource<MSSQLServerContainer<?>> source) {
super(source);
}
@Override
public ConnectionFactoryOptions getConnectionFactoryOptions() {
return MSSQLR2DBCDatabaseContainer.getOptions(this.container);
return MSSQLR2DBCDatabaseContainer.getOptions(getContainer());
}
}

View File

@ -48,20 +48,16 @@ class RedisContainerConnectionDetailsFactory
/**
* {@link RedisConnectionDetails} backed by a {@link ContainerConnectionSource}.
*/
private static final class RedisContainerConnectionDetails extends ContainerConnectionDetails
private static final class RedisContainerConnectionDetails extends ContainerConnectionDetails<Container<?>>
implements RedisConnectionDetails {
private final Standalone standalone;
private RedisContainerConnectionDetails(ContainerConnectionSource<Container<?>> source) {
super(source);
this.standalone = Standalone.of(source.getContainer().getHost(),
source.getContainer().getFirstMappedPort());
}
@Override
public Standalone getStandalone() {
return this.standalone;
return Standalone.of(getContainer().getHost(), getContainer().getFirstMappedPort());
}
}

View File

@ -44,19 +44,16 @@ class RedpandaContainerConnectionDetailsFactory
/**
* {@link KafkaConnectionDetails} backed by a {@link ContainerConnectionSource}.
*/
private static final class RedpandaContainerConnectionDetails extends ContainerConnectionDetails
private static final class RedpandaContainerConnectionDetails extends ContainerConnectionDetails<RedpandaContainer>
implements KafkaConnectionDetails {
private final RedpandaContainer container;
private RedpandaContainerConnectionDetails(ContainerConnectionSource<RedpandaContainer> source) {
super(source);
this.container = source.getContainer();
}
@Override
public List<Node> getBootstrapNodes() {
URI uri = URI.create(this.container.getBootstrapServers());
URI uri = URI.create(getContainer().getBootstrapServers());
return List.of(new Node(uri.getHost(), uri.getPort()));
}

View File

@ -46,7 +46,7 @@ class ContainerConnectionDetailsFactoryTests {
private Origin origin;
private JdbcDatabaseContainer<?> container;
private PostgreSQLContainer<?> container;
private MergedAnnotation<ServiceConnection> annotation;
@ -127,10 +127,10 @@ class ContainerConnectionDetailsFactoryTests {
return new TestContainerConnectionDetails(source);
}
static class TestContainerConnectionDetails extends ContainerConnectionDetails
implements JdbcConnectionDetails {
private static final class TestContainerConnectionDetails
extends ContainerConnectionDetails<JdbcDatabaseContainer<?>> implements JdbcConnectionDetails {
TestContainerConnectionDetails(ContainerConnectionSource<?> source) {
private TestContainerConnectionDetails(ContainerConnectionSource<JdbcDatabaseContainer<?>> source) {
super(source);
}