Enterprise Java

EJB passivation and activation example

In this tutorial we are going to see how activation and passivation works in a Stateful Java Enterprise Session Bean.

1. Introduction

Stateful Session Beans usually hold information about a specific client, and holds that information throughout the whole session. It is a fact though, that client sessions tend to be active for a respectable amount of time, and of course many clients can be online the same time. As a result, it is a necessity for the EJB container to implement a mechanism that makes possible the releasing of resources that are not used at a given moment, and can be activated again when needed.

Passivating a Session Bean means removing it from the Session EJB Cache of the container and storing all the necessary information and properties of the session bean in a file. Activating a session bean means reading the aforementioned file and restoring the passivated session bean in the cache. As you might imagine all the fields of a that session bean must be Serializable.

In this example 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 passivation and activation properties. We are going to use Eclipse Java EE IDE 4,3 Kepler and Glassfish 4.0 as our container.

2. Create a new Enterprise Application Project

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

new-ear-project

3. Create a new EJB Projet

Create a new EJB Project called StatefulEJB. 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 “StatefulBeansEAR” as EAR project name:

new-ejb-project

Click Next twice and choose to create EJB Client JAR, as well as to generate the ejb-jar.xml deployment descriptor :

ejb-client

4. Create a Sateful Session Bean

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

Passivation.java:

package com.javacodegeeks.enterprise.ejb;

import javax.ejb.Local;

import com.javacodegeeks.enterprise.ejb.property.PropertyObject;

@Local
public interface Passivation {

	void setPropertyObject(PropertyObject propertyObject);

	PropertyObject getPropertyObject();

}

And here is the Session Bean:

PassivationBean.java:

package com.javacodegeeks.enterprise.ejb;

import javax.ejb.PostActivate;
import javax.ejb.PrePassivate;
import javax.ejb.Stateful;

import com.javacodegeeks.enterprise.ejb.property.PropertyObject;

@Stateful
public class PassivationBean implements Passivation {

	private PropertyObject myProperty;

	@Override
	public void setPropertyObject(PropertyObject propertyObject) {
		this.myProperty = propertyObject;

	}

	@Override
	public PropertyObject getPropertyObject() {

		return this.myProperty;
	}

	@PrePassivate
	private void prePassivate(){
	    // Free resources 
	    // ...

	    System.out.println("Passivating EJB. Property value: " 
	      + myProperty.getProperty());
	}

	@PostActivate
	private void postActivate(){
	    // Reactivate resources
	    // ...

	    System.out.println("Activating EJB. Property value: " 
	      + myProperty.getProperty());
	}
}

In the above code :

    • private void prePassivate(): Annotated with @PrePassivate is the method to be executed when the EJB container decides to passivate that session bean.
    • private void postActivate(): Annotated with @PostActivate

is the method to be executed when the EJB container activates a passivated session bean because it’s needed again.

Additionally, as you can see the session bean has a private PropertyObject myProperty field. This is an object that can contain information for the session, for the bean, for the resources and any kind of data one can find useful.

So when the bean is passivated we want this property has to be saved and restored as well. Thus, it must be Serilizable as we mentioned in the Introduction. Having said that, if you don’t want to store this property, because you don’t care to retrieve that resource when the bean is activated, you can declare the object transient using the @Transient annotation . For this Object I’ve created a new source Package named com.javacodegeeks.enterprise.ejb.property.

PropertyObject.java:

package com.javacodegeeks.enterprise.ejb.property;

import java.io.Serializable;

public class PropertyObject implements  Serializable  {

	private static final long serialVersionUID = 1L;

	 private String property;

	public PropertyObject(String value){
	    this.property = value;
	  }

	  public String getProperty() {
	    return property;
	  }

}

So this would be the final structure of the EJB project SatefulEJB:

project-structure

5. 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 StatefulBeans EAR as the “EAR project name”:

new-dynamic-web-project

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

deployment-assembly

6. Create a new Servlet

Go to StatefulBeansTest Web project and create a new Servlet named MyServlet:

new-servlet

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

dynamic-web-projecct-structure

MyServlet.java:

package com.javacodegeeks.enterprise.servlet;

import java.io.IOException;

