Set a field from a CDI extension to a producer class
jmesnil Jun 13, 2014 9:36 AMHi,
I'm using a CDI extension to provide a producer method for JMSContext object.
The code is straightforward and works fine:
public class JMSCDIExtension implements Extension { private final PropertyReplacer propertyReplacer; public JMSCDIExtension(PropertyReplacer propertyReplacer) { this.propertyReplacer = propertyReplacer; } void beforeBeanDiscovery(@Observes BeforeBeanDiscovery bbd, BeanManager bm) { AnnotatedType<JMSContextProducer> producer = bm.createAnnotatedType(JMSContextProducer.class); bbd.addAnnotatedType(producer); } }
The JMSContextProducer is a simple java class with a CDI producer method:
public class JMSContextProducer { public JMSContextProducer() { } /** * CDI Producer method for injected {@link JMSContext}. */ @Produces public JMSContext getJMSContext(InjectionPoint injectionPoint) throws NamingException { ... return new JMSContextImpl(...); } ... }
However, I now want to change the JMSContextProducer to use a PropertyReplacer field inside its producer method.
I have a reference on the PropertyReplacer when my CDI extension is instantiated but I can't figure out to set it on the JMSContextProducer object.
public class JMSCDIExtension implements Extension { private final PropertyReplacer propertyReplacer; public JMSCDIExtension(PropertyReplacer propertyReplacer) { this.propertyReplacer = propertyReplacer; } void beforeBeanDiscovery(@Observes BeforeBeanDiscovery bbd, BeanManager bm) { // FIXME somehow push the propertyReplace into the JMSContextProducer instance AnnotatedType<JMSContextProducer> producer = bm.createAnnotatedType(JMSContextProducer.class); bbd.addAnnotatedType(producer); } }
I find a way to having it work by observing for ProcessInjectionTarget event on JMSContextProducer and set the propertyReplacer on the instance:
public void wrapInjectionTarget(@Observes ProcessInjectionTarget<JMSContextProducer> event) { final InjectionTarget<JMSContextProducer> injectionTarget = event.getInjectionTarget(); event.setInjectionTarget(new ForwardingInjectionTarget<JMSContextProducer>() { @Override public void inject(JMSContextProducer instance, CreationalContext<JMSContextProducer> ctx) { super.inject(instance, ctx); instance.setPropertyReplacer(propertyReplacer); } @Override protected InjectionTarget<JMSContextProducer> delegate() { return injectionTarget; } }); }
It looks to work fine but I wonder if that is the best way to do this. Ideally, I would like to create a single JMSContextProducer instance with a propertyReplacer in its constructor and tell CDI to use that instance to produce JMSContext.
What's the best way to do this?
thanks