
Service Provider Interfaces
Each scope type is associated with a context object. The context object is implemented by the CDI framework according the scope type. There usually exists a context object assigned for each scope type.
The CDI container collaborates with the context through the javax.enterprise.context.cdi.Context and javax.enterprise.context.cdi.Contextual interfaces to create and destroy the contextual instances.
CDI 1.1 adds a new context interface, the AlterableContext. It provides an operation for obtaining and destroying contextual instances passing a scope of any contextual type. An instance of context is defined as a context object.
AlterableContext was introduced in CDI 1.1 to allow bean instances to be destroyed by the application. Extensions should implement AlterableContext instead of context.
The context object can create or destroy contextual instances by calling operations extended with the class javax.enterprise.context.Contextual. Mostly, the context can destroy any created contextual instance passing the instance to the Contextual.destroy(Object, CreationalContext) method.
A custom context object can be registered in the container through the following method: AfterBeanDiscovery.addContext(Context).
See now how Weld uses the context spi:
@Inject
private MethodScopedBean methodScopedBean;
All contexts in Weld are Alterable Contexts. Through this code, we get the context for a chosen bean choosing the scope:
AlterableContext dependentContext = (AlterableContext) methodScopedBean.getBeanManager().getContext(Dependent.class);
In our code, we will create a custom contextual for the chosen bean. We can do it using an anonymous class:
Contextual<DependentBean> contextualDependentBean = new Contextual<DependentBean>() {
private DependentBean dependentBean;
@Override
public DependentBean create(CreationalContext<DependentBean> creationalContext) {
dependentBean = new DependentBean();
creationalContext.push(dependentBean);
return dependentBean;
}
@Override
public void destroy(DependentBean instance, CreationalContext<DependentBean> creationalContext) {
creationalContext.release();
dependentBean = null;
}
};
A CreationalContext provides operations that are used by the contextual implementation during instance creation and destruction. Here's how to create a custom:
CreationalContext<T> creationalContext = new CreationalContext<T>() {
private List<T> applicationBeans = new ArrayList<T>();
private T currentInstance;
@Override
public void push(T incompleteInstance) {
applicationBeans.add(incompleteInstance);
currentInstance = incompleteInstance;
}
@Override
public void release() {
applicationBeans.remove(currentInstance);
}
};
Now we have the contextual and the CreationalContext. With them we can operate with the context to do a manual injection:
DependentBean myCustomDependentBean = dependentContext.get(contextualDependentBean, getCreationalContext());
These operations are done internally in any CDI compliant engine. Usually this API is not done for the developer but only for internal use because we have more intuitive instruments as the annotations. This sample teaches what a container does when an Inject annotation is used by the developer.