CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-springframework-boot--spring-boot-autoconfigure

Spring Boot AutoConfigure provides auto-configuration capabilities that automatically configure Spring applications based on jar dependencies present on the classpath

Pending
Overview
Eval results
Files

service-connections.mddocs/reference/

Service Connection Abstractions

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.

Imports

import org.springframework.boot.autoconfigure.service.connection.*;

Core Interfaces

ConnectionDetails

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
}

ConnectionDetailsFactory

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);
}

Infrastructure Classes

ConnectionDetailsFactories

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);
}

Exception Classes

ConnectionDetailsNotFoundException

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);
}

ConnectionDetailsFactoryNotFoundException

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);
}

Usage Examples

Custom ConnectionDetails Implementation

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;
    }
}

Custom ConnectionDetailsFactory

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.MyServiceConnectionDetailsFactory

Using ConnectionDetailsFactories

import 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;
    }
}

Integration with Testcontainers

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);
    }
}

Multiple Service Connections

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);
    }
}

Custom Service Connection with Origin

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 + "}";
    }
}

Best Practices

  1. Null Handling: Factories should return null for unsupported sources
  2. Factory Registration: Always register factories in META-INF/spring.factories
  3. Validation: Validate connection details before returning from factory
  4. Error Messages: Provide clear error messages when connections fail
  5. Testing: Test factories with both valid and invalid sources
  6. Thread Safety: Ensure ConnectionDetails implementations are thread-safe
  7. Resource Management: Clean up resources in ConnectionDetails when applicable

Install with Tessl CLI

npx tessl i tessl/maven-org-springframework-boot--spring-boot-autoconfigure@4.0.1

docs

index.md

tile.json