Open Jim-Harrington opened 2 years ago
@Import
is for importing beans from other jars. It should not be used for your own classes. Thus having @Singleton
on OciAccessClientMicronaut
and importing it would cause duplicate bean definitions
Thanks for the feedback.
The thing is that the project I'm working in is a library intended to deliver the @Singleton class, so I need an instance of it in the respective test classes. If I don't @Import it, I get a dependency injection error stating that there are no beans of that type to inject. I suspect the reason is that the @Singleton class is in the project "main" source, which is similar to importing beans from a different jar.
We will need an example attached
OK, here are links to the example service and it's test case:
https://github.com/Jim-Harrington/micronaut-import-question/blob/main/src/main/java/com/example/test/TestService.java https://github.com/Jim-Harrington/micronaut-import-question/blob/main/src/test/java/com/example/test/TestServiceTest.java
The key seems to be the properties that the service depends on. If I don't annotate the test case with an @Import containing the properties class, the case fails with a missing bean definition for that class. If I do annotate the test case with an @Import containing the service and properties classes, I get a duplicate bean definition for the service class unless I @Inject with @Any.
Expected Behavior
Not sure this is a bug, but I have not been able to explain it. Mainly, I'm hoping for an explanation that I can use to correct the issue.
In my library project I have a single service:
@Singleton @Requires(property = "gts.oci.enabled", value = "true", defaultValue = "true") public class OciAccessClientMicronaut {
an annotation that adds the service into consuming application contexts:@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Import(classes = {OciAccessClientMicronaut.class, OciAuthPropertiesMicronaut.class, OciObjectStoragePropertiesMicronaut.class, OciStreamingPropertiesMicronaut.class}) public @interface EnableOciAccessClientMicronaut { }
and two test cases that inject it for use:
` @MicronautTest(environments = {"svcon"}, rebuildContext = true) @EnableOciAccessClientMicronaut @TestInstance(TestInstance.Lifecycle.PER_CLASS) public class OciAccessClientMicronautComponentTest {
@Inject //@Any private OciAccessClientMicronaut undertest; `
` @MicronautTest(environments = {"svcoff"}, rebuildContext = true) //@EnableOciAccessClientMicronaut - works at compile time, so we only want one in suite @TestInstance(TestInstance.Lifecycle.PER_CLASS) public class OciAccessClientMicronautServicesOffComponentTest {
@Inject //@Any private OciAccessClientMicronaut undertest = null; ` Expected Behavior:
As there is only the one registration of the service in the project source, I expect there to be just one bean registration for the class. So, the two test cases should successfully execute without any qualifier applied at the injection site.
Actual Behaviour
Instead, with no qualifier at the injections site in the test cases, I get:
Caused by: io.micronaut.context.exceptions.NonUniqueBeanException: Multiple possible bean candidates found: [com.oracle.gbu.gaes.oci.OciAccessClientMicronaut, com.oracle.gbu.gaes.oci.OciAccessClientMicronaut]
After doing some debugging, I figured out that applying the @Any annotation works around the problem, but I feel like I need to know why it's necessary.
One thing I noticed is that there bean reference classes are generated:
target/classes/com/oracle/gbu/gaes/oci:
$OciAccessClientMicronaut$Definition$Reference.class $OciAccessClientMicronaut$Definition.class
target/test-classes/com/oracle/gbu/gaes/oci:
$OciAccessClientMicronautComponentTest$OciAccessClientMicronaut0$Definition$Reference.class $OciAccessClientMicronautComponentTest$OciAccessClientMicronaut0$Definition.class
and these are the source of the twin bean definitions. I understand the one in "main", but why is the one in "test" being generated? As a test, I deleted the classes in "test" and the @Any annotation was no longer necessary.
Steps To Reproduce
No response
Environment Information
OS: Lunux JDK: 11
Example Application
No response
Version
3.2.0