Stateless Session Hello
Resin 3.0

Features
Installation
Configuration
Web Applications
IOC/AOP
Resources
JSP
Servlets and Filters
Portlets
Databases
Admin (JMX)
CMP
EJB
Amber
EJB 3.0
Security
XML and XSLT
XTP
JMS
Performance
Protocols
Third-party
Troubleshooting/FAQ

Tutorials
Burlap Clients
Hessian Clients
CORBA/IIOP Server
Scrapbook

Stateless Session Hello
Entity Bean Home methods
Local Session Counter
Message Bean
Tutorials
Tutorials
Entity Bean Home methods

Find this tutorial in: /usr/local/resin/webapps/resin-doc/ejb/tutorial/ejb-stateless-hello
Try the Tutorial

This example creates a stateless session bean. A stateless session bean is similar to a servlet without sessions. The server bean itself can have state, but doesn't remember the client from one request to the next.

A Hello, World example for EJB is fairly complicated. To implement the EJB you need to implement:

  • A remote interface
  • A home interface
  • The bean implementation
  • a deployment descriptor

To configure Resin to be a server for the EJB you need to:

  • Configure the ejb-server
  • Configure a protocol

To use the EJB from a client you need to:

  • Create a factory for the correct protocol
  • Obtain a Home
  • Use the Home to create stubs to the remote object

In this tutorial, a simple "Hello" EJB is created and deployed within Resin. The use of the Hello EJB from a client is also demonstrated.

  1. Remote Interface
  2. Home Interface
  3. Bean Implementation
  4. Deployment descriptor
  5. Configuring the Resin EJB server
  6. Configuring the protocol
  7. Client
  8. JNDI client
    1. JNDI-based client configuration
    2. JNDI-based client code

Remote Interface

The remote interface defines the client view of the bean. It extends EJBObject and declares all the business methods. Our only business method is the hello method.

Hello.java
See it in: WEB-INF/classes/example/Hello.java
package example;

import java.rmi.*;
import javax.ejb.*;

public interface Hello extends EJBObject {
  public String hello() throws RemoteException;
}

Home Interface

The sole responsibility of the Home interface is to create a remote object. The client uses the Home to obtain instances of the bean.

HelloHome.java
See it in: WEB-INF/classes/example/HelloHome.java
package example;

import java.rmi.*;
import javax.ejb.*;

public interface HelloHome extends EJBHome {
  public Hello create() throws RemoteException, CreateException;
}

Bean Implementation

The third class for EJB's is the bean implementation class. It implements the functionality provided by the remote interface.

A stateless session bean needs to have exactly one ejbCreate method with no arguments. It must also define the business methods.

The bean implementation class for all EJB Session bean's must implement the SessionBean interface. Most users will create a com.foo.AbstractSessionBean class that provides default method implementations. This example extends Resin's AbstractSessionBean to simplify the implementation.

HelloBean.java
See it in: WEB-INF/classes/example/HelloBean.java
package example;

import java.rmi.*;
import javax.ejb.*;

public class HelloBean extends com.caucho.ejb.AbstractSessionBean {
  public void ejbCreate()
  {
  }

  public String hello()
  {
    return "Hello, world";
  }
}

Deployment descriptor

A deployment descriptor is used to describe and define the EJB bean. In general, configuration of EJB's belongs in an ejb-jar.xml file. In a jar, it belongs in META-INF/ejb-jar.xml.

This name, of course, only makes sense if the EJB is put into a jar. Jars are inconvenient during development, so Resin lets you rename the ejb-jar.xml file as *.ejb and put it in WEB-INF. We'll name it WEB-INF/hello.ejb. You can have as many *.ejb files as you want, Resin will use them all (for example WEB-INF/hello.ejb, WEB-INF/goodbye.ejb).

<ejb-jar> is the top element for a deployment descriptor for the bean. It's part of the EJB spec. The configuration for the stateless session example looks like the following:

hello.ejb
See it in: WEB-INF/hello.ejb
<ejb-jar>
<enterprise-beans>
  <session>
    <ejb-name>hello</ejb-name>
    <home>example.HelloHome</home>
    <remote>example.Hello</remote>
    <ejb-class>example.HelloBean</ejb-class>
    <session-type>Stateless</session-type>
    <transaction-type>Bean</transaction-type>
  </session>
</enterprise-beans>  
</ejb-jar>

TagMeaning
ejb-jarcontaining XML tag for the whole ejb-jar
enterprise-beansanother container for the beans
sessiondefine a session bean
ejb-namethe bean's name. hello is part of the URL.
homethe home interface class
remotethe remote interface class
ejb-classthe implementation class
session-typeStateless is like a servlet without sessions
transaction-typeTransactions. For now, you can ignore this.

Configuring the Resin EJB server

All of the above steps are needed to define and implement an EJB. Once the bean has bean defined and implemented, it is deployed within the Resin server. Through deployment, Resin becomes aware of the EJB and how it is meant to be used.

<ejb-server> is used to configure the Resin EJB server. The EJB server is responsible for reading the *.ejb descriptor files and deploying the beans within the server.

ejb-server in web.xml
See it in: WEB-INF/web.xml
<web-app>

  ...

  <ejb-server config-directory="WEB-INF"/>
    
  ...

</web-app>

