From 089fef039205f14c19d37d0d7fad9597cd71a584 Mon Sep 17 00:00:00 2001 From: Chris Bono Date: Mon, 22 May 2023 00:15:30 -0500 Subject: [PATCH 1/2] Add Pulsar ConnectionDetails support Add `ConnectionDetails` support for Apache Pulsar and provide adapters for Docker Compose and Testcontainers. See gh-37197 --- .../spring-boot-autoconfigure/build.gradle | 1 + .../PropertiesPulsarConnectionDetails.java | 42 ++++++++ .../pulsar/PulsarConfiguration.java | 25 ++++- .../pulsar/PulsarConnectionDetails.java | 41 ++++++++ .../pulsar/PulsarPropertiesMapper.java | 1 + ...ropertiesPulsarConnectionDetailsTests.java | 46 +++++++++ .../pulsar/PulsarAutoConfigurationTests.java | 1 + .../pulsar/PulsarConfigurationTests.java | 53 ++++++++++- ...DockerComposeConnectionDetailsFactory.java | 74 +++++++++++++++ .../connection/pulsar/package-info.java | 20 ++++ .../main/resources/META-INF/spring.factories | 2 +- ...nectionDetailsFactoryIntegrationTests.java | 46 +++++++++ .../connection/pulsar/pulsar-compose.yaml | 9 ++ .../asciidoc/features/docker-compose.adoc | 3 + .../src/docs/asciidoc/features/testing.adoc | 3 + .../spring-boot-testcontainers/build.gradle | 6 ++ ...lsarContainerConnectionDetailsFactory.java | 62 ++++++++++++ .../connection/pulsar/package-info.java | 20 ++++ .../main/resources/META-INF/spring.factories | 1 + ...nectionDetailsFactoryIntegrationTests.java | 95 +++++++++++++++++++ .../build.gradle | 1 + .../pulsar/SamplePulsarApplicationTests.java | 11 +-- 22 files changed, 549 insertions(+), 14 deletions(-) create mode 100644 spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/pulsar/PropertiesPulsarConnectionDetails.java create mode 100644 spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/pulsar/PulsarConnectionDetails.java create mode 100644 spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/pulsar/PropertiesPulsarConnectionDetailsTests.java create mode 100644 spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/service/connection/pulsar/PulsarDockerComposeConnectionDetailsFactory.java create mode 100644 spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/service/connection/pulsar/package-info.java create mode 100644 spring-boot-project/spring-boot-docker-compose/src/test/java/org/springframework/boot/docker/compose/service/connection/pulsar/PulsarDockerComposeConnectionDetailsFactoryIntegrationTests.java create mode 100644 spring-boot-project/spring-boot-docker-compose/src/test/resources/org/springframework/boot/docker/compose/service/connection/pulsar/pulsar-compose.yaml create mode 100644 spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection/pulsar/PulsarContainerConnectionDetailsFactory.java create mode 100644 spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection/pulsar/package-info.java create mode 100644 spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/service/connection/pulsar/PulsarContainerConnectionDetailsFactoryIntegrationTests.java diff --git a/spring-boot-project/spring-boot-autoconfigure/build.gradle b/spring-boot-project/spring-boot-autoconfigure/build.gradle index b48da7b7bf4..f88acc52eed 100644 --- a/spring-boot-project/spring-boot-autoconfigure/build.gradle +++ b/spring-boot-project/spring-boot-autoconfigure/build.gradle @@ -277,4 +277,5 @@ tasks.named("checkSpringConfigurationMetadata").configure { test { jvmArgs += "--add-opens=java.base/java.net=ALL-UNNAMED" + jvmArgs += "--add-opens=java.base/sun.net=ALL-UNNAMED" } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/pulsar/PropertiesPulsarConnectionDetails.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/pulsar/PropertiesPulsarConnectionDetails.java new file mode 100644 index 00000000000..6865e3a5e6b --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/pulsar/PropertiesPulsarConnectionDetails.java @@ -0,0 +1,42 @@ +/* + * Copyright 2012-2023 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.autoconfigure.pulsar; + +/** + * Adapts {@link PulsarProperties} to {@link PulsarConnectionDetails}. + * + * @author Chris Bono + */ +class PropertiesPulsarConnectionDetails implements PulsarConnectionDetails { + + private final PulsarProperties pulsarProperties; + + PropertiesPulsarConnectionDetails(PulsarProperties pulsarProperties) { + this.pulsarProperties = pulsarProperties; + } + + @Override + public String getPulsarBrokerUrl() { + return this.pulsarProperties.getClient().getServiceUrl(); + } + + @Override + public String getPulsarAdminUrl() { + return this.pulsarProperties.getAdmin().getServiceUrl(); + } + +} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/pulsar/PulsarConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/pulsar/PulsarConfiguration.java index 14551bed70d..6a5baf469fd 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/pulsar/PulsarConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/pulsar/PulsarConfiguration.java @@ -71,17 +71,31 @@ class PulsarConfiguration { this.propertiesMapper = new PulsarPropertiesMapper(properties); } + @Bean + @ConditionalOnMissingBean(PulsarConnectionDetails.class) + PropertiesPulsarConnectionDetails pulsarConnectionDetails() { + return new PropertiesPulsarConnectionDetails(this.properties); + } + @Bean @ConditionalOnMissingBean(PulsarClientFactory.class) - DefaultPulsarClientFactory pulsarClientFactory(ObjectProvider customizersProvider) { + DefaultPulsarClientFactory pulsarClientFactory(PulsarConnectionDetails connectionDetails, + ObjectProvider customizersProvider) { List allCustomizers = new ArrayList<>(); allCustomizers.add(this.propertiesMapper::customizeClientBuilder); + allCustomizers.add((clientBuilder) -> this.applyConnectionDetails(connectionDetails, clientBuilder)); allCustomizers.addAll(customizersProvider.orderedStream().toList()); DefaultPulsarClientFactory clientFactory = new DefaultPulsarClientFactory( (clientBuilder) -> applyClientBuilderCustomizers(allCustomizers, clientBuilder)); return clientFactory; } + private void applyConnectionDetails(PulsarConnectionDetails connectionDetails, ClientBuilder clientBuilder) { + if (connectionDetails.getPulsarBrokerUrl() != null) { + clientBuilder.serviceUrl(connectionDetails.getPulsarBrokerUrl()); + } + } + private void applyClientBuilderCustomizers(List customizers, ClientBuilder clientBuilder) { customizers.forEach((customizer) -> customizer.customize(clientBuilder)); @@ -95,14 +109,21 @@ class PulsarConfiguration { @Bean @ConditionalOnMissingBean - PulsarAdministration pulsarAdministration( + PulsarAdministration pulsarAdministration(PulsarConnectionDetails connectionDetails, ObjectProvider pulsarAdminBuilderCustomizers) { List allCustomizers = new ArrayList<>(); allCustomizers.add(this.propertiesMapper::customizeAdminBuilder); + allCustomizers.add((adminBuilder) -> this.applyConnectionDetails(connectionDetails, adminBuilder)); allCustomizers.addAll(pulsarAdminBuilderCustomizers.orderedStream().toList()); return new PulsarAdministration((adminBuilder) -> applyAdminBuilderCustomizers(allCustomizers, adminBuilder)); } + private void applyConnectionDetails(PulsarConnectionDetails connectionDetails, PulsarAdminBuilder adminBuilder) { + if (connectionDetails.getPulsarAdminUrl() != null) { + adminBuilder.serviceHttpUrl(connectionDetails.getPulsarAdminUrl()); + } + } + private void applyAdminBuilderCustomizers(List customizers, PulsarAdminBuilder adminBuilder) { customizers.forEach((customizer) -> customizer.customize(adminBuilder)); diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/pulsar/PulsarConnectionDetails.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/pulsar/PulsarConnectionDetails.java new file mode 100644 index 00000000000..567134b77a0 --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/pulsar/PulsarConnectionDetails.java @@ -0,0 +1,41 @@ +/* + * Copyright 2012-2023 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.autoconfigure.pulsar; + +import org.springframework.boot.autoconfigure.service.connection.ConnectionDetails; + +/** + * Details required to establish a connection to a Pulsar service. + * + * @author Chris Bono + * @since 3.2.0 + */ +public interface PulsarConnectionDetails extends ConnectionDetails { + + /** + * Returns the Pulsar service URL for the broker. + * @return the Pulsar service URL for the broker + */ + String getPulsarBrokerUrl(); + + /** + * Returns the Pulsar web URL for the admin endpoint. + * @return the Pulsar web URL for the admin endpoint + */ + String getPulsarAdminUrl(); + +} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/pulsar/PulsarPropertiesMapper.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/pulsar/PulsarPropertiesMapper.java index 10c3a77597b..77a6b632126 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/pulsar/PulsarPropertiesMapper.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/pulsar/PulsarPropertiesMapper.java @@ -53,6 +53,7 @@ final class PulsarPropertiesMapper { PulsarProperties.Client properties = this.properties.getClient(); PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); map.from(properties::getServiceUrl).to(clientBuilder::serviceUrl); + map.from(properties::getConnectionTimeout).to(timeoutProperty(clientBuilder::connectionTimeout)); map.from(properties::getOperationTimeout).to(timeoutProperty(clientBuilder::operationTimeout)); map.from(properties::getLookupTimeout).to(timeoutProperty(clientBuilder::lookupTimeout)); diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/pulsar/PropertiesPulsarConnectionDetailsTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/pulsar/PropertiesPulsarConnectionDetailsTests.java new file mode 100644 index 00000000000..8fed356282f --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/pulsar/PropertiesPulsarConnectionDetailsTests.java @@ -0,0 +1,46 @@ +/* + * Copyright 2012-2023 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.autoconfigure.pulsar; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link PropertiesPulsarConnectionDetails}. + * + * @author Chris Bono + */ +class PropertiesPulsarConnectionDetailsTests { + + @Test + void pulsarBrokerUrlIsObtainedFromPulsarProperties() { + var pulsarProps = new PulsarProperties(); + pulsarProps.getClient().setServiceUrl("foo"); + var connectionDetails = new PropertiesPulsarConnectionDetails(pulsarProps); + assertThat(connectionDetails.getPulsarBrokerUrl()).isEqualTo("foo"); + } + + @Test + void pulsarAdminUrlIsObtainedFromPulsarProperties() { + var pulsarProps = new PulsarProperties(); + pulsarProps.getAdmin().setServiceUrl("foo"); + var connectionDetails = new PropertiesPulsarConnectionDetails(pulsarProps); + assertThat(connectionDetails.getPulsarAdminUrl()).isEqualTo("foo"); + } + +} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/pulsar/PulsarAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/pulsar/PulsarAutoConfigurationTests.java index 3710c9313cb..ca05f2edde3 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/pulsar/PulsarAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/pulsar/PulsarAutoConfigurationTests.java @@ -114,6 +114,7 @@ class PulsarAutoConfigurationTests { @Test void autoConfiguresBeans() { this.contextRunner.run((context) -> assertThat(context).hasSingleBean(PulsarConfiguration.class) + .hasSingleBean(PulsarConnectionDetails.class) .hasSingleBean(DefaultPulsarClientFactory.class) .hasSingleBean(PulsarClient.class) .hasSingleBean(PulsarAdministration.class) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/pulsar/PulsarConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/pulsar/PulsarConfigurationTests.java index 70536effaca..e014eabd9df 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/pulsar/PulsarConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/pulsar/PulsarConfigurationTests.java @@ -51,6 +51,7 @@ import org.springframework.pulsar.function.PulsarFunctionAdministration; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.entry; +import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.mock; /** @@ -67,6 +68,15 @@ class PulsarConfigurationTests { .withConfiguration(AutoConfigurations.of(PulsarConfiguration.class)) .withBean(PulsarClient.class, () -> mock(PulsarClient.class)); + @Test + void whenHasUserDefinedConnectionDetailsBeanDoesNotAutoConfigureBean() { + PulsarConnectionDetails customConnectionDetails = mock(PulsarConnectionDetails.class); + this.contextRunner + .withBean("customPulsarConnectionDetails", PulsarConnectionDetails.class, () -> customConnectionDetails) + .run((context) -> assertThat(context).getBean(PulsarConnectionDetails.class) + .isSameAs(customConnectionDetails)); + } + @Nested class ClientTests { @@ -86,17 +96,36 @@ class PulsarConfigurationTests { .run((context) -> assertThat(context).getBean(PulsarClient.class).isSameAs(customClient)); } + @Test + void whenConnectionDetailsAreNullTheyAreNotApplied() { + PulsarConnectionDetails connectionDetails = mock(PulsarConnectionDetails.class); + given(connectionDetails.getPulsarBrokerUrl()).willReturn(null); + PulsarConfigurationTests.this.contextRunner.withBean(PulsarConnectionDetails.class, () -> connectionDetails) + .withPropertyValues("spring.pulsar.client.service-url=fromPropsCustomizer") + .run((context) -> { + DefaultPulsarClientFactory clientFactory = context.getBean(DefaultPulsarClientFactory.class); + Customizers customizers = Customizers + .of(ClientBuilder.class, PulsarClientBuilderCustomizer::customize); + assertThat(customizers.fromField(clientFactory, "customizer")) + .callsInOrder(ClientBuilder::serviceUrl, "fromPropsCustomizer"); + }); + } + @Test void whenHasUserDefinedCustomizersAppliesInCorrectOrder() { + PulsarConnectionDetails connectionDetails = mock(PulsarConnectionDetails.class); + given(connectionDetails.getPulsarBrokerUrl()).willReturn("fromConnectionDetailsCustomizer"); PulsarConfigurationTests.this.contextRunner .withUserConfiguration(PulsarClientBuilderCustomizersConfig.class) + .withBean(PulsarConnectionDetails.class, () -> connectionDetails) .withPropertyValues("spring.pulsar.client.service-url=fromPropsCustomizer") .run((context) -> { DefaultPulsarClientFactory clientFactory = context.getBean(DefaultPulsarClientFactory.class); Customizers customizers = Customizers .of(ClientBuilder.class, PulsarClientBuilderCustomizer::customize); assertThat(customizers.fromField(clientFactory, "customizer")).callsInOrder( - ClientBuilder::serviceUrl, "fromPropsCustomizer", "fromCustomizer1", "fromCustomizer2"); + ClientBuilder::serviceUrl, "fromPropsCustomizer", "fromConnectionDetailsCustomizer", + "fromCustomizer1", "fromCustomizer2"); }); } @@ -133,17 +162,35 @@ class PulsarConfigurationTests { .isSameAs(pulsarAdministration)); } + @Test + void whenConnectionDetailsAreNullTheyAreNotApplied() { + PulsarConnectionDetails connectionDetails = mock(PulsarConnectionDetails.class); + given(connectionDetails.getPulsarAdminUrl()).willReturn(null); + PulsarConfigurationTests.this.contextRunner.withBean(PulsarConnectionDetails.class, () -> connectionDetails) + .withPropertyValues("spring.pulsar.admin.service-url=fromPropsCustomizer") + .run((context) -> { + PulsarAdministration pulsarAdmin = context.getBean(PulsarAdministration.class); + Customizers customizers = Customizers + .of(PulsarAdminBuilder.class, PulsarAdminBuilderCustomizer::customize); + assertThat(customizers.fromField(pulsarAdmin, "adminCustomizers")) + .callsInOrder(PulsarAdminBuilder::serviceHttpUrl, "fromPropsCustomizer"); + }); + } + @Test void whenHasUserDefinedCustomizersAppliesInCorrectOrder() { + PulsarConnectionDetails connectionDetails = mock(PulsarConnectionDetails.class); + given(connectionDetails.getPulsarAdminUrl()).willReturn("fromConnectionDetailsCustomizer"); this.contextRunner.withUserConfiguration(PulsarAdminBuilderCustomizersConfig.class) + .withBean(PulsarConnectionDetails.class, () -> connectionDetails) .withPropertyValues("spring.pulsar.admin.service-url=fromPropsCustomizer") .run((context) -> { PulsarAdministration pulsarAdmin = context.getBean(PulsarAdministration.class); Customizers customizers = Customizers .of(PulsarAdminBuilder.class, PulsarAdminBuilderCustomizer::customize); assertThat(customizers.fromField(pulsarAdmin, "adminCustomizers")).callsInOrder( - PulsarAdminBuilder::serviceHttpUrl, "fromPropsCustomizer", "fromCustomizer1", - "fromCustomizer2"); + PulsarAdminBuilder::serviceHttpUrl, "fromPropsCustomizer", + "fromConnectionDetailsCustomizer", "fromCustomizer1", "fromCustomizer2"); }); } diff --git a/spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/service/connection/pulsar/PulsarDockerComposeConnectionDetailsFactory.java b/spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/service/connection/pulsar/PulsarDockerComposeConnectionDetailsFactory.java new file mode 100644 index 00000000000..c9817d34851 --- /dev/null +++ b/spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/service/connection/pulsar/PulsarDockerComposeConnectionDetailsFactory.java @@ -0,0 +1,74 @@ +/* + * Copyright 2012-2023 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.docker.compose.service.connection.pulsar; + +import org.springframework.boot.autoconfigure.pulsar.PulsarConnectionDetails; +import org.springframework.boot.docker.compose.core.RunningService; +import org.springframework.boot.docker.compose.service.connection.DockerComposeConnectionDetailsFactory; +import org.springframework.boot.docker.compose.service.connection.DockerComposeConnectionSource; + +/** + * {@link DockerComposeConnectionDetailsFactory} to create {@link PulsarConnectionDetails} + * for a {@code pulsar} service. + * + * @author Chris Bono + */ +class PulsarDockerComposeConnectionDetailsFactory + extends DockerComposeConnectionDetailsFactory { + + private static final int PULSAR_BROKER_PORT = 6650; + + private static final int PULSAR_ADMIN_PORT = 8080; + + PulsarDockerComposeConnectionDetailsFactory() { + super("apachepulsar/pulsar"); + } + + @Override + protected PulsarConnectionDetails getDockerComposeConnectionDetails(DockerComposeConnectionSource source) { + return new PulsarDockerComposeConnectionDetails(source.getRunningService()); + } + + /** + * {@link PulsarConnectionDetails} backed by a {@code pulsar} {@link RunningService}. + */ + static class PulsarDockerComposeConnectionDetails extends DockerComposeConnectionDetails + implements PulsarConnectionDetails { + + private final String brokerUrl; + + private final String adminUrl; + + PulsarDockerComposeConnectionDetails(RunningService service) { + super(service); + this.brokerUrl = "pulsar://%s:%s".formatted(service.host(), service.ports().get(PULSAR_BROKER_PORT)); + this.adminUrl = "http://%s:%s".formatted(service.host(), service.ports().get(PULSAR_ADMIN_PORT)); + } + + @Override + public String getPulsarBrokerUrl() { + return this.brokerUrl; + } + + @Override + public String getPulsarAdminUrl() { + return this.adminUrl; + } + + } + +} diff --git a/spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/service/connection/pulsar/package-info.java b/spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/service/connection/pulsar/package-info.java new file mode 100644 index 00000000000..7d8c4d1b1a5 --- /dev/null +++ b/spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/service/connection/pulsar/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2012-2023 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. + */ + +/** + * Auto-configuration for docker compose Pulsar service connections. + */ +package org.springframework.boot.docker.compose.service.connection.pulsar; diff --git a/spring-boot-project/spring-boot-docker-compose/src/main/resources/META-INF/spring.factories b/spring-boot-project/spring-boot-docker-compose/src/main/resources/META-INF/spring.factories index cd5dc75bb4c..cf5ad6c25a2 100644 --- a/spring-boot-project/spring-boot-docker-compose/src/main/resources/META-INF/spring.factories +++ b/spring-boot-project/spring-boot-docker-compose/src/main/resources/META-INF/spring.factories @@ -19,9 +19,9 @@ org.springframework.boot.docker.compose.service.connection.oracle.OracleJdbcDock org.springframework.boot.docker.compose.service.connection.oracle.OracleR2dbcDockerComposeConnectionDetailsFactory,\ org.springframework.boot.docker.compose.service.connection.postgres.PostgresJdbcDockerComposeConnectionDetailsFactory,\ org.springframework.boot.docker.compose.service.connection.postgres.PostgresR2dbcDockerComposeConnectionDetailsFactory,\ +org.springframework.boot.docker.compose.service.connection.pulsar.PulsarDockerComposeConnectionDetailsFactory,\ org.springframework.boot.docker.compose.service.connection.rabbit.RabbitDockerComposeConnectionDetailsFactory,\ org.springframework.boot.docker.compose.service.connection.redis.RedisDockerComposeConnectionDetailsFactory,\ org.springframework.boot.docker.compose.service.connection.sqlserver.SqlServerJdbcDockerComposeConnectionDetailsFactory,\ org.springframework.boot.docker.compose.service.connection.sqlserver.SqlServerR2dbcDockerComposeConnectionDetailsFactory,\ org.springframework.boot.docker.compose.service.connection.zipkin.ZipkinDockerComposeConnectionDetailsFactory - diff --git a/spring-boot-project/spring-boot-docker-compose/src/test/java/org/springframework/boot/docker/compose/service/connection/pulsar/PulsarDockerComposeConnectionDetailsFactoryIntegrationTests.java b/spring-boot-project/spring-boot-docker-compose/src/test/java/org/springframework/boot/docker/compose/service/connection/pulsar/PulsarDockerComposeConnectionDetailsFactoryIntegrationTests.java new file mode 100644 index 00000000000..ed509613f5d --- /dev/null +++ b/spring-boot-project/spring-boot-docker-compose/src/test/java/org/springframework/boot/docker/compose/service/connection/pulsar/PulsarDockerComposeConnectionDetailsFactoryIntegrationTests.java @@ -0,0 +1,46 @@ +/* + * Copyright 2023-2023 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.docker.compose.service.connection.pulsar; + +import org.junit.jupiter.api.Test; + +import org.springframework.boot.autoconfigure.pulsar.PulsarConnectionDetails; +import org.springframework.boot.docker.compose.service.connection.test.AbstractDockerComposeIntegrationTests; +import org.springframework.boot.testsupport.testcontainers.DockerImageNames; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Integration test for {@link PulsarDockerComposeConnectionDetailsFactory}. + * + * @author Chris Bono + */ +class PulsarDockerComposeConnectionDetailsFactoryIntegrationTests extends AbstractDockerComposeIntegrationTests { + + PulsarDockerComposeConnectionDetailsFactoryIntegrationTests() { + super("pulsar-compose.yaml", DockerImageNames.pulsar()); + } + + @Test + void runCreatesConnectionDetails() { + PulsarConnectionDetails connectionDetails = run(PulsarConnectionDetails.class); + assertThat(connectionDetails).isNotNull(); + assertThat(connectionDetails.getPulsarBrokerUrl()).matches("^pulsar:\\/\\/\\S+:\\d+"); + assertThat(connectionDetails.getPulsarAdminUrl()).matches("^http:\\/\\/\\S+:\\d+"); + } + +} diff --git a/spring-boot-project/spring-boot-docker-compose/src/test/resources/org/springframework/boot/docker/compose/service/connection/pulsar/pulsar-compose.yaml b/spring-boot-project/spring-boot-docker-compose/src/test/resources/org/springframework/boot/docker/compose/service/connection/pulsar/pulsar-compose.yaml new file mode 100644 index 00000000000..76cdd274f43 --- /dev/null +++ b/spring-boot-project/spring-boot-docker-compose/src/test/resources/org/springframework/boot/docker/compose/service/connection/pulsar/pulsar-compose.yaml @@ -0,0 +1,9 @@ +services: + pulsar: + image: '{imageName}' + ports: + - '8080' + - '6650' + command: bin/pulsar standalone + healthcheck: + test: curl http://127.0.0.1:8080/admin/v2/namespaces/public/default diff --git a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/docker-compose.adoc b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/docker-compose.adoc index 06f34b69a98..4caedf39606 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/docker-compose.adoc +++ b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/docker-compose.adoc @@ -76,6 +76,9 @@ The following service connections are currently supported: | `MongoConnectionDetails` | Containers named "mongo" +| `PulsarConnectionDetails` +| Containers named "apachepulsar/pulsar" + | `R2dbcConnectionDetails` | Containers named "gvenzl/oracle-xe", "mariadb", "mssql/server", "mysql", or "postgres" diff --git a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/testing.adoc b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/testing.adoc index f5ab2b2ac43..9af81d8d44d 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/testing.adoc +++ b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/testing.adoc @@ -992,6 +992,9 @@ The following service connection factories are provided in the `spring-boot-test | `Neo4jConnectionDetails` | Containers of type `Neo4jContainer` +| `PulsarConnectionDetails` +| Containers of type `PulsarContainer` + | `R2dbcConnectionDetails` | Containers of type `MariaDBContainer`, `MSSQLServerContainer`, `MySQLContainer`, `OracleContainer`, or `PostgreSQLContainer` diff --git a/spring-boot-project/spring-boot-testcontainers/build.gradle b/spring-boot-project/spring-boot-testcontainers/build.gradle index 2d20062409a..67fdb986038 100644 --- a/spring-boot-project/spring-boot-testcontainers/build.gradle +++ b/spring-boot-project/spring-boot-testcontainers/build.gradle @@ -29,6 +29,7 @@ dependencies { optional("org.testcontainers:neo4j") optional("org.testcontainers:oracle-xe") optional("org.testcontainers:postgresql") + optional("org.testcontainers:pulsar") optional("org.testcontainers:rabbitmq") optional("org.testcontainers:redpanda") optional("org.testcontainers:r2dbc") @@ -50,8 +51,13 @@ dependencies { testImplementation("org.springframework:spring-r2dbc") testImplementation("org.springframework.amqp:spring-rabbit") testImplementation("org.springframework.kafka:spring-kafka") + testImplementation("org.springframework.pulsar:spring-pulsar") testImplementation("org.testcontainers:junit-jupiter") testRuntimeOnly("com.oracle.database.r2dbc:oracle-r2dbc") } +test { + jvmArgs += "--add-opens=java.base/java.net=ALL-UNNAMED" + jvmArgs += "--add-opens=java.base/sun.net=ALL-UNNAMED" +} diff --git a/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection/pulsar/PulsarContainerConnectionDetailsFactory.java b/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection/pulsar/PulsarContainerConnectionDetailsFactory.java new file mode 100644 index 00000000000..505a8e564e1 --- /dev/null +++ b/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection/pulsar/PulsarContainerConnectionDetailsFactory.java @@ -0,0 +1,62 @@ +/* + * Copyright 2012-2023 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.testcontainers.service.connection.pulsar; + +import org.testcontainers.containers.PulsarContainer; + +import org.springframework.boot.autoconfigure.pulsar.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 + */ +class PulsarContainerConnectionDetailsFactory + 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 getPulsarBrokerUrl() { + return getContainer().getPulsarBrokerUrl(); + } + + @Override + public String getPulsarAdminUrl() { + return getContainer().getHttpServiceUrl(); + } + + } + +} diff --git a/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection/pulsar/package-info.java b/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection/pulsar/package-info.java new file mode 100644 index 00000000000..4938ad86313 --- /dev/null +++ b/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection/pulsar/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2012-2023 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. + */ + +/** + * Support for testcontainers Pulsar service connections. + */ +package org.springframework.boot.testcontainers.service.connection.pulsar; diff --git a/spring-boot-project/spring-boot-testcontainers/src/main/resources/META-INF/spring.factories b/spring-boot-project/spring-boot-testcontainers/src/main/resources/META-INF/spring.factories index f26cc7230f6..e005e992812 100644 --- a/spring-boot-project/spring-boot-testcontainers/src/main/resources/META-INF/spring.factories +++ b/spring-boot-project/spring-boot-testcontainers/src/main/resources/META-INF/spring.factories @@ -19,6 +19,7 @@ org.springframework.boot.testcontainers.service.connection.kafka.KafkaContainerC org.springframework.boot.testcontainers.service.connection.liquibase.LiquibaseContainerConnectionDetailsFactory,\ org.springframework.boot.testcontainers.service.connection.mongo.MongoContainerConnectionDetailsFactory,\ org.springframework.boot.testcontainers.service.connection.neo4j.Neo4jContainerConnectionDetailsFactory,\ +org.springframework.boot.testcontainers.service.connection.pulsar.PulsarContainerConnectionDetailsFactory,\ org.springframework.boot.testcontainers.service.connection.r2dbc.MariaDbR2dbcContainerConnectionDetailsFactory,\ org.springframework.boot.testcontainers.service.connection.r2dbc.MySqlR2dbcContainerConnectionDetailsFactory,\ org.springframework.boot.testcontainers.service.connection.r2dbc.OracleR2dbcContainerConnectionDetailsFactory,\ diff --git a/spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/service/connection/pulsar/PulsarContainerConnectionDetailsFactoryIntegrationTests.java b/spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/service/connection/pulsar/PulsarContainerConnectionDetailsFactoryIntegrationTests.java new file mode 100644 index 00000000000..51f5ec2a136 --- /dev/null +++ b/spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/service/connection/pulsar/PulsarContainerConnectionDetailsFactoryIntegrationTests.java @@ -0,0 +1,95 @@ +/* + * Copyright 2012-2023 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.testcontainers.service.connection.pulsar; + +import java.time.Duration; +import java.util.ArrayList; +import java.util.List; + +import org.apache.pulsar.client.api.PulsarClientException; +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.autoconfigure.pulsar.PulsarAutoConfiguration; +import org.springframework.boot.testcontainers.service.connection.ServiceConnection; +import org.springframework.boot.testsupport.testcontainers.DockerImageNames; +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 PulsarContainerConnectionDetailsFactory}. + * + * @author Chris Bono + */ +@SpringJUnitConfig +@Testcontainers(disabledWithoutDocker = true) +@TestPropertySource(properties = { "spring.pulsar.consumer.subscription.initial-position=earliest" }) +class PulsarContainerConnectionDetailsFactoryIntegrationTests { + + @Container + @ServiceConnection + @SuppressWarnings("unused") + static final PulsarContainer PULSAR = new PulsarContainer(DockerImageNames.pulsar()) + .withStartupTimeout(Duration.ofMinutes(3)); + + @Autowired + private PulsarTemplate pulsarTemplate; + + @Autowired + private TestListener listener; + + @Test + void connectionCanBeMadeToPulsarContainer() throws PulsarClientException { + 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/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-pulsar/build.gradle b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-pulsar/build.gradle index 6058d1127ae..a0051d3f4ea 100644 --- a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-pulsar/build.gradle +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-pulsar/build.gradle @@ -10,6 +10,7 @@ dependencies { implementation(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-pulsar-reactive")) testImplementation(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-test")) testImplementation(project(":spring-boot-project:spring-boot-tools:spring-boot-test-support")) + testImplementation(project(":spring-boot-project:spring-boot-testcontainers")) testImplementation("org.awaitility:awaitility") testImplementation("org.testcontainers:junit-jupiter") testImplementation("org.testcontainers:pulsar") diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-pulsar/src/test/java/smoketest/pulsar/SamplePulsarApplicationTests.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-pulsar/src/test/java/smoketest/pulsar/SamplePulsarApplicationTests.java index b32be31dfe2..a7e6734e0db 100644 --- a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-pulsar/src/test/java/smoketest/pulsar/SamplePulsarApplicationTests.java +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-pulsar/src/test/java/smoketest/pulsar/SamplePulsarApplicationTests.java @@ -32,10 +32,9 @@ import org.testcontainers.junit.jupiter.Testcontainers; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.system.CapturedOutput; import org.springframework.boot.test.system.OutputCaptureExtension; +import org.springframework.boot.testcontainers.service.connection.ServiceConnection; import org.springframework.boot.testsupport.testcontainers.DockerImageNames; import org.springframework.test.context.ActiveProfiles; -import org.springframework.test.context.DynamicPropertyRegistry; -import org.springframework.test.context.DynamicPropertySource; import static org.assertj.core.api.Assertions.assertThat; @@ -44,15 +43,11 @@ import static org.assertj.core.api.Assertions.assertThat; class SamplePulsarApplicationTests { @Container + @ServiceConnection + @SuppressWarnings("unused") static final PulsarContainer container = new PulsarContainer(DockerImageNames.pulsar()).withStartupAttempts(2) .withStartupTimeout(Duration.ofMinutes(3)); - @DynamicPropertySource - static void pulsarProperties(DynamicPropertyRegistry registry) { - registry.add("spring.pulsar.client.service-url", container::getPulsarBrokerUrl); - registry.add("spring.pulsar.admin.service-url", container::getHttpServiceUrl); - } - abstract class PulsarApplication { private final String type; From 750c5972255161f9314b0fea5d2141f6f49bf4bb Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Wed, 6 Sep 2023 11:57:03 -0700 Subject: [PATCH 2/2] Polish 'Add Pulsar ConnectionDetails support' See gh-37197 --- .../spring-boot-autoconfigure/build.gradle | 1 - .../PropertiesPulsarConnectionDetails.java | 4 +- .../pulsar/PulsarConfiguration.java | 18 +------- .../pulsar/PulsarConnectionDetails.java | 12 ++--- .../pulsar/PulsarPropertiesMapper.java | 9 ++-- ...ropertiesPulsarConnectionDetailsTests.java | 20 ++++----- .../pulsar/PulsarConfigurationTests.java | 45 +++---------------- .../pulsar/PulsarPropertiesMapperTests.java | 35 +++++++++++++-- ...DockerComposeConnectionDetailsFactory.java | 14 +++--- ...nectionDetailsFactoryIntegrationTests.java | 4 +- .../spring-boot-testcontainers/build.gradle | 5 --- ...lsarContainerConnectionDetailsFactory.java | 4 +- .../pulsar/SamplePulsarApplicationTests.java | 1 - 13 files changed, 74 insertions(+), 98 deletions(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/build.gradle b/spring-boot-project/spring-boot-autoconfigure/build.gradle index f88acc52eed..b48da7b7bf4 100644 --- a/spring-boot-project/spring-boot-autoconfigure/build.gradle +++ b/spring-boot-project/spring-boot-autoconfigure/build.gradle @@ -277,5 +277,4 @@ tasks.named("checkSpringConfigurationMetadata").configure { test { jvmArgs += "--add-opens=java.base/java.net=ALL-UNNAMED" - jvmArgs += "--add-opens=java.base/sun.net=ALL-UNNAMED" } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/pulsar/PropertiesPulsarConnectionDetails.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/pulsar/PropertiesPulsarConnectionDetails.java index 6865e3a5e6b..51ed0fadc32 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/pulsar/PropertiesPulsarConnectionDetails.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/pulsar/PropertiesPulsarConnectionDetails.java @@ -30,12 +30,12 @@ class PropertiesPulsarConnectionDetails implements PulsarConnectionDetails { } @Override - public String getPulsarBrokerUrl() { + public String getBrokerUrl() { return this.pulsarProperties.getClient().getServiceUrl(); } @Override - public String getPulsarAdminUrl() { + public String getAdminUrl() { return this.pulsarProperties.getAdmin().getServiceUrl(); } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/pulsar/PulsarConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/pulsar/PulsarConfiguration.java index 6a5baf469fd..64efd410ccf 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/pulsar/PulsarConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/pulsar/PulsarConfiguration.java @@ -82,20 +82,13 @@ class PulsarConfiguration { DefaultPulsarClientFactory pulsarClientFactory(PulsarConnectionDetails connectionDetails, ObjectProvider customizersProvider) { List allCustomizers = new ArrayList<>(); - allCustomizers.add(this.propertiesMapper::customizeClientBuilder); - allCustomizers.add((clientBuilder) -> this.applyConnectionDetails(connectionDetails, clientBuilder)); + allCustomizers.add((builder) -> this.propertiesMapper.customizeClientBuilder(builder, connectionDetails)); allCustomizers.addAll(customizersProvider.orderedStream().toList()); DefaultPulsarClientFactory clientFactory = new DefaultPulsarClientFactory( (clientBuilder) -> applyClientBuilderCustomizers(allCustomizers, clientBuilder)); return clientFactory; } - private void applyConnectionDetails(PulsarConnectionDetails connectionDetails, ClientBuilder clientBuilder) { - if (connectionDetails.getPulsarBrokerUrl() != null) { - clientBuilder.serviceUrl(connectionDetails.getPulsarBrokerUrl()); - } - } - private void applyClientBuilderCustomizers(List customizers, ClientBuilder clientBuilder) { customizers.forEach((customizer) -> customizer.customize(clientBuilder)); @@ -112,18 +105,11 @@ class PulsarConfiguration { PulsarAdministration pulsarAdministration(PulsarConnectionDetails connectionDetails, ObjectProvider pulsarAdminBuilderCustomizers) { List allCustomizers = new ArrayList<>(); - allCustomizers.add(this.propertiesMapper::customizeAdminBuilder); - allCustomizers.add((adminBuilder) -> this.applyConnectionDetails(connectionDetails, adminBuilder)); + allCustomizers.add((builder) -> this.propertiesMapper.customizeAdminBuilder(builder, connectionDetails)); allCustomizers.addAll(pulsarAdminBuilderCustomizers.orderedStream().toList()); return new PulsarAdministration((adminBuilder) -> applyAdminBuilderCustomizers(allCustomizers, adminBuilder)); } - private void applyConnectionDetails(PulsarConnectionDetails connectionDetails, PulsarAdminBuilder adminBuilder) { - if (connectionDetails.getPulsarAdminUrl() != null) { - adminBuilder.serviceHttpUrl(connectionDetails.getPulsarAdminUrl()); - } - } - private void applyAdminBuilderCustomizers(List customizers, PulsarAdminBuilder adminBuilder) { customizers.forEach((customizer) -> customizer.customize(adminBuilder)); diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/pulsar/PulsarConnectionDetails.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/pulsar/PulsarConnectionDetails.java index 567134b77a0..1d21f5802e4 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/pulsar/PulsarConnectionDetails.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/pulsar/PulsarConnectionDetails.java @@ -27,15 +27,15 @@ import org.springframework.boot.autoconfigure.service.connection.ConnectionDetai public interface PulsarConnectionDetails extends ConnectionDetails { /** - * Returns the Pulsar service URL for the broker. - * @return the Pulsar service URL for the broker + * URL used to connect to the broker. + * @return the service URL */ - String getPulsarBrokerUrl(); + String getBrokerUrl(); /** - * Returns the Pulsar web URL for the admin endpoint. - * @return the Pulsar web URL for the admin endpoint + * URL user to connect to the admin endpoint. + * @return the admin URL */ - String getPulsarAdminUrl(); + String getAdminUrl(); } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/pulsar/PulsarPropertiesMapper.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/pulsar/PulsarPropertiesMapper.java index 77a6b632126..04246d0e91c 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/pulsar/PulsarPropertiesMapper.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/pulsar/PulsarPropertiesMapper.java @@ -49,21 +49,20 @@ final class PulsarPropertiesMapper { this.properties = properties; } - void customizeClientBuilder(ClientBuilder clientBuilder) { + void customizeClientBuilder(ClientBuilder clientBuilder, PulsarConnectionDetails connectionDetails) { PulsarProperties.Client properties = this.properties.getClient(); PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); - map.from(properties::getServiceUrl).to(clientBuilder::serviceUrl); - + map.from(connectionDetails::getBrokerUrl).to(clientBuilder::serviceUrl); map.from(properties::getConnectionTimeout).to(timeoutProperty(clientBuilder::connectionTimeout)); map.from(properties::getOperationTimeout).to(timeoutProperty(clientBuilder::operationTimeout)); map.from(properties::getLookupTimeout).to(timeoutProperty(clientBuilder::lookupTimeout)); customizeAuthentication(clientBuilder::authentication, properties.getAuthentication()); } - void customizeAdminBuilder(PulsarAdminBuilder adminBuilder) { + void customizeAdminBuilder(PulsarAdminBuilder adminBuilder, PulsarConnectionDetails connectionDetails) { PulsarProperties.Admin properties = this.properties.getAdmin(); PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); - map.from(properties::getServiceUrl).to(adminBuilder::serviceHttpUrl); + map.from(connectionDetails::getAdminUrl).to(adminBuilder::serviceHttpUrl); map.from(properties::getConnectionTimeout).to(timeoutProperty(adminBuilder::connectionTimeout)); map.from(properties::getReadTimeout).to(timeoutProperty(adminBuilder::readTimeout)); map.from(properties::getRequestTimeout).to(timeoutProperty(adminBuilder::requestTimeout)); diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/pulsar/PropertiesPulsarConnectionDetailsTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/pulsar/PropertiesPulsarConnectionDetailsTests.java index 8fed356282f..3abff9be734 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/pulsar/PropertiesPulsarConnectionDetailsTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/pulsar/PropertiesPulsarConnectionDetailsTests.java @@ -28,19 +28,19 @@ import static org.assertj.core.api.Assertions.assertThat; class PropertiesPulsarConnectionDetailsTests { @Test - void pulsarBrokerUrlIsObtainedFromPulsarProperties() { - var pulsarProps = new PulsarProperties(); - pulsarProps.getClient().setServiceUrl("foo"); - var connectionDetails = new PropertiesPulsarConnectionDetails(pulsarProps); - assertThat(connectionDetails.getPulsarBrokerUrl()).isEqualTo("foo"); + void getClientServiceUrlReturnsValueFromProperties() { + PulsarProperties properties = new PulsarProperties(); + properties.getClient().setServiceUrl("foo"); + PulsarConnectionDetails connectionDetails = new PropertiesPulsarConnectionDetails(properties); + assertThat(connectionDetails.getBrokerUrl()).isEqualTo("foo"); } @Test - void pulsarAdminUrlIsObtainedFromPulsarProperties() { - var pulsarProps = new PulsarProperties(); - pulsarProps.getAdmin().setServiceUrl("foo"); - var connectionDetails = new PropertiesPulsarConnectionDetails(pulsarProps); - assertThat(connectionDetails.getPulsarAdminUrl()).isEqualTo("foo"); + void getAdminServiceHttpUrlReturnsValueFromProperties() { + PulsarProperties properties = new PulsarProperties(); + properties.getAdmin().setServiceUrl("foo"); + PulsarConnectionDetails connectionDetails = new PropertiesPulsarConnectionDetails(properties); + assertThat(connectionDetails.getAdminUrl()).isEqualTo("foo"); } } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/pulsar/PulsarConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/pulsar/PulsarConfigurationTests.java index e014eabd9df..a1136b11ba2 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/pulsar/PulsarConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/pulsar/PulsarConfigurationTests.java @@ -96,36 +96,20 @@ class PulsarConfigurationTests { .run((context) -> assertThat(context).getBean(PulsarClient.class).isSameAs(customClient)); } - @Test - void whenConnectionDetailsAreNullTheyAreNotApplied() { - PulsarConnectionDetails connectionDetails = mock(PulsarConnectionDetails.class); - given(connectionDetails.getPulsarBrokerUrl()).willReturn(null); - PulsarConfigurationTests.this.contextRunner.withBean(PulsarConnectionDetails.class, () -> connectionDetails) - .withPropertyValues("spring.pulsar.client.service-url=fromPropsCustomizer") - .run((context) -> { - DefaultPulsarClientFactory clientFactory = context.getBean(DefaultPulsarClientFactory.class); - Customizers customizers = Customizers - .of(ClientBuilder.class, PulsarClientBuilderCustomizer::customize); - assertThat(customizers.fromField(clientFactory, "customizer")) - .callsInOrder(ClientBuilder::serviceUrl, "fromPropsCustomizer"); - }); - } - @Test void whenHasUserDefinedCustomizersAppliesInCorrectOrder() { PulsarConnectionDetails connectionDetails = mock(PulsarConnectionDetails.class); - given(connectionDetails.getPulsarBrokerUrl()).willReturn("fromConnectionDetailsCustomizer"); + given(connectionDetails.getBrokerUrl()).willReturn("connectiondetails"); PulsarConfigurationTests.this.contextRunner .withUserConfiguration(PulsarClientBuilderCustomizersConfig.class) .withBean(PulsarConnectionDetails.class, () -> connectionDetails) - .withPropertyValues("spring.pulsar.client.service-url=fromPropsCustomizer") + .withPropertyValues("spring.pulsar.client.service-url=properties") .run((context) -> { DefaultPulsarClientFactory clientFactory = context.getBean(DefaultPulsarClientFactory.class); Customizers customizers = Customizers .of(ClientBuilder.class, PulsarClientBuilderCustomizer::customize); assertThat(customizers.fromField(clientFactory, "customizer")).callsInOrder( - ClientBuilder::serviceUrl, "fromPropsCustomizer", "fromConnectionDetailsCustomizer", - "fromCustomizer1", "fromCustomizer2"); + ClientBuilder::serviceUrl, "connectiondetails", "fromCustomizer1", "fromCustomizer2"); }); } @@ -162,35 +146,20 @@ class PulsarConfigurationTests { .isSameAs(pulsarAdministration)); } - @Test - void whenConnectionDetailsAreNullTheyAreNotApplied() { - PulsarConnectionDetails connectionDetails = mock(PulsarConnectionDetails.class); - given(connectionDetails.getPulsarAdminUrl()).willReturn(null); - PulsarConfigurationTests.this.contextRunner.withBean(PulsarConnectionDetails.class, () -> connectionDetails) - .withPropertyValues("spring.pulsar.admin.service-url=fromPropsCustomizer") - .run((context) -> { - PulsarAdministration pulsarAdmin = context.getBean(PulsarAdministration.class); - Customizers customizers = Customizers - .of(PulsarAdminBuilder.class, PulsarAdminBuilderCustomizer::customize); - assertThat(customizers.fromField(pulsarAdmin, "adminCustomizers")) - .callsInOrder(PulsarAdminBuilder::serviceHttpUrl, "fromPropsCustomizer"); - }); - } - @Test void whenHasUserDefinedCustomizersAppliesInCorrectOrder() { PulsarConnectionDetails connectionDetails = mock(PulsarConnectionDetails.class); - given(connectionDetails.getPulsarAdminUrl()).willReturn("fromConnectionDetailsCustomizer"); + given(connectionDetails.getAdminUrl()).willReturn("connectiondetails"); this.contextRunner.withUserConfiguration(PulsarAdminBuilderCustomizersConfig.class) .withBean(PulsarConnectionDetails.class, () -> connectionDetails) - .withPropertyValues("spring.pulsar.admin.service-url=fromPropsCustomizer") + .withPropertyValues("spring.pulsar.admin.service-url=property") .run((context) -> { PulsarAdministration pulsarAdmin = context.getBean(PulsarAdministration.class); Customizers customizers = Customizers .of(PulsarAdminBuilder.class, PulsarAdminBuilderCustomizer::customize); assertThat(customizers.fromField(pulsarAdmin, "adminCustomizers")).callsInOrder( - PulsarAdminBuilder::serviceHttpUrl, "fromPropsCustomizer", - "fromConnectionDetailsCustomizer", "fromCustomizer1", "fromCustomizer2"); + PulsarAdminBuilder::serviceHttpUrl, "connectiondetails", "fromCustomizer1", + "fromCustomizer2"); }); } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/pulsar/PulsarPropertiesMapperTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/pulsar/PulsarPropertiesMapperTests.java index 283e06c1d45..b168d4f7130 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/pulsar/PulsarPropertiesMapperTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/pulsar/PulsarPropertiesMapperTests.java @@ -41,6 +41,7 @@ import org.springframework.boot.autoconfigure.pulsar.PulsarProperties.Consumer; import org.springframework.pulsar.listener.PulsarContainerProperties; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.BDDMockito.given; import static org.mockito.BDDMockito.then; import static org.mockito.Mockito.mock; @@ -60,7 +61,8 @@ class PulsarPropertiesMapperTests { properties.getClient().setOperationTimeout(Duration.ofSeconds(2)); properties.getClient().setLookupTimeout(Duration.ofSeconds(3)); ClientBuilder builder = mock(ClientBuilder.class); - new PulsarPropertiesMapper(properties).customizeClientBuilder(builder); + new PulsarPropertiesMapper(properties).customizeClientBuilder(builder, + new PropertiesPulsarConnectionDetails(properties)); then(builder).should().serviceUrl("https://example.com"); then(builder).should().connectionTimeout(1000, TimeUnit.MILLISECONDS); then(builder).should().operationTimeout(2000, TimeUnit.MILLISECONDS); @@ -74,10 +76,22 @@ class PulsarPropertiesMapperTests { properties.getClient().getAuthentication().setPluginClassName("myclass"); properties.getClient().getAuthentication().setParam(params); ClientBuilder builder = mock(ClientBuilder.class); - new PulsarPropertiesMapper(properties).customizeClientBuilder(builder); + new PulsarPropertiesMapper(properties).customizeClientBuilder(builder, + new PropertiesPulsarConnectionDetails(properties)); then(builder).should().authentication("myclass", params); } + @Test + void customizeClientBuilderWhenHasConnectionDetails() { + PulsarProperties properties = new PulsarProperties(); + properties.getClient().setServiceUrl("https://ignored.example.com"); + ClientBuilder builder = mock(ClientBuilder.class); + PulsarConnectionDetails connectionDetails = mock(PulsarConnectionDetails.class); + given(connectionDetails.getBrokerUrl()).willReturn("https://used.example.com"); + new PulsarPropertiesMapper(properties).customizeClientBuilder(builder, connectionDetails); + then(builder).should().serviceUrl("https://used.example.com"); + } + @Test void customizeAdminBuilderWhenHasNoAuthentication() { PulsarProperties properties = new PulsarProperties(); @@ -86,7 +100,8 @@ class PulsarPropertiesMapperTests { properties.getAdmin().setReadTimeout(Duration.ofSeconds(2)); properties.getAdmin().setRequestTimeout(Duration.ofSeconds(3)); PulsarAdminBuilder builder = mock(PulsarAdminBuilder.class); - new PulsarPropertiesMapper(properties).customizeAdminBuilder(builder); + new PulsarPropertiesMapper(properties).customizeAdminBuilder(builder, + new PropertiesPulsarConnectionDetails(properties)); then(builder).should().serviceHttpUrl("https://example.com"); then(builder).should().connectionTimeout(1000, TimeUnit.MILLISECONDS); then(builder).should().readTimeout(2000, TimeUnit.MILLISECONDS); @@ -100,10 +115,22 @@ class PulsarPropertiesMapperTests { properties.getAdmin().getAuthentication().setPluginClassName("myclass"); properties.getAdmin().getAuthentication().setParam(params); PulsarAdminBuilder builder = mock(PulsarAdminBuilder.class); - new PulsarPropertiesMapper(properties).customizeAdminBuilder(builder); + new PulsarPropertiesMapper(properties).customizeAdminBuilder(builder, + new PropertiesPulsarConnectionDetails(properties)); then(builder).should().authentication("myclass", params); } + @Test + void customizeAdminBuilderWhenHasConnectionDetails() { + PulsarProperties properties = new PulsarProperties(); + properties.getAdmin().setServiceUrl("https://ignored.example.com"); + PulsarAdminBuilder builder = mock(PulsarAdminBuilder.class); + PulsarConnectionDetails connectionDetails = mock(PulsarConnectionDetails.class); + given(connectionDetails.getAdminUrl()).willReturn("https://used.example.com"); + new PulsarPropertiesMapper(properties).customizeAdminBuilder(builder, connectionDetails); + then(builder).should().serviceHttpUrl("https://used.example.com"); + } + @Test @SuppressWarnings("unchecked") void customizeProducerBuilder() { diff --git a/spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/service/connection/pulsar/PulsarDockerComposeConnectionDetailsFactory.java b/spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/service/connection/pulsar/PulsarDockerComposeConnectionDetailsFactory.java index c9817d34851..0568a981193 100644 --- a/spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/service/connection/pulsar/PulsarDockerComposeConnectionDetailsFactory.java +++ b/spring-boot-project/spring-boot-docker-compose/src/main/java/org/springframework/boot/docker/compose/service/connection/pulsar/PulsarDockerComposeConnectionDetailsFactory.java @@ -17,6 +17,7 @@ package org.springframework.boot.docker.compose.service.connection.pulsar; import org.springframework.boot.autoconfigure.pulsar.PulsarConnectionDetails; +import org.springframework.boot.docker.compose.core.ConnectionPorts; import org.springframework.boot.docker.compose.core.RunningService; import org.springframework.boot.docker.compose.service.connection.DockerComposeConnectionDetailsFactory; import org.springframework.boot.docker.compose.service.connection.DockerComposeConnectionSource; @@ -30,9 +31,9 @@ import org.springframework.boot.docker.compose.service.connection.DockerComposeC class PulsarDockerComposeConnectionDetailsFactory extends DockerComposeConnectionDetailsFactory { - private static final int PULSAR_BROKER_PORT = 6650; + private static final int BROKER_PORT = 6650; - private static final int PULSAR_ADMIN_PORT = 8080; + private static final int ADMIN_PORT = 8080; PulsarDockerComposeConnectionDetailsFactory() { super("apachepulsar/pulsar"); @@ -55,17 +56,18 @@ class PulsarDockerComposeConnectionDetailsFactory PulsarDockerComposeConnectionDetails(RunningService service) { super(service); - this.brokerUrl = "pulsar://%s:%s".formatted(service.host(), service.ports().get(PULSAR_BROKER_PORT)); - this.adminUrl = "http://%s:%s".formatted(service.host(), service.ports().get(PULSAR_ADMIN_PORT)); + ConnectionPorts ports = service.ports(); + this.brokerUrl = "pulsar://%s:%s".formatted(service.host(), ports.get(BROKER_PORT)); + this.adminUrl = "http://%s:%s".formatted(service.host(), ports.get(ADMIN_PORT)); } @Override - public String getPulsarBrokerUrl() { + public String getBrokerUrl() { return this.brokerUrl; } @Override - public String getPulsarAdminUrl() { + public String getAdminUrl() { return this.adminUrl; } diff --git a/spring-boot-project/spring-boot-docker-compose/src/test/java/org/springframework/boot/docker/compose/service/connection/pulsar/PulsarDockerComposeConnectionDetailsFactoryIntegrationTests.java b/spring-boot-project/spring-boot-docker-compose/src/test/java/org/springframework/boot/docker/compose/service/connection/pulsar/PulsarDockerComposeConnectionDetailsFactoryIntegrationTests.java index ed509613f5d..c4c18d55ba0 100644 --- a/spring-boot-project/spring-boot-docker-compose/src/test/java/org/springframework/boot/docker/compose/service/connection/pulsar/PulsarDockerComposeConnectionDetailsFactoryIntegrationTests.java +++ b/spring-boot-project/spring-boot-docker-compose/src/test/java/org/springframework/boot/docker/compose/service/connection/pulsar/PulsarDockerComposeConnectionDetailsFactoryIntegrationTests.java @@ -39,8 +39,8 @@ class PulsarDockerComposeConnectionDetailsFactoryIntegrationTests extends Abstra void runCreatesConnectionDetails() { PulsarConnectionDetails connectionDetails = run(PulsarConnectionDetails.class); assertThat(connectionDetails).isNotNull(); - assertThat(connectionDetails.getPulsarBrokerUrl()).matches("^pulsar:\\/\\/\\S+:\\d+"); - assertThat(connectionDetails.getPulsarAdminUrl()).matches("^http:\\/\\/\\S+:\\d+"); + assertThat(connectionDetails.getBrokerUrl()).matches("^pulsar:\\/\\/\\S+:\\d+"); + assertThat(connectionDetails.getAdminUrl()).matches("^http:\\/\\/\\S+:\\d+"); } } diff --git a/spring-boot-project/spring-boot-testcontainers/build.gradle b/spring-boot-project/spring-boot-testcontainers/build.gradle index 67fdb986038..d09e6d485f2 100644 --- a/spring-boot-project/spring-boot-testcontainers/build.gradle +++ b/spring-boot-project/spring-boot-testcontainers/build.gradle @@ -56,8 +56,3 @@ dependencies { testRuntimeOnly("com.oracle.database.r2dbc:oracle-r2dbc") } - -test { - jvmArgs += "--add-opens=java.base/java.net=ALL-UNNAMED" - jvmArgs += "--add-opens=java.base/sun.net=ALL-UNNAMED" -} diff --git a/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection/pulsar/PulsarContainerConnectionDetailsFactory.java b/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection/pulsar/PulsarContainerConnectionDetailsFactory.java index 505a8e564e1..836c1a127d2 100644 --- a/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection/pulsar/PulsarContainerConnectionDetailsFactory.java +++ b/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection/pulsar/PulsarContainerConnectionDetailsFactory.java @@ -48,12 +48,12 @@ class PulsarContainerConnectionDetailsFactory } @Override - public String getPulsarBrokerUrl() { + public String getBrokerUrl() { return getContainer().getPulsarBrokerUrl(); } @Override - public String getPulsarAdminUrl() { + public String getAdminUrl() { return getContainer().getHttpServiceUrl(); } diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-pulsar/src/test/java/smoketest/pulsar/SamplePulsarApplicationTests.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-pulsar/src/test/java/smoketest/pulsar/SamplePulsarApplicationTests.java index a7e6734e0db..c58c743cc8d 100644 --- a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-pulsar/src/test/java/smoketest/pulsar/SamplePulsarApplicationTests.java +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-pulsar/src/test/java/smoketest/pulsar/SamplePulsarApplicationTests.java @@ -44,7 +44,6 @@ class SamplePulsarApplicationTests { @Container @ServiceConnection - @SuppressWarnings("unused") static final PulsarContainer container = new PulsarContainer(DockerImageNames.pulsar()).withStartupAttempts(2) .withStartupTimeout(Duration.ofMinutes(3));