Sun Java System Application Server

Samples Index

The Interceptor-Stateless Session Bean Sample Application

This is a very simple EJB 3.0 Stateless Session Bean with a Remote business interface that uses EJB 3.0 interceptor mechanism to validate the parameter passed to a business method.

Business Interface

The Stateless Session bean has a Remote business interface with a single business method.

import javax.ejb.Remote;

@Remote
public interface StatelessSession {
    public String initUpperCase(String val)
        throws BadArgumentException;
}

Note that unlike prior versions of EJB, the Remote interface is not required to extend java.rmi.Remote and its business methods are not required to throw java.rmi.RemoteException. Here, BadArgumentException is an application exception.

The business interface is designated as a remote business interface via the @javax.ejb.Remote annotation.

Stateless Session Bean Class

Here's the bean implementation:

@Stateless
@Interceptors({ NullChecker.class, ArgumentsChecker.class })
public class StatelessSessionBean
    implements StatelessSession  {
    public String initUpperCase(String val) {
       String first = val.substring(0, 1);
       return first.toUpperCase() +
val.substring(1);
   }
}

The annotation @javax.ejb.Stateless defines the component and designates this class as the bean class for a stateless session bean.

The business method converts the first character in the parameter to upper case. Note that the business method does not check if the argument is null OR if the parameter starts with a alphabet. It could have been done in the business method itself, but we use the EJB 3.0 interceptor facility to do the parameter validation checks.

Interceptors are used to interpose on business method invocations and life cycle events that occur on an enterprise bean instance. An interceptor class is just like any other java class. It need not extend any special class nor does it need to implement any well known interface. An interceptor class defines (exactly) one business method interceptor method by annotating a method with @AroundInvoke annotation. The method must take javax.interceptor.InvocationContext as argument and must return java.lang.Object. (Note:- It is possible to declare interceptors and interceptor methods using .xml file, but for this sample we will use only annotations).

More than one interceptor can be chained to interpose a single business method. @Interceptors is an annotation that can be used to indicate the list of interceptors to be invoked before any business methods are invoked on this bean. Note that since this annotation is defined at the type level, the interceptors are fired before every business method is invoked. The @Interceptors annotation is defined in javax.interceptor package.

Interceptor classes

The bean lists (using @Interceptor annotation) the list of interceptors to be fired before its business methods are called. Here the bean list two interceptors: NullChecker and ArgumentsChecker. The name of these classes can be anything. The exact method to be invoked on these interceptors is designated using the @AroundInvoke annotation. The @AroundInvoke annotation is defined in javax.interceptor package.

In our sample, the two interceptors are defined as follows:

package enterprise.interceptor_stateless_ejb;

import java.lang.reflect.Method;
import javax.interceptor.AroundInvoke;
import javax.interceptor.InvocationContext;

public class NullChecker {

    @AroundInvoke
    public Object checkIfNull(InvocationContext ctx)
        throws Exception {
        Method method = ctx.getMethod();
        if (method.getName().equals("initUpperCase")) {
            String param = (String) (ctx.getParameters()[0]);
                if (param == null) {
                    throw new BadArgumentException("Illegal argument: null");
              }
          }
// An interceptor can throw any runtime exception or
// application exceptions that are allowed in the
// throws clause of the business method

        return ctx.proceed();    // Proceed to the next interceptor
    }
}

package enterprise.interceptor_stateless_ejb;

import java.lang.reflect.Method;
import javax.interceptor.AroundInvoke;
import javax.interceptor.InvocationContext;

public class ArgumentsChecker {

    @AroundInvoke
    public Object checkArgument(InvocationContext ctx) throws Exception {
        Method method = ctx.getMethod();
        if (method.getName().equals("initUpperCase")) {
            String param = (String) (ctx.getParameters()[0]);
            //Note that param cannot be null because
            //it has been validated by the previous interceptor
            char c = param.charAt(0);
            if (!Character.isLetter(c)) {
                throw new BadArgumentException("Illegal argument: " + param);
            }
        }
// An interceptor can throw any runtime exception or
// application exceptions that are allowed in the
// throws clause of the business method

        return ctx.proceed();  // Proceed to call the business method
    }
}

