[
https://issues.redhat.com/browse/WFLY-14254?page=com.atlassian.jira.plugi...
]
Matěj Novotný commented on WFLY-14254:
--------------------------------------
Hmm, the only thing I can think of is that you are combining EJB and CDI annotations -
{{javax.ejb.Singleton}} with {{javax.inject.Singleton}}.
EJB beans have to be initialized by EJB container and CDI container just takes them from
there and performs additional actions such as CDI injection.
Now, with constructor injection, this can create some cyclic dependencies that are
unexpected (and undefined by specifications) - in this case I _think_ it might be the fact
that the EJB singleton is not deemed "complete" until its constructed by EJB and
injected into by CDI. And while CDI tries to perform injection, it will have to construct
{{Child}}, which in turn requires {{Parent}}. And that one wasn't fully constructed
and is not yet registered as bean so an attempt to make new one occurs.
Basically, this is grey area between specs because they don't exactly specify how EJB
and CDI container interoperate and it might (and likely will) differ between EE server
implementations as well as CDI implementations.
BTW if you make the {{Child}} class {{@ApplicationScoped}} instead, it might work because
then there will be a proxy and its init will be lazy - meaning creation and injection into
{{Parent}} will only create the proxy and won't attempt to create {{Child}} bean until
it's used for the first time.
Alternatively, you can OFC use the workaround that you figured out. That's perfectly
fine and will avoid the problem because {{Child}} instance can be created without direct
dependency on {{Parent}}.
WFLYEJB0132: @PostConstruct method of EJB singleton recursively
invoked
-----------------------------------------------------------------------
Key: WFLY-14254
URL:
https://issues.redhat.com/browse/WFLY-14254
Project: WildFly
Issue Type: Bug
Components: CDI / Weld, EE
Affects Versions: 21.0.1.Final
Reporter: nimo stephan
Assignee: Matěj Novotný
Priority: Major
I have following two classes:
The *Parent* class is a "javax.ejb.Singleton" and injects the other Singleton
*Child*:
{code:java}
import javax.annotation.PostConstruct;
import javax.inject.Inject;
@javax.ejb.Singleton
@javax.ejb.Startup
public class Parent {
@Inject
private Child child;
@PostConstruct
private void postConstruct() {
System.out.println("> Parent (" + getId() + ") created.");
child.sendMessage();
}
public Integer getId() {
return this.hashCode();
}
}
{code}
The *Child* class is a "javax.inject.Singleton" and injects the other Singleton
*Parent*:
{code:java}
import javax.annotation.PostConstruct;
import javax.inject.Inject;
@javax.inject.Singleton
//(a)javax.ejb.Singleton
public class Child {
private Parent parent;
// no-args constructor not needed for @javax.inject.Singleton
public Child() {
}
// the parent should be injected if already created by container
@Inject
public Child(Parent parent) {
this.parent = parent;
}
@PostConstruct
private void postConstruct() {
System.out.println("> Child (" + getId() + ") created.");
}
public void sendMessage() {
System.out.println("> Child called to parent: " + parent.getId());
}
public Integer getId() {
return this.hashCode();
}
}
{code}
As both are Singletons, the "postConstruct()" for those two classes should only
be called once. The Child uses a constructor with an injected Parent thus it should look
for it if this instance is already created. However, it seems that the container tries to
create the Parent-Instance twice, hence the following error:
{code:java}
Caused by: java.lang.IllegalStateException: WFLYEJB0132: @PostConstruct method of EJB
singleton Parent of type io.Parent has been recursively invoked
at
org.jboss.as.ejb3@21.0.0.Final//org.jboss.as.ejb3.component.singleton.SingletonComponent.getComponentInstance(SingletonComponent.java:124)
at
org.jboss.as.ejb3@21.0.0.Final//org.jboss.as.ejb3.component.singleton.SingletonComponentInstanceAssociationInterceptor.processInvocation(SingletonComponentInstanceAssociationInterceptor.java:48)
at
org.jboss.invocation@1.6.0.Final//org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:422)
at
org.jboss.as.ejb3@21.0.0.Final//org.jboss.as.ejb3.component.interceptors.AdditionalSetupInterceptor.processInvocation(AdditionalSetupInterceptor.java:54)
at
org.jboss.invocation@1.6.0.Final//org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:422)
at
org.jboss.as.ejb3@21.0.0.Final//org.jboss.as.ejb3.tx.CMTTxInterceptor.invokeInCallerTx(CMTTxInterceptor.java:199)
... 101 more{code}
Of course, I can use "@Inject Parent parent" within the Singleton
"Child" instead of constructor injection, then no error is shown. However,
constructor injection should also work, or? Is this a bug or is this intended?
--
This message was sent by Atlassian Jira
(v8.13.1#813001)