Skip to content
avrecko edited this page Sep 14, 2010 · 40 revisions

What is this

This is a prototype, or proof of principle if you will, of programmatic configuration of CDI.

If somebody wants to make something similar – this is a good starting point. It includes pretty much all of the know-how.

In a nutshell the extensions instantiates Guice Modules to read the programmatic configuration and then it rewrites the annotated type information to match.

What works

Currently Guice API for linked binding works e.g.

bind(Mailer.class).to(AsynchronousMailer.class).in(Singleton.class);

and AOP support e.g.

bindInterceptor(any(), annotatedWith(Transactional.class), new TxnInterceptor());

The rest is left as en excersize for the reader to implement. ;)

One Caveat

Due to the way CDI works it is impossible to express this binding.

bind(Mailer.class).annotatedWith(Blue.class).to(AsynchronousMailer.class).in(Singleton.class);
bind(Mailer.class).annotatedWith(Red.class).to(AsynchronousMailer.class).in(SessionScoped.class);

As both target AsynchronousMailer and CDI reads annotations from the AsynchronousMailer therefore it doesn’t work.

How to use it

Best if you check out unit test(s).

  1. Run ant jar (this will create weld-guiceconfig.jar)
  2. Put weld-guiceconfig.jar in the class path (all internal dependencies (guava, weld-extensions) are baked in using jarjar. Guice, weld, aopalliance and slf4j are not baked-in and have to be put on the classpath seperately.)
  3. Create META-INF/guiceconfig/Modules.properties in your project and reference any Guice modules using fully qualified names

Will there be any more updates

Most probably not. This was principally a fun project to play with Weld a bit. Need to spend time on preparing for exams.

Implementation details

Reading the programmatic configuration

Using beforeBeanDiscovery(Observes BeforeBeanDiscovery event, BeanManager beanManager) we do the work of reading the programmatic configuration.

Using getClass().getClassLoader().getResources(PACKAGES_FILE); we read text file that includes the fully qualified names of Guice modules.

I reused Guice API later on because I did not want to create a 1-to-1 mapping between my own custom programmatic API. But at first I started with custom API.

Check out weld.guiceconfig.attic package for an example of custom fluent style API. Might give you some ideas for implementation of your own.

The modules are instantiated and feed to CdiBindingOracle which prepares all the configuration for easy access by the Phases. What a phase is read on.

Modifying the Annotated Types

At processAnotated(Observes ProcessAnnotatedType<T> event, BeanManager manager)

We feed AnnotatedTypeBuilder based on the event.getAnnotatedType to each Phase. There are 3 phases
*RedefineDefaultInjectionPointsPhase
*ApplyLinkedBindingsAdvicePhase
*ApplyInterceptorAdvicePhase

Reporting Errors

Left as excersize for the reader. (You can see I study for Math exams).

Clone this wiki locally