JSR-299 CDI portable extensions

Markus Eisele
6
One of my fav features of the new CDI spec is the ability to integrate custom extensions. The portable extensions spi is the place to start over with it.
You can find some examples of portable extensions in gavins blog. The latest weld reference documentation (weld-reference.pdf, 867 KiB, application/pdf) contains a chapter (16) with more details about the extension spi.
CDI is intended to be a foundation for frameworks, extensions and integration with other technologies. Therefore,
CDI exposes a set of SPIs for the use of developers of portable extensions to CDI.

Getting started is straight forward. (I was using NetBeans 6.8 with this example)
Add a webproject and a separate java library project. Push whatever is needed to your webproject and don't forget to put an empty beans.xml in your WEB-INF/ folder.
Now, start writing your extension.

1) Create a java class
that implements the marker interface javax.enterprise.inject.spi.Extension


public class MyExtension implements Extension {
//...
}

2) Register your extension
as a provider by creating a folder named META-INF/services/ in your java library project and putt a file named javax.enterprise.inject.spi.Extension in it. This file has to contain the full qualified name of your extension class (in my case net.eisele.cdi.extensions.MyExtension))

3) Implement the extension logic.
Basically extensions listen to events fired by the CDI container and are able to modify the containers metamodel. The events fired are one or all of the following:
javax.enterprise.inject.spi.BeforeBeanDiscovery
javax.enterprise.inject.spi.ProcessAnnotatedType
javax.enterprise.inject.spi.ProcessInjectionTarget and ProcessProducer
javax.enterprise.inject.spi.ProcessBean and ProcessObserverMethod
javax.enterprise.inject.spi.AfterBeanDiscovery
javax.enterprise.inject.spi.AfterDeploymentValidation

You have to add your business methods and declare an @Observes for every event you are willing to catch. Example:

void beforeBeanDiscovery(@Observes BeforeBeanDiscovery bbd) {
log.info("Begin the scanning process");
}


4) You can have a BeanManager
injected to your methods, too.

public void getBeanManager(@Observes BeanManager bm)

The nerve center for extending CDI is the BeanManager object. The BeanManager interface let you obtain beans, interceptors, decorators, observers and contexts programmatically.

5) You can inject your new extension
even it is not really a bean.

@Inject
MyExtension ext;

or

@Inject
MyBean(MyExtension myExtension) {
myExtension.doSomething();
}


If you deploy your app to GlassFish v3 you see something like this in your logfile:
INFO: Begin the scanning process

That was it. You got your first CDI extension up and running.

Post a Comment

6Comments

  1. I agree, this is a sweet extension point.

    ReplyDelete
  2. und was macht man, wenn CDI nicht funkt und man diese Meldung nie sieht? Ich habe GF v3 und ich bekomme meine @Injects einfach nicht zum Laufen.

    ReplyDelete
  3. @ThomasH: Würde gerne helfen .. aber ein paar mehr Details bräuchte ich schon :)

    ReplyDelete
  4. Hi,

    I did all as explained, but glassfish doesn load the extension. Any idea ?

    Thanks,
    Tiago.

    ReplyDelete
  5. No, beans.xml is there. Other common cdi components are loaded fine. It seems that glassfish is not looking for the extensions inside de attached jar at deployment.

    ReplyDelete
Post a Comment