Why this construction works?
@Stateless
public class SomeClass {
@Inject
private SomeClass self;
//...
}
Why is there no infinite recursion of object reference injecting? When does the container realize it's time to stop?
Why this construction works?
@Stateless
public class SomeClass {
@Inject
private SomeClass self;
//...
}
Why is there no infinite recursion of object reference injecting? When does the container realize it's time to stop?
In this particular case you are self-injecting stateless EJB. In case of Wildfly, @Stateless has no correlation to any of CDI scopes, so your bean ends as @Dependent (discussion whether it’s correct or not can be found here https://issues.redhat.com/browse/CDI-414). So, in case of Wildfly it ends with error "WELD-001443: Pseudo scoped bean has circular dependencies".
CDI currently supports circular dependency (in your case self-injecting) when one of the beans (in your case same bean) has normal scope: @RequestScoped, @SessionScoped, @ApplicationScoped, @ConversationScoped.
So @Dependent as pseudo-scope will end in WELD-001443, but other scopes works because framework uses client proxy (if you log @Inject variable you can see that toString() will print info about proxy object). After method is called on this proxy CDI framework does contextual lookup, and this is the reason why no infinite loop happens during initialization of this bean.
For @Dependent, no proxy is used, and direct reference is created. This is purpose of WELD-001443, to protect you from infinite loop.
In addition to the Petr's great answer, one of the core concepts of CDI is that you are actually injecting Proxies, not actual objects. When you invoke a function on the proxy, you are routed to the correct bean instance in the container. This allows self-injection to work, as well as other scenarios like Injecting a RequestScoped bean into an ApplicationScoped (how would this work if the container was injecting actual instances?)