Reputation: 11
I am trying to inject two calsses ClassA and ClassB at quarkus's startup event.
public void init(@Observes StartupEvent startupEvent, ClassA a, ClassB b) throws Exception {
}
Classes:
public class ClassA {
public ClassA() {
}
}
public class ClassB {
private final ClassA dependentClass;
public ClassB(ClassA dependentClass) {
this.dependentClass = dependentClass;
}
}
Producers for these two classes are presented below:
@ApplicationScoped
public class Configuration {
@Produces
@Singleton
public ClassA produceA() {
return new ClassA();
}
@Inject
@Produces
@Singleton
public ClassB produceB(ClassA dependentClass) {
return new ClassB(dependentClass);
}
}
As a result, I am getting stackoverflow error:
Caused by: java.lang.StackOverflowError
at io.quarkus.arc.runtime.devconsole.InvocationInterceptor_Bean.create(Unknown Source)
at io.quarkus.arc.runtime.devconsole.InvocationInterceptor_Bean.get(Unknown Source)
at io.quarkus.arc.runtime.devconsole.InvocationInterceptor_Bean.get(Unknown Source)
at org.acme.getting.started.Configuration_Subclass.<init>(Unknown Source)
at org.acme.getting.started.Configuration_Bean.create(Unknown Source)
at org.acme.getting.started.Configuration_Bean.create(Unknown Source)
at io.quarkus.arc.impl.AbstractSharedContext.createInstanceHandle(AbstractSharedContext.java:96)
at io.quarkus.arc.impl.AbstractSharedContext$1.get(AbstractSharedContext.java:29)
at io.quarkus.arc.impl.AbstractSharedContext$1.get(AbstractSharedContext.java:26)
at io.quarkus.arc.impl.LazyValue.get(LazyValue.java:26)
at io.quarkus.arc.impl.ComputingCache.computeIfAbsent(ComputingCache.java:69)
at io.quarkus.arc.impl.AbstractSharedContext.get(AbstractSharedContext.java:26)
at io.quarkus.arc.impl.ClientProxies.getApplicationScopedDelegate(ClientProxies.java:18)
at org.acme.getting.started.Configuration_ClientProxy.arc$delegate(Unknown Source)
at org.acme.getting.started.Configuration_ClientProxy.arc_contextualInstance(Unknown Source)
at org.acme.getting.started.Configuration_ProducerMethod_produceA_612e78438d1b1b670691525f250ee747f2210b1e_Bean.create(Unknown Source)
at org.acme.getting.started.Configuration_ProducerMethod_produceA_612e78438d1b1b670691525f250ee747f2210b1e_Bean.create(Unknown Source)
at io.quarkus.arc.impl.AbstractSharedContext.createInstanceHandle(AbstractSharedContext.java:96)
at io.quarkus.arc.impl.AbstractSharedContext$1.get(AbstractSharedContext.java:29)
at io.quarkus.arc.impl.AbstractSharedContext$1.get(AbstractSharedContext.java:26)
at io.quarkus.arc.impl.LazyValue.get(LazyValue.java:26)
at io.quarkus.arc.impl.ComputingCache.computeIfAbsent(ComputingCache.java:69)
at io.quarkus.arc.impl.AbstractSharedContext.get(AbstractSharedContext.java:26)
at org.acme.getting.started.Configuration_ProducerMethod_produceA_612e78438d1b1b670691525f250ee747f2210b1e_Bean.get(Unknown Source)
at org.acme.getting.started.Configuration_ProducerMethod_produceA_612e78438d1b1b670691525f250ee747f2210b1e_Bean.get(Unknown Source)
at org.acme.getting.started.Configuration_Bean.create(Unknown Source)
at org.acme.getting.started.Configuration_Bean.create(Unknown Source)
at io.quarkus.arc.impl.AbstractSharedContext.createInstanceHandle(AbstractSharedContext.java:96)
at io.quarkus.arc.impl.AbstractSharedContext$1.get(AbstractSharedContext.java:29)
at io.quarkus.arc.impl.AbstractSharedContext$1.get(AbstractSharedContext.java:26)
at io.quarkus.arc.impl.LazyValue.get(LazyValue.java:26)
at io.quarkus.arc.impl.ComputingCache.computeIfAbsent(ComputingCache.java:69)
at io.quarkus.arc.impl.AbstractSharedContext.get(AbstractSharedContext.java:26)
at io.quarkus.arc.impl.ClientProxies.getApplicationScopedDelegate(ClientProxies.java:18)
at org.acme.getting.started.Configuration_ClientProxy.arc$delegate(Unknown Source)
at org.acme.getting.started.Configuration_ClientProxy.arc_contextualInstance(Unknown Source)
at org.acme.getting.started.Configuration_ProducerMethod_produceA_612e78438d1b1b670691525f250ee747f2210b1e_Bean.create(Unknown Source)
at org.acme.getting.started.Configuration_ProducerMethod_produceA_612e78438d1b1b670691525f250ee747f2210b1e_Bean.create(Unknown Source)
Please, advise me does quarkus support such producers? If is doesn't, what is the solution for produce two dependent classes in one Configuration class? My purpose is to place all Singleton producers in one place, but Singleton scope is not applicable for main config file due to https://github.com/quarkusio/quarkus/issues/3241
Upvotes: 1
Views: 632
Reputation: 6597
I'm not like entirely sure, but I believe you need to remove the @Inject
annotation from the produceB
method. Parameters of producer methods are automatically injection points, so from that perspective, the @Inject
annotation is not necessary.
What's worse, the @Inject
annotation actually does something else than designate the parameters as injection points. It makes the method an initializer method (this is sometimes also known as setter injection). This means that to fully construct an instance of Configuration
, the CDI container has to call the produceB
method and pass it an instance of ClassA
(parameters of initializer methods are also injection points). But to be able to obtain an instance of ClassA
, the container needs a fully constructed instance of Configuration
. That's a cycle that, I believe, leads to the stack overflow you observe.
Technically, the specification forbids an initializer method to be annotated @Produces
, so this should lead to an error during build. I guess ArC (the CDI implementation in Quarkus) doesn't check this properly, which is a bug.
Upvotes: 2