or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

access-methods.mdconfiguration.mddeprecated-api.mdindex.md
tile.json

access-methods.mddocs/

Access Methods

Retrieve connection information for the RabbitMQ container, including mapped ports and connection URLs for AMQP, AMQPS, HTTP, and HTTPS endpoints. These methods provide the host and port details needed to connect to the running RabbitMQ container from test code.

Important Notes for Agents

  • All access methods require the container to be started first (call start() before accessing)
  • Port numbers are dynamically assigned and will vary between container instances
  • URLs use the container host (typically "localhost" or Docker host IP)
  • Port mapping happens automatically; you cannot specify fixed ports
  • All methods return null if container is not started (will throw IllegalStateException in practice)
  • Port values are valid only while container is running
  • Multiple containers get unique port assignments automatically
  • Port access methods are thread-safe for read operations once container is started
  • URL methods construct connection strings using current host and port values
  • All methods throw IllegalStateException if called before start()

Capabilities

Port Access

Get the mapped ports on the host machine for RabbitMQ's four exposed ports. Since Testcontainers maps container ports to random available host ports, these methods are essential for determining the actual connection points.

/**
 * Returns the mapped AMQP port (default container port 5672) on the host.
 * @return The host port mapped to container port 5672
 * @throws IllegalStateException if container is not started
 */
public Integer getAmqpPort()

/**
 * Returns the mapped AMQPS port (default container port 5671) on the host.
 * @return The host port mapped to container port 5671
 * @throws IllegalStateException if container is not started
 */
public Integer getAmqpsPort()

/**
 * Returns the mapped HTTP management port (default container port 15672) on the host.
 * @return The host port mapped to container port 15672
 * @throws IllegalStateException if container is not started
 */
public Integer getHttpPort()

/**
 * Returns the mapped HTTPS management port (default container port 15671) on the host.
 * @return The host port mapped to container port 15671
 * @throws IllegalStateException if container is not started
 */
public Integer getHttpsPort()

Usage Example:

RabbitMQContainer rabbitmq = new RabbitMQContainer(
    DockerImageName.parse("rabbitmq:3.7.25-management-alpine"));
rabbitmq.start();

// Get individual ports
Integer amqpPort = rabbitmq.getAmqpPort();       // e.g., 32768
Integer amqpsPort = rabbitmq.getAmqpsPort();     // e.g., 32769
Integer httpPort = rabbitmq.getHttpPort();       // e.g., 32770
Integer httpsPort = rabbitmq.getHttpsPort();     // e.g., 32771

// Use ports for manual connection setup
String host = rabbitmq.getHost();
String connectionString = String.format("amqp://%s:%d", host, amqpPort);

Error Handling:

RabbitMQContainer rabbitmq = new RabbitMQContainer(
    DockerImageName.parse("rabbitmq:3.7.25-management-alpine"));

try {
    // This will throw IllegalStateException - container not started
    Integer port = rabbitmq.getAmqpPort();
} catch (IllegalStateException e) {
    // Container must be started first
    rabbitmq.start();
    Integer port = rabbitmq.getAmqpPort(); // Now works
}

Multiple Containers:

// Each container gets unique ports
RabbitMQContainer container1 = new RabbitMQContainer(
    DockerImageName.parse("rabbitmq:3.7.25-management-alpine"));
RabbitMQContainer container2 = new RabbitMQContainer(
    DockerImageName.parse("rabbitmq:3.7.25-management-alpine"));

container1.start();
container2.start();

// Ports will be different
Integer port1 = container1.getAmqpPort(); // e.g., 32768
Integer port2 = container2.getAmqpPort(); // e.g., 32769

Port Access After Stop:

RabbitMQContainer rabbitmq = new RabbitMQContainer(
    DockerImageName.parse("rabbitmq:3.7.25-management-alpine"));
rabbitmq.start();

Integer port = rabbitmq.getAmqpPort(); // Valid while running

rabbitmq.stop();

// Port value may still be accessible but container is stopped
// Do not use port values after stop() - they are no longer valid

URL Builders