import javax.naming.InitialContext;
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.Passivation;
import com.javacodegeeks.enterprise.ejb.property.PropertyObject;

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

	private static final long serialVersionUID = 1L;

	public MyServlet() {
		super();

	}

	protected void doGet(HttpServletRequest request,

		HttpServletResponse response) throws ServletException, IOException {

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

		InitialContext ic;

		Passivation passivation;

		String beanCountparam = request.getParameter("count");

		if (beanCountparam != null) {
			int beanCount = Integer.parseInt(beanCountparam);

			try {
				ic = new InitialContext();
				for (int i = 0; i < beanCount; i++) {

					passivation = (Passivation) ic
							.lookup("java:global/StatefulBeansEAR/StatefulEJB/PassivationBean!"
									+ "com.javacodegeeks.enterprise.ejb.Passivation");

					passivation.setPropertyObject(new PropertyObject(
							"bean" + i));

					request.getSession().setAttribute("bean" + i,
							passivation);
				}
			} catch (Exception e) {
				throw new ServletException(e);
			}
		}

		String beanActivationIndex = request.getParameter("activate");

		if (beanActivationIndex != null) {
			try {
				ic = new InitialContext();

				passivation = (Passivation) request.getSession()
						.getAttribute("bean" + beanActivationIndex);

				System.out.println("TestObject property value: "
						+ passivation.getPropertyObject().getProperty());

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

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

}

In the above code, when the Servlet is accessed, it parses the count query parameter, generates count session beans and stores them to the request session. Accordingly, if the activate query parameter is present the corresponding bean is retrieved from the session.

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)

7. Test

After creating the above projects you have to Run StatefulBeansTest on Glassfish.

To test the desired behavior, we have to somehow trigger the passivation and activation of a certain session bean. To force a Session bean to be passivated we have to make the container remove it from the session cache. Glassfish can host 512 session beans at most, by default. So if we trigger a request asking for 600 beans to be created, some of them will be eventually removed from the cache.

This request can be :

http://localhost:8080/StatefulBeansTest/MyServlet?count=600

And the output in the console will be :

2013-12-30T22:29:36.978+0200|INFO: Hello from Servlet
2013-12-30T22:29:37.315+0200|INFO: Passivating EJB. Property value: bean31
2013-12-30T22:29:37.329+0200|INFO: Passivating EJB. Property value: bean64
2013-12-30T22:29:37.332+0200|INFO: Passivating EJB. Property value: bean70
2013-12-30T22:29:37.345+0200|INFO: Passivating EJB. Property value: bean98
2013-12-30T22:29:37.390+0200|INFO: Passivating EJB. Property value: bean117
2013-12-30T22:29:37.390+0200|INFO: Passivating EJB. Property value: bean116
2013-12-30T22:29:37.390+0200|INFO: Passivating EJB. Property value: bean115
2013-12-30T22:29:37.394+0200|INFO: Passivating EJB. Property value: bean114
2013-12-30T22:29:37.394+0200|INFO: Passivating EJB. Property value: bean113
2013-12-30T22:29:37.394+0200|INFO: Passivating EJB. Property value: bean112
2013-12-30T22:29:37.397+0200|INFO: Passivating EJB. Property value: bean111
2013-12-30T22:29:37.398+0200|INFO: Passivating EJB. Property value: bean110
2013-12-30T22:29:37.399+0200|INFO: Passivating EJB. Property value: bean109
2013-12-30T22:29:37.402+0200|INFO: Passivating EJB. Property value: bean108
2013-12-30T22:29:37.403+0200|INFO: Passivating EJB. Property value: bean107
.
.
.

So as you can see some of the beans are removed from the cache and thus get passivated. Now to trigger the activation of a bean we can simply request to retrieve a bean that is already passivated, for example bean31.

This request can be:

http://localhost:8080/StatefulBeansTest/MyServlet?activate=31

And the output in the console will be :

2013-12-30T22:33:48.742+0200|INFO: Hello from Servlet
2013-12-30T22:33:48.744+0200|INFO: Activating EJB. Property value: bean31
2013-12-30T22:33:48.745+0200|INFO: TestObject property value: bean31

That’s it. Now to be convinced that the session beans we actually serialized to the disc you can go to Glassfish_installation_folder/glassfish4/glassfish/domains/domain1/session-store where you can actually see the folder that the beans were saved:

session-store

Download Eclipse Project

This was an example on EJB passivation and activation. Download the Eclipse Project of this tutorial : EJBPassivationActivation.zip

Nikos Maravitsas

Nikos has graduated from the Department of Informatics and Telecommunications of The National and Kapodistrian University of Athens.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

2 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Renan
11 years ago

Hello Goncalo! Thanks for the tutorial, very useful one!

I have one question, when the EJB container does the passivation, where does it passivate the object to? Memory? Serialized file? Or may it mix both? I’m asking because I have an ADF BC background and I’m planning to do some comparisons using both tecnologies, in ADF BC the passivation occurs to a database table called PS_TXN.

Regards,
Renan.

gmarques
11 years ago

Hello Renan,

That’s a subject that would definitely worth a full blog post on it’s own. There are many possible configurations that may affect the container passivation mechanism. By default the container passivates to the file system but there are other details that may come into play. I suggest you to go through documentation related with the following subjects (regarding EJB): Availability, Session Store Location and Passivation Stores.

Back to top button