Building a simple EJB application

Enterprise JavaBeans (EJB) technology is the server-side component architecture for Java Platform, Enterprise Edition (Java EE). EJB technology enables rapid and simplified development of distributed, transactional, secure and portable applications based on Java technology.

In this tutorial, I will show you how to build a very simple application using the EJB Technology: the ‘notorious’ Hello World application

Before getting into work, you should prepare some materials, they are:

J2EE Application Server of your choice. There are plenty application servers that you can use, opensource, closed source, commercial, community, etc. However, in this tutorial I will only mention Sun Java System Application Server PE 8.2. For others, the recipe is similar.

Ok, that’s all about preparation. Now let’s get our hand into work.
Our recipe contains 6 steps:

  1. Installing & Configuring
  2. Creating Project
  3. Implementing
  4. Creating Deployment Descriptor
  5. Packaging & Deploying
  6. Implementing Client

Remember that you can implement the client for your EJB-based application in any language of your choice, but I prefer Java for convenient.

Ok, let’s see what we have to do in our 6-step recipe.

Step 1: Installing and configuring

There’s not much to say in this step. Seemingly, you don’t have to do anything after installing the J2EE Application Server (AS). But there is an issue that almost AS use their own JDK. So if the JDK of the AS has a different version from the JDK you use to compile your EJB application, a “Bad version number” exception will be thrown when deploying (step 5).

To remedy this, you need to point the JDK of the AS to a proper one (the one that you use to compile your app).

For example, with SJSAS you have to:

  1. Open <install_dir>/config/asenv.bat (<install_dir> refers to the directory where you install the SJSAS)
  2. Search for “AS_JAVA” (without the quotes) and change its value to the path of your JDK, for example:
  3. set AS_JAVA=C:\Program Files\Java\jdk1.6.0_12
  4. Restart the application server, if needed

Step 2: Creating Project in Eclipse

Again, not much to say in this step. Change the Target Runtime to your AS. Choose “J2EE Runtime Library” if you install SJSAS. Pay attention when choosing the JRE. Anyway, the JDK when compiling must have the same version as that of the AS.

Step 3: Implementing

Let say we are going to build a EJB application that return the String “Hello World” to a (local/remote) client on demand.

You need 3 classes for your EJB application:

  • EJB Home/EJB Home Local: Client uses this class to retrieve the EJB instance from your server. It is similiar to a factory class.
  • EJB Remote/EJB Local: Client uses this class to interfacing with the actual EJB object (which is hidden from the client).
  • EJB Class: The main class, containing your actual business code and is hidden from clients.

First, create the EJB Home class (well in fact, it is an interface). Every home classes must extend the EJBHome class, and contain create() method, as shown in Listing 1.

Listing 1. HelloworldHome.java

package com.griever.simpleejb;
import java.rmi.RemoteException;

import javax.ejb.CreateException;
import javax.ejb.EJBHome;

public interface HelloworldHome extends EJBHome {

    public HelloworldEJBRemote create() throws CreateException, RemoteException;
}

If you create your EJB as a remote EJB (which is typically in most cases), you must declare the throws RemoteException, as example above.

Second, create the HelloworldEJBRemote class, which contain the abstract business method (in this tutorial, the sayHello() method).

Listing 2. HelloworldEJBRemote.java

package com.griever.simpleejb;
import java.rmi.Remote;
import java.rmi.RemoteException;

import javax.ejb.EJBObject;

public interface HelloworldEJBRemote extends EJBObject, Remote {

    public String sayHello() throws RemoteException;
}

If your EJB is remote, you must extends the Remote class, as well as declare the throws RemoteException.

Finally, create our main class, HelloworldEJB, which contains our actual business code (in this case, return the String “Helloworld”)

This class must implement one of the three types of EJB, these are: Session Bean (which is divided into Stateful and Stateless), Message-driven Bean or Entity Bean.

The session bean is used for performing some tasks for a client. This type of bean is the most appropriate in this tutorial.

The entity bean represents a business entity object that exists in persistent storage. IMHO, this type of bean is similar to the Model in the MVC architecture, although sometimes the Model may not has access to the persistent storage (database).

The message bean acts as a listener for the Java Message Service (JMS) API, processing messages asynchronously.

For more info, consult the following tutorial: http://java.sun.com/j2ee/tutorial/1_3-fcs/doc/EJBConcepts2.html

Ok, let our EJB class extends the SessionBean, as described above.

Listing 3. HelloworldEJB.java

package com.griever.simpleejb;

import java.rmi.RemoteException;

import javax.ejb.EJBException;
import javax.ejb.SessionBean;
import javax.ejb.SessionContext;

