Previamente vimos cómo utilizar una cola de mensajes usando la inyección de dependencias básica de JEE6 >>
Pero resulta que ésto es optimizable si es que estamos en un contenedor que soporte CDI. De hecho, estamos trabajando con el framework Seam que provee un módulo para JMS >>. Entonces la idea de este post es evaluar qué ventajas nos proveen ambas herramientas versus la inyección básica.
Primero que nada, si usamos CDI puro, podemos utilizar @Producer fields para minimizar las inyecciones que no sean type-safe, como dice la especificación de Weld >>
public class PojoProductor{ @Produces @Resource(mappedName="java:jms/ConnectionFactory") public ConnectionFactory fabricaConexiones; @Produces @Resource(mappedName="jms/cola") public Queue q; }
La idea es que el único lugar en que el nombre de la cola esté en duro quede encapsulado en esta clase, y después se utilice por inyección simple en los beans
@Inject private Queue q;
También podemos usar qualifiers si tenemos más de una cola, etc.
Lo que no me queda claro al respecto es cuáles son los recursos que conviente producir, por ej. si quisiéramos minimizar el código necesario para enviar un mensaje.
Justamente ahí es donde podemos empezar a mirar Seam-JMS, que soporta inyección de estos objetos directamente, veamos.
Efectivamente puedo inyectar la cola sin su productor
@Inject @JmsDestination(jndiName="jms/cola")
pero igual estoy necesitando la ConnectionFactory para la conexión y la sesión.
Además perdemos la ventaja de tener el nombre de la cola en un solo lugar.
Lo que sí es interesante es la capacidad de inyectar la javax.jms.Session, sin necesidad de traerse la ConnectionFactory y crearla
@Inject private transient Session session;
(Nótese que el punto de inyección tiene que ser transiente en un SFSB pasivable)
La única duda que me queda al respecto es respecto a las transacciones. ¿La sesión es CMT? ¿Debo cerrarla en un finally?
Eso sí, por defecto Seam JMS utilizará la ConnectionFactory en jms/ConnectionFactory. Si ésta se encuentra en otra parte (como en mi caso), hay que sobrescribirla en seam-beans.xml >>
<jmsi:JmsConnectionFactoryProducer> <s:modifies /> <jmsi:connectionFactoryJNDILocation>otra/ConnectionFactory</jmsi:connectionFactoryJNDILocation> </jmsi:JmsConnectionFactoryProducer>
Al parecer ésto mismo también podría hacerse extendiendo o especializando (CDI) org.jboss.seam.jms.inject.JmsConnectionFactoryProducer…
Así es que hasta ahora, la mejor combinación que se avisora sería dejar la inyección de colas desde producer fields por type-safety, y la de sesiones jms usando SeamJMS con inyección directa. De hecho en la página de inicio de inicio es lo que recomiendan.
Seam JMS at one point supported a Stereotype implementation that wrapped the injection of destinations via JNDI. However, it is much easier to just provide a producer on an injected resource as noted below. Note that the JmsDestination support remains, but it cannot be wrapped in another qualifier.
Otra funcionalidad que provee Seam JMS es un builder que supuestamente hace el envío del mensaje más fácil:
@Inject private QueueBuilder builder; //... public void metodo(){ builder.destination("jms/SomeQueue").sendString("holi"); //según la documentación }
Pero en la práctica hay que pasarle la cola (no recibe String), lo que estaría ok., pero rambién hay que pasarle la ConnectionFactory:
@Inject private QueueConnectionFactory factory; @Inject private Queue queue; @Inject private QueueBuilder builder; //... public void metodo(){ this.builder.connectionFactory(factory).destination(queue).sendString("hola holaa"); }
Así es que al final es más verboso que lo anterior… a menos que esté usando algo mal.
En resumen me estaría quedando con la inyección de sesión y el productor de colas.