Get complete connection URLs for RabbitMQ endpoints. These convenience methods combine the container host and mapped port into ready-to-use connection strings.

/**
 * Returns the AMQP URL for use with AMQP clients.
 * Format: "amqp://host:port"
 * @return The complete AMQP connection URL
 * @throws IllegalStateException if container is not started
 */
public String getAmqpUrl()

/**
 * Returns the AMQPS URL for use with AMQPS clients.
 * Format: "amqps://host:port"
 * @return The complete AMQPS connection URL
 * @throws IllegalStateException if container is not started
 */
public String getAmqpsUrl()

/**
 * Returns the URL of the HTTP management endpoint.
 * Format: "http://host:port"
 * @return The complete HTTP management URL
 * @throws IllegalStateException if container is not started
 */
public String getHttpUrl()

/**
 * Returns the URL of the HTTPS management endpoint.
 * Format: "https://host:port"
 * @return The complete HTTPS management URL
 * @throws IllegalStateException if container is not started
 */
public String getHttpsUrl()

Usage Example:

import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Channel;

RabbitMQContainer rabbitmq = new RabbitMQContainer(
    DockerImageName.parse("rabbitmq:3.7.25-management-alpine"))
    .withAdminUser("admin")
    .withAdminPassword("password");

rabbitmq.start();

// Get AMQP URL for client connections
String amqpUrl = rabbitmq.getAmqpUrl();  // "amqp://localhost:32768"

// Connect using RabbitMQ Java client
ConnectionFactory factory = new ConnectionFactory();
factory.setUri(amqpUrl);
factory.setUsername(rabbitmq.getAdminUsername());
factory.setPassword(rabbitmq.getAdminPassword());
factory.setConnectionTimeout(5000);
factory.setHandshakeTimeout(5000);

try (Connection connection = factory.newConnection();
     Channel channel = connection.createChannel()) {
    // Use connection for testing
    channel.queueDeclare("test-queue", false, false, false, null);
}

AMQPS Example with Complete SSL Setup:

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import java.io.FileInputStream;
import java.security.KeyStore;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import com.rabbitmq.client.ConnectionFactory;
import org.testcontainers.utility.MountableFile;
import org.testcontainers.containers.RabbitMQContainer.SslVerification;

// Configure SSL (see configuration.md for container SSL setup)
RabbitMQContainer rabbitmq = new RabbitMQContainer(
    DockerImageName.parse("rabbitmq:3.7.25-management-alpine"))
    .withSSL(
        MountableFile.forClasspathResource("certs/server_key.pem"),
        MountableFile.forClasspathResource("certs/server_certificate.pem"),
        MountableFile.forClasspathResource("certs/ca_certificate.pem"),
        SslVerification.VERIFY_PEER
    );

rabbitmq.start();

// Get AMQPS URL
String amqpsUrl = rabbitmq.getAmqpsUrl();  // "amqps://localhost:32769"

// Configure SSL context for client
CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509Certificate caCert = (X509Certificate) cf.generateCertificate(
    new FileInputStream("src/test/resources/certs/ca_certificate.pem"));

KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", caCert);

TrustManagerFactory tmf = TrustManagerFactory.getInstance(
    TrustManagerFactory.getDefaultAlgorithm());
tmf.init(keyStore);

SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
sslContext.init(null, tmf.getTrustManagers(), null);

// Configure connection factory with SSL
ConnectionFactory factory = new ConnectionFactory();
factory.setUri(amqpsUrl);
factory.useSslProtocol(sslContext);
factory.setUsername(rabbitmq.getAdminUsername());
factory.setPassword(rabbitmq.getAdminPassword());
factory.setConnectionTimeout(5000);

try (Connection connection = factory.newConnection();
     Channel channel = connection.createChannel()) {
    // Use secure connection
    channel.queueDeclare("secure-queue", false, false, false, null);
}

Management API Example:

import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
import java.util.Base64;
import java.time.Duration;

RabbitMQContainer rabbitmq = new RabbitMQContainer(
    DockerImageName.parse("rabbitmq:3.7.25-management-alpine"));
rabbitmq.start();

