Nikos Maravitsas

About Nikos Maravitsas

Nikos has graduated from the Department of Informatics and Telecommunications of The National and Kapodistrian University of Athens. Currently, his main interests are system’s security, parallel systems, artificial intelligence, operating systems, system programming, telecommunications, web applications, human – machine interaction and mobile development.

Java EE Stateful Session Bean (EJB) example

In this article we are going to see how you can use Stateful Session Beans to keep track of state across a client Session in a simple Web Application.

1. Introduction

Stateful Session Beans usually hold information about a specific client’s session, and holds that information throughout the whole session (opposed to Stateless Session Beans). A Stateful EJB instance is coupled with only one client. One client can of course have many EJB instances is his session.

In this example we are going to create a simple Shopping Cart application. The session bean will hold a list of products. As the client adds more products to his cart, this list will grow accordingly. Finally the client will be able to checkout his order and the products on the aforementioned list will be persisted in a MySQL database.

To implement the above functionality, we are going to create an EAR Project and an EJB Project that will host our Session Bean and a Dynamic Web Application that will host a Servlet, testing the aforementioned behavior. We are going to use Eclipse Java EE IDE 4,3 Kepler and Glassfish 4.0 as our container. Additionally we are going to use standard JPA 2.o to persist our products in a MySQL 5.6.14 database running on localhost. Here is a guide on how to Integrate MySQL with Glassfish.

2. Create a new Enterprise Application Project

Create a new Enterprise Application Project named SatefulEJBEAR . In Eclipse IDE select File -> New -> Enterprise Application Project, fill in the form and click Finish:

new-ear-project

3. Create a new EJB Projet

Create a new EJB Project called StatefulSessionBeansEJB. We are going to create our session bean on this. Go to File -> New -> EJB Project and fill out the form. Be careful to select “Add EAR Project” and Select “StatefulEJBEAR” as EAR project name:

new-ejb-project

4. Create a Sateful Session Bean

Open StatefulSessionBeansEJB Project in the Project Explorer and in the folder ejbModule create a new source package namedcom.javacodegeeks.enterprise.ejb. In that package create a new Interface that will be a local view of the EJB:

Cart.java:

package com.javacodegeeks.enterprise.ejb;

import javax.ejb.Local;

import com.javacodegeeks.enterprise.product.Product;

@Local
public interface Cart {

	  void addProductToCart(Product product);

	  void checkOut();

}

As you can see, we declare two methods, one to add a product to the cart and another to checkout the order.

And here is the Session Bean:

CartBean.java:

package com.javacodegeeks.enterprise.ejb;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

import javax.annotation.PostConstruct;
import javax.ejb.Stateful;
import javax.ejb.StatefulTimeout;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import com.javacodegeeks.enterprise.product.Product;

@Stateful
@StatefulTimeout(unit = TimeUnit.MINUTES, value = 20)
public class CartBean implements Cart {

	@PersistenceContext(unitName = "pu", type = PersistenceContextType.EXTENDED)
	private EntityManager entityManager;

	private List products;

	@PostConstruct
	private void initializeBean(){
	   products = new ArrayList<>();
	}

	@Override
	public void addProductToCart(Product product) {
		 products.add(product);

	}

	@Override
	@TransactionAttribute(TransactionAttributeType.REQUIRED)
	public void checkOut() {
		for(Product product : products){
			entityManager.persist(product);
		}
		products.clear();

	}
}

As you can see, our Session bean implements our Cart interface and simply holds a List of products (more on class Product later).

In the above code notice:

  • We use @Statefulto annotate the class as a Stateful Session Bean.
  • We declare a timeout with @StatefulTimeout(unit = TimeUnit.MINUTES, value = 20) annotation. This timeout denotes the amount of time that the bean should exist, and thus be valid for the session. It should correspond with the HTTP Session timeout value.
  • We use @PersistenceContext to inject an EntityManager that will handle the persistence of our products.
  • We use @PostConstruct annotation on private void initializeBean() method. This will denote to the EJB container to execute that method on bean initialization. You can view it as a constructor.
  • We use @TransactionAttribute(TransactionAttributeType.REQUIRED) annotation on public void checkOut() method. This annotation is required to denote that the container is about to invoke a business method within a transaction context. As you can, see in that method the products on the list are persisted in the database.

5. The Product Entity class

This is the object representing a simple product in our cart application. It consists of an id and a type. As we said, when the order is checked out we want the product on the cart to be persisted in a database. We used JPA 2.0 annotations to map Product class to a MySQL table. For this example, I’ve created a simple database named shop and table named product created with the script:

MySQL product table creation script:

