Search code examples
javainheritanceejbjavabeanscode-injection

How can an injected superclass Bean get the wrong instance ( subclass Bean instance) injected?


Problem: I had some unexpected behaviour when injecting a Bean(In a filter) with 2 subclasses which I injected in two other classes (Servlets). Now the injected superclass could hold a reference to a subclass instance at runtime (changeing with each container restart).

I must have made a serious mistake but I can't quite figure out what exactly.

Additional information:

I use Java EE6

Class structure:

In the filter I inject the super class which holds a random instance to one of the subclasses or the superclass:

@EJB
private ClientLogger clientLogger;

The super class been starts like this:

@Stateless
@LocalBean
public class ClientLogger implements HcpEntityBeanLogger<Client> {

private Client client;

public ClientLogger(){
}

....

}

This subclass bean I inject in one of my Servlets:

@Stateless
@LocalBean
public class AdminClientLogger extends ClientLogger {

public AdminClientLogger(){
}
...
}

Solution attempt:

So as far as I understand the subclass which gets last injected will be the instance referenced by clientLogger, but why, why can't I have 3 different instances and use inheritance here?

Edit: I faced this problem again when injecting multiple query beans which all implement the same interface, all of them would hold a reference to the same instance.

The solution was to add beanName wenn injecting the interface with EJB

@EJB(beanName="name of your bean class or name specified in @Stateless(name=".."))

Solution

  • So basically this happens when you forget to reference to the concrete sub class. Then the container will apparently just inject the same instance of one of the concrete classes;

    There are a number of ways to reference the concrete class:

    lookup (example from @NiranjanBhat)

     @EJB(lookup="java:global/rest/AdminClientLogger")
      private ClientLogger clientLogger;
    

    beanName

    @EJB(beanName="name of your bean class or name specified in @Stateless(name=".."))
    

    there is also