Stateful Session Bean’s Lifecycle Callback Methods

The lifecycle callbacks are methods defined in the bean class but not in business interface which the container calls when specific lifecycle event or transition occurs. The following annotations are used to define lifecycle callbacks on stateful session beans.

@PostConstruct

  • Used to mark a method defined in the bean class so that the container can invoke that marked method just after the creation of stateful session bean instance and dependency injection of any resources.
  • This callback can be used to initialize any resources such as database connection, files etc required for the bean.

@PreDestroy

  • Used to mark a method defined in the bean class so that the container can invoke that marked method before the stateful session bean is destroyed.
  • This callback can be used to release or close any resources used by the bean.

Rules for @PostConstruct and @PreDestroy

  • Their method signature must return a void and take no arguments.
  • The method should not throw Checked Exception.
  • The method can have access modifiers – public, private, package-private and protected.
  • The method may be FINAL.

Passivation and Activation of Stateful Session Bean

An idle stateful session bean instance, (i.e.) a stateful session bean which hasn’t been accessed by the client for some time (which is configurable in the container), may be temporarily transferred to some form of secondary storage (passivated) automatically by the container to efficiently manage the size of its working set (memory and other resources). The transfer from the working set to secondary storage is called instance passivation. The transfer back is called activation.

Conditions for Passivation

  • A container may only passivate a stateful session bean instance when the instance is not in a transaction.
  • A container must not passivate a stateful session bean with an extended persistence context unless the following conditions are met,
    • All the entities in the persistence context are serializable.
    • The EntityManager is serializable.

@PrePassivate

  • Used to mark a method defined in the bean class so that the container can invoke that marked method before the stateful session bean is passivated.
  • This callback can be used to release or close any resources used by the bean.

@PostActivate

  • Used to mark a method defined in the bean class so that the container can invoke that marked method after the stateful session bean is activated.
  • This callback can be used to re-initialize any resources such as database connection, files etc which are closed before passivation.

Rules for @PostActivate and @PrePassivate

  • Their method signature must return a void and take no arguments.
  • The method can have access modifiers – public, private, package-private and protected.
  • The method cannot be STATIC or FINAL.

Example

The example stateful session bean described below is used to insert ‘Person’ data into the database. We use PostConstruct and PostActivate to open/re-open the database connection and PreDestroy and PrePassivate to close the database connection.

Create a ‘Person Transfer Object class and add getters and setters

package com.ibytecode.to;

import java.io.Serializable;
import java.util.Date;

public class Person implements Serializable{

	private int id;
	private String name;
	private Date bdate;
	private Character gender;
	
	public Person(int id, String name, Date bdate, Character gender) {
		super();
		this.id = id;
		this.name = name;
		this.bdate = bdate;
		this.gender = gender;
	}
	//Getters and Setters
}

Create a local or remote business interface for the bean. We used remote interface.

package com.ibytecode.business;
import javax.ejb.Remote;
import com.ibytecode.to.Person;

@Remote
public interface IPerson {
	void addPerson(Person person);
}

Create the stateful session bean and implement the remote interface.

package com.ibytecode.businesslogic;

import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;

import com.ibytecode.business.IPerson;
import com.ibytecode.to.Person;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import javax.ejb.Stateful;
import javax.sql.DataSource;

@Stateful
public class PersonBean implements IPerson {
	private Connection connection;
	
	@Resource(name = "java:/MySQLDS")
	private DataSource dataSource;

	public PersonBean() {}

	@PostConstruct
	@PostActivate
	public void initialize() {
    		System.out.println("In PostActivate/PostConstruct");
		try {
			connection = dataSource.getConnection();
		} catch (SQLException sqle) {
			sqle.printStackTrace();
		}
	}
    
	public void addPerson(Person person) {
		try {
			Statement statement = connection.createStatement();
			statement.execute("INSERT INTO PERSON1 VALUES(" + 
				person.getId() + ", "+ "'" + person.getName() + "'," + 
			person.getBdate()+ ",'" + person.getGender() + "')");
		} catch (Exception sqle) {
			sqle.printStackTrace();
		}
	}
	
	@PreDestroy
	@PrePassivate
	public void releaseResources() {
		System.out.println("In PrePassivate/PreDestroy");
		try {
			if(connection != null)
			{
				connection.close();
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
}
  • In this code, after the stateful session bean instance is created by the container, it will inject the datasource specified by jndi name java:/MySQLDS.
  • Next, the container will call the method of the bean which is annotated with @PostConstruct, in our case, initialize() method to do any resource initialization. In our case, we open the database connection.
  • When the bean is idle for some period of time, the container may decide to passivate the bean. Before passivation, the container will invoke the method marked with @PrePassivate, in our case, releaseResources() method to close any resources used by the bean.
  • When a client request access to the bean, the container may create a new bean or activate a passivated bean. When it activates the bean, the container will invoke the method marked with @PostActivate, in our case, initialize() method to re-initialize any resources required by the bean.
  • When a passivated bean instance times out or when a client invokes the method marked with @Remove, the container may destroy the bean. Before destroying, the container will invoke the method annotated with @PreDestroy, in our case, releaseResources() method. In this method, we close the database connection.

Create a java application client.

package com.ibytecode.client;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.naming.Context;
import javax.naming.NamingException;

import com.ibytecode.business.IPerson;
import com.ibytecode.businesslogic.PersonBean;

import com.ibytecode.to.Person;

public class PersonBeanClient{

	public static void main(String[] args) {
		IPerson bean = doLookup();
		
		String str = "1985/05/19";
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
		Date d = null;
		try {
			d = sdf.parse(str);
		} catch (ParseException e) {
			e.printStackTrace();
		}

		Person p1 = new Person(1, "Raj", d, 'f');
		bean.addPerson(p1);
		System.out.println("Person added");
	}
	
	//JNDI Lookup differs based on different containers
	private static IPerson doLookup() {
	//Refer the example link for the complete code
	. . . .
	}
}

Refer this page for complete code.

Leave a Comment