|
Java™ by example!
|
|
|
How do I get started with an EJB stateful session bean in JBoss?
A stateful session bean maintains conversational state. For example, it may represent a customer's session at an online shopping site.
Just like a stateless session bean, a stateful session bean can be pooled. This is necessary when there are a large number of clients using beans, invoking methods and using up resources such as memory or database connections. So how does the container manage to control resource usage? It can't simply return the bean to the pool to be used by other clients, as it contains state of another client. This is where activation and passivation come into play. When the container passivates a bean, it swaps it out to secondary storage. To determine which bean, it uses a clever algorithm, for example it can swap out the "least recently used" (LRU) bean. activation is its counterpart. Typically, when the bean's client makes a request, the container will swap the bean back into primary storage. When a bean is about to be passivated, the container invokes the bean's callback method ejbPassivate(). This allows the bean to free up resources. Likewise, when the bean is activated, the container invokes its method ejbActivate() allowing the bean to reclaim resources.
Passivation and activation is done by serializing and deserializing beans. Notice that the interface javax.ejb.EnterpriseBean extends java.io.Serializable.
This example creates an enterprise bean capable of maintaining links (URL's) given by the client. After every method invocation of the client, the state is retained (as opposed to a stateless session bean). To keep it simple, our example bean has three business methods:
The following example shows the necessary steps to write this LinkManager stateful session bean and deploy it under JBoss. All of the packaging and deploying will be done using command-line tools. At the end, an ant build script is provided that will make these labour tasks easier.
- Download and install JBoss
This example is written and tested with JBoss 3.0.4. Download and run it!
- Write the remote interface
The remote interface is the view the client has on the bean. It contains the business methods that a client may invoke. It must extend EJBObject and its methods should follow the RMI rules (throw java.rmi.RemoteException and have all parameters as well as the return values be Serializable objects). The remote interface is implemented by the container.
When the client invokes a method on the remote interface, the call gets proxied to the actual bean class. You will notice later on that the bean class does not implement this interface. However, the methods of your bean class must match the signature of the methods defined in your remote interface. com/esus/ejb/linkmanager/LinkManager.java:
- Write the home interface
The home interface is used by the EJB container to create your session bean and can contain multiple create methods. This is different from a stateless session bean that can only have one create method as it cannot guarantee to maintain state. The home interface will be implemented by the EJB container. The create method should return the remote interface of the bean. The Home interface must inherit from EJBHome and must also follow the RMI rules. In our example, the create method takes a single argument title with which the bean is initialized.
com/esus/ejb/linkmanager/LinkManagerHome.java:
When the client calls the create method on the Home interface, it will get back the remote interface and has everything it needs to invoke business methods.
- Write the stateful sessionbean
The business logic sits in the actual Bean. This class must implement all methods listed in the remote interface (but not implement the remote interface itself!). It must implement the interface javax.ejb.SessionBean that contains a number of callback methods:
- ejbRemove(): called by the container when it decides to delete a session bean instance.
- ejbActivate(): is called by the container when the bean is about to be swapped out
- ejbPassivate(): is called by the container right after the bean has been swapped in
- setSessionContext(SessionContext ctx): this method is called once by the container, when the bean is initialized, right before ejbCreate(). It provides access to the container-provided runtime context (eg. the environment properties)
In addition, a stateful session bean is required to contain ejbCreate() methods that return void. The ejbCreate() method acts as the contructor for the session bean and is called by the Container when the create() method on the Home interface is intercepted. com/esus/ejb/linkmanager/LinkManagerBean.java:
Another simple class is used to hold one link: Link. Notice that Link must be Serializable as it goes over the wire between the client and the bean. com/esus/ejb/linkmanager/Link.java:
- Create the deployment descriptor ejb-jar.xml
With a deployment descriptor, you can declaratively specify attributes on the bean. The following attributes are specified in the ejb-jar.xml for our LinkManager bean:
- ejb-name: a symbolic name for the bean, used as a reference in other parts of the deployment descriptor
- home: the fully qualified name of the home interface class
- remote: the fully qualified name of the remote interface class
- ejb-class: the fully qualified name of the bean class
- session-type: the session bean type, stateful or stateless
- transaction-type: Bean or Container (bean or container managed transactions)
META-INF/ejb-jar.xml:
- Compile
Our directory structure now looks like this:
Make sure you put jboss-j2ee.jar in your classpath:
- Package your bean into a JAR file:
- Deploy your EJB
To deploy LinkManager.jar in JBoss, simply copy it to the JBoss deployment directory:
Your JBoss console will display:
- Write the client
The client uses JNDI to locate the home object. Using the home object, it can create an instance that implements the LinkManager remote interface. Using this interface, the bean's business methods can be invoked. About PortableRemoteObject.narrow: The JNDI lookup method returns an object that needs to be cast to the appropriate home interface type. This cast needs to be done using javax.rmi.PortableRemoteObject.narrow which is passed the object you desire to cast and the class to which you want to cast it. PortableRemoteObject performs a safe cast, that is, it ensures interoperability with EJB compliant implementations. client\LinkManagerClient.java:
- Generate a client jar:
Before being able to compile and run your client, it must have access to the EJB's home and remote interface classes via the classpath. You can have this done automatically by an IDE, or by an ant task. Let's do it manually here:
- Compile the client
Set your classpath and compile:
- Run the client
Ant can be used to make the compile/deployment tasks easier. Place the following build.xml file in your current directory. build.xml:
Your directory structure now looks like this:
To use ant, install it and add it to your path. Then, using the build.xml build file, you can execute the following commands:
Further Information
Author of answer: Joris Van den Bogaert
Comments to this answer are only viewable by members. Login or become a member!
|
|
|
|
|