/**
 * Session Bean implementation class HelloworldEJB
 */
public class HelloworldEJB implements SessionBean    {

    /**
     * Default constructor.
     */
    public HelloworldEJB() {
        // TODO Auto-generated constructor stub
    }

    public String sayHello()    {
        // TODO Auto-generated method stub
        return "helloworld";
    }

    //some life-cycle callback method
    ...
}

Well, it is very simple, containing only one method, which returns the string “helloworld”. And pay attention to the last comment. This class must implements the life-cycle callback methods. These methods are automatically called by EJB container, i.e the Application Server (that’s why it’s named callback methods) at specific time. You should consult this tutorial for detailed instructions of all lifecycle callback method: http://java.sun.com/j2ee/tutorial/1_3-fcs/doc/EJBConcepts9.html

Well, that’s all for this step, phew.

Step 4: Creating deployment descriptors

A deployment descriptor is an XML file that specifies information about the bean such as its persistence type and transaction attributes.

In this step we need 2 descriptors:

  • One for the EJB itself, put in ejb-jar.xml. This descriptor specifies the structure of the EJB (the home class, the home interface, and the concrete class). The schema of this descriptor is EJB version-specific
  • One for the Application Server, depending on the Application Server, in SJSAS it is put in sun-ejb-jar.xml. The schema of this descriptor is Application Server-specific

Let’s look at the ejb-jar.xml:

Listing 4. ejb-jar.xml

<?xml version=”1.0″ encoding=”UTF-8″?>
<ejb-jar xmlns=”http://java.sun.com/xml/ns/j2ee&#8221; xmlns:ejb=”http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd&#8221; xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance&#8221; version=”2.1″ xsi:schemaLocation=”http://java.sun.com/xml/ns/j2eehttp://java.sun.com/xml/ns/j2ee/ejb-jar_2_1.xsd Java EE : XML Schemas for Java EE Deployment Descriptorshttp://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd”&gt;
<display-name>SimpleEJB</display-name>
<enterprise-beans>
<session>
<description>Helloworld EJB</description>
<display-name>Helloworld EJB</display-name>
<ejb-name>Helloworld</ejb-name>

<home>com.griever.simpleejb.HelloworldHome</home>
<remote>com.griever.simpleejb.HelloworldEJBRemot e</remote>
<ejb-class>com.griever.simpleejb.HelloworldEJB</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
</session>
</enterprise-beans>
</ejb-jar>

Let’s take a closer look at the meaning of each tag:

  • display-name: The name displayed in the EJB container of our application.
  • enterprise-beans: This is where we put all EJBs descriptions.
  • session: A session EJB.
  • description: Description of our EJB.
  • display-name: The name displayed in the EJB container of our EJB.
  • ejb-name: The name of our EJB. Which differentiate it from other EJBs.
  • home: The home class, in this case, HelloworldHome.
  • remote: The bean interface, interacting with client.
  • ejb-class: The actual EJB class, containing our business method.
  • session-type: Type of session bean, which can be Stateful or Stateless.
  • transaction-type: Type of transaction, which can be container-managed or bean-managed.
  • […]

Then, the sun-ejb-jar.xml:

Listing 5. sun-ejb-jar.xml

<?xml version=”1.0″ encoding=”UTF-8″?>
<!DOCTYPE sun-ejb-jar PUBLIC “-//Sun Microsystems, Inc.//DTD Application Server 8.1 EJB 2.1//EN” “http://www.sun.com/software/appserver/dtds/sun-ejb-jar_2_1-1.dtd”><sun-ejb-jar&gt;
<enterprise-beans>
<name>SimpleEJB</name>
<ejb>
<ejb-name>Helloworld</ejb-name>
<jndi-name>Helloworld</jndi-name>
</ejb>
</enterprise-beans>
</sun-ejb-jar>

Pay attention to the following tags:

  • ejb-name: The name of the ejb, as specified in ejb-jar.xml
  • jndi-name: The JNDI name. JNDI naming services will look up our EJB (or any other resources) via JNDI name. So, in our example, clients can retrieve our EJB using a JNDI naming service via its JNDI name “Helloworld”.

Step 5. Packaging and Deploying

First, package our application into a JAR file. Very easy, huh?

Second, deploy it in our AS. If you use SJSAS, you can use the asadmin tool (CLI) or the Admin Console (Web-based). To use the Admin Console, point your browser to the Admin Console address, typically http://localhost:48484. After logging in, there is an EJB section in the left panel. This section allows you to view all deployed EJBs, their states, and to deploy new EJBs. You can do the rest yourself, it is very easy.

Step 6. Implementing the Client

