Spring Boot AutoConfigure provides auto-configuration capabilities that automatically configure Spring applications based on jar dependencies present on the classpath
—
Spring Boot AutoConfigure provides abstractions for connecting to external services through the ConnectionDetails interface and factory pattern. This enables flexible configuration of service connections from various sources.
import org.springframework.boot.autoconfigure.service.connection.*;Base marker interface for types that provide the details required to establish a connection to a remote service. Implementations can also implement OriginProvider to provide origin information for diagnostics.
public interface ConnectionDetails {
// Marker interface - implementations provide service-specific connection details
// Examples: JdbcConnectionDetails, MongoConnectionDetails, RedisConnectionDetails
}Factory interface for creating ConnectionDetails from a given source. Implementations should be registered in META-INF/spring.factories.
public interface ConnectionDetailsFactory<S, D extends ConnectionDetails> {
/**
* Get the connection details from the given source.
* Returns null if the source is not supported or connection details cannot be created.
*
* @param source the source object
* @return the connection details or null
*/
D getConnectionDetails(S source);
}Registry of ConnectionDetailsFactory instances for creating connection details from various sources.
public class ConnectionDetailsFactories {
/**
* Create a new ConnectionDetailsFactories instance using default factory loading.
*/
public ConnectionDetailsFactories();
/**
* Create a new ConnectionDetailsFactories instance with custom class loader.
*
* @param classLoader the class loader for loading factories
*/
public ConnectionDetailsFactories(ClassLoader classLoader);
/**
* Get connection details for the given source.
*
* @param source the source object
* @param required whether connection details are required
* @param <S> the source type
* @return the connection details or null if not required and not found
* @throws ConnectionDetailsNotFoundException if required and not found
*/
public <S> ConnectionDetails getConnectionDetails(S source, boolean required);
}Runtime exception thrown when required ConnectionDetails could not be found.
public class ConnectionDetailsNotFoundException extends RuntimeException {
/**
* Create a new exception with the given message.
*
* @param message the exception message
*/
public ConnectionDetailsNotFoundException(String message);
}Runtime exception thrown when a ConnectionDetailsFactory could not be found.
public class ConnectionDetailsFactoryNotFoundException extends RuntimeException {
/**
* Create a new exception with the given message.
*
* @param message the exception message
*/
public ConnectionDetailsFactoryNotFoundException(String message);
}import org.springframework.boot.autoconfigure.service.connection.ConnectionDetails;
public class MyServiceConnectionDetails implements ConnectionDetails {
private final String host;
private final int port;
private final String username;
private final String password;
public MyServiceConnectionDetails(
String host,
int port,
String username,
String password) {
this.host = host;
this.port = port;
this.username = username;
this.password = password;
}
public String getHost() {
return host;
}
public int getPort() {
return port;
}
public String getUsername() {
return username;
}
public String getPassword() {
return password;
}
public String getConnectionUrl() {
return "myservice://" + host + ":" + port;
}
}import org.springframework.boot.autoconfigure.service.connection.ConnectionDetailsFactory;
public class MyServiceConnectionDetailsFactory
implements ConnectionDetailsFactory<MyServiceContainer, MyServiceConnectionDetails> {
@Override
public MyServiceConnectionDetails getConnectionDetails(MyServiceContainer source) {
if (source == null || !source.isRunning()) {
return null;
}
return new MyServiceConnectionDetails(
source.getHost(),
source.getMappedPort(8080),
source.getUsername(),
source.getPassword()
);
}
}Register in META-INF/spring.factories:
org.springframework.boot.autoconfigure.service.connection.ConnectionDetailsFactory=\
com.example.MyServiceConnectionDetailsFactoryimport org.springframework.boot.autoconfigure.service.connection.ConnectionDetailsFactories;
import org.springframework.boot.autoconfigure.service.connection.ConnectionDetails;
public class ServiceConnectionManager {
private final ConnectionDetailsFactories factories;
public ServiceConnectionManager() {
this.factories = new ConnectionDetailsFactories();
}
public MyServiceConnectionDetails getConnectionDetails(
MyServiceContainer container) {
ConnectionDetails details = factories.getConnectionDetails(
container,
true // Required - throw exception if not found
);
return (MyServiceConnectionDetails) details;
}
public MyServiceConnectionDetails getOptionalConnectionDetails(
MyServiceContainer container) {
ConnectionDetails details = factories.getConnectionDetails(
container,
false // Optional - return null if not found
);
return details != null ? (MyServiceConnectionDetails) details : null;
}
}import org.springframework.boot.autoconfigure.service.connection.ConnectionDetails;
import org.springframework.boot.autoconfigure.service.connection.ConnectionDetailsFactory;
import org.testcontainers.containers.GenericContainer;
// Container source
public class MyTestContainer extends GenericContainer<MyTestContainer> {
public MyTestContainer() {
super("myservice:latest");
withExposedPorts(8080);
}
public String getConnectionUrl() {
return "myservice://" + getHost() + ":" + getMappedPort(8080);
}
}
// Connection details
public class MyTestConnectionDetails implements ConnectionDetails {
private final String url;
public MyTestConnectionDetails(String url) {
this.url = url;
}
public String getUrl() {
return url;
}
}
// Factory
public class MyTestConnectionDetailsFactory
implements ConnectionDetailsFactory<MyTestContainer, MyTestConnectionDetails> {
@Override
public MyTestConnectionDetails getConnectionDetails(MyTestContainer source) {
return new MyTestConnectionDetails(source.getConnectionUrl());
}
}
// Usage in tests
@SpringBootTest
@Testcontainers
class MyServiceIntegrationTest {
@Container
static MyTestContainer container = new MyTestContainer();
@DynamicPropertySource
static void setupProperties(DynamicPropertyRegistry registry) {
ConnectionDetailsFactories factories = new ConnectionDetailsFactories();
MyTestConnectionDetails details = (MyTestConnectionDetails)
factories.getConnectionDetails(container, true);
registry.add("myservice.url", details::getUrl);
}
}import org.springframework.boot.autoconfigure.service.connection.ConnectionDetails;
import java.util.HashMap;
import java.util.Map;
public class MultiServiceConnectionManager {
private final ConnectionDetailsFactories factories;
private final Map<String, ConnectionDetails> connections;
public MultiServiceConnectionManager() {
this.factories = new ConnectionDetailsFactories();
this.connections = new HashMap<>();
}
public void registerConnection(String name, Object source) {
ConnectionDetails details = factories.getConnectionDetails(source, true);
connections.put(name, details);
}
public <T extends ConnectionDetails> T getConnection(
String name,
Class<T> type) {
ConnectionDetails details = connections.get(name);
if (details == null) {
throw new IllegalArgumentException(
"No connection registered with name: " + name
);
}
if (!type.isInstance(details)) {
throw new IllegalArgumentException(
"Connection " + name + " is not of type " + type.getName()
);
}
return type.cast(details);
}
}import org.springframework.boot.autoconfigure.service.connection.ConnectionDetails;
import org.springframework.boot.origin.Origin;
import org.springframework.boot.origin.OriginProvider;
public class ConfiguredServiceConnectionDetails
implements ConnectionDetails, OriginProvider {
private final String host;
private final int port;
private final Origin origin;
public ConfiguredServiceConnectionDetails(
String host,
int port,
Origin origin) {
this.host = host;
this.port = port;
this.origin = origin;
}
public String getHost() {
return host;
}
public int getPort() {
return port;
}
@Override
public Origin getOrigin() {
return origin;
}
@Override
public String toString() {
return "ServiceConnection{host=" + host +
", port=" + port +
", origin=" + origin + "}";
}
}META-INF/spring.factories