// Get HTTP management URL
String httpUrl = rabbitmq.getHttpUrl();  // "http://localhost:32770"

// Prepare authentication
String credentials = rabbitmq.getAdminUsername() + ":" + rabbitmq.getAdminPassword();
String encodedAuth = Base64.getEncoder().encodeToString(credentials.getBytes());

// Create HTTP client
HttpClient client = HttpClient.newBuilder()
    .connectTimeout(Duration.ofSeconds(5))
    .build();

// Call management API
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create(httpUrl + "/api/overview"))
    .header("Authorization", "Basic " + encodedAuth)
    .timeout(Duration.ofSeconds(10))
    .GET()
    .build();

try {
    HttpResponse<String> response = client.send(request, 
        HttpResponse.BodyHandlers.ofString());
    
    if (response.statusCode() == 200) {
        String body = response.body();
        // Parse JSON response for testing
        System.out.println("RabbitMQ version: " + extractVersion(body));
    } else {
        throw new RuntimeException("Management API returned: " + response.statusCode());
    }
} catch (Exception e) {
    throw new RuntimeException("Failed to call management API", e);
}

Management API - List Queues:

import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
import java.util.Base64;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.JsonNode;

RabbitMQContainer rabbitmq = new RabbitMQContainer(
    DockerImageName.parse("rabbitmq:3.7.25-management-alpine"));
rabbitmq.start();

// Create queue using AMQP
ConnectionFactory factory = new ConnectionFactory();
factory.setUri(rabbitmq.getAmqpUrl());
factory.setUsername(rabbitmq.getAdminUsername());
factory.setPassword(rabbitmq.getAdminPassword());

try (Connection conn = factory.newConnection();
     Channel channel = conn.createChannel()) {
    channel.queueDeclare("test-queue", false, false, false, null);
}

// Query queues via management API
String httpUrl = rabbitmq.getHttpUrl();
String credentials = rabbitmq.getAdminUsername() + ":" + rabbitmq.getAdminPassword();
String encodedAuth = Base64.getEncoder().encodeToString(credentials.getBytes());

HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create(httpUrl + "/api/queues"))
    .header("Authorization", "Basic " + encodedAuth)
    .GET()
    .build();

HttpResponse<String> response = client.send(request, 
    HttpResponse.BodyHandlers.ofString());

ObjectMapper mapper = new ObjectMapper();
JsonNode queues = mapper.readTree(response.body());

// Verify queue exists
boolean found = false;
for (JsonNode queue : queues) {
    if ("test-queue".equals(queue.get("name").asText())) {
        found = true;
        break;
    }
}
assert found : "Queue not found via management API";

Management API - Get Queue Details:

import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
import java.util.Base64;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.JsonNode;

RabbitMQContainer rabbitmq = new RabbitMQContainer(
    DockerImageName.parse("rabbitmq:3.7.25-management-alpine"));
rabbitmq.start();

// Create queue
ConnectionFactory factory = new ConnectionFactory();
factory.setUri(rabbitmq.getAmqpUrl());
factory.setUsername(rabbitmq.getAdminUsername());
factory.setPassword(rabbitmq.getAdminPassword());

try (Connection conn = factory.newConnection();
     Channel channel = conn.createChannel()) {
    channel.queueDeclare("test-queue", true, false, false, null);
    channel.basicPublish("", "test-queue", null, "Test message".getBytes());
}

// Get queue details via management API
String httpUrl = rabbitmq.getHttpUrl();
String credentials = rabbitmq.getAdminUsername() + ":" + rabbitmq.getAdminPassword();
String encodedAuth = Base64.getEncoder().encodeToString(credentials.getBytes());

HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create(httpUrl + "/api/queues/%2F/test-queue"))  // %2F is URL-encoded "/"
    .header("Authorization", "Basic " + encodedAuth)
    .GET()
    .build();

HttpResponse<String> response = client.send(request, 
    HttpResponse.BodyHandlers.ofString());

ObjectMapper mapper = new ObjectMapper();
JsonNode queue = mapper.readTree(response.body());