Before a business method is invoked, the container invokes the interceptor method (annotated with @AroundInvoke) of each interceptor. In our sample, before the bean's initUpperCase() method is invoked, the checkIfNull() and checkArgument() methods are invoked,in that order.

AroundInvoke methods run in the same Java call stack as the bean business method. For a single business method invocation, the container passes (the same) instance of InvocationContext to all the interceptor methods. The InvocationContext (defined in javax.interceptor package) provides various methods to examine as well as modify the parameter values passed to the business method.

The proceed() method in InvocationContext causes the next interceptor method in the chain to be invoked or, when called from the last AroundInvoke interceptor method, the bean's business method. Interceptor methods must always call InvocationContext.proceed() or no subsequent interceptor methods or bean business method or life cycle callback methods will be invoked.

In our sample, the interceptor methods use the InvocationContext.getMethod() and InvocationContext.getParameters() method to examine the parameter passed to the initUpperCase() business method. The NullChecker throws BadArgumentException if the parameter is null whereas the ArgumentChecker throws BadArgumentException if the first character in the string is not a letter. Note that An interceptor can throw any runtime exception or application exceptions that are allowed in the throws clause of the business method. If the interceptors find the parameter value to be valid, they call InvocationContext.proceed()

Deployment Descriptor

The good news is the deployment descriptor is no longer required! The two Java files above are sufficient to completely describe this stateless session bean.

Sun-Specific Deployment Configuration

You do not need to define any Sun-Specific deployment descriptors (for example sun-ejb-jar.xml and sun-application-client.xml) for this example. The JNDI name for the Remote Stateless Session bean will default to: enterprise.interceptor_stateless_ejb.StatelessSession#enterprise.interceptor_stateless_ejb.StatelessSession

Building, Deploying, and Running the Application

Follow these instructions to build, deploy, and run this sample application.

  1. Setup your build environment and Configure the application server with which the build system has to work by following the common build instructions.
  2. app_dir is the sample application base directory: samples_install_dir/javaee5/enterprise/interceptor-stateless-ear
  3. Change directory to app_dir.
  4. Build, Deploy and Run the sample application using the target "all":

    app_dir> ant all

  5. You can accomplish the same thing by issuing separate Ant commands:

    app_dir> ant default compiles and packages the application

    app_dir> ant deploy deploys it to application server

    app_dir> ant run runs the test application client

  6. Use the target clean to remove the temporary directories like build and dist.

    app_dir> ant clean

Building, Deploying, and Running the Application in NetBeans IDE

Follow these instructions to build, deploy, and run this sample application using NetBeans IDE.

  1. Refer to common build instructions. for setting up NetBeans IDE and the application server with which the IDE will use.
  2. In NetBeans IDE, select File->OpenProject and select samples_install_dir/javaee5/enterprise/interceptor-stateless-ear as the project.
  3. Right click on interceptor-stateless-ear and select Run Project which will build, deploy and run the project. Sample output is given below.
  4.   Copying 1 file to /home/sreeni/IAS/SAMPLES/WS/glassfish-samples/ws/javaee5/enterprise/interceptor-stateless-ear/dist
      Converted duke to Duke
      Cannot convert (BadArgument) duke
      Cannot convert (BadArgument)null
      Cannot convert (BadArgument) duke
      Cannot convert (BadArgument)4duke
      Converted Duke to Duke
      run-interceptor-stateless-appclient:
      BUILD SUCCESSFUL (total time: 17 seconds)
      

Troubleshooting

If you have problems when running the application, refer to troubleshooting document.


Copyright © 2006 Sun Microsystems, Inc. All rights reserved.