diff --git a/start-site/src/main/java/io/spring/start/site/container/SimpleDockerServiceResolver.java b/start-site/src/main/java/io/spring/start/site/container/SimpleDockerServiceResolver.java index bb5ec99a7c..664c23cffb 100644 --- a/start-site/src/main/java/io/spring/start/site/container/SimpleDockerServiceResolver.java +++ b/start-site/src/main/java/io/spring/start/site/container/SimpleDockerServiceResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -26,6 +26,7 @@ * @author Stephane Nicoll * @author Moritz Halbritter * @author Chris Bono + * @author Eddú Meléndez */ public class SimpleDockerServiceResolver implements DockerServiceResolver { @@ -34,6 +35,8 @@ public class SimpleDockerServiceResolver implements DockerServiceResolver { public SimpleDockerServiceResolver() { this.dockerServices = new HashMap<>(); this.dockerServices.put("activeMQ", activeMQ()); + this.dockerServices.put("activeMQClassic", activeMQClassic()); + this.dockerServices.put("artemis", artemis()); this.dockerServices.put("cassandra", cassandra()); this.dockerServices.put("elasticsearch", elasticsearch()); this.dockerServices.put("kafka", kafka()); @@ -57,6 +60,20 @@ private static DockerService activeMQ() { .build(); } + private static DockerService activeMQClassic() { + return DockerService.withImageAndTag("apache/activemq-classic") + .website("https://hub.docker.com/r/apache/activemq-classic") + .ports(61616) + .build(); + } + + private static DockerService artemis() { + return DockerService.withImageAndTag("apache/activemq-artemis") + .website("https://hub.docker.com/r/apache/activemq-artemis") + .ports(61616) + .build(); + } + private static DockerService cassandra() { return DockerService.withImageAndTag("cassandra") .website("https://hub.docker.com/_/cassandra") diff --git a/start-site/src/main/java/io/spring/start/site/extension/dependency/activemq/ActiveMQProjectGenerationConfiguration.java b/start-site/src/main/java/io/spring/start/site/extension/dependency/activemq/ActiveMQProjectGenerationConfiguration.java index 211130656c..aa349cbbb3 100644 --- a/start-site/src/main/java/io/spring/start/site/extension/dependency/activemq/ActiveMQProjectGenerationConfiguration.java +++ b/start-site/src/main/java/io/spring/start/site/extension/dependency/activemq/ActiveMQProjectGenerationConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -35,8 +35,10 @@ @ConditionalOnRequestedDependency("activemq") public class ActiveMQProjectGenerationConfiguration { + private static final String TESTCONTAINERS_CLASS_NAME = "org.testcontainers.activemq.ActiveMQContainer"; + @Bean - @ConditionalOnPlatformVersion("3.2.0-M1") + @ConditionalOnPlatformVersion("[3.2.0-M1,3.3.0-M2)") @ConditionalOnRequestedDependency("testcontainers") ServiceConnectionsCustomizer activeMQServiceConnectionsCustomizer(DockerServiceResolver serviceResolver) { return (serviceConnections) -> serviceResolver.doWith("activeMQ", (service) -> serviceConnections @@ -44,11 +46,28 @@ ServiceConnectionsCustomizer activeMQServiceConnectionsCustomizer(DockerServiceR } @Bean - @ConditionalOnPlatformVersion("3.2.0-M1") + @ConditionalOnPlatformVersion("3.3.0-M2") + @ConditionalOnRequestedDependency("testcontainers") + ServiceConnectionsCustomizer activeMQClassicServiceConnectionsCustomizer(DockerServiceResolver serviceResolver) { + return (serviceConnections) -> serviceResolver.doWith("activeMQClassic", + (service) -> serviceConnections.addServiceConnection( + ServiceConnection.ofContainer("activemq", service, TESTCONTAINERS_CLASS_NAME, false))); + } + + @Bean + @ConditionalOnPlatformVersion("[3.2.0-M1,3.3.0-M2)") @ConditionalOnRequestedDependency("docker-compose") ComposeFileCustomizer activeMQComposeFileCustomizer(DockerServiceResolver serviceResolver) { return (composeFile) -> serviceResolver.doWith("activeMQ", (service) -> composeFile.services().add("activemq", service)); } + @Bean + @ConditionalOnPlatformVersion("3.3.0-M2") + @ConditionalOnRequestedDependency("docker-compose") + ComposeFileCustomizer activeMQClassicComposeFileCustomizer(DockerServiceResolver serviceResolver) { + return (composeFile) -> serviceResolver.doWith("activeMQClassic", + (service) -> composeFile.services().add("activemq", service)); + } + } diff --git a/start-site/src/main/java/io/spring/start/site/extension/dependency/activemq/ArtemisProjectGenerationConfiguration.java b/start-site/src/main/java/io/spring/start/site/extension/dependency/activemq/ArtemisProjectGenerationConfiguration.java new file mode 100644 index 0000000000..d3e21c771d --- /dev/null +++ b/start-site/src/main/java/io/spring/start/site/extension/dependency/activemq/ArtemisProjectGenerationConfiguration.java @@ -0,0 +1,56 @@ +/* + * Copyright 2012-2024 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 io.spring.start.site.extension.dependency.activemq; + +import io.spring.initializr.generator.condition.ConditionalOnPlatformVersion; +import io.spring.initializr.generator.condition.ConditionalOnRequestedDependency; +import io.spring.initializr.generator.project.ProjectGenerationConfiguration; +import io.spring.start.site.container.ComposeFileCustomizer; +import io.spring.start.site.container.DockerServiceResolver; +import io.spring.start.site.container.ServiceConnections.ServiceConnection; +import io.spring.start.site.container.ServiceConnectionsCustomizer; + +import org.springframework.context.annotation.Bean; + +/** + * Configuration for generation of projects that depend on ActiveMQ Artemis. + * + * @author Eddú Meléndez + */ +@ProjectGenerationConfiguration +@ConditionalOnRequestedDependency("artemis") +public class ArtemisProjectGenerationConfiguration { + + private static final String TESTCONTAINERS_CLASS_NAME = "org.testcontainers.activemq.ArtemisContainer"; + + @Bean + @ConditionalOnPlatformVersion("3.3.0-M2") + @ConditionalOnRequestedDependency("testcontainers") + ServiceConnectionsCustomizer artemisServiceConnectionsCustomizer(DockerServiceResolver serviceResolver) { + return (serviceConnections) -> serviceResolver.doWith("artemis", (service) -> serviceConnections + .addServiceConnection(ServiceConnection.ofContainer("artemis", service, TESTCONTAINERS_CLASS_NAME, false))); + } + + @Bean + @ConditionalOnPlatformVersion("3.3.0-M2") + @ConditionalOnRequestedDependency("docker-compose") + ComposeFileCustomizer artemisComposeFileCustomizer(DockerServiceResolver serviceResolver) { + return (composeFile) -> serviceResolver.doWith("artemis", + (service) -> composeFile.services().add("artemis", service)); + } + +} diff --git a/start-site/src/main/java/io/spring/start/site/extension/dependency/testcontainers/TestcontainersModuleRegistry.java b/start-site/src/main/java/io/spring/start/site/extension/dependency/testcontainers/TestcontainersModuleRegistry.java index 8e7b7edc9b..c76d5649aa 100644 --- a/start-site/src/main/java/io/spring/start/site/extension/dependency/testcontainers/TestcontainersModuleRegistry.java +++ b/start-site/src/main/java/io/spring/start/site/extension/dependency/testcontainers/TestcontainersModuleRegistry.java @@ -42,8 +42,16 @@ abstract class TestcontainersModuleRegistry { private static final VersionRange SPRING_BOOT_3_2_0_OR_LATER = VersionParser.DEFAULT.parseRange("3.2.0"); + private static final VersionRange SPRING_BOOT_3_3_0_M2_OR_LATER = VersionParser.DEFAULT.parseRange("3.3.0-M2"); + static Iterable create(Version platformVersion) { List builders = new ArrayList<>(); + if (SPRING_BOOT_3_3_0_M2_OR_LATER.match(platformVersion)) { + builders.add(onDependencies("activemq").customizeBuild(addModule("activemq")) + .customizeHelpDocument(addReferenceLink("ActiveMQ Module", "activemq/"))); + builders.add(onDependencies("artemis").customizeBuild(addModule("activemq")) + .customizeHelpDocument(addReferenceLink("ActiveMQ Module", "activemq/"))); + } builders.add(onDependencies("amqp", "amqp-streams").customizeBuild(addModule("rabbitmq")) .customizeHelpDocument(addReferenceLink("RabbitMQ Module", "rabbitmq/"))); builders.add(onDependencies("cloud-gcp", "cloud-gcp-pubsub").customizeBuild(addModule("gcloud")) diff --git a/start-site/src/main/resources/META-INF/spring.factories b/start-site/src/main/resources/META-INF/spring.factories index 0a290ecb12..c38749dbbf 100644 --- a/start-site/src/main/resources/META-INF/spring.factories +++ b/start-site/src/main/resources/META-INF/spring.factories @@ -3,6 +3,7 @@ io.spring.start.site.extension.build.gradle.GradleProjectGenerationConfiguration io.spring.start.site.extension.build.maven.MavenProjectGenerationConfiguration,\ io.spring.start.site.extension.dependency.DependencyProjectGenerationConfiguration,\ io.spring.start.site.extension.dependency.activemq.ActiveMQProjectGenerationConfiguration,\ +io.spring.start.site.extension.dependency.activemq.ArtemisProjectGenerationConfiguration,\ io.spring.start.site.extension.dependency.cassandra.CassandraProjectGenerationConfiguration,\ io.spring.start.site.extension.dependency.derby.DerbyProjectGenerationConfiguration,\ io.spring.start.site.extension.dependency.dgs.DgsCodegenProjectGenerationConfiguration,\ diff --git a/start-site/src/test/java/io/spring/start/site/extension/dependency/activemq/ActiveMQProjectGenerationConfigurationTests.java b/start-site/src/test/java/io/spring/start/site/extension/dependency/activemq/ActiveMQProjectGenerationConfigurationTests.java index c965a755cc..1ec6dc0a95 100644 --- a/start-site/src/test/java/io/spring/start/site/extension/dependency/activemq/ActiveMQProjectGenerationConfigurationTests.java +++ b/start-site/src/test/java/io/spring/start/site/extension/dependency/activemq/ActiveMQProjectGenerationConfigurationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2024 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. @@ -29,6 +29,7 @@ * Tests for {@link ActiveMQProjectGenerationConfiguration}. * * @author Stephane Nicoll + * @author Eddú Meléndez */ class ActiveMQProjectGenerationConfigurationTests extends AbstractExtensionTests { @@ -54,4 +55,11 @@ void dockerComposeCreatesAppropriateService() { assertThat(composeFile(request)).hasSameContentAs(new ClassPathResource("compose/activemq.yaml")); } + @Test + void dockerComposeCreatesAppropriateServiceWithVersion33() { + ProjectRequest request = createProjectRequest("docker-compose", "activemq"); + request.setBootVersion("3.3.0-M2"); + assertThat(composeFile(request)).hasSameContentAs(new ClassPathResource("compose/activemq-classic.yaml")); + } + } diff --git a/start-site/src/test/java/io/spring/start/site/extension/dependency/activemq/ArtemisProjectGenerationConfigurationTests.java b/start-site/src/test/java/io/spring/start/site/extension/dependency/activemq/ArtemisProjectGenerationConfigurationTests.java new file mode 100644 index 0000000000..2d31059658 --- /dev/null +++ b/start-site/src/test/java/io/spring/start/site/extension/dependency/activemq/ArtemisProjectGenerationConfigurationTests.java @@ -0,0 +1,57 @@ +/* + * Copyright 2012-2024 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 io.spring.start.site.extension.dependency.activemq; + +import io.spring.initializr.generator.test.project.ProjectStructure; +import io.spring.initializr.web.project.ProjectRequest; +import io.spring.start.site.extension.AbstractExtensionTests; +import org.junit.jupiter.api.Test; + +import org.springframework.core.io.ClassPathResource; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link ArtemisProjectGenerationConfiguration}. + * + * @author Eddú Meléndez + */ +class ArtemisProjectGenerationConfigurationTests extends AbstractExtensionTests { + + @Test + void dockerComposeWhenDockerComposeIsNotSelectedDoesNotCreateService() { + ProjectRequest request = createProjectRequest("web", "artemis"); + request.setBootVersion("3.3.0-M2"); + ProjectStructure structure = generateProject(request); + assertThat(structure.getProjectDirectory().resolve("compose.yaml")).doesNotExist(); + } + + @Test + void dockerComposeWhenIncompatibleSpringBootVersionDoesNotCreateService() { + ProjectRequest request = createProjectRequest("docker-compose", "artemis"); + request.setBootVersion("3.1.1"); + assertThat(composeFile(request)).doesNotContain("artemis"); + } + + @Test + void dockerComposeCreatesAppropriateService() { + ProjectRequest request = createProjectRequest("docker-compose", "artemis"); + request.setBootVersion("3.3.0-M2"); + assertThat(composeFile(request)).hasSameContentAs(new ClassPathResource("compose/artemis.yaml")); + } + +} diff --git a/start-site/src/test/java/io/spring/start/site/extension/dependency/testcontainers/TestcontainersProjectGenerationConfigurationTests.java b/start-site/src/test/java/io/spring/start/site/extension/dependency/testcontainers/TestcontainersProjectGenerationConfigurationTests.java index 929ff8a9b7..335a85f8c0 100644 --- a/start-site/src/test/java/io/spring/start/site/extension/dependency/testcontainers/TestcontainersProjectGenerationConfigurationTests.java +++ b/start-site/src/test/java/io/spring/start/site/extension/dependency/testcontainers/TestcontainersProjectGenerationConfigurationTests.java @@ -65,6 +65,17 @@ void buildWithSpringBoot32AndOracleJdbcDriverUsesOracleFree() { .hasDependency(getDependency("testcontainers")); } + @ParameterizedTest + @MethodSource("supportedTestcontainersActiveMQEntriesBuild") + void buildWithSpringBoot33AndTestcontainersActiveMQModule(String springBootDependencyId, + String testcontainersArtifactId) { + assertThat(generateProject("3.3.0", "testcontainers", springBootDependencyId)).mavenBuild() + .doesNotHaveBom("org.testcontainers", "testcontainers-bom") + .hasDependency(getDependency(springBootDependencyId).resolve(Version.parse("3.3.0"))) + .hasDependency("org.testcontainers", testcontainersArtifactId, null, "test") + .hasDependency(getDependency("testcontainers")); + } + static Stream supportedEntriesBuild() { return Stream.of(Arguments.arguments("amqp", "rabbitmq"), Arguments.of("amqp-streams", "rabbitmq"), Arguments.arguments("cloud-gcp", "gcloud"), Arguments.arguments("cloud-gcp-pubsub", "gcloud"), @@ -83,6 +94,10 @@ static Stream supportedEntriesBuild() { Arguments.arguments("sqlserver", "mssqlserver")); } + static Stream supportedTestcontainersActiveMQEntriesBuild() { + return Stream.of(Arguments.arguments("activemq", "activemq"), Arguments.arguments("artemis", "activemq")); + } + @ParameterizedTest @MethodSource("supportedEntriesHelpDocument") void linkToSupportedEntriesWhenTestContainerIsPresentIsAdded(String dependencyId, String docHref) { diff --git a/start-site/src/test/resources/compose/activemq-classic.yaml b/start-site/src/test/resources/compose/activemq-classic.yaml new file mode 100644 index 0000000000..269d4e2a2c --- /dev/null +++ b/start-site/src/test/resources/compose/activemq-classic.yaml @@ -0,0 +1,5 @@ +services: + activemq: + image: 'apache/activemq-classic:latest' + ports: + - '61616' diff --git a/start-site/src/test/resources/compose/artemis.yaml b/start-site/src/test/resources/compose/artemis.yaml new file mode 100644 index 0000000000..1aa745eb00 --- /dev/null +++ b/start-site/src/test/resources/compose/artemis.yaml @@ -0,0 +1,5 @@ +services: + artemis: + image: 'apache/activemq-artemis:latest' + ports: + - '61616'