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.
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.
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>
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 attributesFIELD | MEANING | DEFAULT |
---|
value | Lists 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 attributesFIELD | 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 . | | 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 attributesFIELD | MEANING | DEFAULT |
---|
value | Lists 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 methodsMETHOD | 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.
| 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 attributesFIELD | 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 | 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 attributesFIELD | 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 | javax.ejb.Stateless
@Target(TYPE)
@Retention(RUNTIME)
public @interface Stateless {
String name() default "";
String mappedName() default "";
String description() default "";
}
@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 propertiesVALUE | MEANING | DEFAULT |
---|
value | Lists 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 methodsMETHOD | 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 | 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 propertiesVALUE | MEANING | DEFAULT |
---|
value | Lists 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 propertiesVALUE | MEANING | DEFAULT |
---|
value | The 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. TransactionAttributeTypeVALUE | 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
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. jndiName | The jndi name of the resource | The 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. 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 |
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 namesRESOURCE 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 |
@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. |
|