CDI Transactions tested with Arquillian
How to implement a scope like an transaction? The main goal was the reusability for an SE environment.
After a little bit google- searching I found the ConversationScope. A google start, but not usable in an SE environment.
So I started to write my own Scope. (Source –> Bitbucket) First step will be an annotation CDITransactionScope with the default Annotations.
The only new one is the annotation @NormalScope. With this annotation the container will use this as an Scope-Qualifier.
The next step is the implementation of an extension. This is done by the class CDITransactionExtension extends Extension.
The interface Extension itself is empty and only a marker. The task to full fill is the registration of an context.
The AfterBeanDiscovery event is used to add the instance of the context implementation. Important to know is, that at this point the init-phase of the weld-container is not ready.
No @Inject is possible and the only instance that can be injected is the BeanManager.
Finally we have to implement the heard of the transaction, the CDITransactionContext implements Context.
This is a class, not managed by the Container and again no @Inject is possible, but the BeanManager
is usable. (see CDITransactionExtension )
Four methods are found to implement from the interface Context.
1) public Class<? extends Annotation> getScope()
2) public <T> T get(Contextual<T> contextual, CreationalContext<T> creationalContext);
3) public <T> T get(Contextual<T> contextual);
4) public boolean isActive();
Nr 2 and 3 are the important methods to implement. This methods are handling the instance-management.
The easiest implementation could be a map like HashMap<Class, Object>.
This implementation will cache all classes implementing the Interface Cacheable. (GenericCache)
If an Class is implementing this Interface it will be cached, otherwise you will always get a new instance.
To activate this Extension, the class CDITransactionExtension must be registered in the file META-INF/javax.enterprise.inject.spi.Extension
with the full class name.
Now we can start writing transactions.
The Transaction (AbstractCDITransaction) is an Executor-Pattern.
To Implement a transaction you have to implement an transaction – class with the method doIt().
Here is an excample with references inside and ad the same time outside of the active transaction.
Inside the transaction are all instances with the Qualifier @CDITransactionScop .
For this jUnitTest I implemented two Producers, one for the Instances inside the transaction and one for the outside one.
Finally the UML for this small demo.