Guido
Guido

Reputation: 47675

Choose EJB to be injected without recompiling

Imagine you have two implementations of a @Local interface

@Local
public interface LocalInterface {
}

@Stateless
public class MyFirstImplementation implements LocalInterface {
}

@Stateless
public class MySecondImplementation implements LocalInterface {
}

And I want to choose, without recompiling the project (that is, at runtime or using an external configuration property) which one (MyFirstImplementation or MySecondImplementation) I want to use.

public class MyClass {
   @EJB
   LocalInterface local;
}

Once one implementation is chosen, it does not have to change. I am using JBoss 5.1 if that helps.

Upvotes: 4

Views: 2635

Answers (3)

Guido
Guido

Reputation: 47675

Another approach is to find the EJB reference with JNDI instead of relying on the automatic injection, just in case it could help anyone else:

public class MyClass {
   LocalInterface local;

   @PostConstruct
   public void init() {
       local = findImplementation();
   }

   private LocalInterface findImplementation() {
       try {
            InitialContext context = new InitialContext();
            String ejbPath = // read from an external property
            return (LocalInterface) context.lookup(ejbPath);
       } catch ... { ... }
   }
}

This is what I finally did, because with JBoss 5 (< Java EE 6, EJB 3.0) you can not make use of the useful @Produces annotation. I mark PedroKowalski's answer as accepted because CDI annotations seem to be the better solution if you do not have other restrictions.

Upvotes: 2

Arjan Tijms
Arjan Tijms

Reputation: 38163

The method outlined by PedroKowalski is a typical way to do this. Another trick with respect to the "external configuration property", is simply configuring your builder such that only 1 implementation ends up in the jar you generate that holds the EJBs.

So you don't have to recompile classes or change any source code, but you do have to rebuild your jar to choose another implementation.

Upvotes: 1

Piotr Nowicki
Piotr Nowicki

Reputation: 18174

You can achieve it using the deployment descriptor - ejb-jar.xml. Something like this (might not be 100% accurate, but I think you've got the point):

<ejb-jar> 
   <enterprise-beans>
      <session>
         <ejb-name>MyClass</ejb-name>
         <ejb-ref>
            <ejb-ref-name>ejb/myLocalReferencedBean</ejb-ref-name>
            <ejb-ref-type>Session</ejb-ref-type>
            <local>com.yourpackage.LocalInterface</local>
            <ejb-link>MyFirstImplementation</ejb-link>
            <injection-target>local</injection-target>
         </ejb-ref>
      </session>

      <session>
         <ejb-name>MyFirstImplementation</ejb-name>
         <!-- ... -->
      </session>
      <session>
         <ejb-name>MySecondImplementation</ejb-name>
         <!-- ... -->
      </session>
   </enterprise-beans>
</ejb-jar>

Another way is to use the CDI as described here: Inject @EJB bean based on conditions

Upvotes: 3

Related Questions