Stateless Session Bean vs Stateful Session Bean

We already discussed the fundamentals of Enterprise Java Bean . Also we discussed EJB Stateless Session Bean and EJB Stateful Session Bean with examples.In this chapter we are discussing an example which illustrates the difference between both stateless and stateful session beans.

Stateless Session Bean vs Stateful Session Bean

There are two types of Session Beans. They are:

a)Stateless Session Bean,

b)Stateful session Bean

A stateless Session Bean , as the name implies , does not keep a conversational state with the calling client. In other words , if a stateless session bean has two business methods , and if a client is simultaneously accessing both the methods. Then we cannot guarantee that  the state of the bean remains the same. If another client is trying to access the bean , the container may give the existing instance to that client. So the state can be modified by the new client.

In case of a Stateful Session Bean , a conversational state is maintained between the client and the bean. In other words there will be separate bean instances for each client.So state for a client cannot be changed by a new client.

Now let us discuss the life cycles of each type of beans.

Statelful Session Bean Life Cycle

1)In case of  Stateful Session Bean , the life cycle starts when the client invokes the bean.

2)If a method with @PostConstruct annotation is there , it will be invoked

3)Now the init() or ejbCreate() method will be invoked,if any. Now the bean is active.

4)Now the container can  move the bean to deactivate state or passive state. Passive state means , the bean instance will be moved to secondary storage.If there is a method exists with @PrePassivate annotation , it will be executed before moving the bean to passive state.

5)If a client invokes a bean in existing in passive state , it will go to  active state .If a method with  @PostActivate annotation is there  , it will be executed by the EJB container. The bean will stay in active state.

6)Now if the client invokes the method with @Remove annotation, the method with @PreDestroy will be invoked by EJB container .Now the bean is ready for garbage collection.

Stateless Session Bean Life Cycle

There are only two states in a Stateless Session Bean life cycle .

1)Does not exist state

2)Ready for invocation from client.

The EJB container creates a pool of beans and does the necessary dependency injection. Then , if a method with @PostConstruct annotation is there ,it will be invoked.Now the bean is ready for client invocation.If a method annotated with@PreDestroy is there , then that method will be invoked at the end of client invocation. Now the bean is ready for garbage collection.

Stateless  Session Bean vs Stateful Session Bean example

Now we can discuss an example  which compares both types of beans. Each bean has two methods. First method sets a String attribute to bean .Second method Retrieves the value of attribute.The  client application has two bean references. Client invokes the bean methods simultaneously . In  case of Stateless Session Bean , the bean is not  keeping a conversational  state with client. In case of Stateful session Bean , bean keeps a conversational state with Client. In other words , in case of a Stateful Session Bean, the  two bean references from the client are unique. In case of Stateless Session Bean,  the same reference can be reused by the EJB container .

Tools And Software Required

1)Java EE SDK 1.6  – Download link

2)Eclipse Indigo – Download link

3)JBoss-6.0.0.M1 – Download link

Steps

1)Install Java EE SDK. Download and extract JBoss and Eclipse to appropriate locations.Open eclipse in a suitable workspace.

2)In eclipse , start a new EJB Project by  File–>New–>EJB Project. Give suitable name to the project. In our case , it is given as SessionBeanSample. Select EJB version as 3.x and run time as JBoss 6.x.

1

3)Now right click on the ejbModules . Then select New –>Package.Give suitable name as package . In this example , we are using com.beans as package name.

4)Right click on the package . The select New–>Session Bean.Select State Type as Stateless.Give the name as StatelessBean.Select both local and remote options for interfaces.

3-1

Press Finish.Now the interfaces and class will be created. paste the contents as given.

StatelessBeanRemote.java

import javax.ejb.Remote;

@Remote
public interface StatelessBeanRemote {
public void setMessage(String message);

public String getMessage();
}

StatelessBeanLocal.java

import javax.ejb.Local;

@Local
public interface StatelessBeanLocal {
public void setMessage(String message);

public String getMessage();
}

StatelessBean.java

import javax.ejb.Stateless;

/**
* Session Bean implementation class StatelessBean
*/
@Stateless
public class StatelessBean implements StatelessBeanRemote, StatelessBeanLocal {
private String message;

/**
* Default constructor.
*/
public StatelessBean() {

}

@Override
public void setMessage(String message) {
this.message = message;
}

@Override
public String getMessage() {
String reply;
if(null == message){
reply = "Empty message";
}else{
reply = message;
}
return reply;
}

}

5)Right click on the package name and New–>SessionBean.This time create a Stateful SessionBean.

3-2

Press Finish . Interfaces and class will be generated. Now paste the contents as given.

StatefulBeanRemote.java

import javax.ejb.Remote;

@Remote
public interface StatefulBeanRemote {
public void setMessage(String message);

public String getMessage();
}

StatefulBeanLocal.java

import javax.ejb.Local;

@Local
public interface StatefulBeanLocal {
public void setMessage(String message);

public String getMessage();
}

StatefulBean.java

import javax.ejb.Stateful;

