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.
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.
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.
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.
Then 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.