EJB 3.0 tutorial : Session Beans

Enterprise JavaBeans (EJB) technology is a J2EE technology for developing business components in a component-based, enterprise Java application.

EJB technology is generally viewed as powerful and sophisticated. The technology helps developers build business applications that meet the heavy-duty needs of an enterprise. In particular, applications built using EJB and other J2EE technologies are secure, scale to support very large numbers of simultaneous users, and are transaction-enabled so that data maintains its integrity even though it’s processed concurrently by multiple users. 

Despite its power and sophistication, some developers are hesitant to use EJB technology. The major obstacle for these developers is complexity. But there’s good news in store.

 Java 5 introduced metadata annotations, which are property settings that mark a piece of code, such as a class or method, as having particular attributes. This is a declarative style of programming, where the developer specifies what should be done and the system adds the code to do it.

In EJB, metadata annotations dramatically simplify development and testing of applications, without having to depend on an external XML configuration file. It allows developers to declaratively add services to EJB components as and when they need.

Here we’ll assume you have already a basic knowledge of the three types of Enterprise Java so we’ll focus on the innovation introduced by the new release. So let’s start from Session Bean.

Stateless Session Bean lifecycle

To define a session bean, you first need to define the service interface containing all its business methods. The session bean interface is just plain old Java interface without any annotation. The client uses this interface to retrieve a stub object of the session bean from the EJB 3.0 container

package demo.ejb3;

public interface SessionDemoItf {

public String doQuery (String param);

}

The @Stateless annotation indicates that this bean is a stateless session bean. Just add this notation and you’ll turn your POJO into an EJB !

We’ve also added the @PostConstruct and @PreDestroy notations, which are not compulsory but it’s helpful to understand the lifecycle of the EJB.
 

package demo.ejb3;

import javax.annotation.PostConstruct;
import javax.ejb.*;

@Stateless
public class SessionDemoBean implements SessionDemoItf {

    public String doQuery(String param) {
        return "Query with param " + param + " executed.";
    }

    @PostConstruct
    public void initialize () {
        // Initialize here objects which will be used
        // by the session bean
        System.out.println("SessionDemoBean initialized.");
    } 


    @PreDestory
    public void destroyBean() {
        // Free here resources acquired by the session bean
        System.out.println("SessionDemoBean initialized.");
    } 
}

ejb 3.0 stateless jboss

Picture 1: Stateless Session Bean lifecycle

Compile everything using a JDK 1.5 or greater and remember to include in the classpath jboss-ejb3x.jar which contains the implementations necessary to compile the EJB annotations.

Now it’s time to pack your EJB. Simply jar the two files and throw them in the “deploy” folder of JBoss ! Isn’t that sooo simple ?? I guess you might be wondering what happened to the EJB configuration, for example without any configuration file of do you code JNDI name ? There’s of course an annotation also for this but if you don’t use them JBoss will assign one for you, depending if your EJB is packaged in an ear or in a jar file.

What is the default EJB JNDI name ?

 If the application is deployed in a EAR file, the default JNDI name is the EAR-FILE-BASE-NAME/EJB-CLASS-NAME/local for the stub for local interface. For the remote interface (see below), it is EAR-FILE-BASE-NAME/EJB-CLASS-NAME/remote.

 If the bean is deployed in a JAR file, the JNDI names are EJB-CLASS-NAME/local and EJB-CLASS-NAME/remote.

Now a minimal client to test your EJB can be a jsp:

<%@ page import="demo.ejb3.*, javax.naming.*, java.text.*" %> 

<%!

private SessionDemoItf ejb = null;
public void jspInit () {

 try {
  InitialContext ctx = new InitialContext();
   ejb = (SessionDemoItf) ctx.lookup(
    "StatefulExample/SessionDemoBean/local");
 } catch (Exception e) {
  e.printStackTrace ();
 }
}
 %>

EJB invoked  <%=ejb.doQuery("param1")%>

See the JNDI name: since we have packaged it in an ear file named StatefulExample.ear the JNDI name will be StatefulExample/SessionDemoBean/local.

If everything was done correctly you’ll display in the jsp page the simple string you see in the bottom. What if you aren’t satisfied with default bindings ? use the LocalBinding/RemoteBinding to define your custom JNDI name.

@Local ({SessionDemoLocalItf.class})