// Verify queue properties
assert queue.get("name").asText().equals("test-queue");
assert queue.get("durable").asBoolean() == true;
assert queue.get("messages").asInt() == 1;

Complete Integration Example

import org.testcontainers.containers.RabbitMQContainer;
import org.testcontainers.utility.DockerImageName;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.DeliverCallback;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.AfterEach;
import static org.junit.jupiter.api.Assertions.*;

public class RabbitMQIntegrationTest {
    private RabbitMQContainer rabbitmq;
    private Connection connection;
    private Channel channel;

    @BeforeEach
    public void setUp() throws Exception {
        rabbitmq = new RabbitMQContainer(
            DockerImageName.parse("rabbitmq:3.7.25-management-alpine"));
        rabbitmq.start();

        ConnectionFactory factory = new ConnectionFactory();
        factory.setUri(rabbitmq.getAmqpUrl());
        factory.setUsername(rabbitmq.getAdminUsername());
        factory.setPassword(rabbitmq.getAdminPassword());
        factory.setConnectionTimeout(5000);
        factory.setHandshakeTimeout(5000);

        connection = factory.newConnection();
        channel = connection.createChannel();
    }

    @AfterEach
    public void tearDown() throws Exception {
        if (channel != null && channel.isOpen()) {
            channel.close();
        }
        if (connection != null && connection.isOpen()) {
            connection.close();
        }
        if (rabbitmq != null) {
            rabbitmq.stop();
        }
    }

    @Test
    public void testRabbitMQConnection() throws Exception {
        // Declare queue
        channel.queueDeclare("test-queue", false, false, false, null);

        // Publish message
        String message = "Hello RabbitMQ!";
        channel.basicPublish("", "test-queue", null, message.getBytes());

        // Consume message
        String[] receivedMessage = new String[1];
        DeliverCallback deliverCallback = (consumerTag, delivery) -> {
            receivedMessage[0] = new String(delivery.getBody(), "UTF-8");
        };
        
        String consumerTag = channel.basicConsume("test-queue", true, 
            deliverCallback, consumerTag -> {});

        // Wait and verify
        Thread.sleep(100);
        assertEquals("Hello RabbitMQ!", receivedMessage[0]);
        
        channel.basicCancel(consumerTag);
    }

    @Test
    public void testMultipleQueues() throws Exception {
        // Create multiple queues
        channel.queueDeclare("queue1", false, false, false, null);
        channel.queueDeclare("queue2", false, false, false, null);
        channel.queueDeclare("queue3", false, false, false, null);

        // Publish to each
        channel.basicPublish("", "queue1", null, "Message 1".getBytes());
        channel.basicPublish("", "queue2", null, "Message 2".getBytes());
        channel.basicPublish("", "queue3", null, "Message 3".getBytes());

        // Verify all queues exist via management API
        // (See management API example above)
    }
}

Edge Cases and Error Scenarios

Container Not Started

RabbitMQContainer rabbitmq = new RabbitMQContainer(
    DockerImageName.parse("rabbitmq:3.7.25-management-alpine"));

// This will throw IllegalStateException
try {
    String url = rabbitmq.getAmqpUrl();
    fail("Should throw IllegalStateException");
} catch (IllegalStateException e) {
    // Expected - container must be started first
    rabbitmq.start();
    String url = rabbitmq.getAmqpUrl(); // Now works
}

Connection Timeout

RabbitMQContainer rabbitmq = new RabbitMQContainer(
    DockerImageName.parse("rabbitmq:3.7.25-management-alpine"));
rabbitmq.start();

ConnectionFactory factory = new ConnectionFactory();
factory.setUri(rabbitmq.getAmqpUrl());
factory.setConnectionTimeout(100); // Very short timeout

try {
    Connection connection = factory.newConnection();
    // May timeout if container is slow to start
} catch (java.net.SocketTimeoutException e) {
    // Handle timeout - container may need more time
    // Wait and retry, or increase timeout
    factory.setConnectionTimeout(5000);
    Connection connection = factory.newConnection(); // Retry
}

Port Already in Use (Rare)

