Introducción a Spring JMS

1. Información general

Spring proporciona un marco de integración JMS que simplifica el uso de la API JMS. Este artículo presenta los conceptos básicos de dicha integración.

2. Dependencia de Maven

Para usar Spring JMS en nuestra aplicación, necesitamos agregar los artefactos necesarios en pom.xml :

 org.springframework spring-jms 4.3.3.RELEASE  

La versión más reciente del artefacto se puede encontrar aquí.

3. El JmsTemplate

La clase JmsTemplate maneja la creación y liberación de recursos al enviar o recibir mensajes sincrónicamente.

Por lo tanto, la clase que usa este JmsTemplate solo necesita implementar interfaces de devolución de llamada como se especifica en la definición del método.

A partir de Spring 4.1, JmsMessagingTemplate se basa en JmsTemplate, que proporciona una integración con la abstracción de mensajería, es decir, org.springframework.messaging.Message. Esto, a su vez, nos permite crear un mensaje para enviar de forma genérica.

4. Gestión de conexiones

Para poder conectarnos y poder enviar / recibir mensajes, necesitamos configurar una ConnectionFactory .

Una ConnectionFactory es uno de los objetos administrados por JMS que están preconfigurados por un administrador . Un cliente con la ayuda de la configuración hará la conexión con un proveedor JMS.

Spring proporciona 2 tipos de ConnectionFactory :

  • SingleConnectionFactory: es una implementación de lainterfaz ConnectionFactory , que devolverá la misma conexión en todas lasllamadas a createConnection () e ignorará las llamadas a close ()
  • CachingConnectionFactory : amplía la funcionalidad de SingleConnectionFactory y la mejora con un almacenamiento en caché de Sessions , MessageProducers y MessageConsumers

5. Gestión de destinos

Como se mencionó anteriormente, junto con ConnectionFactory , los destinos también son objetos administrados por JMS y pueden almacenarse y recuperarse desde un JNDI.

Spring proporciona resolutores genéricos como DynamicDestinationResolver y resolutores específicos como JndiDestinationResolver .

El JmsTemplate delegará la resolución del nombre de un destino a una de las implementaciones basándonos en nuestra selección.

También proporcionará una propiedad llamada defaultDestination , que se utilizará con las operaciones de envío y recepción que no se refieren a un destino específico.

6. Conversión de mensajes

Spring JMS estaría incompleto sin el soporte de Message Converters.

La estrategia de conversión predeterminada que utiliza JmsTemplate para las operaciones ConvertAndSend () y ReceiveAndConvert () es la clase SimpleMessageConverter .

SimpleMessageConverter puede manejar TextMessages , BytesMessages , MapMessages y ObjectMessages . Esta clase implementa la interfaz MessageConverter .

Además de SimpleMessageConverter , Spring JMS proporciona algunas otras clases de MessageConverter listas para usar como MappingJackson2MessageConverter , MarshallingMessageConverter , MessagingMessageConverter .

Además, podemos crear una funcionalidad de conversión de mensajes personalizada simplemente implementando los métodos toMessage () y FromMessage () de la interfaz MessageConverter .

Veamos un fragmento de código de muestra sobre la implementación de un MessageConverter personalizado ,

public class SampleMessageConverter implements MessageConverter { public Object fromMessage(Message message) throws JMSException, MessageConversionException { //... } public Message toMessage(Object object, Session session) throws JMSException, MessageConversionException { //... } }

7. Ejemplo de Spring JMS

En esta sección, veremos cómo usar un JmsTemplate para enviar y recibir mensajes.

El método predeterminado para enviar el mensaje es JmsTemplate.send () . Tiene dos parámetros clave de los cuales, el primer parámetro es el destino JMS y el segundo parámetro es una implementación de MessageCreator. El JmsTemplate utiliza el MessageCreator 's método de devolución de llamada createMessage () para construir el mensaje.

JmsTemplate.send () es bueno para enviar mensajes de texto sin formato, pero para enviar mensajes personalizados, JmsTemplate tiene otro método llamado c onvertAndSend () .

Podemos ver a continuación la implementación de estos métodos:

public class SampleJmsMessageSender { private JmsTemplate jmsTemplate; private Queue queue; // setters for jmsTemplate & queue public void simpleSend() { jmsTemplate.send(queue, s -> s.createTextMessage("hello queue world")); }
 public void sendMessage(Employee employee) { System.out.println("Jms Message Sender : " + employee); Map map = new HashMap(); map.put("name", employee.getName()); map.put("age", employee.getAge()); jmsTemplate.convertAndSend(map); } }

A continuación se muestra la clase de receptor de mensajes, la llamamos POJO controlado por mensajes (MDP). Podemos ver que la clase SampleListener está implementando la interfaz MessageListener y proporciona la implementación específica de texto para el método de interfaz onMessage ().

Además del método onMessage () , nuestra clase SampleListener también llamó a un método receiveAndConvert () para recibir mensajes personalizados:

public class SampleListener implements MessageListener { public JmsTemplate getJmsTemplate() { return getJmsTemplate(); } public void onMessage(Message message) { if (message instanceof TextMessage) { try { String msg = ((TextMessage) message).getText(); System.out.println("Message has been consumed : " + msg); } catch (JMSException ex) { throw new RuntimeException(ex); } } else { throw new IllegalArgumentException("Message Error"); } } public Employee receiveMessage() throws JMSException { Map map = (Map) getJmsTemplate().receiveAndConvert(); return new Employee((String) map.get("name"), (Integer) map.get("age")); } }

Vimos cómo implementar MessageListener y a continuación vemos la configuración en el contexto de la aplicación Spring:

DefaultMessageListenerContainer es el contenedor de escucha de mensajes predeterminado que Spring proporciona junto con muchos otros contenedores especializados.

8. Basic Configuration With Java Annotations

The @JmsListener is the only annotation required to convert a method of a normal bean into a JMS listener endpoint. Spring JMS provides many more annotations to ease the JMS implementation.

We can see some of the sample classes annotated below:

@JmsListener(destination = "myDestination") public void SampleJmsListenerMethod(Message order) { ... }

In order to add multiple listeners to a single method we just need to add multiple @JmsListener annotations.

We need to add the @EnableJms annotation to one of our configuration classes to support the @JmsListener annotated methods:

@Configuration @EnableJms public class AppConfig { @Bean public DefaultJmsListenerContainerFactory jmsListenerContainerFactory() { DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory(); factory.setConnectionFactory(connectionFactory()); return factory; } }

9. Error Handler

We can also configure a custom error handler for our message listener container.

Let's first implement the org.springframework.util.ErrorHandler interface:

@Service public class SampleJmsErrorHandler implements ErrorHandler { // ... logger @Override public void handleError(Throwable t) { LOG.warn("In default jms error handler..."); LOG.error("Error Message : {}", t.getMessage()); } }

Note that we have overridden the handleError() method, which simply logs the error message.

And then, we need to reference our error handler service in the DefaultJmsListenerConnectionFactory using the setErrorHandler() method:

@Bean public DefaultJmsListenerContainerFactorybjmsListenerContainerFactory() { DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory(); factory.setConnectionFactory(connectionFactory()); factory.setErrorHandler(sampleJmsErrorHandler); return factory; }

With this, our configured error handler will now catch any unhandled exceptions and log the message.

Optionally, we can also configure the error handler using the plain-old XML configurations by updating our appContext.xml:

10. Conclusion

In this tutorial, we discussed the configuration and basic concepts of Spring JMS. We also had a brief look at the Spring-specific JmsTemplate classes which are used for sending and receiving messages.

Puede encontrar la implementación del código en el proyecto GitHub.