Make an EJB from any Java class with Java Reflection

Make any single-tier Java application into an enterprise application

Every EJB application server allows you to install an EJB if you provide a bean implementation, remote interface, and a home interface but, in most cases, you have to write them yourself. That is unavoidable and worth the effort for brand-new EJBs. But what if you have an existing class that performs the tasks you want your Enterprise Bean to do? Wouldn't it be nice to say, "Make me an EJB that does that?" Taking the idea further, what if you use those classes within existing applications? Wouldn't it be nice if the applications could be modified easily to use your new EJBs without having to manually replace every class instantiation with a JNDI lookup followed by a HomeInterface.create()?

The idea first occurred to me near the end of 1999, while working with the ObjectSpace Voyager Application Server, and I have subsequently applied the idea with Oracle Application Server. Next, I will turn my attention to the J2EE reference implementation.

What's the big idea?

For any EJB that you wish to install in an application server, you must supply three Java classes: a bean implementation (for example,, a home interface (for example, and a remote interface (for example, The bean implementation provides the functionality, the home interface allows you to lookup and create new bean instances, and the remote interface allows you to communicate with the bean. That is all shown for an EJB called BankBean in Figure 1.

Figure 1. BankBean implementation, home interface, and remote interface

So for a new EJB, you need three Java classes, each of which must adhere to the EJB specification. For just one new EJB, creating three classes -- all EJB compliant -- might not be so bad. But if you're creating lots of EJBs -- perhaps from functionality you've already coded into existing classes -- a more automated solution would be beneficial.

The basis of my idea is, therefore, to produce an EJBWizard utility that will take any given Java class and generate all of the additional support classes that will allow it to be used remotely as an EJB. I have set myself the additional requirement that the original class should be left unchanged. That will allow the class to be used locally as it is now and will enable functional changes to be made more easily in the future. That means that the bean implementation that I will generate will be a wrapper, which delegates method calls to the original class, instead of a modified version of the class itself. You will see what that looks like in Figure 2.

Figure 2. BankBean implementation delegating to Bank

Thus, existing applications will be completely unaffected in their use of the original class, whereas new applications that will use the class' EJB version will now have to use JNDI to look up the home interface and then call create() on the home interface to access an EJB instance through the remote interface. To make it easier to write new client applications and to facilitate the conversion of existing applications to use the distributed versions of their classes, I will add a client-side factory that hides the details of the JNDI lookup and creation via the home interface, as seen in Figure 3.

Figure 3. Addition of the client-side BankFactory

How will it work?

When interviewing potential employees, a former colleague said he would ask them, "Can you give me an example of a use for Java Reflection?" The implication was that few situations require the use of Reflection and, in most cases, a better technique can be used. I never quite believed that, so here is my one good use for Reflection.

I will use Reflection to analyze an original Java class given as input to find out which method signatures the class provides. That information will be used to generate a remote interface and a (delegating) bean implementation class, both of which support the same set of methods. The constructor method signatures will be used to generate a home interface that provides equivalent create methods.

The EJBWizard class is the entry point in my design. It has a constructor that takes the original Java class, that is, the one that will become an EJB:

public EJBWizard(Class originalClass)

The EJBWizard also has a set of methods, each dedicated to generating one aspect of the EJB:

  • public String getRemote()
  • public String getHome()
  • public String getBean()

Each method returns a string containing the complete source code for the home interface, remote interface, or (delegating) bean instance as appropriate, based on the original Java class. Within each method, reflection discovers the constructor and method signatures of the original class, and those are then written out in modified form as new Java source code. Let's take each method in turn.

Generating the remote interface with getRemote()

The code for the getRemote() method shows the general principle upon which the other methods will be based:

public String getRemote()
  String codeString="";
  // -- generate package name if there is one --
  if (!this.introspector.getPackage().equals(""))
  // -- ejb import statement --
  codeString=codeString+"import javax.ejb.*;\n";
  // -- interface declaration --
  codeString=codeString+"\npublic interface ";      
  codeString=codeString+this.introspector.getShortName()+ "Remote
extends javax.ejb.EJBObject";
  // -- public methods --
  String[] methods=this.introspector.getMethods();
  for (int i=0; i<methods.length; i++)
    if (methods[i].indexOf("throws")>=0)
      codeString=codeString+"  "+methods[i]+",
      codeString=codeString+"  "+methods[i]+" throws
  return codeString;

The code above shows how the source code for a new remote interface -- comprising a package statement, EJB import statement, interface declaration, and a set of methods signatures -- is written into an output string based on the information provided by an introspector instance. The introspector is an instance of ClassIntrospector whose job is to hide the details of how Java Reflection is applied to the original class supplied as input. We'll see the inner workings of ClassIntrospector later but, for now, I don't want to lose the plot line.

Given a simple Java class:

public class Bank
  public Bank(String bankName)
  { // -- construct the bank --
  public String createAccount(int balance)
  { // -- create an account and return accno --
    return "00000"; }
  public boolean transfer(String acc1, String acc2, int amount)
  { // -- transfer an amount between accounts --
    return true; }

the getRemote() method would generate the following code for the remote interface:

import javax.ejb.*;
public interface BankRemote extends javax.ejb.EJBObject
  public java.lang.String createAccount(int p0) throws
  public boolean transfer(java.lang.String p0,java.lang.String p1,int
p2) throws java.rmi.RemoteException;

That's it for the remote interface. Next, we see something similar for the home interface.

Generating the home interface with getHome()

The getHome() method follows the same pattern as the getRemote() method, with just a couple of changes. First, the interface declaration is changed to that of a home interface:

codeString=codeString+"\npublic interface ";
codeString=codeString+this.introspector.getShortName()+ "Home extends

Second, the original class methods are ignored, but the constructors are used to generate one or more create methods:

String[] constructors=this.introspector.getConstructors();
for (int i=0; i<constructors.length; i++)
  codeString=codeString+"  public "+this.introspector.getName()+"Remote
create"+constructors[i]+" throws javax.ejb.CreateException,

Thus, the source code for the home interface generated for the example Bank class is:

import javax.ejb.*;
public interface BankHome extends javax.ejb.EJBHome
  public BankRemote create(String p0) throws javax.ejb.CreateException,

When I applied that technique with Oracle Application Server, I discovered that it allows only one create method per home interface because the EJB implementation sits on top of a CORBA ORB that does not allow methods to be overloaded with differing signatures. The create methods that I generate are meant to mirror the original class' constructors, which may be overloaded, so that was a significant limitation. My solution was to separate the creation of an instance (via a single, parameterless, create method on the home interface) from the initialization of an instance (via one or more initialization methods on the bean itself), each doing one of the constructors' jobs. Next up: the bean implementation.

Generating the bean implementation

Generation of the bean implementation combines aspects of the getRemote() and getHome() implementations. The original class' constructors become ejbCreate() methods that correspond with the create methods on the home interface, and the original class' method signatures are used to generate methods that delegate to an instance of the original class (which has been left intact throughout).

So for the constructors we have:

String[] constructors=this.introspector.getConstructors();
String[] constructorCalls=this.introspector.getConstructorCalls();
for (int i=0; i<constructors.length; i++)
  codeString=codeString+"  public "+this.introspector.getName()+"Remote
    +constructors[i]+" throws javax.ejb.CreateException\n";
  codeString=codeString+"  {\n";
  codeString=codeString+"    realInstance=new "+this.introspector.getName()+constructorCalls[i]+";\n";
  codeString=codeString+"  }\n";

You will see here that within each ejbCreate() method of the bean implementation, we create an instance of the original class, named realInstance(). All calls to that bean implementation will be delegated to the realInstance().

Below you'll find the code that generates the methods on the bean implementation, which will delegate to the realInstance:

String[] methodCalls=this.introspector.getMethodCalls("realInstance",true);
String[] methods=this.introspector.getMethods();
for (int i=0; i<methods.length; i++)
  codeString=codeString+"  "+methods[i]+"\n";
  codeString=codeString+"  {\n";
  codeString=codeString+"    "+methodCalls[i]+"\n";
  codeString=codeString+"  }\n";

Note in the code above that when asking the introspector for the original class's method calls, I pass the text "realInstance" to be prepended to each method call.

Now that the code for the constructors and business methods has been generated, some EJB methods must be added to make that a valid bean implementation. For simplicity, I will use the following code to generate empty methods:

codeString=codeString+"  public void setSessionContext(SessionContext
codeString=codeString+"  { this.sessionContext=ctx; }\n";
codeString=codeString+"  public void ejbActivate() {}\n";
codeString=codeString+"  public void ejbPassivate() {}\n";
codeString=codeString+"  public void ejbRemove() {}\n";

The final generated code for the bean implementation, to support the original Bank class, will look like this:

public class BankBean implements javax.ejb.SessionBean
  private Bank realInstance;
  private SessionContext sessionContext;
  // -- business methods --
  public java.lang.String createAccount(int p0)
    java.lang.String returnValue=realInstance.createAccount( p0);
return returnValue;
  public boolean transfer(java.lang.String p0,java.lang.String p1,int
    boolean returnValue=realInstance.transfer( p0, p1, p2); return
  // -- ejb create --
  public void ejbCreate(java.lang.String p0) throws
    realInstance=new Bank( p0);
  // -- ejb methods --
  public void setSessionContext(SessionContext ctx) {
this.sessionContext=ctx; }
  public void ejbActivate() {}
  public void ejbPassivate() {}
  public void ejbRemove() {}

The code to generate each aspect of an EJB from any supplied class has been kept simple, thanks to the elusive introspector, which comes up next.

Inside the introspector

To get across the main points about how to generate the new EJB's Java code, I have so far ducked the issue of how to analyze the original Java class using Reflection. Remember that we have used an extra object called introspector in the examples to hide the details of how reflection is used. The introspector object is an instance of a class called ClassIntropector, which we will now crack open to take a look inside.

When creating a new instance of ClassInstropector, we pass the original Java class -- something like ClassIntrospector introspector= new ClassIntrospector(Class.forName("Bank")); -- which calls the constructor:

public ClassIntrospector(java.lang.Class sourceClass)
{ this.sourceClass=sourceClass; }

ClassIntrospector has a set of methods to tell about the methods and constructors declared on the original class:

public String[] getMethods()
public String[] getMethodCalls(String callInstance, boolean returnFlag)
public String[] getConstructors()
public String[] getConstructorCalls()
1 2 Page
Join the discussion
Be the first to comment on this article. Our Commenting Policies
See more