// Testcontainers handles this automatically, but in edge cases:
RabbitMQContainer rabbitmq = new RabbitMQContainer(
    DockerImageName.parse("rabbitmq:3.7.25-management-alpine"));

try {
    rabbitmq.start();
} catch (org.testcontainers.containers.ContainerLaunchException e) {
    if (e.getMessage().contains("port")) {
        // Port conflict - testcontainers should retry automatically
        // If this happens, check for Docker issues
        System.err.println("Port conflict detected: " + e.getMessage());
    }
    throw e;
}

URL Format Validation

RabbitMQContainer rabbitmq = new RabbitMQContainer(
    DockerImageName.parse("rabbitmq:3.7.25-management-alpine"));
rabbitmq.start();

String amqpUrl = rabbitmq.getAmqpUrl();
// URL format: "amqp://localhost:32768"
assert amqpUrl.startsWith("amqp://");
assert amqpUrl.contains(":");

String httpUrl = rabbitmq.getHttpUrl();
// URL format: "http://localhost:32770"
assert httpUrl.startsWith("http://");
assert httpUrl.contains(":");

Container Stopped During Access

RabbitMQContainer rabbitmq = new RabbitMQContainer(
    DockerImageName.parse("rabbitmq:3.7.25-management-alpine"));
rabbitmq.start();

String url = rabbitmq.getAmqpUrl(); // Valid
Integer port = rabbitmq.getAmqpPort(); // Valid

rabbitmq.stop();

// Do not use url or port after stop - container is no longer accessible
// Attempting to connect will fail

Multiple Containers with Different Ports

RabbitMQContainer container1 = new RabbitMQContainer(
    DockerImageName.parse("rabbitmq:3.7.25-management-alpine"));
RabbitMQContainer container2 = new RabbitMQContainer(
    DockerImageName.parse("rabbitmq:3.7.25-management-alpine"));

container1.start();
container2.start();

// Each container has unique ports
String url1 = container1.getAmqpUrl(); // "amqp://localhost:32768"
String url2 = container2.getAmqpUrl(); // "amqp://localhost:32769"

// Use different URLs for different containers
ConnectionFactory factory1 = new ConnectionFactory();
factory1.setUri(url1);
Connection connection1 = factory1.newConnection();

ConnectionFactory factory2 = new ConnectionFactory();
factory2.setUri(url2);
Connection connection2 = factory2.newConnection();

URL Construction with Custom Host

RabbitMQContainer rabbitmq = new RabbitMQContainer(
    DockerImageName.parse("rabbitmq:3.7.25-management-alpine"));
rabbitmq.start();

// getAmqpUrl() uses getHost() which is typically "localhost"
String url = rabbitmq.getAmqpUrl(); // "amqp://localhost:32768"

// For remote Docker hosts, getHost() may return different value
String host = rabbitmq.getHost(); // May be "localhost" or Docker host IP
Integer port = rabbitmq.getAmqpPort();

// Construct custom URL if needed
String customUrl = String.format("amqp://%s:%d", host, port);

Notes

  • All URLs use the container host (typically "localhost" or Docker host IP)
  • Port numbers are dynamically assigned by Testcontainers and will vary between container instances
  • The AMQP URL (port 5672) is the most commonly used endpoint for message publishing and consuming
  • The HTTP management URL (port 15672) provides access to RabbitMQ's management API and web UI
  • AMQPS and HTTPS endpoints require SSL configuration (see Configuration)
  • Connection credentials must be set using withAdminUser() and withAdminPassword() if non-default values are required
  • All access methods are thread-safe for read operations once container is started
  • Port values remain valid only while container is running; accessing ports after stop() may return stale values
  • Use try-with-resources or JUnit lifecycle hooks to ensure containers are properly started before accessing ports/URLs
  • URL methods construct strings using current host and port values; if container is stopped, URLs are no longer valid
  • For remote Docker hosts, getHost() may return the Docker host IP address instead of "localhost"
  • Port mapping is automatic and cannot be overridden; Testcontainers selects available ports from the ephemeral port range
  • Multiple containers in the same test will get different port assignments automatically
  • Access methods do not validate that the container is actually ready to accept connections; use health checks or wait strategies if needed