CREATE TABLE `product` (
  `ID` int(11) NOT NULL AUTO_INCREMENT,
  `TYPE` varchar(256) COLLATE utf8_unicode_ci NOT NULL,
  PRIMARY KEY (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

So this is the table:

product-table

Let’s see the code of Product class:

Product.java:

package com.javacodegeeks.enterprise.product;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "PRODUCT", catalog = "shop")
public class Product implements Serializable {

  private static final long serialVersionUID = 1L;

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Column(name = "ID", nullable = false)
  private int id;

  @Column(name = "TYPE", nullable = false)
  private String type;

  public int getId() {
    return id;
  }

  public String getType() {
    return type;
  }

  public void setType(String description) {
    this.type = description;
  }

}

The above annotations are self explanatory. Very briefly, we use:

  • @Entity to declare the class as an Entity.
  • @Table(name = "PRODUCT", catalog = "shop") to show that the class will be mapped to a table named product in a database named shop.
  • @Id, @GeneratedValue(strategy = GenerationType.IDENTITY) to declare that the field id of the class Product will be the primary key of the corresponding database table.
  • @Column to map a class field to a database column of table product.

Finally, for the persistence to work we need to create a persistence.xml file inside ejbModule/META-INF folder. The file looks like this:

application.xml:

<persistence xmlns="http://java.sun.com/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
             version="2.0">

    <persistence-unit name="pu" transaction-type="JTA">

        <jta-data-source>jdbc/MySQLDataSource</jta-data-source> 
        <class>com.javacodegeeks.enterprise.product.Product</class>
    </persistence-unit>

</persistence>

Make sure you’ve integrated MySQL with Glassfish correctly using this quide. For more information on persistence.xml file you can see this Oracle guide.

So the final project structure of StatefulBeansEJB is :

ejb-project-structure

6. Create a new Dynamic Web Project

Go to File -> New -> Dynamic Web Project. Fill out the form and make sure you check “Add project to an EAR” and put StatefulEJBEAR as the “EAR project name”:

new-dynamic-web-project

After clicking “Finish”, go to the project Explorer and Right click on the Project StatefulSessionBeansTest and go to Properties-> Deployment Assembly -> Add -> Porject -> StatefulEJB :

deplyment-assembply

7. Create a new Servlet

Go to StatefulSessionBeansTest Web project and create a new Servlet named ShoppingCartServlet:

new-servlet

So this would be the final structure of the Web Project :

dynamic-web-project-structure

Here is the code of the Servlet:

ShoppingCartServlet.java:

package com.javacodegeeks.enterprise.servlet;

import java.io.IOException;

import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.javacodegeeks.enterprise.ejb.Cart;
import com.javacodegeeks.enterprise.product.Product;

@WebServlet("/ShoppingCartServlet")
public class ShoppingCartServlet extends HttpServlet {

	private static final long serialVersionUID = 1L;
	private static final String CART_SESSION_KEY = "shoppingCart";

    public ShoppingCartServlet() {
        super();

    }

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

		System.out.println("Hello from servlet");

		Cart cartBean = (Cart) request.getSession().getAttribute(CART_SESSION_KEY);

		 if(cartBean == null){
		      // EJB is not yet in the HTTP session
		      // This means that the client just sent his first request
			  // We obtain a CartBean instance and add it to the session object.
		      try {
		        InitialContext ic = new InitialContext();
		        cartBean = (Cart) 
		         ic.lookup("java:global/StatefulEJBEAR/StatefulSessionBeansEJB/CartBean!"
		         		+ "com.javacodegeeks.enterprise.ejb.Cart");

		        request.getSession().setAttribute(CART_SESSION_KEY, cartBean);

		        System.out.println("shoppingCart created");

		      } catch (NamingException e) {
		        throw new ServletException(e);
		      }
		 }

		 String productName = request.getParameter("product");
		 if(productName != null && productName.length() > 0){

		      Product product = new Product();
		      product.setType(productName);
		      cartBean.addProductToCart(product);

		      System.out.println("product "+productName+" added");
		 }

		 String checkout = request.getParameter("checkout");
		 if(checkout != null && checkout.equalsIgnoreCase("yes")){
		      // Request instructs to complete the purchase
		      cartBean.checkOut();
		      System.out.println("Shopping cart checked out ");
		 }

	}

}

In the above Serlvet, when the user sents a GET request for the fist time, a new CartBean instance will be obtained from the container and added to the session. Then the product query parameter is parsed, and if it’s not null a new Product with type productName, and will e added to the list of products in the session bean.

Then the checkout query parameter is parsed and if it’s evaluated to 'yes' the products in the session bean will be persisted.

Tip: If you are having trouble figuring out the Portable JNDI names for EJB PassivationObject look at the logs or output of Glassfish when deploying the project and you will find a line like this :2013-12-13T18:22:28.598+0200|INFO: EJB5181:Portable JNDI names for EJB PassivationObject: (java:global/StatefulBeans/StatefulEJB/PassivationObject, java:global/StatefulBeans/StatefulEJB/PassivationObject!com.javacodegeeks.enterprise.ejb.Passivation)

