From 73685d1d02ea2574392249ab3a36e76378f104c9 Mon Sep 17 00:00:00 2001 From: Moritz Halbritter Date: Wed, 25 Oct 2023 10:17:44 +0200 Subject: [PATCH] Register required class names for reflection in Testcontainer factory Closes gh-36606 --- .../ContainerConnectionDetailsFactory.java | 10 ++++- .../resources/META-INF/spring/aot.factories | 12 +++++- ...ontainerConnectionDetailsFactoryTests.java | 41 +++++++++++++++++++ ...ontainerConnectionDetailsFactoryTests.java | 41 +++++++++++++++++++ ...ontainerConnectionDetailsFactoryTests.java | 41 +++++++++++++++++++ ...ontainerConnectionDetailsFactoryTests.java | 41 +++++++++++++++++++ ...ontainerConnectionDetailsFactoryTests.java | 10 +++++ ...ontainerConnectionDetailsFactoryTests.java | 41 +++++++++++++++++++ ...ontainerConnectionDetailsFactoryTests.java | 41 +++++++++++++++++++ ...ontainerConnectionDetailsFactoryTests.java | 41 +++++++++++++++++++ 10 files changed, 317 insertions(+), 2 deletions(-) create mode 100644 spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/service/connection/mongo/MongoContainerConnectionDetailsFactoryTests.java create mode 100644 spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/service/connection/neo4j/Neo4jContainerConnectionDetailsFactoryTests.java create mode 100644 spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/service/connection/r2dbc/MariaDbR2dbcContainerConnectionDetailsFactoryTests.java create mode 100644 spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/service/connection/r2dbc/MySqlR2dbcContainerConnectionDetailsFactoryTests.java create mode 100644 spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/service/connection/r2dbc/PostgresR2dbcContainerConnectionDetailsFactoryTests.java create mode 100644 spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/service/connection/r2dbc/SqlServerR2dbcContainerConnectionDetailsFactoryTests.java create mode 100644 spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/service/connection/zipkin/ZipkinContainerConnectionDetailsFactoryTests.java diff --git a/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection/ContainerConnectionDetailsFactory.java b/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection/ContainerConnectionDetailsFactory.java index c4f01a7ad34..174b84d103d 100644 --- a/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection/ContainerConnectionDetailsFactory.java +++ b/spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection/ContainerConnectionDetailsFactory.java @@ -20,6 +20,8 @@ import java.util.Arrays; import org.testcontainers.containers.Container; +import org.springframework.aot.hint.RuntimeHints; +import org.springframework.aot.hint.RuntimeHintsRegistrar; import org.springframework.beans.factory.InitializingBean; import org.springframework.boot.autoconfigure.service.connection.ConnectionDetails; import org.springframework.boot.autoconfigure.service.connection.ConnectionDetailsFactory; @@ -42,7 +44,7 @@ import org.springframework.util.ObjectUtils; * @since 3.1.0 */ public abstract class ContainerConnectionDetailsFactory, D extends ConnectionDetails> - implements ConnectionDetailsFactory, D> { + implements ConnectionDetailsFactory, D>, RuntimeHintsRegistrar { /** * Constant passed to the constructor when any connection name is accepted. @@ -90,6 +92,12 @@ public abstract class ContainerConnectionDetailsFactory, return null; } + @Override + public void registerHints(RuntimeHints hints, ClassLoader classLoader) { + Arrays.stream(this.requiredClassNames) + .forEach((clazz) -> hints.reflection().registerTypeIfPresent(classLoader, clazz)); + } + private boolean hasRequiredClasses() { return ObjectUtils.isEmpty(this.requiredClassNames) || Arrays.stream(this.requiredClassNames) .allMatch((requiredClassName) -> ClassUtils.isPresent(requiredClassName, null)); diff --git a/spring-boot-project/spring-boot-testcontainers/src/main/resources/META-INF/spring/aot.factories b/spring-boot-project/spring-boot-testcontainers/src/main/resources/META-INF/spring/aot.factories index 52cbdbe6b16..a4aa3dfc74e 100644 --- a/spring-boot-project/spring-boot-testcontainers/src/main/resources/META-INF/spring/aot.factories +++ b/spring-boot-project/spring-boot-testcontainers/src/main/resources/META-INF/spring/aot.factories @@ -1,2 +1,12 @@ org.springframework.beans.factory.aot.BeanRegistrationExcludeFilter=\ -org.springframework.boot.testcontainers.service.connection.ConnectionDetailsRegistrar.ServiceConnectionBeanRegistrationExcludeFilter \ No newline at end of file +org.springframework.boot.testcontainers.service.connection.ConnectionDetailsRegistrar.ServiceConnectionBeanRegistrationExcludeFilter + +org.springframework.aot.hint.RuntimeHintsRegistrar=\ +org.springframework.boot.testcontainers.service.connection.mongo.MongoContainerConnectionDetailsFactory,\ +org.springframework.boot.testcontainers.service.connection.neo4j.Neo4jContainerConnectionDetailsFactory,\ +org.springframework.boot.testcontainers.service.connection.r2dbc.MariaDbR2dbcContainerConnectionDetailsFactory,\ +org.springframework.boot.testcontainers.service.connection.r2dbc.MySqlR2dbcContainerConnectionDetailsFactory,\ +org.springframework.boot.testcontainers.service.connection.r2dbc.OracleR2dbcContainerConnectionDetailsFactory,\ +org.springframework.boot.testcontainers.service.connection.r2dbc.PostgresR2dbcContainerConnectionDetailsFactory,\ +org.springframework.boot.testcontainers.service.connection.r2dbc.SqlServerR2dbcContainerConnectionDetailsFactory,\ +org.springframework.boot.testcontainers.service.connection.zipkin.ZipkinContainerConnectionDetailsFactory diff --git a/spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/service/connection/mongo/MongoContainerConnectionDetailsFactoryTests.java b/spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/service/connection/mongo/MongoContainerConnectionDetailsFactoryTests.java new file mode 100644 index 00000000000..812ce2b9dcd --- /dev/null +++ b/spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/service/connection/mongo/MongoContainerConnectionDetailsFactoryTests.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.testcontainers.service.connection.mongo; + +import com.mongodb.ConnectionString; +import org.junit.jupiter.api.Test; + +import org.springframework.aot.hint.RuntimeHints; +import org.springframework.aot.hint.predicate.RuntimeHintsPredicates; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link MongoContainerConnectionDetailsFactory}. + * + * @author Moritz Halbritter + */ +class MongoContainerConnectionDetailsFactoryTests { + + @Test + void shouldRegisterHints() { + RuntimeHints hints = new RuntimeHints(); + new MongoContainerConnectionDetailsFactory().registerHints(hints, getClass().getClassLoader()); + assertThat(RuntimeHintsPredicates.reflection().onType(ConnectionString.class)).accepts(hints); + } + +} diff --git a/spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/service/connection/neo4j/Neo4jContainerConnectionDetailsFactoryTests.java b/spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/service/connection/neo4j/Neo4jContainerConnectionDetailsFactoryTests.java new file mode 100644 index 00000000000..f1f962745a0 --- /dev/null +++ b/spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/service/connection/neo4j/Neo4jContainerConnectionDetailsFactoryTests.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.testcontainers.service.connection.neo4j; + +import org.junit.jupiter.api.Test; +import org.neo4j.driver.AuthToken; + +import org.springframework.aot.hint.RuntimeHints; +import org.springframework.aot.hint.predicate.RuntimeHintsPredicates; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link Neo4jContainerConnectionDetailsFactory}. + * + * @author Moritz Halbritter + */ +class Neo4jContainerConnectionDetailsFactoryTests { + + @Test + void shouldRegisterHints() { + RuntimeHints hints = new RuntimeHints(); + new Neo4jContainerConnectionDetailsFactory().registerHints(hints, getClass().getClassLoader()); + assertThat(RuntimeHintsPredicates.reflection().onType(AuthToken.class)).accepts(hints); + } + +} diff --git a/spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/service/connection/r2dbc/MariaDbR2dbcContainerConnectionDetailsFactoryTests.java b/spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/service/connection/r2dbc/MariaDbR2dbcContainerConnectionDetailsFactoryTests.java new file mode 100644 index 00000000000..ed4d79b46a5 --- /dev/null +++ b/spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/service/connection/r2dbc/MariaDbR2dbcContainerConnectionDetailsFactoryTests.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.testcontainers.service.connection.r2dbc; + +import io.r2dbc.spi.ConnectionFactoryOptions; +import org.junit.jupiter.api.Test; + +import org.springframework.aot.hint.RuntimeHints; +import org.springframework.aot.hint.predicate.RuntimeHintsPredicates; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link MariaDbR2dbcContainerConnectionDetailsFactory}. + * + * @author Moritz Halbritter + */ +class MariaDbR2dbcContainerConnectionDetailsFactoryTests { + + @Test + void shouldRegisterHints() { + RuntimeHints hints = new RuntimeHints(); + new MariaDbR2dbcContainerConnectionDetailsFactory().registerHints(hints, getClass().getClassLoader()); + assertThat(RuntimeHintsPredicates.reflection().onType(ConnectionFactoryOptions.class)).accepts(hints); + } + +} diff --git a/spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/service/connection/r2dbc/MySqlR2dbcContainerConnectionDetailsFactoryTests.java b/spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/service/connection/r2dbc/MySqlR2dbcContainerConnectionDetailsFactoryTests.java new file mode 100644 index 00000000000..d7717c5b9d6 --- /dev/null +++ b/spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/service/connection/r2dbc/MySqlR2dbcContainerConnectionDetailsFactoryTests.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.testcontainers.service.connection.r2dbc; + +import io.r2dbc.spi.ConnectionFactoryOptions; +import org.junit.jupiter.api.Test; + +import org.springframework.aot.hint.RuntimeHints; +import org.springframework.aot.hint.predicate.RuntimeHintsPredicates; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link MySqlR2dbcContainerConnectionDetailsFactory}. + * + * @author Moritz Halbritter + */ +class MySqlR2dbcContainerConnectionDetailsFactoryTests { + + @Test + void shouldRegisterHints() { + RuntimeHints hints = new RuntimeHints(); + new MySqlR2dbcContainerConnectionDetailsFactory().registerHints(hints, getClass().getClassLoader()); + assertThat(RuntimeHintsPredicates.reflection().onType(ConnectionFactoryOptions.class)).accepts(hints); + } + +} diff --git a/spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/service/connection/r2dbc/OracleR2dbcContainerConnectionDetailsFactoryTests.java b/spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/service/connection/r2dbc/OracleR2dbcContainerConnectionDetailsFactoryTests.java index f4b03d4fefe..a21ec3c6e45 100644 --- a/spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/service/connection/r2dbc/OracleR2dbcContainerConnectionDetailsFactoryTests.java +++ b/spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/service/connection/r2dbc/OracleR2dbcContainerConnectionDetailsFactoryTests.java @@ -19,12 +19,15 @@ package org.springframework.boot.testcontainers.service.connection.r2dbc; import java.time.Duration; import io.r2dbc.spi.ConnectionFactory; +import io.r2dbc.spi.ConnectionFactoryOptions; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.OS; import org.testcontainers.containers.OracleContainer; import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; +import org.springframework.aot.hint.RuntimeHints; +import org.springframework.aot.hint.predicate.RuntimeHintsPredicates; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.ImportAutoConfiguration; import org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration; @@ -67,6 +70,13 @@ class OracleR2dbcContainerConnectionDetailsFactoryTests { assertThat(result).isEqualTo("Hello"); } + @Test + void shouldRegisterHints() { + RuntimeHints hints = new RuntimeHints(); + new OracleR2dbcContainerConnectionDetailsFactory().registerHints(hints, getClass().getClassLoader()); + assertThat(RuntimeHintsPredicates.reflection().onType(ConnectionFactoryOptions.class)).accepts(hints); + } + @Configuration(proxyBeanMethods = false) @ImportAutoConfiguration(R2dbcAutoConfiguration.class) static class TestConfiguration { diff --git a/spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/service/connection/r2dbc/PostgresR2dbcContainerConnectionDetailsFactoryTests.java b/spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/service/connection/r2dbc/PostgresR2dbcContainerConnectionDetailsFactoryTests.java new file mode 100644 index 00000000000..2780f04d8ef --- /dev/null +++ b/spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/service/connection/r2dbc/PostgresR2dbcContainerConnectionDetailsFactoryTests.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.testcontainers.service.connection.r2dbc; + +import io.r2dbc.spi.ConnectionFactoryOptions; +import org.junit.jupiter.api.Test; + +import org.springframework.aot.hint.RuntimeHints; +import org.springframework.aot.hint.predicate.RuntimeHintsPredicates; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link PostgresR2dbcContainerConnectionDetailsFactory}. + * + * @author Moritz Halbritter + */ +class PostgresR2dbcContainerConnectionDetailsFactoryTests { + + @Test + void shouldRegisterHints() { + RuntimeHints hints = new RuntimeHints(); + new PostgresR2dbcContainerConnectionDetailsFactory().registerHints(hints, getClass().getClassLoader()); + assertThat(RuntimeHintsPredicates.reflection().onType(ConnectionFactoryOptions.class)).accepts(hints); + } + +} diff --git a/spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/service/connection/r2dbc/SqlServerR2dbcContainerConnectionDetailsFactoryTests.java b/spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/service/connection/r2dbc/SqlServerR2dbcContainerConnectionDetailsFactoryTests.java new file mode 100644 index 00000000000..73a5f3a6307 --- /dev/null +++ b/spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/service/connection/r2dbc/SqlServerR2dbcContainerConnectionDetailsFactoryTests.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.testcontainers.service.connection.r2dbc; + +import io.r2dbc.spi.ConnectionFactoryOptions; +import org.junit.jupiter.api.Test; + +import org.springframework.aot.hint.RuntimeHints; +import org.springframework.aot.hint.predicate.RuntimeHintsPredicates; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link SqlServerR2dbcContainerConnectionDetailsFactory}. + * + * @author Moritz Halbritter + */ +class SqlServerR2dbcContainerConnectionDetailsFactoryTests { + + @Test + void shouldRegisterHints() { + RuntimeHints hints = new RuntimeHints(); + new SqlServerR2dbcContainerConnectionDetailsFactory().registerHints(hints, getClass().getClassLoader()); + assertThat(RuntimeHintsPredicates.reflection().onType(ConnectionFactoryOptions.class)).accepts(hints); + } + +} diff --git a/spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/service/connection/zipkin/ZipkinContainerConnectionDetailsFactoryTests.java b/spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/service/connection/zipkin/ZipkinContainerConnectionDetailsFactoryTests.java new file mode 100644 index 00000000000..6e9def4f46f --- /dev/null +++ b/spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/service/connection/zipkin/ZipkinContainerConnectionDetailsFactoryTests.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.testcontainers.service.connection.zipkin; + +import org.junit.jupiter.api.Test; + +import org.springframework.aot.hint.RuntimeHints; +import org.springframework.aot.hint.predicate.RuntimeHintsPredicates; +import org.springframework.boot.actuate.autoconfigure.tracing.zipkin.ZipkinAutoConfiguration; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link ZipkinContainerConnectionDetailsFactory}. + * + * @author Moritz Halbritter + */ +class ZipkinContainerConnectionDetailsFactoryTests { + + @Test + void shouldRegisterHints() { + RuntimeHints hints = new RuntimeHints(); + new ZipkinContainerConnectionDetailsFactory().registerHints(hints, getClass().getClassLoader()); + assertThat(RuntimeHintsPredicates.reflection().onType(ZipkinAutoConfiguration.class)).accepts(hints); + } + +}