The client of an EJB is anything using the services provided by that EJB. It may be another EJB, a web client, an application client, a standalone client or a program in other languages.

In this tutorial, we will create a standalone client. Well, it is very simple, just have a main method (the entry-point of every applications, you know), doing the following steps:

  1. Use JNDI naming service to retrieve the Home class.
  2. Retrieve the EJB interface via Home class.
  3. Call the method sayHello() to get the “helloworld” String.

Let’s look into it!

package com.griever.simpleejb;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.rmi.PortableRemoteObject;

public class Client {

    public static void main(String []args)    {
        new Client();
    }

    public Client()    {
        try    {
            Context ctx = new InitialContext();
            Object obj = ctx.lookup("Helloworld");
            HelloworldHome home = (HelloworldHome) PortableRemoteObject.narrow(obj, HelloworldHome.class);
            HelloworldEJBRemote remoteEJB = home.create();
            System.out.println(remoteEJB.sayHello());
        } catch (Exception ex)    {
            ex.printStackTrace();
        }
    }
}

Pay attention to the first line: it creates a new instance of the InitialContext. This will invoke a JNDI naming service so that the client can lookup for remote resources via JNDI name. But where’s the location of the JNDI naming service? Well, for a flexible application, you should not specify that location explicitly in the application (or in other word, you should not hardcode the location of the JNDI naming service). You should specify them via environment properties when starting the client, which will be described as below:

  • java.naming.factory.initial: The context factory.
  • java.naming.provider.url: The provider url, that means the url of the JNDI naming service.
  • […]

Refers to the document of your AS for detailed instructions.

All remaining lines are straight-forward and easy to understand (I hope :D).

Well, that’s all for our “simple stupid” application. This is EJB 2.1-compliant. I will post another tutorial for EJB 3.0 in the next tutorial. Phew.

About javarchive

I'm swimming into the depth of Java world
This entry was posted in My Tuts and tagged , . Bookmark the permalink.

3 Responses to Building a simple EJB application

  1. Krishna Chourasiya says:

    When I run the above code, I am getting following error message——

    java.lang.NullPointerException
    at com.sun.enterprise.naming.impl.SerialContext.getRemoteProvider(SerialContext.java:297)
    at com.sun.enterprise.naming.impl.SerialContext.getProvider(SerialContext.java:271)
    at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:430)
    at javax.naming.InitialContext.lookup(InitialContext.java:392)
    at com.griever.simpleejb.Client.(Client.java:13)
    at com.griever.simpleejb.Client.main(Client.java:7)
    javax.naming.NamingException: Lookup failed for ‘Helloworld’ in SerialContext [Root exception is javax.naming.NamingException: Unable to acquire SerialContextProvider for SerialContext [Root exception is java.lang.NullPointerException]]
    at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:442)
    at javax.naming.InitialContext.lookup(InitialContext.java:392)
    at com.griever.simpleejb.Client.(Client.java:13)
    at com.griever.simpleejb.Client.main(Client.java:7)
    Caused by: javax.naming.NamingException: Unable to acquire SerialContextProvider for SerialContext [Root exception is java.lang.NullPointerException]
    at com.sun.enterprise.naming.impl.SerialContext.getProvider(SerialContext.java:276)
    at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:430)
    … 3 more
    Caused by: java.lang.NullPointerException
    at com.sun.enterprise.naming.impl.SerialContext.getRemoteProvider(SerialContext.java:297)
    at com.sun.enterprise.naming.impl.SerialContext.getProvider(SerialContext.java:271)
    … 4 more

    • javarchive says:

      Hi Krishna
      The exception is thrown because you might not specify the required environment properties (the last step in my tutorial). Please specify the following properties when you run the client
      java.naming.factory.initial: The context factory, depends on your Application Server
      java.naming.provider.url: The provider url, that means the url of the JNDI naming service.
      Please refer to your Application Server’s document for detailed instructions.

      Alternatively, you can hardcode the properties in your client using System.setProperty (the properties are Context.INITIAL_CONTEXT_FACTORY and Context.PROVIDER_URL respectively)

      Hope that it will help

  2. javarchive says:

    Hi Krishna
    The exception is thrown because you might not specify the required environment properties (the last step in my tutorial). Please specify the following properties when you run the client
    java.naming.factory.initial: The context factory, depends on your Application Server
    java.naming.provider.url: The provider url, that means the url of the JNDI naming service.
    Please refer to your Application Server’s document for detailed instructions.

    Alternatively, you can hardcode the properties in your client using System.setProperty (the properties are Context.INITIAL_CONTEXT_FACTORY and Context.PROVIDER_URL respectively)

    Hope that it will help

Leave a comment