SeamFramework.orgCommunity Documentation
Currently the Web Beans RI only runs in JBoss AS 5; integrating the RI into other EE environments (for example another application server like Glassfish), into a servlet container (like Tomcat), or with an Embedded EJB3.1 implementation is fairly easy. In this Appendix we will briefly discuss the steps needed.
It should be possible to run Web Beans in an SE environment, but you'll to do more work, adding your own contexts and lifecycle. The Web Beans RI currently doesn't expose lifecycle extension points, so you would have to code directly against Web Beans RI classes.
The Web Beans SPI is located in webbeans-spi
module, and packaged as webbeans-spi.jar
. Some
SPIs are optional, if you need to override the default behavior,
others are required.
All interfaces in the SPI support the decorator pattern and provide a
Forwarding
class.
public interface WebBeanDiscovery {
/**
* Gets list of all classes in classpath archives with web-beans.xml files
*
* @return An iterable over the classes
*/
public Iterable<Class<?>> discoverWebBeanClasses();
/**
* Gets a list of all web-beans.xml files in the app classpath
*
* @return An iterable over the web-beans.xml files
*/
public Iterable<URL> discoverWebBeansXml();
}
The discovery of Web Bean classes and web-bean.xml
files is self-explanatory (the algorithm is described in Section 11.1
of the JSR-299 specification, and isn't repeated here).
The Web Beans RI also delegates EJB3 bean discovery to the container
so that it doesn't have to scan for EJB3 annotations or parse
ejb-jar.xml
. For each EJB in the application an
EJBDescriptor should be discovered:
public interface EjbServices
{
/**
* Gets a descriptor for each EJB in the application
*
* @return The bean class to descriptor map
*/
public Iterable<EjbDescriptor<?>> discoverEjbs();
public interface EjbDescriptor<T> {
/**
* Gets the EJB type
*
* @return The EJB Bean class
*/
public Class<T> getType();
/**
* Gets the local business interfaces of the EJB
*
* @return An iterator over the local business interfaces
*/
public Iterable<BusinessInterfaceDescriptor<?>> getLocalBusinessInterfaces();
/**
* Gets the remote business interfaces of the EJB
*
* @return An iterator over the remote business interfaces
*/
public Iterable<BusinessInterfaceDescriptor<?>> getRemoteBusinessInterfaces();
/**
* Get the remove methods of the EJB
*
* @return An iterator over the remove methods
*/
public Iterable<Method> getRemoveMethods();
/**
* Indicates if the bean is stateless
*
* @return True if stateless, false otherwise
*/
public boolean isStateless();
/**
* Indicates if the bean is a EJB 3.1 Singleton
*
* @return True if the bean is a singleton, false otherwise
*/
public boolean isSingleton();
/**
* Indicates if the EJB is stateful
*
* @return True if the bean is stateful, false otherwise
*/
public boolean isStateful();
/**
* Indicates if the EJB is and MDB
*
* @return True if the bean is an MDB, false otherwise
*/
public boolean isMessageDriven();
/**
* Gets the EJB name
*
* @return The name
*/
public String getEjbName();
}
The EjbDescriptor
is fairly self-explanatory,
and should return the relevant metadata as defined in the EJB
specification. In addition to these two interfaces, there is
BusinessInterfaceDescriptor
which represents a
local business interface (encapsulating the interface class and
jndi name used to look up an instance of the EJB).
The resolution of @EJB
and
@Resource
is delegated to the container. You must
provide an implementation of
org.jboss.webbeans.ejb.spi.EjbServices
which
provides these operations. Web Beans passes in the
javax.inject.manager.InjectionPoint
the
resolution is for, as well as the NamingContext
in use for each resolution request.
Just as resolution of @EJB
is delegated to the
container, so is resolution of
@PersistenceContext
.
OPEN ISSUE: Web Beans also requires the container to provide a list of entities in the deployment, so that they aren't discovered as simple beans.
The Web Beans RI must delegate JTA activities to the container.
The SPI provides a couple hooks to easily achieve this with the
TransactionServices
interface.
public interface TransactionServices
{
/**
* Possible status conditions for a transaction. This can be used by SPI
* providers to keep track for which status an observer is used.
*/
public static enum Status
{
ALL, SUCCESS, FAILURE
}
/**
* Registers a synchronization object with the currently executing
* transaction.
*
* @see javax.transaction.Synchronization
* @param synchronizedObserver
*/
public void registerSynchronization(Synchronization synchronizedObserver);
/**
* Queries the status of the current execution to see if a transaction is
* currently active.
*
* @return true if a transaction is active
*/
public boolean isTransactionActive();
}
The enumeration Status
is a convenience for implementors
to be able to keep track of whether a synchronization is supposed to notify
an observer only when the transaction is successful, or after a failure, or
regardless of the status of the transaction.
Any javax.transaction.Synchronization
implementation
may be passed to the registerSynchronization()
method
and the SPI implementation should immediately register the synchronization
with the JTA transaction manager used for the EJBs.
To make it easier to determine whether or not a transaction is currently
active for the requesting thread, the isTransactionActive()
method can be used. The SPI implementation should query the same
JTA transaction manager used for the EJBs.
Web Beans expects the Application Server or other container to
provide the storage for each application's context. The
org.jboss.webbeans.context.api.BeanStore
should
be implemented to provide an application scoped storage. You may
find
org.jboss.webbeans.context.api.helpers.ConcurrentHashMapBeanStore
useful.
The org.jboss.webbeans.bootstrap.api.Bootstrap
interface defines the bootstrap for Web Beans. To boot Web Beans,
you must obtain an instance of
org.jboss.webbeans.bootstrap.WebBeansBootstrap
(which implements Boostrap
), tell it about the
SPIs in use, and then request the container start.
The bootstrap is split into phases, bootstrap initialization and boot and shutdown. Initialization will create a manager, and add the standard (specification defined) contexts. Bootstrap will discover EJBs, classes and XML; add beans defined using annotations; add beans defined using XML; and validate all beans.
The bootstrap supports multiple environments. Different environments
require different services to be present (for example servlet
doesn't require transaction, EJB or JPA services). By default an
EE environment is assumed, but you can adjust the environment by
calling bootstrap.setEnvironment()
.
To initialize the bootstrap you call
Bootstrap.initialize()
. Before calling
initialize()
, you must register any services
required by your environment. You can do this by calling
bootstrap.getServices().add(JpaServices.class, new MyJpaServices())
.
You must also provide the application context bean store.
Having called initialize()
, the
Manager
can be obtained by calling
Bootstrap.getManager()
.
To boot the container you call Bootstrap.boot()
.
To shutdown the container you call
Bootstrap.shutdown()
. This allows the container
to perform any cleanup operations needed.
The Web Beans RI implements JNDI binding and lookup according to
standards, however you may want to alter the binding and lookup (for
example in an environment where JNDI isn't available). To do this,
implement
org.jboss.webbeans.resources.spi.NamingContext
:
public interface NamingContext extends Serializable {
/**
* Typed JNDI lookup
*
* @param <T> The type
* @param name The JNDI name
* @param expectedType The expected type
* @return The object
*/
public <T> T lookup(String name, Class<? extends T> expectedType);
/**
* Binds an item to JNDI
*
* @param name The key to bind under
* @param value The item to bind
*/
public void bind(String name, Object value);
}
The Web Beans RI needs to load classes and resources from the
classpath at various times. By default, they are loaded from the
same classloader that was used to load the RI, however this may not
be correct for some environments. If this is case, you can implement
org.jboss.webbeans.spi.ResourceLoader
:
public interface ResourceLoader {
/**
* Creates a class from a given FQCN
*
* @param name The name of the clsas
* @return The class
*/
public Class<?> classForName(String name);
/**
* Gets a resource as a URL by name
*
* @param name The name of the resource
* @return An URL to the resource
*/
public URL getResource(String name);
/**
* Gets resources as URLs by name
*
* @param name The name of the resource
* @return An iterable reference to the URLS
*/
public Iterable<URL> getResources(String name);
}
Java EE / Servlet does not provide any hooks which can be used to provide injection into Servlets, so Web Beans provides an API to allow the container to request JSR-299 injection for a Servlet.
To be compliant with JSR-299, the container should request servlet injection for each newly instantiated servlet after the constructor returns and before the servlet is placed into service.
To perform injection on a servlet call
WebBeansManager.injectServlet()
. The manager
can be obtained from Bootstrap.getManager()
.
There are a number of requirements that the Web Beans RI places on the container for correct functioning that fall outside implementation of APIs
If you are integrating the Web Beans RI into an environment that supports deployment of multiple applications, you must enable, automatically, or through user configuation, classloader isolation for each Web Beans application.
If you are integrating the Web Beans into a Servlet
environment you must register
org.jboss.webbeans.servlet.WebBeansListener
as a Servlet listener, either automatically, or through user
configuration, for each Web Beans application which uses
Servlet.
If you are integrating the Web Beans into a JSF environment
you must register
org.jboss.webbeans.servlet.ConversationPropagationFilter
as a Servlet listener, either automatically, or through user
configuration, for each Web Beans application which uses
JSF. This filter can be registered for all Servlet deployment
safely.
If you are integrating the Web Beans into an EJB
environment you must register
org.jboss.webbeans.ejb.SessionBeanInterceptor
as a EJB interceptor for all EJBs in the application, either
automatically, or through user configuration, for each Web
Beans application which uses enterprise beans.
You must register the SessionBeanInterceptor
as the inner most interceptor in the stack for all EJBs.
webbeans-core.jar
If you are integrating the Web Beans into an environment that
supports deployment of applications, you must insert the
webbeans-core.jar
into the applications
isolated classloader. It cannot be loaded from a shared
classloader.