Weld SiteCommunity Documentation
If you want to use Weld in another environment, you will need to provide certain information to Weld via the integration SPI. In this Appendix we will briefly discuss the steps needed.
If you are upgrading existing Weld integration to work with Weld 2, see this migration document.
If you just want to use managed beans, and not take advantage of enterprise services (EE resource injection, CDI injection into EE component classes, transactional events, support for CDI services in EJBs) and non-flat deployments, then the generic servlet support provided by the "Weld: Servlets" extension will be sufficient, and will work in any container supporting the Servlet API.
All SPIs and APIs described have extensive JavaDoc, which spell out the detailed contract between the container and Weld.
The Weld SPI is located in the weld-spi
module, and packaged as
weld-spi.jar
. Some SPIs are optional, and should only be implemented
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 located in the helpers
sub package. Additional,
commonly used, utility classes, and standard implementations are also
located in the helpers
sub package.
Weld supports multiple environments. An environment is defined by an
implementation of the Environment
interface. A number of standard
environments are built in, and described by the Environments
enumeration. Different environments require different services to be
present. For example a Servlet container doesn’t require transaction,
EJB or JPA services.
Weld uses services to communicate with its environment. A service is a
java class that implements the org.jboss.weld.bootstrap.api.Service
interface and is explicitly registered. A service may be BDA-specific or
may be shared across the entire application.
public interface Service {
public void cleanup();
}
Certain services are only used at bootstrap and need to be cleaned up
afterwards in order not to consume memory. A service that implements the
specialized org.jboss.weld.bootstrap.api.BootstrapService
interface
receives a cleanupAfterBoot()
method invocation once Weld
initialization is finished but before the deployment is put into
service.
public interface BootstrapService extends Service {
void cleanupAfterBoot();
}
Weld uses a generic-typed service registry to allow services to be
registered. All services implement the Service
interface. The service
registry allows services to be added and retrieved.
An application is often comprised of a number of modules. For example, a
Java EE deployment may contain a number of EJB modules (containing
business logic) and war modules (containing the user interface). A
container may enforce certain accessibility rules which limit the
visibility of classes between modules. CDI allows these same rules to
apply to bean and observer method resolution. As the accessibility rules
vary between containers, Weld requires the container to describe the
deployment structure, via the Deployment
SPI.
The CDI specification discusses Bean Archives (BAs)—archives which are marked as containing beans which should be deployed to the CDI container, and made available for injection and resolution. Weld reuses this description and uses Bean Deployment Archives (BDA) in its deployment structure SPI.
Each deployment exposes the containing BDAs that form a graph. A node in the graph represents a BDA. Directed edges between nodes designate visibility. Visibility is not transitive (i.e. a bean from BDA A can only see beans in BDAs with which A is directly connected by a properly oriented edge).
To describe the deployment structure to Weld, the container should
provide an implementation of Deployment
.
Deployment.getBeanDeploymentArchives()
allows Weld to discover the
modules which make up the application. The CDI specification also allows
beans to be specified programmatically as part of the bean deployment.
These beans may, or may not, be in an existing BDA. For this reason,
Weld will call Deployment.loadBeanDeploymentArchive(Class clazz)
for
each programmatically described bean.
As programmatically described beans may result in additional BDAs being
added to the graph, Weld will discover the BDA structure every time an
unknown BDA is returned by Deployment.loadBeanDeploymentArchive
.
In a strict container, each BDA might have to explicitly specify which
other BDAs it can access. However many containers will allow an easy
mechanism to make BDAs bi-directionally accessible (such as a library
directory). In this case, it is allowable (and reasonable) to describe
all such archives as a single, virtual BeanDeploymentArchive
.
A container, might, for example, use a flat accessibility structure for
the application. In this case, a single BeanDeploymentArchive
would be
attached to the Deployment
.
BeanDeploymentArchive
provides three methods which allow it’s contents
to be discovered by Weld—BeanDeploymentArchive.getBeanClasses()
must
return all the classes in the BDA, BeanDeploymentArchive.getBeansXml()
must return a data structure representing the beans.xml
deployment
descriptor for the archive, and BeanDeploymentArchive.getEjbs()
must
provide an EJB descriptor for every EJB in the BDA, or an empty list if
it is not an EJB archive.
To aid container integrator, Weld provides a built-in beans.xml
parser. To parse a beans.xml
into the data-structure required by
BeanDeploymentArchive
, the container should call
Bootstrap.parse(URL)
. Weld can also parse multiple beans.xml
files,
merging them to become a single data-structure. This can be achieved by
calling Bootstrap.parse(Iterable<URL>)
.
When multiple beans.xml
files are merged, Weld keeps duplicate enabled
entries (interceptors, decorators or alternatives). This may cause
validation problems when multiple physical archives which define an
overlapping enabled entries are merged. A version of the
Bootstrap.parse()
method that provides control over whether duplicate
enabled entries are remove or not is provided:
Bootstrap.parse(Iterable<URL> urls, boolean removeDuplicates)
.
BDA X may also reference another BDA Y whose beans can be resolved by, and injected into, any bean in BDA X. These are the accessible BDAs, and every BDA that is directly accessible by BDA X should be returned. A BDA will also have BDAs which are accessible transitively, and the transitive closure of the sub-graph of BDA X describes all the beans resolvable by BDA X.
In practice, you can regard the deployment structure represented by
Deployment
, and the virtual BDA graph as a mirror of the classloader
structure for a deployment. If a class can from BDA X can be loaded by
another in BDA Y, it is accessible, and therefore BDA Y’s accessible
BDAs should include BDA X.
To specify the directly accessible BDAs, the container should provide an
implementation of BeanDeploymentArchive.getBeanDeploymentArchives()
.
Weld allows the container to describe a circular graph, and will convert a graph to a tree as part of the deployment process.
Certain services are provided for the whole deployment, whilst some are
provided per-BDA. BDA services are provided using
BeanDeploymentArchive.getServices()
and only apply to the BDA on which
they are provided.
The contract for Deployment
requires the container to specify the
portable extensions (see chapter 12 of the CDI specification) which
should be loaded by the application. To aid the container integrator,
Weld provides the method Bootstrap.loadExtensions(ClassLoader)
which
will load the extensions for the specified classloader.
In Java EE environment, description of each Java EE module that contains bean archives deployment should be provided. This applies to:
For each such module the integrator should create an instance of the EEModuleDescriptor
which describes the module. EEModuleDescriptorImpl
is provided for convenience.
An EEModuleDescriptor
instance that represents a given module should be registered
as a per bean archive service in each BeanDeploymentArchive
that belongs to the given
module. This applies both to physical bean archives deployed within the given module
and also to logical bean archives that belong to the module. Bean archives that are not
part of a Java EE module (e.g. built-in server libraries) are not required to have a
EEModuleDescriptor
service registered.
Weld delegates EJB 3 bean discovery to the container so that it doesn’t duplicate the work done by the EJB container, and respects any vendor-extensions to the EJB definition.
The EjbDescriptor
should return the relevant metadata as defined in
the EJB specification. Each business interface of a session bean should
be described using a BusinessInterfaceDescriptor
.
By default, Weld uses the EJB component class when creating new EJB instances.
This may not always be desired especially if the EJB container uses subclassing
internally. In such scenario, the EJB container requires that the subclass
it generated is used for creating instances instead of the component class.
An integrator can communicate such layout to Weld by additionally implementing the optional
SubclassedComponentDescriptor
interface in the EjbDescriptor
implementation.
The return value of the
SubclassedComponentDescriptor.getComponentSubclass()
method determines which class will be used by Weld when creating new EJB instances.
All the EE resource services are per-BDA services, and may be provided using one of two methods. Which method to use is at the discretion of the integrator.
The integrator may choose to provide all EE resource injection services
themselves, using another library or framework. In this case the
integrator should use the EE
environment, and implement the Section A.1.9, “Injection Services” SPI.
Alternatively, the integrator may choose to use CDI to provide EE
resource injection. In this case, the EE_INJECT
environment should be
used, and the integrator should implement the Section A.1.4, “EJB services”, Section A.1.7, “Resource Services”
and Section A.1.5, “JPA services”.
CDI only provides annotation-based EE resource injection; if you wish to
provide deployment descriptor (e.g. ejb-jar.xml
) injection, you must
use Section A.1.9, “Injection Services”.
If the container performs EE resource injection, the injected resources must be serializable. If EE resource injection is provided by Weld, the resolved resource must be serializable.
If you use a non-EE environment then you may implement any of the EE service SPIs, and Weld will provide the associated functionality. There is no need to implement those services you don’t need!
Weld registers resource injection points with EjbInjectionServices
,
JpaInjectionServices
, ResourceInjectionServices
and
JaxwsInjectionServices
implementations upfront (at bootstrap). This
allows validation of resource injection points to be performed at boot
time rather than runtime. For each resource injection point Weld obtains
a ResourceReferenceFactory
which it then uses at runtime for creating
resource references.
public interface ResourceReferenceFactory<T> {
ResourceReference<T> createResource();
}
A ResourceReference
provides access to the resource reference to be
injected. Furthermore, ResourceReference
allows resource to be release
once the bean that received resource injection is destroyed.
public interface ResourceReference<T> {
T getInstance();
void release();
}
EJB services are split between two interfaces which are both per-BDA.
EjbServices
is used to resolve local EJBs used to back session beans,
and must always be provided in an EE environment.
EjbServices.resolveEjb(EjbDescriptor ejbDescriptor)
returns a
wrapper—SessionObjectReference
—around the EJB reference. This wrapper
allows Weld to request a reference that implements the given business
interface, and, in the case of SFSBs, both request the removal of the
EJB from the container and query whether the EJB has been previously
removed.
EjbInjectionServices.registerEjbInjectionPoint(InjectionPoint injectionPoint)
registers an @EJB
injection point (on a managed bean) and returns a
ResourceReferenceFactory
as explained above. This service is not
required if the implementation of Section A.1.9, “Injection Services” takes care of @EJB
injection.
EJBInjectionServices.resolveEjb(InjectionPoint ij)
, which allows
@EJB
injection point to be resolved without prior registration was
deprecated in Weld 2 and should no longer be used. An injection point
should be registered properly using
EjbInjectionServices.registerEjbInjectionPoint(InjectionPoint injectionPoint)
instead.
Just as EJB resolution is delegated to the container, resolution of
@PersistenceContext
for injection into managed beans (with the
InjectionPoint
provided), is delegated to the container.
To allow JPA integration, the org.jboss.weld.injection.spi.JpaInjectionServices
interface
should be implemented. This service is not required if the implementation of
Section A.1.9, “Injection Services” takes care of @PersistenceContext
injection.
The following methods were deprecated in Weld 2:
*
JpaInjectionServices.resolvePersistenceContext(InjectionPoint injectionPoint)
*
JpaInjectionServices.resolvePersistenceUnit(InjectionPoint injectionPoint)
An injection point should instead be registered properly using the following methods:
*
JpaInjectionServices.registerPersistenceContextInjectionPoint(InjectionPoint injectionPoint)
*
JpaInjectionServices.registerPersistenceUnitInjectionPoint(InjectionPoint injectionPoint)
Weld delegates JTA activities to the container. The SPI provides a
couple hooks to easily achieve this with the TransactionServices
interface.
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.
The resolution of @Resource
(for injection into managed beans) is
delegated to the container. You must provide an implementation of
ResourceInjectionServices
which provides these operations. This
service is not required if the implementation of Section A.1.9, “Injection Services” takes care of
@Resource
injection.
The following methods were deprecated in Weld 2:
*
ResourceInjectionServices.resolveResource(InjectionPoint injectionPoint)
*
ResourceInjectionServices.resolveResource(String jndiName, String mappedName)
An injection point should instead be registered properly using the following methods:
*
ResourceInjectionServices.registerResourceInjectionPoint(InjectionPoint injectionPoint)
*
ResourceInjectionServices.registerResourceInjectionPoint(String jndiName, String mappedName)
The resolution of @WebServiceRef
(for injection into managed beans) is
delegated to the container. An integrator must provide an implementation
of JaxwsInjectionServices
. This service is not required if the
implementation of Section A.1.9, “Injection Services” takes care of @WebServiceRef
injection.
An integrator may wish to use InjectionServices
to provide additional
field or method injection over-and-above that provided by Weld. An
integration into a Java EE environment may use InjectionServices
to
provide EE resource injection for managed beans.
InjectionServices
provides a very simple contract, the
InjectionServices.aroundInject(InjectionContext ic);
interceptor will
be called for every instance that CDI injects, whether it is a
contextual instance, or a non-contextual instance injected by
InjectionTarget.inject()
.
The InjectionContext
can be used to discover additional information
about the injection being performed, including the target
being
injected. ic.proceed()
should be called to perform CDI-style
injection, and call initializer methods.
For each
Weld calls the InjectionServices.registerInjectionTarget()
method.
That allows the integrator to validate resource injection points before
the application is deployed.
In order to obtain the Principal
representing the current caller
identity, the container should provide an implementation of
SecurityServices
.
The org.jboss.weld.bootstrap.api.Bootstrap
interface defines the
initialization for Weld, bean deployment and bean validation. To boot
Weld, you must create an instance of
org.jboss.weld.bootstrap.WeldBootstrap
which implements
org.jboss.weld.bootstrap.api.CDI11Bootstrap
which extends the above mentioned
Bootstrap
. Then you need to tell it about the services in use, and finally request the
container start.
public interface Bootstrap {
public Bootstrap startContainer(Environment environment, Deployment deployment);
public Bootstrap startInitialization();
public Bootstrap deployBeans();
public Bootstrap validateBeans();
public Bootstrap endInitialization();
public void shutdown();
public WeldManager getManager(BeanDeploymentArchive beanDeploymentArchive);
public BeansXml parse(URL url);
public BeansXml parse(Iterable<URL> urls);
public BeansXml parse(Iterable<URL> urls, boolean removeDuplicates);
public Iterable<Metadata<Extension>> loadExtensions(ClassLoader classLoader);
}
The bootstrap is split into phases, container initialization, bean deployment, bean validation and shutdown. Initialization will create a manager, and add the built-in contexts, and examine the deployment structure. Bean deployment will deploy any beans (defined using annotations, programmatically, or built in). Bean validation will validate all beans.
To initialize the container, you call Bootstrap.startInitialization()
.
Before calling startInitialization()
, you must register any services
required by the environment. You can do this by calling, for example,
bootstrap.getManager().getServices().add(JpaServices.class, new
MyJpaServices())
.
Having called startInitialization()
, the org.jboss.weld.manager.api.WeldManager
for each BDA can be obtained by calling Bootstrap.getManager(BeanDeploymentArchive bda)
.
To deploy the discovered beans, call Bootstrap.deployBeans()
.
To validate the deployed beans, call Bootstrap.validateBeans()
.
To place the container into a state where it can service requests, call
Bootstrap.endInitialization()
To shutdown the container you call Bootstrap.shutdown()
. This allows
the container to perform any cleanup operations needed.
Weld needs to load classes and resources from the classpath at various
times. By default, they are loaded from the Thread Context ClassLoader
if available, if not the same classloader that was used to load Weld,
however this may not be correct for some environments. If this is case,
you can implement org.jboss.weld.resources.spi.ResourceLoader
.
import org.jboss.weld.bootstrap.api.Service;
public interface ResourceLoader extends Service {
public Class<?> classForName(String name);
public URL getResource(String name);
public Collection<URL> getResources(String name);
}
The optional AnnotationDiscovery
service has been deprecated and is
not used by Weld since Weld 2.2. Integrators are encouraged to implement
ClassFileServices
instead.
Integrators with bytecode-scanning capabilities may implement an
optional ClassFileServices
service.
Bytecode-scanning is used by some application servers to speed up
deployment. Compared to loading a class using ClassLoader
,
bytecode-scanning allows to obtain only a subset of the Java class file
metadata (e.g. annotations, class hierarchy, etc.) which is usually
loaded much faster. This allows the container to scan all classes
initially by a bytecode scanner and then use this limited information to
decide which classes need to be fully loaded using ClassLoader
.
Jandex is an example of a
bytecode-scanning utility.
ClassFileServices
may be used by an integrator to provide container’s
bytecode-scanning capabilities to Weld. If present, Weld will try to use
the service to avoid loading of classes that do not need to be loaded.
These are classes that:
This usually yields improved bootstrap performance especially in large deployments with a lot of classes in explicit bean archives.
public interface ClassFileServices extends BootstrapService {
ClassFileInfo getClassFileInfo(String className);
}
public interface ClassFileInfo {
String getClassName();
String getSuperclassName();
boolean isAnnotationDeclared(Class<? extends Annotation> annotationType);
boolean containsAnnotation(Class<? extends Annotation> annotationType);
int getModifiers();
boolean hasCdiConstructor();
boolean isAssignableFrom(Class<?> javaClass);
boolean isAssignableTo(Class<?> javaClass);
boolean isVetoed();
boolean isTopLevelClass();
See the JavaDoc for more details.
The standard way for an integrator to provide Service implementations is via
the deployment structure. Alternatively, services may be registered
using the ServiceLoader
mechanism. This is useful e.g. for a library running
in weld-servlet
environment. Such library may provide TransactionServices
implementation
which would not otherwise be provided by weld-servlet
.
A service implementation should be listed in a file named META-INF/services/org.jboss.weld.bootstrap.api.Service
A service implementation can override another service implementation. The priority of a service
implementation is determined from the javax.annotation.Priority
annotation. Service implementations with
higher priority have precedence. A service implementation that does not define priority explicitly
is given implicit priority of 4500.
There are a number of requirements that Weld places on the container for correct functioning that fall outside implementation of APIs.
If you are integrating Weld into an environment that supports deployment of multiple applications, you must enable, automatically, or through user configuration, classloader isolation for each CDI application.
If you are integrating Weld into a Servlet environment you must register
org.jboss.weld.servlet.WeldInitialListener
and
org.jboss.weld.servlet.WeldTerminalListener
as Servlet listeners,
either automatically, or through user configuration, for each CDI
application which uses Servlet.
You must ensure that WeldInitialListener
is called before any other
application-defined listener is called and that WeldTerminalListener
is called only after all application-defined listeners have been called.
You must ensure that WeldInitialListener.contextInitialized()
is called after
beans are deployed is complete (Bootstrap.deployBeans()
has been
called).
A CDI implementation is required to provide a Servlet filter named “CDI Conversation Filter”. The filter may be mapped by an application in the web descriptor. That allows application to place another filter around the CDI filter for dealing with exceptions.
Weld provides this filter with a fully qualified class name of`org.jboss.weld.servlet.ConversationFilter`.
If the application contains a filter mapping for a filter named “CDI
Conversation Filter”, the integrator is required to register
org.jboss.weld.servlet.ConversationFilter
as a filter with “CDI
Conversation Filter” as its filter name. If no such mapping exists in
the application, the integrator is not required to register the filter.
In that case, WeldInitialListener
will take care of conversation context
activation/deactivation at the beginning of HTTP request processing.
If you are integrating Weld into a JSF environment you must register
org.jboss.weld.el.WeldELContextListener
as an EL Context listener.
If you are integrating Weld into a JSF environment you must register
org.jboss.weld.jsf.ConversationAwareViewHandler
as a delegating view
handler.
If you are integrating Weld into a JSF environment you must obtain the
bean manager for the module and then call
BeanManager.wrapExpressionFactory()
, passing
Application.getExpressionFactory()
as the argument. The wrapped
expression factory must be used in all EL expression evaluations
performed by JSF in this web application.
If you are integrating Weld into a JSF environment you must obtain the
bean manager for the module and then call BeanManager.getELResolver()
,
The returned EL resolver should be registered with JSF for this web
application.
There are a number of ways you can obtain the bean manager for the
module. You could call Bootstrap.getManager()
, passing in the BDA for
this module. Alternatively, you could use the injection into Java EE
component classes, or look up the bean manager in JNDI.
If you are integrating Weld into a JSF environment you must register
org.jboss.weld.servlet.ConversationPropagationFilter
as a Servlet
listener, either automatically, or through user configuration, for each
CDI application which uses JSF. This filter can be registered for all
Servlet deployment safely.
Weld only supports JSF 1.2 and above.
org.jboss.weld.jsf.WeldPhaseListener
was deprecated in Weld 2 and is
no longer present in Weld.
org.jboss.weld.servlet.ConversationPropagationFilter
was deprecated
and should no longer be used.
If you are integrating Weld into a JSP environment you must register
org.jboss.weld.el.WeldELContextListener
as an EL Context listener.
If you are integrating Weld into a JSP environment you must obtain the
bean manager for the module and then call
BeanManager.wrapExpressionFactory()
, passing
Application.getExpressionFactory()
as the argument. The wrapped
expression factory must be used in all EL expression evaluations
performed by JSP.
If you are integrating Weld into a JSP environment you must obtain the
bean manager for the module and then call BeanManager.getELResolver()
,
The returned EL resolver should be registered with JSP for this web
application.
There are a number of ways you can obtain the bean manager for the
module. You could call Bootstrap.getManager()
, passing in the BDA for
this module. Alternatively, you could use the injection into Java EE
component classes, or look up the bean manager in JNDI.
org.jboss.weld.ejb.SessionBeanInterceptor
takes care of activating the
request scope around EJB method invocations in a non-servlet
environment, such as message-driven bean invocation, @Asynchronous
invocation or @Timeout
. If you are integrating Weld into an EJB
environment you must register the aroundInvoke
method of
SessionBeanInterceptor
as a EJB around-invoke interceptor for all EJBs
in the application, either automatically, or through user configuration,
for each CDI application which uses enterprise beans.
If you are running in a EJB 3.2 environment, you should register this as an around-timeout interceptor as well.
In addition, since CDI 1.1 the aroundInvoke
method of
SessionBeanInterceptor
should be invoked around @PostConstruct
callbacks of EJBs.
You must register the SessionBeanInterceptor
as the outer most
interceptor in the stack for all EJBs.
Weld can reside on an isolated classloader, or on a shared classloader.
If you choose to use an isolated classloader, the default
SingletonProvider
, IsolatedStaticSingletonProvider
, can be used. If
you choose to use a shared classloader, then you will need to choose
another strategy.
You can provide your own implementation of Singleton
and
SingletonProvider
and register it for use using
SingletonProvider.initialize(SingletonProvider provider)
.
Weld also provides an implementation of Thread Context Classloader per
application strategy, via the TCCLSingletonProvider
.
You should bind the bean manager for the bean deployment archive into
JNDI at java:comp/BeanManager
. The type should be
javax.enterprise.inject.spi.BeanManager
. To obtain the correct bean
manager for the bean deployment archive, you may call
bootstrap.getBeanManager(beanDeploymentArchive)
CDI 1.1 provides a simplified approach to accessing the BeanManager /
CDI container from components that do not support injection. This is
done by the CDI class API. The integrating part can either use
org.jboss.weld.AbstractCDI
or org.jboss.weld.SimpleCDI
provided by
Weld core and register it using
javax.enterprise.inject.spi.CDIProvider
file that is visible to the
CDI API classes or use the CDI.setCDIProvider(CDIProvider provider)
method method early in the deployment.
Alternatively, an integrating part may provide a specialized implementation such as the one provided by WildFly integration.
The CDI specification requires the container to provide injection into
non-contextual resources for all Java EE component classes. Weld
delegates this responsibility to the container. This can be achieved
using the CDI defined InjectionTarget
SPI. Furthermore, you must
perform this operation on the correct bean manager for the bean
deployment archive containing the EE component class.
The CDI specification also requires that a ProcessInjectionTarget
event is fired for every Java EE component class. Furthermore, if an
observer calls ProcessInjectionTarget.setInjectionTarget()
the
container must use the specified injection target to perform
injection.
To help the integrator, Weld provides
WeldManager.fireProcessInjectionTarget()
which returns the
InjectionTarget
to use.
// Fire ProcessInjectionTarget, returning the InjectionTarget
// to use
InjectionTarget it = weldBeanManager.fireProcessInjectionTarget(clazz);
// Per instance required, create the creational context
CreationalContext<?> cc = beanManager.createCreationalContext(null);
// Produce the instance, performing any constructor injection required
Object instance = it.produce();
// Perform injection and call initializers
it.inject(instance, cc);
// Call the post-construct callback
it.postConstruct(instance);
// Call the pre-destroy callback
it.preDestroy(instance);
// Clean up the instance
it.dispose(instance);
cc.release();
The container may intersperse other operations between these calls. Further, the integrator may choose to implement any of these calls in another manner, assuming the contract is fulfilled.
When performing injections on EJBs you must use the Weld-defined SPI,
WeldManager
. Furthermore, you must perform this operation on the
correct bean manager for the bean deployment archive containing the EJB.
// Obtain the EjbDescriptor for the EJB
// You may choose to use this utility method to get the descriptor
EjbDescriptor<T> ejbDescriptor = beanManager.<T>getEjbDescriptor(ejbName);
// Get an the Bean object
Bean<T> bean = beanManager.getBean(ejbDescriptor);
// Create the injection target
InjectionTarget<T> it = beanManager.createInjectionTarget(ejbDescriptor);
// Per instance required, create the creational context
WeldCreationalContext<T> cc = beanManager.createCreationalContext(bean);
// register an AroundConstructCallback if needed
cc.setConstructorInterceptionSuppressed(true);
cc.registerAroundConstructCallback(new AroundConstructCallback<T>() {
public T aroundConstruct(ConstructionHandle<T> handle, AnnotatedConstructor<T> constructor, Object[] parameters,
Map<String, Object> data) throws Exception {
// TODO: invoke @AroundConstruct interceptors
return handle.proceed(parameters, data);
}
});
// Produce the instance, performing any constructor injection required
T instance = it.produce(cc);
// Perform injection and call initializers
it.inject(instance, cc);
// You may choose to have CDI call the post construct and pre destroy
// lifecycle callbacks
// Call the post-construct callback
it.postConstruct(instance);
// Call the pre-destroy callback
it.preDestroy(instance);
// Clean up the instance
it.dispose(instance);
cc.release();
Weld implements support for constructor call interception and invokes interceptors that are
associated with the particular component either using an interceptor binding
or the @Interceptors
annotation.
This can be suppressed by calling WeldCreationalContext.setConstructorInterceptionSuppressed(true)
In addition, an integrator may register a callback in which it performs additional operations around the constructor call. This way an integrator may for example implement support for additional interceptors (e.g. those bound using the deployment descriptor).
See AroundConstructCallback and WeldCreationalContext.registerAroundConstructCallback() for more details.
Optionally, an integrator may register the following Probe Development Tool components in order to enable its functionality. Note that these components should only be registered if the development mode is enabled - see also Section 21.1, “How to enable the development mode”.
Table A.1. Probe components
Class | Type | Description |
---|---|---|
| Servlet filter | An integrator is required to register this filter for every web application which should be a subject of inspection. The filter should only be mapped to a single URL pattern of value |
| CDI extension | An integrator is required to register this extension for every application which should be a subject of inspection. |
Probe classes reside in a separate module with the following coordinates: org.jboss.weld.probe:weld-probe-core
. This module is a dependency of a Weld Servlet integration module and it’s also a part of the weld-servlet-shaded
artifact and Weld OSGi bundle.
Probe REST API is implemented using a servlet filter. However, not all servlet containers trigger filters when recieving a request to a path which is not mapped to any servlet (although most of them define a "default" servlet for each application). In this case, an integrator should register a "dummy" servlet (its methods will never be invoked) mapped to the URL pattern /weld-probe/*
.
This part of the appendix documents the changes in Weld across major and minor releases that an integrator should be aware of. These changes mostly touch changes in the SPI or in the container contract.
All the changes are documented in this external migration document.
Weld no longer uses slf4j
for logging. Instead,
jboss-logging
is now used as a logging facade.
A new service named HttpContextActivationFilter was added to the Weld SPI. This optional service allows an integrator to decide if CDI contexts should be activated or not for a given HTTP request. By default, CDI contexts are always active but this hook allows an integrator to eliminate the overhead of CDI context activation for certain types of requests where CDI is known not to be needed (e.g. request for a static resource).
Note that when the service is provided, user configuration is overriden.
The BootstrapConfiguration service now allows the non-portable mode to be enabled by the integrator.
Since Weld 2.1 the
Singleton
SPI requires the singleton to be identified by a String context id
.
This allows multiple Weld containers to run at the same time in
environments where the TCCL cannot be used to distinguish the containers
(e.g. OSGi environment).
The integrator should:
The Weld-OSGi bundle does no include Weld’s runtime dependencies anymore. Therefore, it is possible to deploy the following artifacts in order to satisfy Weld’s dependencies:
group id | artifact id | version |
---|---|---|
org.jboss.logging | jboss-logging | 3.1.3.GA |
com.google.guava | guava | 13.0.1 |
javax.enterprise | cdi-api | 1.1-20130918 |
javax.annotation | javax.annotation-api | 1.2 |
javax.interceptor | javax.interceptor-api | 1.2 |
org.apache.geronimo.specs | geronimo-el_2.2_spec | 1.0.3 |
InjectionTarget
implementation using the builder pattern.jboss-classfilewriter
dependency, which is used by Weld for runtime bytecode generation, is no longer bundled within the Weld OSGi bundle.
Instead, this dependency needs to be deployed separately to the OSGi container.group id | artifact id | version |
---|---|---|
org.jboss.classfilewriter | jboss-classfilewriter | 1.1.2.Final |
EEModuleDescriptor
which describes Java EE modules has been introduced and is now required as part of deployment structure metadata.
See Section A.1.1.1, “EE Modules” for details.@Initialized(ConversationScoped.class)
or @Destroyed(ConversationScoped.class)
event no longer forces eager conversation context initialization. See also Section 5.3.5, “Lazy and eager conversation context initialization”.ScheduledExecutorServiceFactory
is deprecated and no default implementation is provided by default. This service has not been used by Weld internals at least since version 1.1.0.Final.com.google.guava:guava
anymore. The dependency is also not bundled with shaded artifacts for Weld SE and Weld Servlet.org.jboss.weld.resources.SingleThreadScheduledExecutorServiceFactory
was removed.Weld SE:
org.jboss.weld.environment.se.contexts.activators.ActivateRequestScope
was moved to the Weld API. From now on, the FQCN of the interceptor binding is: org.jboss.weld.context.activator.ActivateRequestScope
.org.jboss.weld.environment.se.beans.InstanceManager
was removed.org.jboss.weld.environment.se.ShutdownManager
was removed.org.jboss.weld.environment.se.contexts.interceptors.ActivateThreadScope
was removed.