/**
* Session Bean implementation class StatefulBean
*/
@Stateful
public class StatefulBean implements StatefulBeanRemote, StatefulBeanLocal {
private String message;

/**
* Default constructor.
*/
public StatefulBean() {

}

@Override
public void setMessage(String message) {
this.message = message;
}

@Override
public String getMessage() {
String reply;
if (null == message) {
reply = "Empty message";
} else {
reply = message;
}
return reply;
}

}

6)Now right click on the server tab and create new JBoss 6.x server instance.Add our SessionBeanSample project to server run time.

4Then start the server.Once the deployment is done.The JNDI details will be displayed in the console.

INFO  [JndiSessionRegistrarBase] Binding the following Entries in Global JNDI:

    StatefulBean/remote – EJB3.x Default Remote Business Interface

    StatefulBean/remote-com.beans.StatefulBeanRemote – EJB3.x Remote Business Interface

    StatefulBean/local – EJB3.x Default Local Business Interface

    StatefulBean/local-com.beans.StatefulBeanLocal – EJB3.x Local Business Interface

 [JndiSessionRegistrarBase] Binding the following Entries in Global JNDI:

    StatelessBean/remote – EJB3.x Default Remote Business Interface

    StatelessBean/remote-com.beans.StatelessBeanRemote – EJB3.x Remote Business Interface

    StatelessBean/local – EJB3.x Default Local Business Interface

    StatelessBean/local-com.beans.StatelessBeanLocal – EJB3.x Local Business Interface

7)Now let us create a client project .Create a dynamic web project with JBoss 6.x as target run time.Create the following classes in it.

Client for Stateless Session Bean

StatelessClient.java

import java.util.Properties;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import com.beans.StatelessBeanRemote;

public class StatelessClient {

/**
* @param args
*/
public static void main(String[] args) {
Properties props = new Properties();
props.setProperty("java.naming.factory.initial",
"org.jnp.interfaces.NamingContextFactory");
props.setProperty("java.naming.factory.url.pkgs", "org.jboss.naming");
props.setProperty("java.naming.provider.url", "127.0.0.1:1099");
try {
InitialContext ctx = new InitialContext(props);
StatelessBeanRemote exampleBean = (StatelessBeanRemote) ctx
.lookup("StatelessBean/remote");
exampleBean.setMessage("This is from main");
StatelessClient client = new StatelessClient();
client.doLookup();
System.out.println("Message from Bean in main:"
+ exampleBean.getMessage());
} catch (NamingException e) {
e.printStackTrace();
}

}

public void doLookup() {
Properties props = new Properties();
props.setProperty("java.naming.factory.initial",
"org.jnp.interfaces.NamingContextFactory");
props.setProperty("java.naming.factory.url.pkgs", "org.jboss.naming");
props.setProperty("java.naming.provider.url", "127.0.0.1:1099");
try {
InitialContext ctx = new InitialContext(props);
StatelessBeanRemote exampleBean = (StatelessBeanRemote) ctx
.lookup("StatelessBean/remote");
exampleBean.setMessage("This is from lookup");
System.out.println("Message from Bean in doLookup:"
+ exampleBean.getMessage());
} catch (NamingException e) {
e.printStackTrace();
}

}

}

Client for Stateful Session Bean

StatefulClient.java

import java.util.Properties;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import com.beans.StatefulBeanRemote;

public class StatefulClient {

public static void main(String[] args) {
Properties props = new Properties();
props.setProperty("java.naming.factory.initial",
"org.jnp.interfaces.NamingContextFactory");
props.setProperty("java.naming.factory.url.pkgs", "org.jboss.naming");
props.setProperty("java.naming.provider.url", "127.0.0.1:1099");
try {
InitialContext ctx = new InitialContext(props);
StatefulBeanRemote exampleBean = (StatefulBeanRemote) ctx
.lookup("StatefulBean/remote");
exampleBean.setMessage("This is from main");
StatelessClient client = new StatelessClient();
client.doLookup();
System.out.println("Message from Bean in main:"
+ exampleBean.getMessage());
} catch (NamingException e) {
e.printStackTrace();
}

}

public void doLookup() {
Properties props = new Properties();
props.setProperty("java.naming.factory.initial",
"org.jnp.interfaces.NamingContextFactory");
props.setProperty("java.naming.factory.url.pkgs", "org.jboss.naming");
props.setProperty("java.naming.provider.url", "127.0.0.1:1099");
try {
InitialContext ctx = new InitialContext(props);
StatefulBeanRemote exampleBean = (StatefulBeanRemote) ctx
.lookup("StatefulBean/remote");
exampleBean.setMessage("This is from lookup");
System.out.println("Message from Bean in doLookup:"
+ exampleBean.getMessage());
} catch (NamingException e) {
e.printStackTrace();
}

}

}

Output

Output of Stateless Session Bean

Compile and run StatelessClient.java.The output is:

Message from Bean in doLookup:This is from lookup

Message from Bean in main:This is from lookup

The output indicates that the same bean reference is reused by the container. For the second access , the existing instance is reused.

Output of Stateful Session Bean

Compile and run StatefulClient.java.The output is:

Message from Bean in doLookup:This is from lookup

Message from Bean in main:This is from main

The output indicates that different instances were created for each access from client.

See Related Topics

EJB Overview

Stateless Session Bean Example

Stateful Session Bean example

EJB Message Driven Bean example