2. Stateful Session Beans
Overview
Stateful EJB 3 session beans, as opposed to stateless ones, save their states between method calls. All configuration steps for stateless session beans apply for stateful beans, with the addition of some extra options described below.
Note that GraniteDS manages stateful EJBs by looking up their name in JNDI and caching the returned handle in the caller HTTP session. You must be aware of potential HTTP session expiration beside the standard stateful EJB 3 lifecycle timeout and must set consistant values for both.
Standard Configuration
Standard configuration uses declarative destination setup in your services-config.xml file.
Let's say we have an EJB 3 stateful session bean defined by those classes:
package myapp.ejb3.services; public interface PositionService { public int getX(); public void saveX(int x); public void remove(); }
package myapp.ejb3.services; import javax.ejb.Local; import javax.ejb.Remove; import javax.ejb.Stateful; @Stateful @Local(PositionService.class) public class PositionServiceBean implements PositionService { int x = 300; public int getX() { return x; } public void saveX(int x) { this.x = x; } @Remove public void remove() { } }
The lifecycle of this bean begins when a users HTTP session first accesses it. The bean supports setting and retrieving an integer value, and is destroyed when the client invokes the remove() method or when an expiration timeout occurs.
However, without scanning the PositionServiceBean class, there is no way for GraniteDS to know that this bean is a stateful one, nor to know that the remove() method is a removal method. You must provide this information in the services-config.xml as follows:
<?xml version="1.0" encoding="UTF-8"?> <services-config> <services> <service id="granite-service" class="flex.messaging.services.RemotingService" messageTypes="flex.messaging.messages.RemotingMessage"> <destination id="position"> <channels> <channel ref="my-graniteamf"/> </channels> <properties> <factory>ejbFactory</factory> <!-- Specific for stateful beans --> <ejb-stateful> <remove-method> <signature>remove</signature> <retain-if-exception>false</retain-if-exception> </remove-method> </ejb-stateful> </properties> </destination> </service> </services> <factories> <factory id="ejbFactory" class="org.granite.messaging.service.EjbServiceFactory"> <properties> <lookup>myApp/{capitalized.destination.id}ServiceBean/local</lookup> </properties> </factory> </factories> <channels> <channel-definition id="my-graniteamf" class="mx.messaging.channels.AMFChannel"> <endpoint uri="http://{server.name}:{server.port}/{context.root}/graniteamf/amf" class="flex.messaging.endpoints.AMFEndpoint"/> </channel-definition> </channels> </services-config>
The destination configuration is similar to the one used for stateless beans, except for the <ejb-stateful> subsection. The presence of this <ejb-stateful> node, even empty, informs GDS that this EJB 3 is stateful and should be managed as such. Otherwise, the bean will be considered stateless and one instance will be shared between all users.
The inner <remove-method> node contains information about the remove() methods of your stateful bean:
- signature: This is the name of the method, optionally followed by a parameter list. If your remove() method has arguments, the signature should follow the conventions used in java.lang.reflect.Method.toString() calls. For example, with the following remove() method:
@Remove public int remove(boolean arg1, Integer arg2, String[] arg3) {...}
... you should write this signature:
<signature>remove(boolean,java.lang.Integer,java.lang.String[])</signature>
- retain-if-exception (optional): This is the equivalent of the @Remove annotation attribute; the default is false.
You may of course add multiple <remove-method> nodes in one ejb-stateful node if necessary.
InitialContext & Automatic Configuration
Everything documented about stateless session beans applies here. Again, be sure to put a META-INF/services-config.properties file in your jars and to make them available in the GDS classpath.
Automatic configuration avoids destination configuration in your services-config.xml file as well as any related <ejb-stateful> metadata. The scanner will automatically recognize the beans annotated with the @Stateful annotation and discover all remove methods.
You may have a look at a sample application using those annotations with EJB 3 by importing the graniteds_ejb3 project from the examples folder of the GDS distribution.