8. Test

Now we are simply going to deploy the Dynamic Web Application to Glassfish, and add some products on the cart. Then we will request to checkout the order.

Let’s say we want to add some products, we can issue the following requests :

http://localhost:8080/StatefulSessionBeansTest/ShoppingCartServlet?product=ram

http://localhost:8080/StatefulSessionBeansTest/ShoppingCartServlet?product=mouse


http://localhost:8080/StatefulSessionBeansTest/ShoppingCartServlet?product=ssd

While posting these requests this is the output from the console:

2014-01-07T22:02:07.622+0200|INFO: Hello from servlet
2014-01-07T22:02:07.684+0200|INFO: shoppingCart created
2014-01-07T22:02:07.687+0200|INFO: product ram added
2014-01-07T22:02:12.236+0200|INFO: Hello from servlet
2014-01-07T22:02:12.237+0200|INFO: product mouse added
2014-01-07T22:02:24.851+0200|INFO: Hello from servlet
2014-01-07T22:02:24.851+0200|INFO: product ssd added

Now to checkout the order you can issue:

http://localhost:8080/StatefulSessionBeansTest/ShoppingCartServlet?checkout=yes

This is the output from the console:

2014-01-07T22:19:46.444+0200|INFO: Hello from servlet
2014-01-07T22:19:46.537+0200|INFO: Shopping cart checked out

Here you can see the products on the database :

mysql-terminal

Dowload Eclipse Project

This was an example on Java EE Stateful Session Bean (EJB). Here are the Eclipse Projects of this example : StatefulEJBS.zip

Do you want to know how to develop your skillset to become a Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you two of our best selling eBooks for FREE!

JPA Mini Book

Learn how to leverage the power of JPA in order to create robust and flexible Java applications. With this Mini Book, you will get introduced to JPA and smoothly transition to more advanced concepts.

JVM Troubleshooting Guide

The Java virtual machine is really the foundation of any Java EE platform. Learn how to master it with this advanced guide!

Given email address is already subscribed, thank you!
Oops. Something went wrong. Please try again later.
Please provide a valid email address.
Thank you, your sign-up request was successful! Please check your e-mail inbox.
Please complete the CAPTCHA.
Please fill in the required fields.

5 Responses to "Java EE Stateful Session Bean (EJB) example"

  1. I think that you should not create resource in get request:

    Product product = new Product();
    product.setDescription(productName);
    shoppingCartBean.addProduct(product);

    • gmarques says:

      Hello Tomasz,

      I agree with you when you say that HTTP GET requests should never change data in the server, but the tutorial is written this way to simplify both the user reading plus the tutorial testing section, ie. focusing on the Stateful Session Bean itself.

      Thank you,
      Gonçalo

  2. santiago says:

    Hi, I tried to pass this example to WAS Liberty but I have a trouble.

    The lookup is not working, please maybe I am doing some wrong. please can you help me??

    Application Error
    SRVE0777E: Exception thrown by application class ‘com.javacodegeeks.enterprise.servlet.ShoppingCartServlet.doGet:51′
    javax.servlet.ServletException: javax.naming.NameNotFoundException: javax.naming.NameNotFoundException: java:global/StatefulEJBEAR/StatefulSessionBeansEJB/CartBean!com.javacodegeeks.enterprise.ejb.Cart
    at com.javacodegeeks.enterprise.servlet.ShoppingCartServlet.doGet(ShoppingCartServlet.java:51)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:575)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:668)
    at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1274)
    at [internal classes]
    Caused by: javax.naming.NameNotFoundException: javax.naming.NameNotFoundException: java:global/StatefulEJBEAR/StatefulSessionBeansEJB/CartBean!com.javacodegeeks.enterprise.ejb.Cart
    at com.ibm.ws.jndi.url.contexts.javacolon.internal.JavaURLContext.lookup(JavaURLContext.java:327)
    at [internal classes]
    at javax.naming.InitialContext.lookup(InitialContext.java:411)
    at com.javacodegeeks.enterprise.servlet.ShoppingCartServlet.doGet(ShoppingCartServlet.java:44)
    … 4 more

    • Me too says:

      I also get the same error. Did you find a way to get pass by this?

    • Shane says:

      I figure it out. If you don’t create database, don’t create persistence.xml file and comment out
      // @PersistenceContext(unitName = “pu”, type = PersistenceContextType.EXTENDED)
      // private EntityManager entityManager;

Leave a Reply


− 7 = zero



Java Code Geeks and all content copyright © 2010-2014, Exelixis Media Ltd | Terms of Use | Privacy Policy
All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries.
Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.
Do you want to know how to develop your skillset and become a ...
Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you two of our best selling eBooks for FREE!

Get ready to Rock!
You can download the complementary eBooks using the links below:
Close