@LocalBinding (jndiBinding=”SessionDemoBean/local”)

@Remote ({SessionDemoRemoteItf.class})

@RemoteBinding (jndiBinding=”SessionDemoBean/remote”)


 

Stateful Session Bean lifecycle

 

The stateful session bean is a session bean that maintains its internal states. If the client invokes method calls against the same bean stub, the calls are always tunneled to the same bean instance in the container. So, all field variables in the bean instance retain their values as long as the client application retains the bean stub (or reference for a local client).  

The stateful session bean is typically used to track states in an application: In a web application, the servlet (or JSP page) caches the bean stub as an attribute in the HttpSession object. The HTTP session’s state is therefore tracked and stored in the bean instance.

In a rich client Java application (e.g., Swing application), the application determines what is a “session” and caches the stateful session bean stub accordingly.

 It is very easy to create a Stateful Bean with EJB 3.0. All bean types are homeless in EJB 3.0 so all you have to do to create a Stateful bean is to create a bean class and have it implement at least one interface. Take a look at this:

@Stateful

public class HelloWorldBean implements HelloWorldItf, Serializable {

    int counter;

    public void doSomething() {
        counter++;
        System.out.println("Value of counter is " + counter);

    }


    @PostConstruct
    public void initialize () {
        // As with stateless EJB, the container immediately calls the 
        // annotated method after a bean instance 
        // is instantiated. 
    }

    @PreDestroy
    public void exit () {
        // The annotated method is called before the container destroys 
        // an unused or expired bean instance from its object pool.
    }

    @PrePassivate
    public void beforePassivate () {
        // Called before SFSB is passivated 
    }


    @PostActivate
    public void afterActivation () {
        // Called before after SFSB is restored 
    }

    @Init
    public void initialize () {
        // Called to initialize SFSB 
    }

    @Remove
    public void stopSession () {
        // Call to this method signals the container
        // to remove this bean instance and terminates
        // the session. The method body can be empty.
    } 

}

The first thing to notice is that the class is tagged as @Stateful. This marks the class as a stateful bean and the deployer will deploy that class as a stateful bean EJB container.

 So a Stateful SB can be basically in three States: Does not Exist, Ready and Passivated. When the Bean is first instantiated it is moved to the Ready State. If the instance is idle for too long, the container might passivate it and store its state to a cache. The method is tagged by the annotation @PrePassivate.

 

lifesfsb

Picture 2: Stateful Session Bean lifecycle

When the client uses the passivated stateful session bean again, a new instance is created and the bean state is restored. The method tagged by this annotation is @PostActivate and when it’s called the activated bean instance is ready.

Another useful annotation for a lifecycle method, especially for stateful session beans, is @Remove. This is not a callback method: when the application calls remove on the bean instance it will signal the container to remove this bean instance and terminates the session. 

How do you control the timeout period ?

Stateful session beans have configurable timeout values which can control the amount of time a bean can remain idle prior to passivation or removal. Notice the @org.jboss.annotation.ejb.cache.simple.CacheConfig annotation. The idleTimeoutSeconds parameter configures the amount of idle time before the bean is passivated and the removalTimeoutSeconds configures the amount of idle time before the bean is permanently removed. For example, in order to set the timeout to 300 seconds:

@CacheConfig (idleTimeoutSeconds=300)

Client lookup 

public class Client {

 public static void main(String[] args) throws Exception {
  Properties p = new Properties(); 
  p.put(Context.INITIAL_CONTEXT_FACTORY, 
     "org.jnp.interfaces.NamingContextFactory"); 
  p.put(Context.URL_PKG_PREFIXES, "jboss.naming:org.jnp.interfaces"); 
  p.put(Context.PROVIDER_URL, "10.2.25.35:1100");

  InitialContext ctx = new InitialContext(p);
  HelloBeanItf ejb = (HelloBeanItf) ctx.lookup("cluster/HelloBean/remote");

  ejb.doSomething();

 }
}

The session bean client obtains a stub object of the bean via JNDI (Java Naming and Directory Interface). Provided by the container, the stub object implements the session bean’s business interface. All calls made to the stub object are routed to the container and invoked against the managed bean instances.

For stateless session beans, you can obtain a new stub every time you make a call. For stateful session beans, you must cache the stub on the client side so the container knows to provide you with the same bean instance for each subsequent call