Caucho Technology
documentation
examples
changes

overview
quick start
installation
command-line
configuration
admin
amber
clustering
caching
database
deployment
ejb 3.0
embedding
filters
hessian
hmtp
ioc
jsp
logging
messaging
performance
quercus/php
remoting
scheduled tasks
security
server push
servlets
third-party
troubleshooting
virtual hosting
watchdog
webapp
xml and xslt

resin ejb 3.0


Resin's EJB support is integrated with Resin IoC. This integration means plain Java beans can use EJB annotations and interception, EJBs can use Resin IoC annotations, and both kinds of beans can be configured directly from the resin-web.xml or discovered by classpath scanning.

See Also

Overview

Resin's EJB support is integrated with Resin IoC. This integration means plain Java beans can use EJB annotations and interception, EJBs can use Resin IoC annotations, and both kinds of beans can be configured directly from the resin-web.xml or discovered by classpath scanning.

So it's best to think of EJBs as a set of orthogonal capabilities that are available to any registered bean. The basic capability types are:

  • Lifecycle model: Java, @Stateless, @Stateful, or @MessageDriven. Resin-managed objects like Servlets and Filters are POJO model beans.
  • Dependency injection: injection annotations @In, @Named, @EJB, @PersistenceUnit, etc are available to all beans.
  • Registration: all beans are registered in a unified typed-namespace registry (i.e. the registration half of dependency injection.)
  • Lifecycle events: the @PostConstruct and @PreDestroy
  • Predefined aspects: the @TransactionAttribute, @RunAs, @RolesAllowed, etc. annotations are available to all beans.
  • Custom interceptors: EJB-style @AroundInvoke, and @Interceptors, as well as WebBeans-style @Interceptor and @InterceptorBindingType are available to all beans.
  • Event handling: the WebBeans @Observes capability is available to all beans.

Hello, World

The Hello, World example is the smallest example deploying and using a @Stateless session bean. The bean is configured in the resin-web.xml and used in MyServlet with the WebBeans @In providing dependency injection.

Example: Bean.java
package demo;

public interface Bean {
  public String hello();
}
Example: @Stateless MyBean.java
package demo;

import javax.ejb.*;

@Stateless
public class MyBean implements Bean {
  public String hello()
  {
    return "hello, world";
  }
}
Example: MyServlet.java
package demo;

import java.io.*;
import javax.servlet.*;
import javax.webbeans.*;

public MyServlet extends GenericServlet {
  @In private Bean _bean;

  public void service(ServletRequest, ServletResponse res)
    throws ServletException, IOException
  {
    PrintWriter out = res.getWriter();

    out.println(_bean.hello());
  }
}
Example: WEB-INF/resin-web.xml
<web-app xmlns="http://caucho.com/ns/resin">

  <bean class="demo.MyBean"/>

  <servlet-mapping url-pattern="/test"
                   servlet-class="demo.MyServlet"/>

</web-app>

EJB Models

Resin's EJB integration provides four lifecycle choices: plain Java, @Stateless, @Stateful, and @MessageDriven.

  • Java: multithreaded, single instance, with no special method calling code by default, e.g. Servlets, Filters or @Component instances.
  • @Stateless: pooled instances, each is single-threaded, REQUIRED transactions and classloader environment enabled by default.
  • @Stateful: enforced single-threaded instances. REQUIRED transactions and classloader environment enabled by default. Only @Stateful beans can implement the SessionSynchronization interface.
  • @MessageDriven: pool instances, each single-threaded, specifically tailored for JMS/Messaging tasks (See Resin messaging.) REQUIRED transactions and classloader environment enabled by default.

Java

A Java bean is a multithreaded instance, e.g. a servlet or filter. Because it's multithreaded, application developers must take extra care to handle their own synchronization. In particular, threads must not store thread-specific data in Java bean fields and should generally avoid using static fields.

Java beans can use all the EJB and Resin-IoC aspects, including @TransactionAttribute, can use EJB @Interceptor classes, and Resin-Ioc @InterceptorBinding. They can handle events with the @Observes annotation, and add lifecycle callbacks with @PostConstruct and @PreDestroy.

