<document>
<localtoc/>

- For persistence, see Amber.
- Resin IoC for more information on dependency injection.
- See session tutorial

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.

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.

package demo; public interface Bean { public String hello(); } package demo; import javax.ejb.*; @Stateless public class MyBean implements Bean { public String hello() { return "hello, world"; } } 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()); } } <web-app xmlns="http://caucho.com/ns/resin"> <bean class="demo.MyBean"/> <servlet-mapping url-pattern="/test" servlet-class="demo.MyServlet"/> </web-app>

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.

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`.

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.

Field Meaning Default
value Lists the interfaces to export for the bean.
@Target(TYPE) @Retention(RUNTIME) public @interface Local { Class []value() default {}; }

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.

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

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.

Field Meaning Default
value Lists the interfaces to export for the bean.
@Target(TYPE) @Retention(RUNTIME) public @interface Remote { Class []value() default {}; }

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.

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

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

Field Meaning Default
description An optional description of the bean, typically for the benefit of administration
mappedName An optional provider-specific name. Resin doesn't use this
name The EJB's name used for jndi and Resin IoC registration The classname of the bean
@Target(TYPE) @Retention(RUNTIME) public @interface Stateful { String name() default ""; String mappedName() default ""; String description() default ""; }

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

Field Meaning Default
description An optional description of the bean, typically for the benefit of administration
mappedName An optional provider-specific name. Resin doesn't use this
name The EJB's name used for jndi and Resin IoC registration The classname of the bean
@Target(TYPE) @Retention(RUNTIME) public @interface Stateless { String name() default ""; String mappedName() default ""; String description() default ""; }

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

@Target(METHOD) @Retention(RUNTIME) public @interface AroundInvoke { } 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` annotation marks a method as forbidden to all users.

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

`@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.

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

`@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.

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

`@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`.

Value Meaning Default
value Lists the interceptor classes to apply to the method.
@Target({TYPE,METHOD}) @Retention(RUNTIME) public @interface Interceptors { public Class []value(); } 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; } }

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.

Method Description
getContextData Returns a map containing any context information
getMethod Returns the called API method
getParameters Returns the Java parameters for the call
getTarget Returns the target object, i.e. the Java object that will receive the call after all the interceptors complete.
proceed Call the next interceptor in the chain, or call the final object at the end of the chain.
setParameters Sets the Java parameters for the call
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` annotation marks a method as allowed for all users.

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

`@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.

Value Meaning Default
value Lists the roles (permissions) that are allowed.
@Target({TYPE,METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface RolesAllowed { String []value(); }

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

Value Meaning Default
value The role name to run as.
@Target({TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface RunAs { String value(); }

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.

Value Meaning
REQUIRED Start a new transaction if necessary
SUPPORTS Don't start a new transaction, but use one if it exists
MANDATORY Require the caller to have started a transaction
NEVER Forbid the caller to have started a transaction
REQUIRESNEW Always start a new transaction, suspending the old one
NOTSUPPORTED Suspend any active transaction

- SUPPORTS is typically used for read-only methods
- REQUIRED is typically used for updating (read/write) methods

@Target({TYPE,METHOD}) @Retention(RUNTIME) public @interface TransactionAttribute { TransactionAttributeType value() default REQUIRED; }

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
@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.

@EJB void setFoo(example.Test test) { _test = test; }

`@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.

Property Description Default
authenticationType What kind of authentication is expected for the resource: APPLICATION or CONTAINER CONTAINER
description An optional description of the resource
name The jndi-name of the resource java:comp/env/class-name#field-name
type The class of the expected resource The field type
shareable True if the bean follows JCA shareability requirements. true
mappedName The produce-specific name of the resource The field name
@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.

Resource Type JNDI Prefix
javax.sql.DataSource java:comp/env/jdbc
javax.mail.* java:comp/env/mail
javax.ejb.EntityManager java:comp/EntityManager
javax.transaction.UserTransaction java:comp/UserTransaction
javax.ejb.EJBHome java:comp/env/ejb
javax.jms.* java:comp/env/jms
<example> @Resource(name="test") void setDataSource(javax.sql.DataSource dataSource) { _dataSource = dataSource; }
</document>