EJB 3 tutorial : Session Beans

Enterprise JavaBeans (EJB) technology is an Enterprise 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 Enterprise 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.");
    } 
}

Picture 1: Stateless Session Bean lifecycle

In order to compile a project which uses EJBs, it is sufficient to include the jakarta.jakartaee-api dependency in your pom.xml:

<dependencies>
        <dependency>
          <groupId>jakarta.platform</groupId>
          <artifactId>jakarta.jakartaee-api</artifactId>
          <version>${jakartaee.version}</version>
          <scope>provided</scope>
        </dependency>
</dependencies>

And specify the exact version of Jakarta EE. For example, for Jakarta EE 8:

<properties>
        <jakartaee.version>8.0.0</jakartaee.version>
</properties>

On the other hand, if you are developing for Jakarta EE 9:

<properties>
        <jakartaee.version>9.0.0</jakartaee.version>
</properties>

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.

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.

What is the JNDI Name of an EJB ?

The JNDI binding of an EJB is generated based on the EJB name and the module’s name containing the EJB. Here is the magic formula:

ejb:<app-name>/<module-name>/<distinct-name>/<bean-name>!<fully-qualified-classname-of-the-remote-interface>

Now some explanations how to determine these values:

  • app-name: this is the enterprise application name ( without ear ) if your EJB has been packed in an EAR. It is empty if you packed the EJB in a JAR or WAR archive
  • module-name: this is the archive name where the EJB has been packaged (in our case ee-ejb-server-basic)
  • distinct-name: this is an optional parameter that can be set on a single deployment unit
  • bean-name: this is the implementation class that is used by the EJB
  • fully-qualified-classname-of-the-remote-interface: this is the fully qualified classname of the remote interface interface

In addition, Stateful EJBs must include an additional suffix named “?stateful“.

For example, this is the binding for a Stateless EJB named com.sample.Calculator packaged in a WAR archive:

ejb:/ee-ejb-server-basic/CalculatorEJB!com.sample.Calculator

And this is the binding for a Stateful EJB named com.sample.Account packaged in a WAR archive:

ejb:/ee-ejb-server-basic/AccountEJB!com.itbuzzpress.ejb.Account?stateful

How to control the timeout period of a Stateful Bean?

Stateful session beans have configurable timeout values which can control the amount of time a bean can remain idle prior to passivation or removal.

The timeout can be configured in different ways depending on the version of the application server used.

  • WildFly / JBoss EAP 7

We recommend checking the following tutorial: Configuring Timeout policies for your EJBs

  • JBoss 5

You can apply the the @org.jboss.annotation.ejb.cache.simple.CacheConfig annotation on your EJBs. For non clustered applications use:

@CacheConfig (maxSize=100000, idleTimeoutSeconds=300, removalTimeoutSeconds=0)

For clustered applications use:

@CacheConfig (name="jboss.cache:service=EJB3SFSBClusteredCache", maxSize=100000, idleTimeoutSeconds=300, removalTimeoutSeconds=0)

EJB 3 Client lookup

We cover in detail EJB 3 Client lookup in this tutorial: WildFly remote EJB client tutorial

Controlling EJB 3 initialization

To Control the initialization process of EJBs you can decorate your EJBs with the @Startup annotation.

We cover in detail this topic in the following tutorial: How to create an EJB Startup Service