Develop stateful session beans
We can create a bean implementation class for a stateful session bean as introduced in the Enterprise JavaBeans™ (EJB) 1.0 specification and significantly simplified by the EJB 3.0 specification. A stateful bean is a type of session bean intended for use by a single client during its lifetime and maintains a conversational state with the client that is calling it.
Make sure that you understand the inheritance rules for each annotation you implement. For example, the @TransactionManagement annotation is coded on the stateful session bean class only. We cannot use the @TransactionManagement annotation in the class that it extends, or any class higher in the class inheritance tree.
Stateful session beans can have the following views: no-interface local view (new in EJB 3.1), business local, business remote, EJB 2.1 local, and EJB2.1 remote client views. One example is a shopping cart where the client adds items to the cart over the course of an on-line shopping session.
The following example shows a basic stateful session bean:
package com.ibm.example; public interface ShoppingCart { void addToCart (Object o); Collection getContents(); } package com.ibm.example; @Stateful public class ShoppingCartBean implements ShoppingCart { private ArrayList contents = new ArrayList(); public void addToCart (Object o) { contents.add(o); } public Collection getContents() { return contents; } }As with other enterprise bean types, we can also declare metadata for stateful session beans in the deployment descriptor rather than using annotations; for example:<?xml version="1.0"?> <ejb-jar xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_1.xsd" version="3.1"> <enterprise-beans> <ejb-name>ShoppingCartBean</ejb-name> <business-local>com.ibm.example.ShoppingCart</business-local> <ejb-class>com.ibm.example.ShoppingCartBean</ejb-class> <session-type>Stateful</session-type> </enterprise-beans> </ejb-jar>
- Code the initialization and destruction methods, understanding that they run in an unspecified security context and an unspecified transaction context. During initialization, the instance is created, dependency injection occurs, and PostConstruct life cycle interceptor callbacks are invoked. The PreDestroy life cycle interceptor callbacks are invoked for a stateful session bean when a remove method is called. Also keep in mind that the PreDestroy life cycle interceptor callbacks are not called if the stateful session bean times out while in the passive state, or if an unexpected exception occurs during a method invocation on the bean and the bean is discarded.
- Use PrePassivate and PostActivate methods if the stateful session bean can contain state that is not serializable. The container can passivate a stateful session bean instance anytime that it is not enlisted in a transaction or currently running a method request. The stateful session bean instance is moved to the passive state by serializing all the state data. If any of the state data does not serialize, the stateful session bean instance is discarded by the container.
- Consider implementing the optional javax.ejb.SessionSynchronization interface if the state data of the stateful session bean needs to be reset after a transaction rollback. The state data of a stateful session bean is not transactional and is not automatically reset to the initial state as the result of a transaction rollback. By implementing the afterCompletion method of the javax.ejb.SessionSynchronization interface, the stateful session bean instance might reset itself to the initial or consistent state.
- Use the @AccessTimeout notation to prohibit concurrent client requests or limit how long a method waits for the instance lock to be granted. By default, the container allows concurrent client requests, but serializes all method calls and container-invoked callbacks to prevent multi-threaded access to the stateful session bean instance. This behavior is like using container-managed concurrency with write locks for singleton session beans. However, unlike singleton session beans, stateful session beans cannot be configured to use bean-managed concurrency and the lock type cannot be changed. Only the access-timeout value can be modified for stateful session beans. The following code example illustrates a stateful session bean with a concurrent access-timeout value that prohibits concurrent client requests:
package com.ibm.example; @Stateful public class ShoppingCartBean implements ShoppingCart { private ArrayList contents = new ArrayList(); @AccessTimeout( value=0 ) public void addToCart (Object o) { contents.add(o); } public Collection getContents() { return contents; } } package com.ibm.example; @Stateful public class ShoppingCartBean implements ShoppingCart { private ArrayList contents = new ArrayList(); @AccessTimeout( value=0 ) public void addToCart (Object o) { contents.add(o); } public Collection getContents() { return contents; } }If no annotation is provided, the default behavior is to wait until a lock is granted. No time limit exists for how long a client waits for the lock to be granted. Because nothing is coded at the class level, no wait time limit exists for a lock to be granted for all methods of the class. If the @AccessTimeout annotation is used and the container cannot grant the lock within the specified time limit, a javax.ejb.ConcurrentAccessTimeoutException exception occurs on the client. The @AccessTimeout annotation only applies to methods that are declared in the same class as the @AccessTimeout annotation. For a given class, the metadata for the @AccessTimeout annotation is never inherited from a class higher in the class inheritance tree.
An access-timeout value of -1 indicates that concurrent method calls block access to the bean instance indefinitely (the default). An access-timeout value of 0 indicates that concurrent method calls are not allowed. The exception, javax.ejb.ConcurrentAccessException, occurs when concurrency is detected. And any positive value indicates the amount of time to wait until the method can proceed.
Prior to Java EE 6, the only concurrency behavior supported for stateful session beans was an access-timeout of -1, no concurrency. Since the Java EE 6 specification changed the default behavior, a system property is supported that provides the older default behavior. See EJB container system properties for more information about the com.ibm.websphere.ejbcontainer.EE5Compatibility system property.
We can also specify the @AccessTimeout annotation using the XML deployment descriptor, and if you use the XML deployment descriptor, the metadata from the @AccessTimeout annotation is ignored. The following example uses the XML deployment descriptor to specify the same metadata as the previous example.
<session> <ejb-name>ShoppingCartBean</ejb-name> <concurrent-method> <method> <method-name>addToCart</method-name> </method> <access-timeout> <timeout>0</timeout> <unit>Milliseconds</unit> </access-timeout> </concurrent-method> </session>
- It is important to know that the XML coding of the concurrent-methodType follows the three styles outlined in the EJB specification for composing the XML for container-transaction method elements. The three styles are: Style 1 uses the special method name * to apply the access-timeout value to all business methods for the specified bean.
<!-- Example: Style 1 --> <concurrent-method> <method> <method-name>*</method-name> </method> <access-timeout> <timeout>2000</timeout> <unit>Milliseconds</unit> </access-timeout> </concurrent-method>Style 2 is used to refer to a business method with a specific name and assign it the specified access-timeout value. If the method name is overloaded, meaning multiple methods have the same name but different method signatures, all methods with this name have the specified access-timeout value.
<!-- Example: Style 2 --> <concurrent-method> <method> <method-name>businessMethod</method-name> </method> <access-timeout> <timeout>2000</timeout> <unit>Milliseconds</unit> </access-timeout> </concurrent-method>Style 3 is used to refer to a distinct method that matches the given method name and has a method signature that matches the method parameters listed. Style 3 takes precedence over both style 1 and style 2.
<!-- Example: Style 3 --> <concurrent-method> <method> <method-name>businessMethod</method-name> <method-params> <method-param>long</method-param> <method-param>int</method-param> </method-params> </method> <access-timeout> <timeout>2000</timeout> <unit>Milliseconds</unit> </access-timeout> </concurrent-method>If style 1 XML is used to define an access-timeout value, then all @AccessTimeout annotations on the bean are ignored because the method level one is used instead.
- Ensure that you understand the inheritance rules for the annotations that we have used.
- Stateful session beans are not reentrant, which means that the stateful session bean method calls itself back. If a reentrant call is made to a stateful session bean, a javax.ejb.ConcurrentAccessTimeoutException exception occurs on the client, regardless of the access-timeout value. This exception does not result in the stateful session bean being discarded, nor does it mark the transaction for rollback, unless the exception is not handled by the caller.
Related concepts
Stateful session bean failover for the EJB container
Related tasks
Use asynchronous beans
EJB container system properties