Thursday, March 10, 2011

EJB 3 Stateful Session Bean

In this guide I am going to talk about the EJB3 Stateful Session Beans.
In one of my previous posts I talked about Stateless Session Beans; the difference between these two tipes of beans is that the container maintains the state of the Stateful session bean and subsequent method invocations by the same client are handled by the same stateful bean instance.

Bean instances cannot be returned to the pool and reused while a client session is still active. Instead, a bean instance must be held in memory to wait for the next request from the client owning the session. As a result, stateful session bean instances held by a large number of concurrent clients can have a significant memory footprint. The technique called passivation, that I presented in an older post about EJB 3 lifecycle, is used to alleviate this problem.
In the next picture I show you an example of a Stateful Session Bean used to maintain informations of a user during a registration process:


Stateful Session Bean's instance variable used to store the state must be Serializable objects. This is because during the passivation process the bean object must be serialized to maintain his state in memory and to be restored at the next method invocation by the same client. In my bean, the instance variables Account, Contacts and UserBean implements the Serializable interface for this reason. 

Since Stateful Session beans could not be pooled like stateless session beans, there is a danger of accumulating many of them if we don't have a way to destroy them. Therefore, we have to define a business method designed for removing the bean instance by the client using the @Remove annotation. There could be more than one method designated for this reason, in my bean I have only one and it is the register method. The session is terminated and bean instance removed when a client calls this method .


We can also see from the picture the lifecycle callback methods, initialize() and cleanUp(). The first one is called by the container for both the PostConstruct lifecycle and PostActivate, while the second is called by the container before Destroy and before Passivating the bean. The initialize method is used to initialize resources such as connection to the dataSource in my case, while the cleanUp is used to close connections and release resources not serializable, in my case to close the connection to the dataSource.

Business interface for Stateful Session beans works at almost the same way as it does for stateless session beans, with some exceptions. Stateful Session Beans support only @Local and @Remote invocations and could not be called and exposed as web service because of the stateless nature of SOAP web services. It could be possible to annotate business interface methods with the @Remove annotation.


As you can see from the previous picture I used to expose a @Remote business interface with the methods to call the Stateful bean. It is a simple POJI (Plain Old Java Interface).

Now we could give a look at the client that calls the Stateful Session Bean.
Almost any Java component could be a Stateful bean client: jsp pages, servlet, pojo or other beans, but NOT stateless session beans. 
Stateful session bean clients follows these general steps to use a stateful bean: 
  • the client receives a reference to use to the bean from JNDI;
  • all the invocations to the bean are made through the appropriate interface, in my case the remote interface I presented before;
  • the client makes as many calls to the bean methods as required to complete the session;
  • the last method invocation is the method annotated with the remove metadata annotation that removes the instance and distruct it.

I used a servlet as client for my stateful session bean, and because the servlet may be shared by multiple clients and the instance that we inject to a servlet instance could be used by more than one client at the same time. 
Because of this fact I retrieve a bean instance using the JNDI lookup from the initial context instead of using the @EJB annotation as I used for the Stateless Session Bean. 
The previous picture shows the servlet I used to call the setAccount() method from the business interface, and other servlet similar to this one are used to call the other business methods. 
To handle the instance of the bean I used to put the bean instance to the HttpSession of the client. I don't know if it is the best way to hold the bean instance. I searched for other ways to do so and I have not found so many other ways. Someone used to Serialize the bean instance in a file using a BufferOutputStream but, I repeat, I don't know which is the best way. 
In EJB 2 we used the Handle interface to Serialize the EJBObject but in this version of the EJBs there is not an interface that extends the EJBObject so I don't know how to do this in the same way.
Thats all for now. We'll see other components in the next posts.

2 comments:

  1. Hi,

    I'm making a Struts2/EJB3 application, but my Stateful bean can't remember its state from a request to another, even if I save the bean in the session.
    I tried various things (JNDI, http://code.google.com/p/struts2ejb3/ plugin) but it's the same problem.
    If I use a fat client, it's ok, but my Struts actions work only if I set the bean as Stateless, but then the bean is shared among all clients.
    Do you have an idea? Thanks.

    ReplyDelete
  2. Hi Danicela,

    I have never worked with both together.
    I had a search on google and I've found this other blog:
    http://jpa-qlhibernateejb3struts.blogspot.it/2009/05/jpa-ql-hibernate-3-ejb3-struts-2.html seems he used those together, maybe can help...

    Alberto

    ReplyDelete