diff --git a/module/spring-boot-amqp/src/dockerTest/java/org/springframework/boot/amqp/testcontainers/DeprecatedRabbitContainerConnectionDetailsFactoryIntegrationTests.java b/module/spring-boot-amqp/src/dockerTest/java/org/springframework/boot/amqp/testcontainers/DeprecatedRabbitContainerConnectionDetailsFactoryIntegrationTests.java new file mode 100644 index 00000000000..51e32711184 --- /dev/null +++ b/module/spring-boot-amqp/src/dockerTest/java/org/springframework/boot/amqp/testcontainers/DeprecatedRabbitContainerConnectionDetailsFactoryIntegrationTests.java @@ -0,0 +1,102 @@ +/* + * Copyright 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.amqp.testcontainers; + +import java.time.Duration; +import java.util.ArrayList; +import java.util.List; + +import org.awaitility.Awaitility; +import org.junit.jupiter.api.Test; +import org.testcontainers.containers.RabbitMQContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; + +import org.springframework.amqp.rabbit.annotation.Queue; +import org.springframework.amqp.rabbit.annotation.RabbitListener; +import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.amqp.autoconfigure.RabbitAutoConfiguration; +import org.springframework.boot.amqp.autoconfigure.RabbitConnectionDetails; +import org.springframework.boot.autoconfigure.ImportAutoConfiguration; +import org.springframework.boot.testcontainers.service.connection.ServiceConnection; +import org.springframework.boot.testsupport.container.TestImage; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link DeprecatedRabbitContainerConnectionDetailsFactory}. + * + * @author Moritz Halbritter + * @author Andy Wilkinson + * @author Phillip Webb + * @deprecated since 4.0.0 for removal in 4.2.0 in favor of + * {@link RabbitContainerConnectionDetailsFactoryIntegrationTests}. + */ +@SpringJUnitConfig +@Testcontainers(disabledWithoutDocker = true) +@Deprecated(since = "4.0.0", forRemoval = true) +class DeprecatedRabbitContainerConnectionDetailsFactoryIntegrationTests { + + @Container + @ServiceConnection + static final RabbitMQContainer rabbit = TestImage.container(RabbitMQContainer.class); + + @Autowired(required = false) + private RabbitConnectionDetails connectionDetails; + + @Autowired + private RabbitTemplate rabbitTemplate; + + @Autowired + private TestListener listener; + + @Test + void connectionCanBeMadeToRabbitContainer() { + assertThat(this.connectionDetails).isNotNull(); + this.rabbitTemplate.convertAndSend("test", "message"); + Awaitility.waitAtMost(Duration.ofMinutes(4)) + .untilAsserted(() -> assertThat(this.listener.messages).containsExactly("message")); + + } + + @Configuration(proxyBeanMethods = false) + @ImportAutoConfiguration(RabbitAutoConfiguration.class) + static class TestConfiguration { + + @Bean + TestListener testListener() { + return new TestListener(); + } + + } + + static class TestListener { + + private final List messages = new ArrayList<>(); + + @RabbitListener(queuesToDeclare = @Queue("test")) + void processMessage(String message) { + this.messages.add(message); + } + + } + +} diff --git a/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/testcontainers/DeprecatedRabbitContainerConnectionDetailsFactory.java b/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/testcontainers/DeprecatedRabbitContainerConnectionDetailsFactory.java new file mode 100644 index 00000000000..b641c37e439 --- /dev/null +++ b/module/spring-boot-amqp/src/main/java/org/springframework/boot/amqp/testcontainers/DeprecatedRabbitContainerConnectionDetailsFactory.java @@ -0,0 +1,85 @@ +/* + * Copyright 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.amqp.testcontainers; + +import java.net.URI; +import java.util.List; + +import org.jspecify.annotations.Nullable; +import org.testcontainers.containers.RabbitMQContainer; + +import org.springframework.boot.amqp.autoconfigure.RabbitConnectionDetails; +import org.springframework.boot.ssl.SslBundle; +import org.springframework.boot.testcontainers.service.connection.ContainerConnectionDetailsFactory; +import org.springframework.boot.testcontainers.service.connection.ContainerConnectionSource; +import org.springframework.boot.testcontainers.service.connection.ServiceConnection; + +/** + * {@link ContainerConnectionDetailsFactory} to create {@link RabbitConnectionDetails} + * from a {@link ServiceConnection @ServiceConnection}-annotated + * {@link RabbitMQContainer}. + * + * @author Moritz Halbritter + * @author Andy Wilkinson + * @author Phillip Webb + * @deprecated since 4.0.0 for removal in 4.2.0 in favor of + * {@link RabbitContainerConnectionDetailsFactory}. + */ +@Deprecated(since = "4.0.0", forRemoval = true) +class DeprecatedRabbitContainerConnectionDetailsFactory + extends ContainerConnectionDetailsFactory { + + @Override + protected RabbitConnectionDetails getContainerConnectionDetails( + ContainerConnectionSource source) { + return new RabbitMqContainerConnectionDetails(source); + } + + /** + * {@link RabbitConnectionDetails} backed by a {@link ContainerConnectionSource}. + */ + private static final class RabbitMqContainerConnectionDetails extends ContainerConnectionDetails + implements RabbitConnectionDetails { + + private RabbitMqContainerConnectionDetails(ContainerConnectionSource source) { + super(source); + } + + @Override + public String getUsername() { + return getContainer().getAdminUsername(); + } + + @Override + public String getPassword() { + return getContainer().getAdminPassword(); + } + + @Override + public List
getAddresses() { + URI uri = URI.create((getSslBundle() != null) ? getContainer().getAmqpsUrl() : getContainer().getAmqpUrl()); + return List.of(new Address(uri.getHost(), uri.getPort())); + } + + @Override + public @Nullable SslBundle getSslBundle() { + return super.getSslBundle(); + } + + } + +} diff --git a/module/spring-boot-amqp/src/main/resources/META-INF/spring.factories b/module/spring-boot-amqp/src/main/resources/META-INF/spring.factories index 412b6813fab..f086b1a88ce 100644 --- a/module/spring-boot-amqp/src/main/resources/META-INF/spring.factories +++ b/module/spring-boot-amqp/src/main/resources/META-INF/spring.factories @@ -1,4 +1,5 @@ # Connection Details Factories org.springframework.boot.autoconfigure.service.connection.ConnectionDetailsFactory=\ org.springframework.boot.amqp.docker.compose.RabbitDockerComposeConnectionDetailsFactory,\ +org.springframework.boot.amqp.testcontainers.DeprecatedRabbitContainerConnectionDetailsFactory,\ org.springframework.boot.amqp.testcontainers.RabbitContainerConnectionDetailsFactory diff --git a/module/spring-boot-mongodb/src/dockerTest/java/org/springframework/boot/mongodb/testcontainers/DeprecatedMongoDbContainerConnectionDetailsFactoryTests.java b/module/spring-boot-mongodb/src/dockerTest/java/org/springframework/boot/mongodb/testcontainers/DeprecatedMongoDbContainerConnectionDetailsFactoryTests.java new file mode 100644 index 00000000000..3f2f433632d --- /dev/null +++ b/module/spring-boot-mongodb/src/dockerTest/java/org/springframework/boot/mongodb/testcontainers/DeprecatedMongoDbContainerConnectionDetailsFactoryTests.java @@ -0,0 +1,60 @@ +/* + * Copyright 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.mongodb.testcontainers; + +import com.mongodb.client.MongoClient; +import com.mongodb.client.MongoClients; +import org.junit.jupiter.api.Test; +import org.testcontainers.containers.MongoDBContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.mongodb.autoconfigure.MongoConnectionDetails; +import org.springframework.boot.testcontainers.service.connection.ServiceConnection; +import org.springframework.boot.testsupport.container.TestImage; +import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Integration tests for {@link DeprecatedMongoDbContainerConnectionDetailsFactory}. + * + * @author Andy Wilkinson + * @deprecated since 4.0.0 for removal in 4.2.0 in favor of + * {@link MongoDbContainerConnectionDetailsFactory}. + */ +@SpringJUnitConfig +@Testcontainers(disabledWithoutDocker = true) +@Deprecated(since = "4.0.0", forRemoval = true) +class DeprecatedMongoDbContainerConnectionDetailsFactoryTests { + + @Container + @ServiceConnection + static final MongoDBContainer mongoDb = TestImage.container(MongoDBContainer.class); + + @Autowired(required = false) + private MongoConnectionDetails connectionDetails; + + @Test + void connectionCanBeMadeToContainer() { + assertThat(this.connectionDetails).isNotNull(); + MongoClient client = MongoClients.create(this.connectionDetails.getConnectionString()); + assertThat(client.listDatabaseNames()).containsExactly("admin", "config", "local"); + } + +} diff --git a/module/spring-boot-mongodb/src/main/java/org/springframework/boot/mongodb/testcontainers/DeprecatedMongoDbContainerConnectionDetailsFactory.java b/module/spring-boot-mongodb/src/main/java/org/springframework/boot/mongodb/testcontainers/DeprecatedMongoDbContainerConnectionDetailsFactory.java new file mode 100644 index 00000000000..1f4084270e4 --- /dev/null +++ b/module/spring-boot-mongodb/src/main/java/org/springframework/boot/mongodb/testcontainers/DeprecatedMongoDbContainerConnectionDetailsFactory.java @@ -0,0 +1,43 @@ +/* + * Copyright 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.mongodb.testcontainers; + +import org.testcontainers.containers.MongoDBContainer; + +import org.springframework.boot.mongodb.autoconfigure.MongoConnectionDetails; +import org.springframework.boot.testcontainers.service.connection.ContainerConnectionDetailsFactory; +import org.springframework.boot.testcontainers.service.connection.ServiceConnection; + +/** + * {@link ContainerConnectionDetailsFactory} to create {@link MongoConnectionDetails} from + * a {@link ServiceConnection @ServiceConnection}-annotated {@link MongoDBContainer}. + * + * @author Moritz Halbritter + * @author Andy Wilkinson + * @author Phillip Webb + * @deprecated since 4.0.0 for removal in 4.2.0 in favor of + * {@link MongoDbContainerConnectionDetailsFactory}. + */ +@Deprecated(since = "4.0.0", forRemoval = true) +class DeprecatedMongoDbContainerConnectionDetailsFactory + extends AbstractMongoContainerConnectionDetailsFactory { + + DeprecatedMongoDbContainerConnectionDetailsFactory() { + super(MongoDBContainer::getReplicaSetUrl); + } + +} diff --git a/module/spring-boot-mongodb/src/main/resources/META-INF/spring.factories b/module/spring-boot-mongodb/src/main/resources/META-INF/spring.factories index 189e62c27c3..a772684516f 100644 --- a/module/spring-boot-mongodb/src/main/resources/META-INF/spring.factories +++ b/module/spring-boot-mongodb/src/main/resources/META-INF/spring.factories @@ -1,5 +1,6 @@ # Connection Details Factories org.springframework.boot.autoconfigure.service.connection.ConnectionDetailsFactory=\ org.springframework.boot.mongodb.docker.compose.MongoDockerComposeConnectionDetailsFactory,\ +org.springframework.boot.mongodb.testcontainers.DeprecatedMongoDbContainerConnectionDetailsFactory,\ org.springframework.boot.mongodb.testcontainers.MongoDbAtlasLocalContainerConnectionDetailsFactory,\ org.springframework.boot.mongodb.testcontainers.MongoDbContainerConnectionDetailsFactory diff --git a/module/spring-boot-neo4j/src/dockerTest/java/org/springframework/boot/neo4j/testcontainers/DeprecatedNeo4jContainerConnectionDetailsFactoryIntegrationTests.java b/module/spring-boot-neo4j/src/dockerTest/java/org/springframework/boot/neo4j/testcontainers/DeprecatedNeo4jContainerConnectionDetailsFactoryIntegrationTests.java new file mode 100644 index 00000000000..feeb6ad630d --- /dev/null +++ b/module/spring-boot-neo4j/src/dockerTest/java/org/springframework/boot/neo4j/testcontainers/DeprecatedNeo4jContainerConnectionDetailsFactoryIntegrationTests.java @@ -0,0 +1,62 @@ +/* + * Copyright 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.neo4j.testcontainers; + +import org.junit.jupiter.api.Test; +import org.neo4j.driver.Driver; +import org.neo4j.driver.GraphDatabase; +import org.testcontainers.containers.Neo4jContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.neo4j.autoconfigure.Neo4jConnectionDetails; +import org.springframework.boot.testcontainers.service.connection.ServiceConnection; +import org.springframework.boot.testsupport.container.TestImage; +import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Integration tests for {@link DeprecatedNeo4jContainerConnectionDetailsFactory}. + * + * @author Stephane Nicoll + * @deprecated since 4.0.0 for removal in 4.2.0 in favor of + * {@link Neo4jContainerConnectionDetailsFactory}. + */ +@SpringJUnitConfig +@Testcontainers(disabledWithoutDocker = true) +@Deprecated(since = "4.0.0", forRemoval = true) +class DeprecatedNeo4jContainerConnectionDetailsFactoryIntegrationTests { + + @Container + @ServiceConnection + static final Neo4jContainer container = TestImage.container(Neo4jContainer.class); + + @Autowired(required = false) + private Neo4jConnectionDetails connectionDetails; + + @Test + void connectionCanBeMadeToContainer() { + assertThat(this.connectionDetails).isNotNull(); + try (Driver driver = GraphDatabase.driver(this.connectionDetails.getUri(), + this.connectionDetails.getAuthToken())) { + driver.verifyConnectivity(); + } + } + +} diff --git a/module/spring-boot-neo4j/src/main/java/org/springframework/boot/neo4j/testcontainers/DeprecatedNeo4jContainerConnectionDetailsFactory.java b/module/spring-boot-neo4j/src/main/java/org/springframework/boot/neo4j/testcontainers/DeprecatedNeo4jContainerConnectionDetailsFactory.java new file mode 100644 index 00000000000..d762b04fa7c --- /dev/null +++ b/module/spring-boot-neo4j/src/main/java/org/springframework/boot/neo4j/testcontainers/DeprecatedNeo4jContainerConnectionDetailsFactory.java @@ -0,0 +1,77 @@ +/* + * Copyright 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.neo4j.testcontainers; + +import java.net.URI; + +import org.neo4j.driver.AuthToken; +import org.neo4j.driver.AuthTokens; +import org.testcontainers.containers.Neo4jContainer; + +import org.springframework.boot.neo4j.autoconfigure.Neo4jConnectionDetails; +import org.springframework.boot.testcontainers.service.connection.ContainerConnectionDetailsFactory; +import org.springframework.boot.testcontainers.service.connection.ContainerConnectionSource; +import org.springframework.boot.testcontainers.service.connection.ServiceConnection; + +/** + * {@link ContainerConnectionDetailsFactory} to create {@link Neo4jConnectionDetails} from + * a {@link ServiceConnection @ServiceConnection}-annotated {@link Neo4jContainer}. + * + * @author Moritz Halbritter + * @author Andy Wilkinson + * @author Phillip Webb + * @deprecated since 4.0.0 for removal in 4.2.0 in favor of + * {@link Neo4jContainerConnectionDetailsFactory}. + */ +@Deprecated(since = "4.0.0", forRemoval = true) +class DeprecatedNeo4jContainerConnectionDetailsFactory + extends ContainerConnectionDetailsFactory, Neo4jConnectionDetails> { + + DeprecatedNeo4jContainerConnectionDetailsFactory() { + super(ANY_CONNECTION_NAME, "org.neo4j.driver.AuthToken"); + } + + @Override + protected Neo4jConnectionDetails getContainerConnectionDetails( + ContainerConnectionSource> source) { + return new Neo4jContainerConnectionDetails(source); + } + + /** + * {@link Neo4jConnectionDetails} backed by a {@link ContainerConnectionSource}. + */ + private static final class Neo4jContainerConnectionDetails extends ContainerConnectionDetails> + implements Neo4jConnectionDetails { + + private Neo4jContainerConnectionDetails(ContainerConnectionSource> source) { + super(source); + } + + @Override + public URI getUri() { + return URI.create(getContainer().getBoltUrl()); + } + + @Override + public AuthToken getAuthToken() { + String password = getContainer().getAdminPassword(); + return (password != null) ? AuthTokens.basic("neo4j", password) : AuthTokens.none(); + } + + } + +} diff --git a/module/spring-boot-neo4j/src/main/resources/META-INF/spring.factories b/module/spring-boot-neo4j/src/main/resources/META-INF/spring.factories index 98d3b5dfdbe..70daabc504b 100644 --- a/module/spring-boot-neo4j/src/main/resources/META-INF/spring.factories +++ b/module/spring-boot-neo4j/src/main/resources/META-INF/spring.factories @@ -1,4 +1,5 @@ # Connection Details Factories org.springframework.boot.autoconfigure.service.connection.ConnectionDetailsFactory=\ org.springframework.boot.neo4j.docker.compose.Neo4jDockerComposeConnectionDetailsFactory,\ +org.springframework.boot.neo4j.testcontainers.DeprecatedNeo4jContainerConnectionDetailsFactory,\ org.springframework.boot.neo4j.testcontainers.Neo4jContainerConnectionDetailsFactory diff --git a/module/spring-boot-pulsar/src/dockerTest/java/org/springframework/boot/pulsar/testcontainers/DeprecatedPulsarContainerConnectionDetailsFactoryIntegrationTests.java b/module/spring-boot-pulsar/src/dockerTest/java/org/springframework/boot/pulsar/testcontainers/DeprecatedPulsarContainerConnectionDetailsFactoryIntegrationTests.java new file mode 100644 index 00000000000..ec1edb553b3 --- /dev/null +++ b/module/spring-boot-pulsar/src/dockerTest/java/org/springframework/boot/pulsar/testcontainers/DeprecatedPulsarContainerConnectionDetailsFactoryIntegrationTests.java @@ -0,0 +1,97 @@ +/* + * Copyright 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.pulsar.testcontainers; + +import java.time.Duration; +import java.util.ArrayList; +import java.util.List; + +import org.awaitility.Awaitility; +import org.junit.jupiter.api.Test; +import org.testcontainers.containers.PulsarContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.ImportAutoConfiguration; +import org.springframework.boot.pulsar.autoconfigure.PulsarAutoConfiguration; +import org.springframework.boot.testcontainers.service.connection.ServiceConnection; +import org.springframework.boot.testsupport.container.TestImage; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.pulsar.annotation.PulsarListener; +import org.springframework.pulsar.core.PulsarTemplate; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link DeprecatedPulsarContainerConnectionDetailsFactory}. + * + * @author Chris Bono + * @author Stephane Nicoll + * @deprecated since 4.0.0 for removal in 4.2.0 in favor of + * {@link PulsarContainerConnectionDetailsFactory}. + */ +@SpringJUnitConfig +@Testcontainers(disabledWithoutDocker = true) +@TestPropertySource(properties = { "spring.pulsar.consumer.subscription.initial-position=earliest" }) +@Deprecated(since = "4.0.0", forRemoval = true) +class DeprecatedPulsarContainerConnectionDetailsFactoryIntegrationTests { + + @Container + @ServiceConnection + @SuppressWarnings("unused") + static final PulsarContainer pulsar = TestImage.container(PulsarContainer.class); + + @Autowired + private PulsarTemplate pulsarTemplate; + + @Autowired + private TestListener listener; + + @Test + void connectionCanBeMadeToPulsarContainer() { + this.pulsarTemplate.send("test-topic", "test-data"); + Awaitility.waitAtMost(Duration.ofSeconds(30)) + .untilAsserted(() -> assertThat(this.listener.messages).containsExactly("test-data")); + } + + @Configuration(proxyBeanMethods = false) + @ImportAutoConfiguration(PulsarAutoConfiguration.class) + static class TestConfiguration { + + @Bean + TestListener testListener() { + return new TestListener(); + } + + } + + static class TestListener { + + private final List messages = new ArrayList<>(); + + @PulsarListener(topics = "test-topic") + void processMessage(String message) { + this.messages.add(message); + } + + } + +} diff --git a/module/spring-boot-pulsar/src/main/java/org/springframework/boot/pulsar/testcontainers/DeprecatedPulsarContainerConnectionDetailsFactory.java b/module/spring-boot-pulsar/src/main/java/org/springframework/boot/pulsar/testcontainers/DeprecatedPulsarContainerConnectionDetailsFactory.java new file mode 100644 index 00000000000..46ba6a8a2e7 --- /dev/null +++ b/module/spring-boot-pulsar/src/main/java/org/springframework/boot/pulsar/testcontainers/DeprecatedPulsarContainerConnectionDetailsFactory.java @@ -0,0 +1,65 @@ +/* + * Copyright 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.pulsar.testcontainers; + +import org.testcontainers.containers.PulsarContainer; + +import org.springframework.boot.pulsar.autoconfigure.PulsarConnectionDetails; +import org.springframework.boot.testcontainers.service.connection.ContainerConnectionDetailsFactory; +import org.springframework.boot.testcontainers.service.connection.ContainerConnectionSource; +import org.springframework.boot.testcontainers.service.connection.ServiceConnection; + +/** + * {@link ContainerConnectionDetailsFactory} to create {@link PulsarConnectionDetails} + * from a {@link ServiceConnection @ServiceConnection}-annotated {@link PulsarContainer}. + * + * @author Chris Bono + * @deprecated since 4.0.0 for removal in 4.2.0 in favor of + * {@link PulsarContainerConnectionDetailsFactory}. + */ +@Deprecated(since = "4.0.0", forRemoval = true) +class DeprecatedPulsarContainerConnectionDetailsFactory + extends ContainerConnectionDetailsFactory { + + @Override + protected PulsarConnectionDetails getContainerConnectionDetails(ContainerConnectionSource source) { + return new PulsarContainerConnectionDetails(source); + } + + /** + * {@link PulsarConnectionDetails} backed by a {@link ContainerConnectionSource}. + */ + private static final class PulsarContainerConnectionDetails extends ContainerConnectionDetails + implements PulsarConnectionDetails { + + private PulsarContainerConnectionDetails(ContainerConnectionSource source) { + super(source); + } + + @Override + public String getBrokerUrl() { + return getContainer().getPulsarBrokerUrl(); + } + + @Override + public String getAdminUrl() { + return getContainer().getHttpServiceUrl(); + } + + } + +} diff --git a/module/spring-boot-pulsar/src/main/resources/META-INF/spring.factories b/module/spring-boot-pulsar/src/main/resources/META-INF/spring.factories index ceb868e08f0..b04e3949dce 100644 --- a/module/spring-boot-pulsar/src/main/resources/META-INF/spring.factories +++ b/module/spring-boot-pulsar/src/main/resources/META-INF/spring.factories @@ -1,4 +1,5 @@ # Connection Details Factories org.springframework.boot.autoconfigure.service.connection.ConnectionDetailsFactory=\ org.springframework.boot.pulsar.docker.compose.PulsarDockerComposeConnectionDetailsFactory,\ +org.springframework.boot.pulsar.testcontainers.DeprecatedPulsarContainerConnectionDetailsFactory,\ org.springframework.boot.pulsar.testcontainers.PulsarContainerConnectionDetailsFactory diff --git a/module/spring-boot-r2dbc/src/main/java/org/springframework/boot/r2dbc/testcontainers/DeprecatedMariaDbR2dbcContainerConnectionDetailsFactory.java b/module/spring-boot-r2dbc/src/main/java/org/springframework/boot/r2dbc/testcontainers/DeprecatedMariaDbR2dbcContainerConnectionDetailsFactory.java new file mode 100644 index 00000000000..f25f4f27347 --- /dev/null +++ b/module/spring-boot-r2dbc/src/main/java/org/springframework/boot/r2dbc/testcontainers/DeprecatedMariaDbR2dbcContainerConnectionDetailsFactory.java @@ -0,0 +1,68 @@ +/* + * Copyright 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.r2dbc.testcontainers; + +import io.r2dbc.spi.ConnectionFactoryOptions; +import org.testcontainers.containers.MariaDBContainer; +import org.testcontainers.containers.MariaDBR2DBCDatabaseContainer; + +import org.springframework.boot.r2dbc.autoconfigure.R2dbcConnectionDetails; +import org.springframework.boot.testcontainers.service.connection.ContainerConnectionDetailsFactory; +import org.springframework.boot.testcontainers.service.connection.ContainerConnectionSource; +import org.springframework.boot.testcontainers.service.connection.ServiceConnection; + +/** + * {@link ContainerConnectionDetailsFactory} to create {@link R2dbcConnectionDetails} from + * a {@link ServiceConnection @ServiceConnection}-annotated {@link MariaDBContainer}. + * + * @author Moritz Halbritter + * @author Andy Wilkinson + * @author Phillip Webb + * @deprecated since 4.0.0 for removal in 4.2.0 in favor of + * {@link MariaDbR2dbcContainerConnectionDetailsFactory}. + */ +@Deprecated(since = "4.0.0", forRemoval = true) +class DeprecatedMariaDbR2dbcContainerConnectionDetailsFactory + extends ContainerConnectionDetailsFactory, R2dbcConnectionDetails> { + + DeprecatedMariaDbR2dbcContainerConnectionDetailsFactory() { + super(ANY_CONNECTION_NAME, "io.r2dbc.spi.ConnectionFactoryOptions"); + } + + @Override + public R2dbcConnectionDetails getContainerConnectionDetails(ContainerConnectionSource> source) { + return new MariaDbR2dbcDatabaseContainerConnectionDetails(source); + } + + /** + * {@link R2dbcConnectionDetails} backed by a {@link ContainerConnectionSource}. + */ + private static final class MariaDbR2dbcDatabaseContainerConnectionDetails + extends ContainerConnectionDetails> implements R2dbcConnectionDetails { + + private MariaDbR2dbcDatabaseContainerConnectionDetails(ContainerConnectionSource> source) { + super(source); + } + + @Override + public ConnectionFactoryOptions getConnectionFactoryOptions() { + return MariaDBR2DBCDatabaseContainer.getOptions(getContainer()); + } + + } + +} diff --git a/module/spring-boot-r2dbc/src/main/java/org/springframework/boot/r2dbc/testcontainers/DeprecatedMySqlR2dbcContainerConnectionDetailsFactory.java b/module/spring-boot-r2dbc/src/main/java/org/springframework/boot/r2dbc/testcontainers/DeprecatedMySqlR2dbcContainerConnectionDetailsFactory.java new file mode 100644 index 00000000000..f926b5bc6dc --- /dev/null +++ b/module/spring-boot-r2dbc/src/main/java/org/springframework/boot/r2dbc/testcontainers/DeprecatedMySqlR2dbcContainerConnectionDetailsFactory.java @@ -0,0 +1,68 @@ +/* + * Copyright 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.r2dbc.testcontainers; + +import io.r2dbc.spi.ConnectionFactoryOptions; +import org.testcontainers.containers.MySQLContainer; +import org.testcontainers.containers.MySQLR2DBCDatabaseContainer; + +import org.springframework.boot.r2dbc.autoconfigure.R2dbcConnectionDetails; +import org.springframework.boot.testcontainers.service.connection.ContainerConnectionDetailsFactory; +import org.springframework.boot.testcontainers.service.connection.ContainerConnectionSource; +import org.springframework.boot.testcontainers.service.connection.ServiceConnection; + +/** + * {@link ContainerConnectionDetailsFactory} to create {@link R2dbcConnectionDetails} from + * a {@link ServiceConnection @ServiceConnection}-annotated {@link MySQLContainer}. + * + * @author Moritz Halbritter + * @author Andy Wilkinson + * @author Phillip Webb + * @deprecated since 4.0.0 for removal in 4.2.0 in favor of + * {@link MySqlR2dbcContainerConnectionDetailsFactory}. + */ +@Deprecated(since = "4.0.0", forRemoval = true) +class DeprecatedMySqlR2dbcContainerConnectionDetailsFactory + extends ContainerConnectionDetailsFactory, R2dbcConnectionDetails> { + + DeprecatedMySqlR2dbcContainerConnectionDetailsFactory() { + super(ANY_CONNECTION_NAME, "io.r2dbc.spi.ConnectionFactoryOptions"); + } + + @Override + public R2dbcConnectionDetails getContainerConnectionDetails(ContainerConnectionSource> source) { + return new MySqlR2dbcDatabaseContainerConnectionDetails(source); + } + + /** + * {@link R2dbcConnectionDetails} backed by a {@link ContainerConnectionSource}. + */ + private static final class MySqlR2dbcDatabaseContainerConnectionDetails + extends ContainerConnectionDetails> implements R2dbcConnectionDetails { + + private MySqlR2dbcDatabaseContainerConnectionDetails(ContainerConnectionSource> source) { + super(source); + } + + @Override + public ConnectionFactoryOptions getConnectionFactoryOptions() { + return MySQLR2DBCDatabaseContainer.getOptions(getContainer()); + } + + } + +} diff --git a/module/spring-boot-r2dbc/src/main/java/org/springframework/boot/r2dbc/testcontainers/DeprecatedPostgresR2dbcContainerConnectionDetailsFactory.java b/module/spring-boot-r2dbc/src/main/java/org/springframework/boot/r2dbc/testcontainers/DeprecatedPostgresR2dbcContainerConnectionDetailsFactory.java new file mode 100644 index 00000000000..d8ee6ba41f4 --- /dev/null +++ b/module/spring-boot-r2dbc/src/main/java/org/springframework/boot/r2dbc/testcontainers/DeprecatedPostgresR2dbcContainerConnectionDetailsFactory.java @@ -0,0 +1,69 @@ +/* + * Copyright 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.r2dbc.testcontainers; + +import io.r2dbc.spi.ConnectionFactoryOptions; +import org.testcontainers.containers.PostgreSQLContainer; +import org.testcontainers.containers.PostgreSQLR2DBCDatabaseContainer; + +import org.springframework.boot.r2dbc.autoconfigure.R2dbcConnectionDetails; +import org.springframework.boot.testcontainers.service.connection.ContainerConnectionDetailsFactory; +import org.springframework.boot.testcontainers.service.connection.ContainerConnectionSource; +import org.springframework.boot.testcontainers.service.connection.ServiceConnection; + +/** + * {@link ContainerConnectionDetailsFactory} to create {@link R2dbcConnectionDetails} from + * a {@link ServiceConnection @ServiceConnection}-annotated {@link PostgreSQLContainer}. + * + * @author Moritz Halbritter + * @author Andy Wilkinson + * @author Phillip Webb + * @deprecated since 4.0.0 for removal in 4.2.0 in favor of + * {@link PostgresR2dbcContainerConnectionDetailsFactory}. + */ +@Deprecated(since = "4.0.0", forRemoval = true) +class DeprecatedPostgresR2dbcContainerConnectionDetailsFactory + extends ContainerConnectionDetailsFactory, R2dbcConnectionDetails> { + + DeprecatedPostgresR2dbcContainerConnectionDetailsFactory() { + super(ANY_CONNECTION_NAME, "io.r2dbc.spi.ConnectionFactoryOptions"); + } + + @Override + public R2dbcConnectionDetails getContainerConnectionDetails( + ContainerConnectionSource> source) { + return new PostgresR2dbcDatabaseContainerConnectionDetails(source); + } + + /** + * {@link R2dbcConnectionDetails} backed by a {@link ContainerConnectionSource}. + */ + private static final class PostgresR2dbcDatabaseContainerConnectionDetails + extends ContainerConnectionDetails> implements R2dbcConnectionDetails { + + PostgresR2dbcDatabaseContainerConnectionDetails(ContainerConnectionSource> source) { + super(source); + } + + @Override + public ConnectionFactoryOptions getConnectionFactoryOptions() { + return PostgreSQLR2DBCDatabaseContainer.getOptions(getContainer()); + } + + } + +} diff --git a/module/spring-boot-r2dbc/src/main/java/org/springframework/boot/r2dbc/testcontainers/DeprecatedSqlServerR2dbcContainerConnectionDetailsFactory.java b/module/spring-boot-r2dbc/src/main/java/org/springframework/boot/r2dbc/testcontainers/DeprecatedSqlServerR2dbcContainerConnectionDetailsFactory.java new file mode 100644 index 00000000000..b9efcc9457a --- /dev/null +++ b/module/spring-boot-r2dbc/src/main/java/org/springframework/boot/r2dbc/testcontainers/DeprecatedSqlServerR2dbcContainerConnectionDetailsFactory.java @@ -0,0 +1,70 @@ +/* + * Copyright 2012-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.r2dbc.testcontainers; + +import io.r2dbc.spi.ConnectionFactoryOptions; +import org.testcontainers.containers.MSSQLR2DBCDatabaseContainer; +import org.testcontainers.containers.MSSQLServerContainer; + +import org.springframework.boot.r2dbc.autoconfigure.R2dbcConnectionDetails; +import org.springframework.boot.testcontainers.service.connection.ContainerConnectionDetailsFactory; +import org.springframework.boot.testcontainers.service.connection.ContainerConnectionSource; +import org.springframework.boot.testcontainers.service.connection.ServiceConnection; + +/** + * {@link ContainerConnectionDetailsFactory} to create {@link R2dbcConnectionDetails} from + * a {@link ServiceConnection @ServiceConnection}-annotated {@link MSSQLServerContainer}. + * + * @author Moritz Halbritter + * @author Andy Wilkinson + * @author Phillip Webb + * @deprecated since 4.0.0 for removal in 4.2.0 in favor of + * {@link SqlServerR2dbcContainerConnectionDetailsFactory}. + */ +@Deprecated(since = "4.0.0", forRemoval = true) +class DeprecatedSqlServerR2dbcContainerConnectionDetailsFactory + extends ContainerConnectionDetailsFactory, R2dbcConnectionDetails> { + + DeprecatedSqlServerR2dbcContainerConnectionDetailsFactory() { + super(ANY_CONNECTION_NAME, "io.r2dbc.spi.ConnectionFactoryOptions"); + } + + @Override + public R2dbcConnectionDetails getContainerConnectionDetails( + ContainerConnectionSource> source) { + return new MsSqlServerR2dbcDatabaseContainerConnectionDetails(source); + } + + /** + * {@link R2dbcConnectionDetails} backed by a {@link ContainerConnectionSource}. + */ + private static final class MsSqlServerR2dbcDatabaseContainerConnectionDetails + extends ContainerConnectionDetails> implements R2dbcConnectionDetails { + + private MsSqlServerR2dbcDatabaseContainerConnectionDetails( + ContainerConnectionSource> source) { + super(source); + } + + @Override + public ConnectionFactoryOptions getConnectionFactoryOptions() { + return MSSQLR2DBCDatabaseContainer.getOptions(getContainer()); + } + + } + +} diff --git a/module/spring-boot-r2dbc/src/main/resources/META-INF/spring.factories b/module/spring-boot-r2dbc/src/main/resources/META-INF/spring.factories index 92eacd6c66f..b71026ca9c7 100644 --- a/module/spring-boot-r2dbc/src/main/resources/META-INF/spring.factories +++ b/module/spring-boot-r2dbc/src/main/resources/META-INF/spring.factories @@ -8,6 +8,10 @@ org.springframework.boot.r2dbc.docker.compose.OracleXeR2dbcDockerComposeConnecti org.springframework.boot.r2dbc.docker.compose.PostgresR2dbcDockerComposeConnectionDetailsFactory,\ org.springframework.boot.r2dbc.docker.compose.SqlServerR2dbcDockerComposeConnectionDetailsFactory,\ org.springframework.boot.r2dbc.testcontainers.ClickHouseR2dbcContainerConnectionDetailsFactory,\ +org.springframework.boot.r2dbc.testcontainers.DeprecatedMariaDbR2dbcContainerConnectionDetailsFactory,\ +org.springframework.boot.r2dbc.testcontainers.DeprecatedMySqlR2dbcContainerConnectionDetailsFactory,\ +org.springframework.boot.r2dbc.testcontainers.DeprecatedPostgresR2dbcContainerConnectionDetailsFactory,\ +org.springframework.boot.r2dbc.testcontainers.DeprecatedSqlServerR2dbcContainerConnectionDetailsFactory,\ org.springframework.boot.r2dbc.testcontainers.MariaDbR2dbcContainerConnectionDetailsFactory,\ org.springframework.boot.r2dbc.testcontainers.MySqlR2dbcContainerConnectionDetailsFactory,\ org.springframework.boot.r2dbc.testcontainers.OracleFreeR2dbcContainerConnectionDetailsFactory,\ diff --git a/test-support/spring-boot-docker-test-support/src/main/java/org/springframework/boot/testsupport/container/TestImage.java b/test-support/spring-boot-docker-test-support/src/main/java/org/springframework/boot/testsupport/container/TestImage.java index 0f930d19bc8..e17094ef812 100644 --- a/test-support/spring-boot-docker-test-support/src/main/java/org/springframework/boot/testsupport/container/TestImage.java +++ b/test-support/spring-boot-docker-test-support/src/main/java/org/springframework/boot/testsupport/container/TestImage.java @@ -160,6 +160,16 @@ public enum TestImage { (container) -> ((MongoDBContainer) container).withStartupAttempts(5) .withStartupTimeout(Duration.ofMinutes(5))), + /** + * A container image suitable for testing MongoDB using the deprecated + * {@link org.testcontainers.containers.MongoDBContainer}. + * @deprecated since 4.0.0 for removal in 4.2.0 in favor of {@link #MONGODB} + */ + @Deprecated(since = "3.4.0", forRemoval = true) + MONGODB_DEPRECATED("mongo", "5.0.17", () -> org.testcontainers.containers.MongoDBContainer.class, + (container) -> ((org.testcontainers.containers.MongoDBContainer) container).withStartupAttempts(5) + .withStartupTimeout(Duration.ofMinutes(5))), + /** * A container image suitable for testing MongoDB Atlas. */ @@ -179,6 +189,16 @@ public enum TestImage { (container) -> ((Neo4jContainer) container).withStartupAttempts(5) .withStartupTimeout(Duration.ofMinutes(10))), + /** + * A container image suitable for testing Neo4j using the deprecated + * {@link org.testcontainers.containers.Neo4jContainer}. + * @deprecated since 4.0.0 for removal in 4.2.0 in favor of {@link #NEO4J} + */ + @Deprecated(since = "3.4.0", forRemoval = true) + NEO4J_DEPRECATED("neo4j", "5.26.11", () -> org.testcontainers.containers.Neo4jContainer.class, + (container) -> ((org.testcontainers.containers.Neo4jContainer) container).withStartupAttempts(5) + .withStartupTimeout(Duration.ofMinutes(10))), + /** * A container image suitable for testing Oracle Free. */ @@ -210,12 +230,32 @@ public enum TestImage { (container) -> ((PulsarContainer) container).withStartupAttempts(2) .withStartupTimeout(Duration.ofMinutes(3))), + /** + * A container image suitable for testing Pulsar using the deprecated + * {@link org.testcontainers.containers.PulsarContainer}. + * @deprecated since 4.0.0 for removal in 4.2.0 in favor of {@link #PULSAR} + */ + @Deprecated(since = "3.4.0", forRemoval = true) + PULSAR_DEPRECATED("apachepulsar/pulsar", "3.3.3", () -> org.testcontainers.containers.PulsarContainer.class, + (container) -> ((org.testcontainers.containers.PulsarContainer) container).withStartupAttempts(2) + .withStartupTimeout(Duration.ofMinutes(3))), + /** * A container image suitable for testing RabbitMQ. */ RABBITMQ("rabbitmq", "3.11-alpine", () -> RabbitMQContainer.class, (container) -> ((RabbitMQContainer) container).withStartupTimeout(Duration.ofMinutes(4))), + /** + * A container image suitable for testing RabbitMQ using the deprecated + * {@link org.testcontainers.containers.RabbitMQContainer}. + * @deprecated since 4.0.0 for removal in 4.2.0 in favor of {@link #RABBITMQ} + */ + @Deprecated(since = "3.4.0", forRemoval = true) + RABBITMQ_DEPRECATED("rabbitmq", "3.11-alpine", () -> org.testcontainers.containers.RabbitMQContainer.class, + (container) -> ((org.testcontainers.containers.RabbitMQContainer) container) + .withStartupTimeout(Duration.ofMinutes(4))), + /** * A container image suitable for testing Redis. */