The ejb-server automatically searches for all *.ejb files in WEB-INF. It will find the hello.ejb file and deploy the "hello" EJB bean.

Configuring the protocol

The server needs to make the EJB's available to remote clients using a protocol. The protocol defines the language that is used by the client and the server to communicate.

This example uses the Hessian EJB Servlet to make the EJB's available to remote clients using the Hessian protocol.

Configuring hessian in web.xml
See it in: WEB-INF/web.xml
<web-app>

  ...

  <ejb-server config-directory="WEB-INF"/>
    
  <servlet servlet-name='hessian' servlet-class='com.caucho.hessian.EJBServlet'/>   
  <servlet-mapping url-pattern='/hessian/*' servlet-name='hessian'/>

  ...

</web-app>

When the EJB is used by a Hessian client, the client adds the ejb-name from the hello.ejb file to the url that points to the Hessian servlet. In this example, it is http://localhost:8080/hessian/hello.

Client

The whole point of EJB stateless session beans is to provide a means of communication between a client and a server. Typically, the client will be on a different machine, or at least a different Java virtual machine, than the server.

The client needs to be provided with some things to be able to accomplish this. It needs:

  • The Home interface (HelloHome.class)
  • The Remote interface (Hello.class)
  • A library of the standard ejb classes
  • A library of classes that implement the protocol being used

EJB clients perform the following steps in obtaining and using a remote object:

  1. Create a protocol-specific factory that is used to obtain Home objects from the remote server
  2. Use the factory to obtain a home for a particular ejb.
  3. Use the home to create a remote object stub.
  4. Call business methods on the remote object stub.

The factory is the link between the client and the server. Once the factory is created, it is used to obtain Home's for particular EJB's. The factory, and the Home's, do not change, Usually the factory and the Home for each EJB are created once and then stored for future use. An applet, for example, creates the factory on startup and stores it as a member variable. Individual classes within the applet, that need particular Home's, create them once and store them as member variables.

The home is used to create a stub to a particular remote instance of an object. A stub is a placeholder or proxy object. The client uses the stub just like any other object, the actual execution of the methods provided by the stub happens on the server.

In this example, the client is a servlet and the Home is obtained in the init() method and stored as a member variable. A HessianProxyFactory is created and then used to obtain the HelloHome for the Hello ejb.

The url of the server is passed as an init-param to the servlet. This allows for easy configuration if the url of the server adress changes. The reulsting url that is passed to the factory will look something like http://localhost:8080/hessian/home.

See it in: WEB-INF/classes/example/HelloServlet.java
  private HelloHome helloHome;

  public void init(ServletConfig config)
    throws ServletException
  {
    super.init(config);

    serverUrl = config.getInitParameter("java.naming.provider.url");

    if (serverUrl == null)
      throw new ServletException("init-param java.naming.provider.url is required");

    if (!serverUrl.endsWith("/"))
      serverUrl = serverUrl + "/";

    try {
      HessianProxyFactory factory = new HessianProxyFactory();
      helloHome = (HelloHome) factory.create(HelloHome.class, serverUrl + "hello");
    } catch (Exception e) {
      throw new ServletException(serverUrl + "hello", e);
    }
  }

JNDI client

The preceding example used Hessian directly. This is a good idea for applets or other clients that do not have good support for the use of JNDI.

More often, clients will use JNDI, the Java Naming and Directory Interface, to get the Home. JNDI is used to configure the factory, the factory is obtained with a JNDI lookup and is used to obtain Home's for the different EJB's.

JNDI is based on naming contexts. Contexts are like paths on a file system, but store objects instead of files. By convention, the path java:comp/env/ejb is used for EJB.

JNDI-based client configuration

Typically, the client will be on a different machine, or at least a different Java virtual machine, than the server. Each client environment will provide a different means of configuring a JNDI factory.

Resin uses jndi-link to configure the JNDI factory.

The url of the server is passed as an init-param to the HessianContextFactory. This allows for easy configuration if the url of the server address changes.

Resin JNDI client configuration
See it in: WEB-INF/web.xml
<web-app>

  ...

  <jndi-link jndi-name='java:comp/env/ejb'
             factory='com.caucho.hessian.HessianContextFactory'>
    <init-param java.naming.provider.url='http://localhost:8080/hessian'/>
  </jndi-link>

  ...

</web-app>

HessianContextFactory can be used in any server or other Java environment that supports JNDI.

JNDI-based client code

The client code does a JNDI lookup to get the factory. As in the previous client example, the client is a servlet and the Home is obtained in the init() method and stored as a member variable.

Only the init() method is differet in the HelloJndiServlet, the rest of the class is identical to the previous HelloServlet.

See it in: WEB-INF/classes/example/HelloJndiServlet.java

  private HelloHome helloHome;

  public void init(ServletConfig config)
    throws ServletException
  {
    super.init(config);

    try {
      Context ejb = (Context) new InitialContext().lookup("java:comp/env/ejb");
      helloHome = (HelloHome) ejb.lookup("hello");

    } catch (NamingException e) {
      throw new ServletException("java:comp/env/ejb",e);
    }
  }

Try the Tutorial


Tutorials
Tutorials
Entity Bean Home methods
Copyright © 1998-2005 Caucho Technology, Inc. All rights reserved.
Resin® is a registered trademark, and HardCoretm and Quercustm are trademarks of Caucho Technology, Inc.