-
15. Re: Bean property configuration
gavin.king Dec 28, 2009 6:08 AM (in response to johaneltes)
Alternative still have some hard code. And do i have all preconcerted Alternative?Well, not really, not if you use producer methods/fields, like I show above.
BWT Alternative is not clear than xmlI actually think it's more clear to have everything expressed in Java code, instead of split out into XML. I think you'll get used to @Alternative. It looks a little strange at first, because it's not what you're used to. But once you figure out that it's possible to do all the things you do today with XML, it will get natural.
-
16. Re: Bean property configuration
alin.heyoulin.qq.com Dec 28, 2009 6:26 AM (in response to johaneltes)
Well, not really, not if you use producer methods/fields, like I show above.I mean producer methods/fields could be any value. For example to config datasource url or username... . It could't geive all the producer methods/fields .
Thanks your reply!
-
17. Re: Bean property configuration
alin.heyoulin.qq.com Dec 28, 2009 6:30 AM (in response to johaneltes)And an other question. Why load all managed bean to container? In seam3 can i just load my special bean by config file?
-
18. Re: Bean property configuration
johaneltes Dec 28, 2009 4:15 PM (in response to johaneltes)Thought I share were I ended up with my JmsTemplate experiment. The case is to find a CDI-ish approach for configuration of multiple beans of the same class, so that these bean configurations can be injected into various injection points across the application. The scenario at hand is about JmsTemplates. The application needs a set of JmsTemplate - one per destination - to be pre-configured. I would like to do the configuration using as little procedural Java code as possible. First, the injection point (sample): private @Inject @Named("error") JmsTemplate template; The semantics of the injection point is: Inject the pre-configured JmsTemplate instance named "error". The application will then use the template to send error messages. The pre-configured JMS templates are defined in Java, not XML. A annotation has been created to support configuration of the properties of the templates. A configuration is represented by a producer method, The complete set of JMS Template configurations are represented by a CDI bean hosting all the producer methods. The following template configuration class defines two named JmsTemplate configurations: "log" and "error": public class JmsTemplateProducers { @Produces @Resource(name="java:app/jms/NoXA_CF") ConnectionFactory cf; @Produces @Named("error") public JmsTemplate getErrorQueueTemplate( @JmsTemplateConfig(defaultDestinationName = "errorQueue", timeout = 3600) JmsTemplate template) { template.setConnectionFactory(cf); return template; } @Produces @Named("log") public JmsTemplate getLogQueueTemplate( @JmsTemplateConfig(defaultDestinationName = "logQueue", timeout = 100) JmsTemplate template) { template.setConnectionFactory(cf); return template; } } The difference to just assigning all values the usual way isn't paramount: @Produces @Named("log") public JmsTemplate getLogQueueTemplate() { JmsTemplate template = new JmsTemplate(); template.setConnectionFactory(cf); template.setDefaultDestinationName("logQueue"); template.setTimeout(100); return template; } The value of the annotation approach is that it does not require the producers to be created, when I'm not concerned about reusing a configuration: private @Inject @JmsTemplateConfig(defaultDestination = "logQueue", timeout = 100) JmsTemplate template; For the annotation merging to work, there need to be an annotation type and a supporting injection point producer. These two classes are generic utilities: @Qualifier @Target( { METHOD, FIELD, PARAMETER, TYPE }) @Retention(RUNTIME) public @interface JmsTemplateConfig { @Nonbinding String defaultDestinationName() default ""; @Nonbinding int timeout() default 0; } public class JmsTemplateConfigurationProducer { @Produces @JmsTemplateConfig public JmsTemplate produceJmsTemplate(InjectionPoint injectionPoint) { if (injectionPoint.getAnnotated().isAnnotationPresent(JmsTemplateConfig.class)) { JmsTemplateConfig t = injectionPoint.getAnnotated().getAnnotation(JmsTemplateConfig.class); JmsTemplate tmp = new JmsTemplate(); tmp.setDefaultDestinationName(t.defaultDestinationName()); tmp.setReceiveTimeout(t.timeout()); return tmp; } else { return new JmsTemplate(); } } }
Thanks to all who guided me through this journey. It definitely way to increased my understanding of CDI.
-
19. Re: Bean property configuration
meetoblivion Dec 28, 2009 4:28 PM (in response to johaneltes)just a note, Johan
in this code:
@Produces @JmsTemplateConfig public JmsTemplate produceJmsTemplate(InjectionPoint injectionPoint) { if (injectionPoint.getAnnotated().isAnnotationPresent(JmsTemplateConfig.class)) { JmsTemplateConfig t = injectionPoint.getAnnotated().getAnnotation(JmsTemplateConfig.class); JmsTemplate tmp = new JmsTemplate(); tmp.setDefaultDestinationName(t.defaultDestinationName()); tmp.setReceiveTimeout(t.timeout()); return tmp; } else { return new JmsTemplate(); } }
@Produces @JmsTemplateConfig makes the isAnnotationPresent part of your code unnecessary, as this will only ever be called to @Inject @JmsTemplateConfig JmsTemplate,
-
20. Re: Bean property configuration
gavin.king Dec 28, 2009 7:21 PM (in response to johaneltes)
Thought I share were I ended up with my JmsTemplate experiment.A couple of notes:
- I agree that @ErrorQueue, @LogQueue is much better than @Named("error"), @Named("log"). I don't think you are ever going to have so many queues in your app that defining an annotation for each one is a significant burden.
- Why not suck the connection factory JNDI name into @JmsTemplateConfig, and have produceJmsTemplate() look it up from JNDI instead of using injection? That would significantly simplify the code.
- When we introduce abstract producer methods, the code for getErrorQueueTemplate() and getLogQueueTemplate() will get waaay simpler!
With all these changes, including abstract producer methods, the code would look like:
@Produces @ErrorQueue abstract JmsTemplate getErrorQueueTemplate(@JmsTemplateConfig(defaultDestinationName="errorQueue", timeout=3600, name="java:app/jms/NoXA_CF") JmsTemplate template);
Which I think is a significant simplification.
-
21. Re: Bean property configuration
gavin.king Dec 28, 2009 7:30 PM (in response to johaneltes)
Gavin King wrote on Dec 28, 2009 19:21:
With all these changes, including abstract producer methods, the code would look like:@Produces @ErrorQueue abstract JmsTemplate getErrorQueueTemplate(@JmsTemplateConfig(defaultDestinationName="errorQueue", timeout=3600, name="java:app/jms/NoXA_CF") JmsTemplate template);
Which I think is a significant simplification.Hrm. Who would prefer to be able to write:
@Produces @ErrorQueue @GenericResource @JmsTemplateConfig(defaultDestinationName="errorQueue", timeout=3600, name="java:app/jms/NoXA_CF") JmsTemplate template;
Perhaps abstract @Produces methods are the wrong way to go, and @Produces @GenericResource fields are more readable construct....
-
22. Re: Bean property configuration
gavin.king Dec 28, 2009 7:35 PM (in response to johaneltes)
Perhaps abstract @Produces methods are the wrong way to go, and @Produces @GenericResource fields are more readable construct....I guess it's not the right way to go, since it opens up a whole can of worms of resolving
generic resources
. Better to just not go there, I guess. The abstract producer method solves the problem (along with several other problems). -
23. Re: Bean property configuration
gavin.king Dec 28, 2009 7:42 PM (in response to johaneltes)
Gavin King wrote on Dec 28, 2009 19:35:Perhaps abstract @Produces methods are the wrong way to go, and @Produces @GenericResource fields are more readable construct....
I guess it's not the right way to go, since it opens up a whole can of worms of resolvinggeneric resources
. Better to just not go there, I guess. The abstract producer method solves the problem (along with several other problems).Actually, here's an interesting possibility: give portable extensions the possibility to
inject into
(i.e. define the value of) @Producer fields at the right time, by registering a callback on the particular Producer object. This generalizes a capability that already exists implicitly in CDI and is used by the container for stuff like @Resource, @PersistenceContext, @EJB and friends. We would just be opening up that capability to portable extensions.Then the code would look like:
@Produces @ErrorQueue @JmsTemplateConfig(defaultDestinationName="errorQueue", timeout=3600, name="java:app/jms/NoXA_CF") JmsTemplate template;
And the portable extension would register some callback object when it encounters a @Produces field annotated @JmsTemplateConfig. Yeah, I think that would be a really nice capability! I'll add it to the wishlist.
-
24. Re: Bean property configuration
gavin.king Dec 28, 2009 8:14 PM (in response to johaneltes)Even better, this feature would allow us to eliminate the whole special bean category
Resources
from the spec, and suck the whole of 3.5 into 3.4, in a new subsection forProducer field initializers
. Now that's really nice! All we would need to do is introduce a new interface in the SPI package:public interface Initializer<X> { public X getInitialValue(AnnotatedField<?> field); }
Along with a ProcessProducerField event type extending ProcessProducer with a setInitializer() method.
-
25. Re: Bean property configuration
johaneltes Dec 28, 2009 9:31 PM (in response to johaneltes)@Produces @ErrorQueue @JmsTemplateConfig(defaultDestinationName="errorQueue", timeout=3600, name="java:app/jms/NoXA_CF") JmsTemplate template;
...is really nice. It is an important achievement to get rid of the producer method. I the
abstract
method is axactly that: a bit (too) abstract.I'm note sure I like the idea of introducing an annotation type for each queue. I see the point of type safe injection, but it is important to reduce level of abstractions and the bloat of intruducing new queues. The reason is that I have a different experience regarding the number of queues that may be present. Having an annotation type per domain/app with a supporting enum of queue names may be the ideal intersection of type safety and footprint.
Regarding the @Resource: baking the lookup into the injection point producer method makes sense in this simple case. In a real-world app it will sometimes be a reasource but most likely an alternative, one of which being an out-of-container configuration based on e.g. MQQueueConnectionFactory with several properties.