EJB 3.0 Compatibility and Migration

Guest Author

By Ken Saks

The Enterprise JavaBeans (EJB) 3.0 specification
introduced a new, vastly
simpler, API for implementing and accessing session beans. Many
developers have questions about how applications written to this
new API can interact with legacy EJB applications, or how legacy
applications can interact with the new API.

It would be impractical to require developers to entirely
rewrite all existing EJB applications in order to take advantage
of any of the new capabilities. In some cases, developers plan
to upgrade their applications, but would prefer to do it using
a phased approach. In other cases they prefer to write new
EJB 3.0 applications, but would still like to take advantage of
their existing application's services. The EJB 3.0
specification makes both of these strategies possible. This tip
explains how.

A sample application package
accompanies the tip. The code examples in the tip are taken from the source code of the sample (which is included in the
package). The sample uses the Java EE 5 SDK. You can download the Java EE 5 SDK from the Java EE Downloads page

EJB 3.0-to-EJB 2.x Compatibility

Let's first look at an example of an application written to the
simplified EJB 3.0 API calling a legacy EJB application. In the
source code for the sample that accompanies this tip you'll find
an EJB 3.0 stateless session bean named MigrationBean. The bean
invokes a remote EJB 2.x stateless session bean named EJB2xBean.
MigrationBean could either be an entirely new bean or an
existing bean that was recoded to use the EJB 3.0 API. For
simplicity both beans in this example are packaged in the same
archive, but that is not required. Here are the EJB 2.x home and
remote interfaces for EJB2xBean:

   public interface EJB2xHome extends EJBHome {

       public EJB2xRemote create()

           throws CreateException, RemoteException;


   public interface EJB2xRemote extends EJBObject {

       public void foo() throws RemoteException;



Here is the first part of the MigrationBean class:


   public class MigrationBean implements MigrationRemote {

       // Inject a reference to the Home interface 

       // of the EJB 2.x bean.

       @EJB private EJB2xHome ejb2xHome;

       private EJB2xRemote ejb2x;   

MigrationBean uses the @EJB annotation to inject a reference to
EJB2xHome. The @EJB annotation was introduced as part of the
EJB 3.0 specification. However, it was designed to be used with
the older-style EJB 2.x home view in addition to the EJB 3.0
business interface view. Whenever the EJB container instantiates
MigrationBean, it injects a reference to EJB2xHome in the
ejb2xHome data member.

An important benefit of using the @EJB annotation with a
2.x home interface is that it frees you from having to use
PortableRemoteObject.narrow(). The PortableRemoteObject.narrow()
method is used to cast to the correct type the Object returned
when you lookup the home interface. In EJB 3.0 the injected home
reference can be used without any special casting.

The MigrationBean class defines a @PostConstruct method that
uses the home reference to create an EJB2xRemote reference. The
class then stores the result in another data member.


    private void initialization() {

        try {

            ejb2x = ejb2xHome.create();

        } catch(Exception e) {

            throw new EJBException(e);




In the last part of the class, MigrationBean invokes the EJB2x business method within its own business method.

    public void bar() {

      try {

          // Call operation on legacy EJB.


      } catch(Exception e) {

          throw new EJBException(e);



All standard EJB services such as security and transaction propagation work as expected between the two beans.

Note that using an @EJB annotation to access EJB 2.x beans is
not limited to EJB components. You can use the same approach to
access a legacy bean from other types of components in
a Java EE 5 application, such as a servlet or an application
client. Also, even though this example used a remote EJB 2.x
bean, you can use the approach to access a local EJB 2.x bean as

EJB 2.x-to-EJB 3.0 Compatibility

In the first example, you saw how an EJB component written using
the new EJB 3.0 API could be a client of a legacy EJB component.
Now let's look at the reverse case. Here you'll see how a legacy
component that is coded using the EJB 2.x client API can access
a session bean that is implemented using the EJB 3.0 simplified
API. The idea here is to use the new EJB without making any
changes to the existing EJB client code.

In this second example, a stateful session bean named
AdaptedBean is implemented using the simplified EJB 3.0 API. The
bean exposes a 2.x remote home interface to a standalone Java
client. Here are the home and remote interfaces for AdaptedBean:

   public interface AdaptedHome extends EJBHome {

       public AdaptedRemote create(String id)

           throws CreateException, RemoteException;


   public interface AdaptedRemote extends EJBObject {

       public String getId() throws RemoteException;



Here is the AdaptedBean class :



   public class AdaptedBean {

       private String myId = "unknown";


       public void create(String id) {

           myId = id;


       public String getId() {

           return myId;



Notice that the bean class is implemented using the POJO-like
simplifications of EJB 3.0. However, it uses the
@RemoteHome annotation to exposes an EJB 2.x style remote home
interface. This annotation tells the EJB container that the
bean has a home interface named AdaptedHome and a remote
interface named AdaptedRemote. You don't need a separate
annotation to specify the AdaptedRemote interface. That's
because the container can derive it from the signature of the
AdaptedHomes create() method. If the bean exposed a local home
interface, it would use the @LocalHome annotation instead.

The other important annotation in the class is @Init. The
EJB 2.x view always defines a create method, so you must define
a method on the bean class to handle the create operation. The
@Init annotation tells the EJB container which method that is.
The method can have any name, but its method parameters must
match the create method in the corresponding home interface.

Here is the standalone client code for accessing AdaptedBean:

   try {

        InitialContext ic = new InitialContext();

        Object o = ic.lookup(AdaptedHome.class.getName());

        AdaptedHome adaptedHome = (AdaptedHome)

            PortableRemoteObject.narrow(o, AdaptedHome.class);

        AdaptedRemote adapted = adaptedHome.create("duke");

        System.out.println("Adapted id = " + adapted.getId());

   } catch(Exception e) { ... }


Notice that the client code uses the standard EJB 2.x client
programming model. It does not need to know that the target bean
is implemented with EJB 3.0.

Running the Sample Code

A sample package accompanies this tip. To install and run the

  1. If you haven't already done so, download the Java EE 5 SDK
    from the Java EE Downloads Page. Also be
    sure to have an installed version of the Java Platform
    Standard Edition (Java SE) 5 SDK.

  2. Download the sample package for the tip
    and extract its contents. You should now see the newly
    extracted directory as
    <sample_install_dir>/ttfeb2007ejbmigration, where
    <sample_install_dir> is the directory where you installed the
    sample package. For example, if you extracted the contents to
    C:\\ on a Windows machine, then your newly created directory
    should be at C:\\ttfeb2007ejbmigration. Below this directory you
    should see two subdirectories: Migration and Adapted.

  3. To build and run the EJB 3.0-to-EJB 2.x compatibility
    example, change to the Migration directory. To build and run
    the EJB 2.x-to-EJB 3.0 compatibility example, change to the
    Adapted directory. Then set the javaee.home location
    attribute in the build.xml file in the selected directory to
    the directory in which you installed the Java EE 5
    application server.

  4. Start the application server by entering the following

       <appserv_install>/bin/asadmin start-domain domain1


    where <appsrv_install> is where you installed the Java EE 5 application server.

  5. Enter the command:

        ant all

    This builds the sample application then deploys and executes

    You should see the following in the output for the
    EJB 3.0-to-EJB 2.x compatibility example :


              [exec] Successfully called EJB 3.0 bean

    You should see the following in the output for the EJB 2.x-to-EJB 3.0 compatibility example:


              [java] Adapted id = duke

    The application is then automatically undeployed and its build resources erased.


The EJB 3.0 specification greatly simplifies the session bean
API. But it does so with the understanding that there is a large
investment in EJB applications built with earlier versions of
the specification. For this reason, a goal of EJB 3.0 is to
ensure smooth interoperability between new and existing
applications. If you are a developer using EJB 3.0, you have
a lot flexibility in deciding whether to migrate legacy
applications to the new API or to take advantage of those legacy
applications from new components.

About the Author

Ken Saks is the lead architect for the EJB 3.0 container in the
Java EE 5 SDK. He has been a member of the Enterprise Java group
at Sun Microsystems since 1999.

Join the discussion

Comments ( 3 )
  • Jeet Monday, March 9, 2009

    I have a question for Ken regarding the migration to 3.0 apps.

    Hi Ken,

    I am working in a Application which has more than 1000 ejbs(transactions) running with ejb 2.0 . We want to migrate the Application to a different environment where it has to run with ejb 3.0 . We can't go and make changes in code for the 1000 transactions and make it compatible for ejb 3.0 . Is there any other option/way that without changing the code (ejb 2.0) we can still run this app with ejb 3.0 specification .

  • Ken Saks Tuesday, March 10, 2009

    Hi Jeet,

    It depends what you mean by "run this app with ejb 3.0". Just like Java SE, every release of Java EE is backward compatible with its previous releases, so at minimum you could just deploy your existing EJB 2.0 (J2EE 1.3) app to a product that supports EJB 3.0 (Java EE 5)

    If you want new code to call your old beans, that's fine too. Any Java EE 5 component --whether it's an EJB or not -- can call your old beans using the EJB 2.x client view. It's even a bit simpler to do since they can inject the Home/LocalHome references using @EJB instead of a lookup, but that approach is not required.

    You could also change the implementation of your old beans to start taking advantage of the new EJB 3.0 API. Obviously, that's more work, especially given the number of components in your application. However, the key is that you don't have to do this for the old components to still be callable from completely new code.

    Let me know if you need more info.


  • John Neyman Friday, October 16, 2009

    Thanks for the helpful information sharing!

Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.