@Local

The @Local annotation marks an interface of a bean as the exposed proxy API. Since @Stateless and @Stateful beans are proxy-based, they need an interface to expose to users of the bean. If the bean implements exactly in interface, it's chosen by default, otherwise the developer needs to mark the interface to export.

Local attributes
FIELDMEANINGDEFAULT
valueLists the interfaces to export for the bean.
javax.ejb.Local
@Target(TYPE)
@Retention(RUNTIME)
public @interface Local {
  Class []value() default {};
}

@MessageDriven

MessageDriven beans receive messages from a Queue, using a pooled, single-threaded model like @Stateless beans.

See Resin messaging for more information.

The MessageDriven bean connects with the messaging provider through an ActivationSpec. For JMS, the activation spec specifies the JMS Queue.

MessageDriven attributes
FIELDMEANINGDEFAULT
activationConfigDefault properties for the ActivationSpec, e.g. the JMS Queue name or destination type.
descriptionAn optional description of the bean, typically for the benefit of administration
mappedNameAn optional provider-specific name. Resin doesn't use this
nameThe EJB's nameThe classname of the bean
messageListenerInterfaceDefines the interface to be used to receive messages. The interface will match the messaging-provider's API, e.g. JMS uses javax.jms.MessageListener.
javax.ejb.MessageDriven
@Target(TYPE)
@Retention(RUNTIME)
public @interface Stateful {
  String name() default "";
  Class messageListenerInterface() default Object.class;
  ActivationConfigProperty []activationConfig() default {};
  String mappedName() default "";
  String description() default "";
}

@Remote

The @Local annotation marks an interface of a bean as the exposed proxy API for remoting. See Resin remoting for more information on exposing beans as remote objects for protocols such as Hessian, Burlap, and SOAP.

Remote attributes
FIELDMEANINGDEFAULT
valueLists the interfaces to export for the bean.
javax.ejb.Remote
@Target(TYPE)
@Retention(RUNTIME)
public @interface Remote {
  Class []value() default {};
}

SessionSynchronization

The SessionSynchronization interfaces tells Resin to enlist a @Stateful session bean in the current transaction. Before the transaction starts its commit processing, the bean will receive a callback message, allowing it to coordinate any data persistence. When the transaction either commits or rollsback, the bean will receive another callback indicating success or failure, allowing the bean to complete any transaction processing.

Only @Stateful session beans can implement SessionSynchronization because the bean itself will be registered with the transaction. The unique capability makes stateful session beans valuable for transaction processing.

SessionSynchronization methods
METHODDESCRIPTION
afterBeginCalled when the transaction starts
beforeCompletionThe transaction will call beforeCompletion before it starts the two-phase commit, allowing the bean to flush any cached data if necessary.
afterCompletionThe transaction will call afterCompletion when the transaction completes, reporting whether the transaction completed with a successful commit or a rollback.
javax.ejb.SessionSynchronization
public interface SessionSynchronization {
  public void afterBegin()
    throws EJBException, RemoteException;
  
  public void beforeCompletion()
    throws EJBException, RemoteException;
  
  public void afterCompletion(boolean committed)
    throws EJBException, RemoteException;
}

@Stateful

A stateful session bean is a single-threaded instance. Applications will need to create a new stateful instance for each thread or request.

Stateful attributes
FIELDMEANINGDEFAULT
descriptionAn optional description of the bean, typically for the benefit of administration
mappedNameAn optional provider-specific name. Resin doesn't use this
nameThe EJB's name used for jndi and Resin IoC registrationThe classname of the bean
javax.ejb.Stateful
@Target(TYPE)
@Retention(RUNTIME)
public @interface Stateful {
  String name() default "";
  String mappedName() default "";
  String description() default "";
}

@Stateless

A stateless session bean is a pooled proxy, where each request gets its own bean instance.

