4

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.

Guido
  • 46,642
  • 28
  • 120
  • 174

3 Answers3

3

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

Community
  • 1
  • 1
Piotr Nowicki
  • 17,914
  • 8
  • 63
  • 82
  • Thank you. The ejb-jar solution does not seem to work if "MyClass" is not an EJB itself because, according to the DTD, you have to specify the home/remote interfaces. The CDI approach is only valid for JEE 6, if I am not wrong. – Guido Oct 28 '11 at 11:21
  • 2
    @GuidoGarcía you're right - the MyClass must be an EJB class. The CDI solution is more flexible as you can even put the configuration to some other place - i.e. database. Moreover it will work wherever you use the `@Inject`. Just a small remarks: it's a XML Schema and not a DTD. The home/remote interfaces are not required - it depends on what EJB version you're using. – Piotr Nowicki Oct 28 '11 at 12:35
2

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.

Guido
  • 46,642
  • 28
  • 120
  • 174
  • Unfortunately the `web.xml` of the WAR where `MyClass` exists would still need to provide an `` declaration to be able to look up the bean in the JNDI tree. The `` sub-element would indicate where to find the EJB, under `java:comp/env`. Modifying `web.xml` is obviously a build-time change. – lotz May 28 '13 at 20:19
1

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.

Arjan Tijms
  • 37,782
  • 12
  • 108
  • 140
  • 1
    Thanks Arjan. This is the current approach is use, but it is no longer valid because rebuilding the jar is not an option in a production environment. – Guido Oct 28 '11 at 10:22