Stateful Beans Using Deployment Descriptors

Take a look at ejb-jar.xml and ShoppingCartBean.java. You specify a stateful bean with the "session" and "session-type" tags. Note that all bean types in EJB 3.0 are homeless, so there is no requirement for a "home" or "local-home" tag. The bean class is specified with the "ejb-class" tag. ShoppingCartBean also implements a remote interface. Take a look at ShoppingCart.java. To define this as the remote interface of ShoppingCartBean you need to use the "remote" tag.

XML Validation

Notice that schemas are referenced in ejb-jar.xml and jboss.xml. In the former, the URL is http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd. In the latter, the URL is http://www.jboss.org/j2ee/schema/jboss_5_0.xsd. We recommend that you include these schemas in your deployment descriptors so that on deployment, the xml can be validated. If the schemas are provided, a deployment exception will occur if either of the two descriptors are invalid. If the schemas are not included, there is no validation on deployment and debugging can be more difficult. Note that these schema files are also provided locally in the jboss-ejb3.jar file so that validation can occur off-line.

@Remove

Take another look at ejb-jar.xml. Look for the "remove-list" tag. Instead of explicitly calling EJBObject.remove() in your applications and thus polluting it further with J2EE specific code, any method specified in the "remove-list" tag will cause the stateful bean instance to be removed from the container at the end of the method call. This deployment descriptor behavior mimics the @Remove annotation.

JNDI Bindings

The CalculatorBean will have its remote interface bound in JNDI. Take a look at jboss.xml. Note the "jndi-name" tag. This specifies the jndi binding for the remote interface.

Timeouts and @CacheConfig

Stateful session beans have configurable timeout values which can control the amount of time a bean can remain idle prior to passivation or removal. Notice the cache-config element in jboss.xml. The idle-timeout-seconds element configures the amount of idle time before the bean is passivated and the remove-timeout-seconds configures the amount of idle time before the bean is permanently removed.

Client

Open up Client.java. You'll see that it looks up the stateful bean under its jndi name. Also notice that there is no Home interface and you can begin executing on the stateful bean right away. When you access the bean in JNDI, an instance of the stateful bean will be created on the server. So, when you need a different instance of the stateful bean, you do an additional jndi.lookup() to get this new reference.

Building and Running

To build and run the example, make sure you have ejb3.deployer installed in JBoss 4.0.x and have JBoss running. See the reference manual on how to install EJB 3.0.
Unix:    $ export JBOSS_HOME=<where your jboss 4.0 distribution is>
Windows: $ set JBOSS_HOME=<where your jboss 4.0 distribution is>
$ ant
$ ant run

run:
run:
     [java] Buying 1 memory stick
     [java] 2004-10-06 19:37:16,869 INFO org.jboss.remoting.InvokerRegistry[main] - Failed to load soap remoting transpo
rt: org/apache/axis/AxisFault
     [java] Buying another memory stick
     [java] Buying a laptop
     [java] Print cart:
     [java] 2     Memory stick
     [java] 1     Laptop
     [java] Checkout
     [java] Should throw an object not found exception by invoking on cart after @Remove method
     [java] Successfully caught no such object exception.

The INFO message you can ignore. It will be fixed in later releases of JBoss 4.0.

Jar structure

EJB 3.0 beans must be packaged in a JAR file with the suffix .jar. Running the ant script above creates a JAR file within the deploy/ directory of JBoss. All that needs to be in that jar is your server-side class files. So basically just the ShoppingCartBean and the interfaces it implements. JBoss will automatically browse the JAR file to determine if any EJBs are annotated by any classes within it. THere is no precompilation step.