Stateless attributes
FIELDMEANINGDEFAULT
descriptionAn optional description of the bean, typically for the benefit of administration
mappedNameAn optional provider-specific name. Resin doesn't use this
nameThe EJB's name used for jndi and Resin IoC registrationThe classname of the bean
javax.ejb.Stateless
@Target(TYPE)
@Retention(RUNTIME)
public @interface Stateless {
  String name() default "";
  String mappedName() default "";
  String description() default "";
}

Aspect Annotations

@AroundInvoke

@AroundInvoke marks an interception method on the bean or an interceptor class. The interceptor is invoked while processing a business method.

javax.interceptor.AroundInvoke
@Target(METHOD)
@Retention(RUNTIME)
public @interface AroundInvoke {
}
Example: @AroundInvoke method
import javax.interceptor.*;

public class MyBean {
  @AroundInvoke
  protected Object log(InvocationContext cxt)
    throws Exception
  {
    System.out.println("Before: " + cxt.getMethod());

    Object value = cxt.proceed();

    System.out.println("After: " + cxt.getMethod());

    return value;
  }

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

@DenyAll

@DenyAll annotation marks a method as forbidden to all users.

javax.annotation.security.DenyAll
@Target({METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface DenyAll {
}

@Interceptor

@Interceptor marks a class as an interceptor using WebBeans-style interception. The class will normally also have an @AroundInvoke method as well as any InterceptorBindingType annotations.

javax.webbeans.Interceptor
@Target({TYPE})
@Retention(RUNTIME)
public @interface Interceptor {
}

@InterceptorBindingType

@InterceptorBindingType is a WebBeans meta-annotation for creating interceptor binding types. Applications will use @InterceptorBindingType to create application-specific interceptors. The WebBeans-style of interception decouples the interception declaration from the interceptor classes, in contrast with the EJB-style which specifies the interceptor class directly.

javax.webbeans.InterceptorBindingType
@Target({TYPE})
@Retention(RUNTIME)
public @interface InterceptorBindingType {
}

@Interceptors

@Interceptors marks an method or class as being intercepted by the named classes. The interceptor classes will implement an @AroundInvoke method to process the InvocationContext.

@Interceptors properties
VALUEMEANINGDEFAULT
valueLists the interceptor classes to apply to the method.
javax.interceptor.Interceptors
@Target({TYPE,METHOD})
@Retention(RUNTIME)
public @interface Interceptors {
  public Class []value();
}
Example: @Interceptor method
import javax.interceptor.*;

public class MyBean {
  @Interceptors(MyInterceptor.class)
  public String hello()
  {
    return "hello, world";
  }
}

public class MyInterceptor {
  @AroundInvoke
  protected Object log(InvocationContext cxt)
    throws Exception
  {
    System.out.println("Before: " + cxt.getMethod());

    Object value = cxt.proceed();

    System.out.println("After: " + cxt.getMethod());

    return value;
  }
}

InvocationContext

The InvocationContext API is used by invocation methods to examine the calling context, and possibly set parameters. A no-op interceptor would just call the proceed() method.

InvocationContext methods
METHODDESCRIPTION
getContextDataReturns a map containing any context information
getMethodReturns the called API method
getParametersReturns the Java parameters for the call
getTargetReturns the target object, i.e. the Java object that will receive the call after all the interceptors complete.
proceedCall the next interceptor in the chain, or call the final object at the end of the chain.
setParametersSets the Java parameters for the call
javax.interceptor.InvocationContext
public interface InvocationContext {
  public Object proceed() throws Exception;

  public Map<String, Object> getContextData();
  public Method getMethod();
  public Object[] getParameters() throws IllegalStateException;
  public void setParameters(Object[] parameters) throws IllegalStateException;
  public Object getTarget();
}

@PermitAll

@PermitAll annotation marks a method as allowed for all users.

javax.annotation.security.PermitAll
@Target({METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface PermitAll {
}

@RolesAllowed

@RolesAllowed lists all the roles (i.e. permissions) allowed to access the method. If the user in the security context does not match the role, an exception will be thrown.

RolesAllowed properties
VALUEMEANINGDEFAULT
valueLists the roles (permissions) that are allowed.
javax.annotation.security.RolesAllowed
@Target({TYPE,METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface RolesAllowed {
  String []value();
}

@RunAs

@RunAs changes the security context user to a defined role. Security tests within the context of the @RunAs will match the specified role.

RunAs properties
VALUEMEANINGDEFAULT
valueThe role name to run as.
javax.annotation.security.RunAs
@Target({TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface RunAs {
  String value();
}

@TransactionAttribute

Defines the transaction boundary for business methods. The default value is REQUIRED. If @TransactionAttribute annotates the class, it defines the default value.

All Resin-managed beans can use @TransactionAttribute: @Stateful, @Stateless, @MessageDriven and plain Java beans.

TransactionAttributeType
VALUEMEANING
REQUIREDStart a new transaction if necessary
SUPPORTSDon't start a new transaction, but use one if it exists
MANDATORYRequire the caller to have started a transaction
NEVERForbid the caller to have started a transaction
REQUIRESNEWAlways start a new transaction, suspending the old one
NOTSUPPORTEDSuspend any active transaction
  • SUPPORTS is typically used for read-only methods
  • REQUIRED is typically used for updating (read/write) methods
javax.ejb.TransactionAttribute
@Target({TYPE,METHOD})
@Retention(RUNTIME)
public @interface TransactionAttribute {
  TransactionAttributeType value() default REQUIRED;
}

Dependency Injection Annotations

@EJB

Configures an EJB values for a field or method.

@EJB is essentially a @Resource where it's known that the result is an EJB interface.

jndiNameThe jndi name of the resourceThe field name
javax.ejb.EJB
@Target({TYPE, METHOD, FIELD, PARAMETER})
@Retention(RUNTIME)
public @interface EJB {
  String name() default "";
  String businessInterface() default "";
  String jndiName() default "";
}

In the following exaple, Resin will call setFoo method with the bean in "java:comp/env/ejb/foo" before the session is started.

Example: @EJB method injection
@EJB
void setFoo(example.Test test)
{
  _test = test;
}

@Resource

@Resource provides JNDI-based resource injection. @Resource can also be used at the Class level to declare a dependency in cases where the session bean loads the JNDI value by itself.

In general, it's better to use the WebBeans annotations: @In, @Named or custom @BindingType annotations, since they use the type-safe WebBeans registry instead of JNDI. @Resource is supported for backwards compatibility.

PROPERTYDESCRIPTIONDEFAULT
authenticationTypeWhat kind of authentication is expected for the resource: APPLICATION or CONTAINERCONTAINER
descriptionAn optional description of the resource
nameThe jndi-name of the resourcejava:comp/env/class-name#field-name
typeThe class of the expected resourceThe field type
shareableTrue if the bean follows JCA shareability requirements.true
mappedNameThe produce-specific name of the resourceThe field name
javax.ejb.Resource
@Target({TYPE, METHOD, FIELD, PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface Resource {
  AuthenticationType authenticationType() CONTAINER;
  String description() default "";
  String mappedName() default "";
  String name() default "";
  boolean shareable() default true;
  Class<?> type() default Object.class;
}

In the following exaple, Resin will call setDataSource method with the data source in "java:comp/env/jdbc/test" before the session is started. The "java:comp/env/jdbc" full name is inferred from the DataSource type.

default JNDI names
RESOURCE TYPEJNDI PREFIX
javax.sql.DataSourcejava:comp/env/jdbc
javax.mail.*java:comp/env/mail
javax.ejb.EntityManagerjava:comp/EntityManager
javax.transaction.UserTransactionjava:comp/UserTransaction
javax.ejb.EJBHomejava:comp/env/ejb
javax.jms.*java:comp/env/jms
@Resource(name="test")
void setDataSource(javax.sql.DataSource dataSource)
{
  _dataSource = dataSource;
}

Copyright © 1998-2008 Caucho Technology, Inc. All rights reserved.
Resin ® is a registered trademark, and Quercustm, Ambertm, and Hessiantm are trademarks of Caucho Technology.