spring-projects / spring-projects/spring-boot
Using @ServiceConnection on a Container @Bean method does not work with AOT-processed tests
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 81.5k
- Forks
- 42.7k
- Avg merge
- 2d 4h
- Merged PRs (30d)
- 65
Description
Spring Boot application fails to run the nativeTest task with Testcontainers.
I generated a simple project using start.spring.io:
On the first run, it fails due to a reflection issue:
...
o.t.d.DockerClientProviderStrategy : Could not find a valid Docker environment. Please check configuration. Attempted configurations were:
UnixSocketClientProviderStrategy: failed with exception RuntimeException (org.testcontainers.shaded.com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of com.github.dockerjava.api.model.RuntimeInfo: no suitable constructor found, can not deserialize from Object value (missing default constructor or creator, or perhaps need to add/enable type information?)
at [Source: N/A; line: -1, column: -1] (through reference chain: com.github.dockerjava.api.model.Info["Runtimes"]->java.util.LinkedHashMap["io.containerd.runc.v2"])). Root cause JsonMappingException (Can not construct instance of com.github.dockerjava.api.model.RuntimeInfo: no suitable constructor found, can not deserialize from Object value (missing default constructor or creator, or perhaps need to add/enable type information?)
at [Source: N/A; line: -1, column: -1] (through reference chain: com.github.dockerjava.api.model.Info["Runtimes"]->java.util.LinkedHashMap["io.containerd.runc.v2"]))
DockerDesktopClientProviderStrategy: failed with exception RuntimeException (org.testcontainers.shaded.com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of com.github.dockerjava.api.model.RuntimeInfo: no suitable constructor found, can not deserialize from Object value (missing default constructor or creator, or perhaps need to add/enable type information?)
at [Source: N/A; line: -1, column: -1] (through reference chain: com.github.dockerjava.api.model.Info["Runtimes"]->java.util.LinkedHashMap["io.containerd.runc.v2"])). Root cause JsonMappingException (Can not construct instance of com.github.dockerjava.api.model.RuntimeInfo: no suitable constructor found, can not deserialize from Object value (missing default constructor or creator, or perhaps need to add/enable type information?)
at [Source: N/A; line: -1, column: -1] (through reference chain: com.github.dockerjava.api.model.Info["Runtimes"]->java.util.LinkedHashMap["io.containerd.runc.v2"]))As no valid configuration was found, execution cannot continue.
See https://java.testcontainers.org/on_failure.html for more details.
...
I solved this issue by adding a reflect.json file in src/test/resources/META-INF/native-image/ with the following content::
[
{
"name":"com.github.dockerjava.api.model.RuntimeInfo",
"allDeclaredFields":true,
"queryAllDeclaredMethods":true,
"queryAllDeclaredConstructors":true,
"methods":[{"name":"<init>","parameterTypes":[] }, {"name":"setPath","parameterTypes":["java.lang.String"] }]
},
{
"name":"com.github.dockerjava.api.model.Info",
"allDeclaredFields":true,
"queryAllDeclaredMethods":true,
"queryAllDeclaredConstructors":true,
"methods":[{"name":"<init>","parameterTypes":[] }]
}
]
However, I'm confused because Testcontainers seems to be supported by GraalVM as indicated here: https://www.graalvm.org/native-image/libraries-and-frameworks/
With that configuration, I encountered another issue that I'm unsure how to resolve:
> Task :nativeTest
JUnit Platform on Native Image - report
----------------------------------------
12:37:58.794 [main] INFO org.springframework.test.context.support.AnnotationConfigContextLoaderUtils -- Could not detect default configuration classes for test class [com.example.demo.DemoApplicationTests]: DemoApplicationTests does not declare any static, non-private, non-final, nested classes annotated with @Configuration.
12:37:58.797 [main] INFO org.springframework.boot.test.context.SpringBootTestContextBootstrapper -- Found @SpringBootConfiguration com.example.demo.DemoApplication for test class com.example.demo.DemoApplicationTests
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v3.3.4)
2024-10-23T12:37:58.813+02:00 INFO 9667 --- [demo] [ main] com.example.demo.DemoApplicationTests : Starting AOT-processed DemoApplicationTests using Java 21.0.4 with PID 9667 (started by rowickim in /private/tmp/demo)
2024-10-23T12:37:58.813+02:00 INFO 9667 --- [demo] [ main] com.example.demo.DemoApplicationTests : No active profile set, falling back to 1 default profile: "default"
2024-10-23T12:37:58.816+02:00 INFO 9667 --- [demo] [ main] org.testcontainers.images.PullPolicy : Image pull policy will be performed by: DefaultPullPolicy()
2024-10-23T12:37:58.816+02:00 INFO 9667 --- [demo] [ main] o.t.utility.ImageNameSubstitutor : Image name substitution will be performed by: DefaultImageNameSubstitutor (composite of 'ConfigurationFileImageNameSubstitutor' and 'PrefixingImageNameSubstitutor')
2024-10-23T12:37:58.825+02:00 INFO 9667 --- [demo] [ main] o.t.d.DockerClientProviderStrategy : Loaded org.testcontainers.dockerclient.UnixSocketClientProviderStrategy from ~/.testcontainers.properties, will try it first
2024-10-23T12:37:58.846+02:00 INFO 9667 --- [demo] [ main] o.t.d.DockerClientProviderStrategy : Found Docker environment with local Unix socket (unix:///var/run/docker.sock)
2024-10-23T12:37:58.847+02:00 INFO 9667 --- [demo] [ main] org.testcontainers.DockerClientFactory : Docker host IP address is localhost
2024-10-23T12:37:58.852+02:00 INFO 9667 --- [demo] [ main] org.testcontainers.DockerClientFactory : Connected to docker:
Server Version: 27.2.0
API Version: 1.47
Operating System: Docker Desktop
Total Memory: 7838 MB
2024-10-23T12:37:58.852+02:00 WARN 9667 --- [demo] [ main] o.testcontainers.utility.ResourceReaper :
********************************************************************************
Ryuk has been disabled. This can cause unexpected behavior in your environment.
********************************************************************************
2024-10-23T12:37:58.852+02:00 INFO 9667 --- [demo] [ main] org.testcontainers.DockerClientFactory : Checking the system...
2024-10-23T12:37:58.852+02:00 INFO 9667 --- [demo] [ main] org.testcontainers.DockerClientFactory : ✔︎ Docker server version should be at least 1.6.0
2024-10-23T12:37:58.859+02:00 INFO 9667 --- [demo] [ main] tc.mongo:latest : Creating container for image: mongo:latest
2024-10-23T12:37:59.004+02:00 INFO 9667 --- [demo] [ main] tc.mongo:latest : Container mongo:latest is starting: cb2dd662645f26c2cb8ffdf5dd73d4332628b60c2a5e6487fcfe101c4480456e
2024-10-23T12:37:59.877+02:00 INFO 9667 --- [demo] [ main] tc.mongo:latest : Container mongo:latest started in PT1.018256S
2024-10-23T12:38:00.339+02:00 WARN 9667 --- [demo] [ main] o.s.c.support.GenericApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'standardMongoSettingsCustomizer': Unsatisfied dependency expressed through method 'standardMongoSettingsCustomizer' parameter 1: No qualifying bean of type 'org.springframework.boot.autoconfigure.mongo.MongoConnectionDetails' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
It looks like the task aotTestClasses doesn't add any MongoConnectionDetails to the application context.
Here is the zipped project for reference: demo.zip
Environment Details
I'm using the following version of GraalVM:
❯ java -version
java version "21.0.4" 2024-07-16 LTS
Java(TM) SE Runtime Environment Oracle GraalVM 21.0.4+8.1 (build 21.0.4+8-LTS-jvmci-23.1-b41)
Java HotSpot(TM) 64-Bit Server VM Oracle GraalVM 21.0.4+8.1 (build 21.0.4+8-LTS-jvmci-23.1-b41, mixed mode, sharing)
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reproducing the reported nativeTest failure from the attached generated project and inspect what aotTestClasses contributes to the AOT-processed test context. Compare the failing @ServiceConnection container setup with the missing MongoConnectionDetails bean; done means the nativeTest task starts the Mongo container, creates the connection details, and completes successfully.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- docker, java, mongodb, spring-boot
- Domain
- backend, build-system, testing-qa
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100