SeamFramework.orgCommunity Documentation
Attualmente Web Bean RI funziona solo in JBoss AS 5; l'integrazione di RI in altri ambienti EE (per esempio in un application server come Glassfish), in un servlet container (come Tomcat), o con un'implementazione EJB3.1 Embedded è abbastanza facile. In questo appendice si discuterà brevemente dei passi necessari.
Dovrebbe essere possibile far funzionare Web Beans in un ambiente SE, ma occorre molto lavoro per aggiungere i propri contesti ed il ciclo di vita. Web Beans RI attualmente non espone punti di estensione del ciclo di vita, così occorre codificare direttamente nelle classi Web Beans RI.
Web Beans SPI è collocato nel modulo webbeans-ri-spi
, ed è impacchettato come webbeans-ri-spi.jar
. Alcuni SPI sono opzionali se occorre fare override del comportamento di default, altri sono richiesti.
Tutte le interfacce in SPI supportano il pattern decorator e forniscono una classe Forwarding
.
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();
}
L'analisi dei file delle classi Web Bean e di web-bean.xml
è molto istruttiva (l'algoritmo è descritto nella sezione 11.1 della specifica JSR-299 e non viene qua ripetuto).
Web Beans RI delega al container la rilevazione dei bean EJB3 e quindi risulta non essere necessario eseguire lo scan delle annotazioni EJB3 o fare il parsing di ejb-jar.xml
. Per ciascun EJB nell'applicazione dovrebbe essere rilevato un EJBDescriptor:
public interface EjbDiscovery
{
public static final String PROPERTY_NAME = EjbDiscovery.class.getName();
/**
* 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();
}
Il EjbDescriptor
è abbastanza auto-esplicatorio e dovrebbe restituire i metadati rilevanti definiti nella specifica EJB. In aggiunta a queste due interfacce, vi è BusinessInterfaceDescriptor
a rappresentare un'interfaccia locale di business (che incapsula la classe d'interfaccia ed il nome jndi usato per la ricerca di una istanza EJB).
La risoluzione di @EJB
, @PersistenceContext
e @Resource
è delegata al container. Occorre fornire un'implementazione di org.jboss.webbeans.ejb.spi.EjbResolver
che rende disponibili queste operazioni. Web Beans passa nel javax.inject.manager.InjectionPoint
la risoluzione, anche come NamingContext
, che è in uso per ogni richiesta di risoluzione.
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 si aspetta che l'Application Server od un altro container fornisca la memorizzazione per ogni contesto applicazione. org.jboss.webbeans.context.api.BeanStore
dovrebbe essere implementato per fornire uno storage con scope applicazione. Si può trovare molto utile org.jboss.webbeans.context.api.helpers.ConcurrentHashMapBeanStore
.
L'interfaccia org.jboss.webbeans.bootstrap.api.Bootstrap
definisce il bootstrap per Web Beans. Per avviare Web Beans occorre ottenere un'istanza di org.jboss.webbeans.bootstrap.WebBeansBootstrap
(che implementa Boostrap
), e comunicare le SPI in uso, e poi chiedere che il container venga avviato.
Il bootstrap è suddiviso in due fasi, inizializzazione del bootstrap e bootstrap. L'inizializzazione creerà un manager, e aggiungerà i contesti standard (definiti dalla specifica). Bootstrap scoprirà EJB, classi e XML; aggiungerà i bean definiti con le annotazioni; aggiungerà i bean definiti con XML; e validerà tutti i bean.
Per inizializzare il bootstrap si chiama Bootstrap.initialize()
. Prima della chiamata di initialize()
occorre aver chiamato Bootstrap.setEjbResolver()
. Se non si usa il DefaultNamingContext
o DefaultResourceLoader
predefiniti, occorre impostare questi prima di chiamare initialize()
.
Dopo aver chiamato initialize()
, il Manager
può essere ottenuto chiamando Bootstrap.getManager()
.
Per avviare il container si chiama Bootstrap.boot()
. Prima di chiamare boot()
occorre aver chiamato Bootstrap.setWebBeanDiscovery()
, Bootstrap.setEjbDiscovery()
e Bootstrap.setApplicationContext()
.
Per spegnere il container si chiama Bootstrap.shutdown()
. Questo consente al container di eseguire ogni pulizia necessaria delle operazioni.
Web Beans RI implementa la ricerca e l'associazione JNDI secondo gli standard, ma può capitare di dover modificare la ricerca e l'associazione (per esempio in un ambiente dove JNDI non è disponibile). Per fare questo occorre implementare 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);
}
Web Beans RI deve caricare le classi e le risorse dal classpath in vari momenti. Di default vengono caricati dallo stesso classloader usato per caricare RI, comunque questo potrebbe non essere corretto in alcuni ambienti. Se è questo il caso si può implementare 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 non fornisce alcun hook da usare per fornire l'iniezione nei Servlet, quindi Web Beans fornisce un'API per consentire al container di richiedere l'iniezione JSR-299 per un Servlet.
Per soddisfare la JSR-299 il container deve richiedere l'iniezione servlet per ogni nuovo servlet istanziato dopo che il costruttore ritorni e prima che il servlet sia messo in servizio.
Per eseguire l'iniezione su un servlet si chiami WebBeansManager.injectServlet()
. Il manager può essere ottenuto da Bootstrap.getManager()
.
Per il corretto funzionamento al di fuori dell'implementazione delle API, ci sono un numero di requisiti che Web Beans RI pone nel container.
Se si integra Web Beans in un ambiente che supporta il deploy di applicazioni, occorre abilitare, automaticamente o attraverso la configurazione utente, l'isolamento del classloader per ogni applicazione Web Beans.
Se si integra Web Beans in un ambiente Servlet occorre registrare org.jboss.webbeans.servlet.WebBeansListener
come Servlet listener, o automaticamente, o attraverso una configurazione utente, per ciascuna applicazione Web Beans che usa Servlet.
Se si integra Web Beans in un ambiente Servlet occorre registrare org.jboss.webbeans.servlet.ConversationPropagationFilter
come Servlet listener, o automaticamente, o attraverso una configurazione utente, per ciascuna applicazione Web Beans che usa JSF. Questo filtro può venir registrato in modo sicuro per tutti i deploy dei servlet.
Se si integra Web Beans in un ambiente EJB occorre registrare org.jboss.webbeans.ejb.SessionBeanInterceptor
come interceptor EJB per ogni EJB dell'applicazione, o automaticamente o attraverso una configurazione utente, per ciascuna applicazione Web Beans che utilizza bean enterprise.
Occorre registrare il SessionBeanInterceptor
come interceptor più interno allo stack per tutti gli EJB.
webbeans-ri.jar
Se si integra Web Beans in un ambiente che supporta il deploy di applicazioni, occorre inserire webbeans-ri.jar
nel classloader isolato delle applicazioni. Non può essere caricato da un classloader condiviso.