Choose EJB to be injected without recompiling

2019-01-28 11:31发布

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.

3条回答
别忘想泡老子
2楼-- · 2019-01-28 11:47

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.

查看更多
Lonely孤独者°
3楼-- · 2019-01-28 12:05

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

查看更多
神经病院院长
4楼-- · 2019-01-28 12:05

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 set PedroKowalski's answer as accepted as CDI annotations seems to be the better solution if you do not have other restrictions.

查看更多
登录 后发表回答