Local Session Counter
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
Entity Bean Home methods
Tutorials
Message Bean

This example creates a local counter using a session bean. Session beans have a similar API to stateless session beans, but have internal state. In other words, they're like servlets sessions.

The EJB 2.0 spec introduced local interfaces. Local interfaces let you pass arguments by reference to your beans. This gives a small performance boost, but also adds a new use for EJB. EJBs can now be used to better structure web applications, even applications that have no need for distributed objects.

For example, almost every web application needs some sort of database interface. Because EJB 2.0 provides strong support for container-managed-persistence, you can now use EJB for much of the database work without dealing with distributed objects or worrying about a performance.

  1. Remote Interface
  2. Local Home Interface
  3. Server Implementation
  4. Servlet
  5. Configuring with Resin
  6. JNDI configuration
  7. Client

Remote Interface

The only exposed method in the local method is the hit() method, used for the next count. Notice that it does not throw RemoteException, unlike a remote interface and that it extends EJBLocalObject instead of EJBObject.

CounterLocal.java
package test;

import javax.ejb.*;

public interface CounterLocal extends EJBLocalObject {
  int hit();
}

Local Home Interface

The Home interface's sole responsibility is to create a new counter instance. For session beans, only create() methods belong in the home.

CounterLocalHome.java
package test;

import javax.ejb.*;

public interface CounterLocalHome extends EJBLocalHome {
  CounterLocal create() throws CreateException;
}

Server Implementation

Developers will generally create a com.foo.AbstractSessionBean class which provides default implementations for the SessionBean methods. This example uses Resin's abstract implementation of AbstractSessionBean in com.caucho.ejb that provides stubs for the SessionBean methods.

The session bean needs to create exactly one ejbCreate method with no arguments to match the create in SessionLocalHome. It must also define the business methods.

CounterBean.java
package test;

import javax.ejb.*;

import com.caucho.ejb.*;

public class CounterBean extends AbstractSessionBean {
  int count;

  // no initialization needed
  public void ejbCreate()
  {
  }

  public int hit()
  {
    return ++count;
  }
}

Servlet

In general, EJB server configuration 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-EJB lets you rename the ejb-jar.xml file as *.ejb and put it in WEB-INF. We'll name it WEB-INF/hello.ejb.

Local interfaces use local-home and local, corresponding to the familiar home and remote. It's possible for a bean to have both local and remote interfaces.

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

counter.ejb
<ejb-jar>
<enterprise-beans>
  <session>
    <ejb-name>counter</ejb-name>
    <local-home>test.CounterLocalHome</local-home>
    <local>test.CounterLocal</local>
    <ejb-class>test.CounterBean</ejb-class>
    <session-type>Stateful</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.
local-homethe local home interface class
localthe local interface class
ejb-classthe implementation class
session-typeStateful is like a servlet with sessions
transaction-typeTransactions. For now, you can ignore this.

Configuring with Resin

Configuration for local beans is exactly the same as for remote beans.

Since the ejb-jar is server-independent, it's still necessary to instantiate the bean in a server-dependent way. Since Resin-EJB is JNDI resource-based configuring the bean involves configuring a resource-ref.

part of resin.conf
  <ejb-server config-directory="WEB-INF"/>

The EJBServer automatically searches for all *.ejb files in WEB-INF. So it will find our hello.ejb deploy the session servlet.

The url-prefix parameter tells the EJB servlet its own URL. During initialization, servlets don't know their own URL, so we need to tell it.

Finally, the servlet is a load-on-startup servlet so it will be initialized on server startup.

JNDI configuration

The JNDI configuration needs to link the local-ejbs into the full JNDI namespace. We'll put the EJB's at java:comp/env/local-ejb.

resin.conf for JNDI
<jndi-link>
  <jndi-name>java:comp/env/local-ejb</jndi-name>
  <factory>com.caucho.ejb.LocalContextFactory</factory>
  <init-param java.naming.provider.url="http://localhost:8080/ejb"/>
</jndi-link>

tagmeaning
jndi-linklinks a foreign JNDI namespace into the application
jndi-namethe "mount point" of the foreign namespace
jndi-factorythe EJB's factory for looking up local contexts.
init-paramParameters to the factory

Client

EJB clients follow the following steps in using a local object:

  1. Lookup the home stub using JNDI.
  2. Create an local stub from the home object.
  3. Call business methods on the stub.

Typically, an EJB client will get the home handle using JNDI.

counter.jsp
<%@ page import="test.*, javax.ejb.*, javax.naming.*" %>
<%!
CounterLocalHome home;

// Get the home stub once and save it in home
public void _jspInit()
  throws ServletException
{
  try {
    Context cmp = (Context) new InitialContext().lookup("java:comp/env/cmp");

    home = (CounterLocalHome) env.lookup("counter");
  } catch (NamingException e) {
    e.printStackTrace();
  }
}
%><%

// create the remote object
CounterLocal counter = home.create();
%>
hit: <%= counter.hit() %><br/>
hit: <%= counter.hit() %>

hit: 1
hit: 2


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