MADforFUNandHappy
MADforFUNandHappy

Reputation: 567

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=".."))

Upvotes: 1

Views: 439

Answers (2)

MADforFUNandHappy
MADforFUNandHappy

Reputation: 567

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

Upvotes: 0

NiranjanBhat
NiranjanBhat

Reputation: 1832

You can use the lookup attribute on the @EJB annotation and get the required subclass injected. E.g.

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

Obviously you would have to change the JNDI lookup path in the example above.

Upvotes: 1

Related Questions