Question

does anybody know if it is possible to iteratively replace EJB2.1 beans with EJB3 beans in Java EE application?

That is: at one time remove one 2.1 bean from the code and add corresponding EJB3 bean that implements the same behavior without touching the rest of the code (+ be able to inject the legacy EJBs via annotations in the new EJB3).

I am not expert at EJB specs (and I have experience only with EJB3), but to me EJB is a simply component with given business interface that is managed by the appserver. AFAIK EJB3 brought big simplification how to write the component (no artifical interfaces) and most of the time xml descriptor can be omitted thanks to the annotations, but the basics are the same. So it is seem plausible, it could work.

Is there any incompatibility between EJB2.1 & EJB3?

The core of the question is if migration EJB2.1 --> EJB3 needs to be stop-the-world/complete-rewrite operation or one can do it while adding new feature and fixing bugs to the legacy application (so there will be mix of EJB2.1 and EJB3 for some time in the running app).

EDIT:

  • I am interested in session beans only.
  • I am curious if (and how) the lookup will work. AFAIK EJB2.1 requires something called home interface to get a reference to a different EJB, but EJB3 does not have home interface ...
Was it helpful?

Solution

Coexist of EJB 2.1 and EJB 3 beans

EJB2 and EJB3 beans can coexist in one enterprise application (.ear), but can’t reside on the same ejb jar file (module). Hence, the EJB3 beans must reside in a different jar to the EJB2 beans.

Invoke EJB 3 from EJB 2.1

EJB3 bean hasn't home interface while EJB 2.1 requires it. In order to make EJB3 bean being able to access from EJB2, you need to add local home interface (or remote home if remote call is required) to EJB3 bean.

Create home interface:

public interface SystemTimeLocalHome extends EJBLocalHome {  
  SystemTimeLocal create() throws CreateException;  
}  

Add home interface to EJB3 bean:

@Stateless  
@Local(TimeServiceLocal.class)  
@LocalHome(TimeServiceLocalHome.class)  
public class TimeServiceBean implements TimeServiceLocal {  
   public long getCurrentTimeMillis() {  
      return System.currentTimeMillis();  
   }  
}  

Inside EJB2 bean the code to invoke the EJB3 bean just follows EJB2 specification: looks up the reference, call the home interface to create local interface, then invoke method on the local interface.

Context ctx = new InitialContext();  
TimeServiceLocalHome home = (TimeServiceLocalHome)ctx.lookup("java:comp/env/" + ejbRefName);  
TimeServiceLocal timeService = home.create();  
timeService.getCurrentTimeMillis();  

Invoke EJB 2.1 from EJB 3

Dependency injection is utilized to inject the EJB 2.1 component references into EJB3 bean. The different to injecting EJB3 bean is that it's the home interface of EJB2 being injected. Call create() method on injected EJB home interface to instantiate the bean class.

@EJB BankingServiceHome bsHome;

BankingService bs = bsHome.create();
bs.getBalance(...);

OTHER TIPS

Migration is possible, though it is not without hiccups.

Start with upgrading the descriptor to the Java EE 5 schemas. This is usually the flag that servers use to determine if they need to scan for annotations.

Once you have the descriptor upgraded (but otherwise unchanged), you can start migrating your Session and Message Driven Beans into Java EE 5 beans. As you convert a bean, you can also remove it from the deployment descriptor, if you want.

After all your other beans are done, you can start to work on removing your entity beans and converting the persistence to JPA entity classes. This is the non-trivial part of the exercise.

Sure you can. Have a look here for the beginning: http://www.coderanch.com/t/321218/EJB-JEE/java/EJB-call-EJB

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top