-
Notifications
You must be signed in to change notification settings - Fork 1
Home
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.
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. ;)
Due to the way CDI works things like
bind(Mailer.class).annotatedWith(Blue.class).to(AsynchronousMailer.class).in(Singleton.class);
bind(Mailer.class).annotatedWith(Red.class).to(AsynchronousMailer.class).in(SessionScoped.class);
currently doesn’t work as AsynchronousMailer gets both @Singleton and @SessionScoped.
Best if you check out unit test(s).
- Run ant jar (this will create weld-guiceconfig.jar)
- 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.)
- Create META-INF/guiceconfig/Modules.properties in your project and reference any Guice modules using fully qualified names
Most probably not. This was principally a fun project to play with Weld a bit. Need to spend time on preparing for exams and do some work.
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. Guice is only used for providing the configuration API. It is possible to integrate things more intimately, like using Guice Injector but didn’t explore this path.
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. The term “phase” is explained later on.
At processAnotated(
Observes ProcessAnnotatedType<T> event, BeanManager manager)
We feed AnnotatedTypeBuilder
based on the event.getAnnotatedType
to each Phase. There are 3 phases
This phase replaces @Default
qualifier with @HardDefault
for all injection points for which there is a no qualified default binding. E.g.
bind(Foo.class).to(FooImpl.class); causes
@Inject Foo foo;
is redefined with @Inject @HardDefault Foo foo;
Classes are not modified, just the way Weld sees them using AnnotatedType.
We need to do this so there is no chance of ambiguity.
This phase puts correct annotations on the implementation. E.g.
bind(Foo.class).annotatedWith(Red.class).to(FooImpl.class).in(Singleton.class);
causes Weld to see
@Singleton
@Red
public void FooImpl{}
This puts @GuiceIntercepted
on all methods that pass both Class and Method matcher and creates a entry in the Multimap<Method, MethodInterceptors>
.
bindInterceptor(any(),annotatedWith(Transactional.class), new MethodInterceptor...);
will cause
@Transactional
public void someMethod(){ ... }
to be seen by Weld/CDI as
@GuiceIntercepted @Transactional
public void someMethod(){ ... }
the GuiceConfigInterceptor
will be used to intercept all methods annotated with GuiceConfigIntercepted
. The interceptor will invoke the correct set of interceptors for the Method being intercepted.
After all the phases are complete the call event.setAnnotatedType(builder.create());
is called.
Just thought it is a nice way to structure all the processing code. Might need a refacture.
Left as excersize for the reader.