Introduzione a Spring JMS

1. Panoramica

Spring fornisce un framework di integrazione JMS che semplifica l'uso dell'API JMS. Questo articolo introduce i concetti di base di tale integrazione.

2. Dipendenza da Maven

Per poter utilizzare Spring JMS nella nostra applicazione, dobbiamo aggiungere gli artefatti necessari nel pom.xml :

 org.springframework spring-jms 4.3.3.RELEASE  

La versione più recente del manufatto può essere trovata qui.

3. JmsTemplate

La classe JmsTemplate gestisce la creazione e il rilascio di risorse durante l'invio o la ricezione sincrona di messaggi.

Quindi la classe che utilizza questo JmsTemplate deve solo implementare le interfacce di callback come specificato nella definizione del metodo.

A partire dalla Spring 4.1, JmsMessagingTemplate è costruito sopra JmsTemplate che fornisce un'integrazione con l'astrazione della messaggistica, cioè org.springframework.messaging.Message. Questo, a sua volta, ci permette di creare un messaggio da inviare in maniera generica.

4. Gestione della connessione

Per connettersi ed essere in grado di inviare / ricevere messaggi, è necessario configurare una ConnectionFactory .

Una ConnectionFactory è uno degli oggetti amministrati JMS preconfigurati da un amministratore . Un client con l'aiuto della configurazione effettuerà la connessione con un provider JMS.

Spring fornisce 2 tipi di ConnectionFactory :

  • SingleConnectionFactory - è un'implementazione dell'interfaccia ConnectionFactory , che restituirà la stessa connessione su tutte lechiamate createConnection () e ignorerà le chiamate a close ()
  • CachingConnectionFactory : estende la funzionalità di SingleConnectionFactory e la migliora con la memorizzazione nella cache di Sessioni , MessageProducers e MessageConsumers

5. Gestione della destinazione

Come discusso in precedenza, insieme a ConnectionFactory , le destinazioni sono anche oggetti amministrati da JMS e possono essere archiviate e richiamate da un JNDI.

Spring fornisce risolutori generici come DynamicDestinationResolver e risolutori specifici come JndiDestinationResolver .

Il JmsTemplate delegherà la risoluzione del nome di destinazione per una delle implementazioni basando sulla nostra selezione.

Fornirà anche una proprietà chiamata defaultDestination , che verrà utilizzata con le operazioni di invio e ricezione che non si riferiscono a una destinazione specifica.

6. Conversione dei messaggi

Spring JMS sarebbe incompleto senza il supporto dei convertitori di messaggi.

La strategia di conversione predefinita utilizzata da JmsTemplate per entrambe le operazioni ConvertAndSend () e ReceiveAndConvert () è la classe SimpleMessageConverter .

SimpleMessageConverter è in grado di gestire TextMessages , BytesMessages , MapMessages e ObjectMessage . Questa classe implementa l' interfaccia MessageConverter .

Oltre a SimpleMessageConverter , Spring JMS fornisce alcune altre classi MessageConverter predefinite come MappingJackson2MessageConverter , MarshallingMessageConverter , MessagingMessageConverter .

Inoltre, possiamo creare funzionalità di conversione dei messaggi personalizzate semplicemente implementando i metodi toMessage () e FromMessage () dell'interfaccia MessageConverter .

Vediamo uno snippet di codice di esempio sull'implementazione di un MessageConverter personalizzato ,

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

7. Esempio di Spring JMS

In questa sezione vedremo come utilizzare un JmsTemplate per inviare e ricevere messaggi.

Il metodo predefinito per inviare il messaggio è JmsTemplate.send () . Ha due parametri chiave di cui, il primo parametro è la destinazione JMS e il secondo parametro è un'implementazione di MessageCreator. JmsTemplate utilizza il metodo di callback di MessageCreator createMessage () per costruire il messaggio.

JmsTemplate.send () è utile per l'invio di messaggi di testo semplice ma per inviare messaggi personalizzati, JmsTemplate ha un altro metodo chiamato c onvertAndSend () .

Di seguito possiamo vedere l'implementazione di questi metodi:

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); } }

Di seguito è riportata la classe del destinatario del messaggio, che chiamiamo POJO guidato dai messaggi (MDP). Possiamo vedere che la classe SampleListener sta implementando l' interfaccia MessageListener e fornisce l'implementazione specifica del testo per il metodo di interfaccia onMessage ().

Oltre al metodo onMessage () , la nostra classe SampleListener ha anche chiamato un metodo receiveAndConvert () per ricevere messaggi personalizzati:

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")); } }

Abbiamo visto come implementare MessageListener e di seguito vediamo la configurazione nel contesto dell'applicazione Spring:

DefaultMessageListenerContainer è il contenitore di listener di messaggi predefinito che Spring fornisce insieme a molti altri contenitori specializzati.

8. Configurazione di base con annotazioni Java

Il @JmsListener è l'unica annotazione richiesta per convertire un metodo di un bean normale in un ascoltatore endpoint JMS. Spring JMS fornisce molte altre annotazioni per facilitare l'implementazione di JMS.

Possiamo vedere alcune delle classi di esempio annotate di seguito:

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

Per aggiungere più listener a un singolo metodo, è sufficiente aggiungere più annotazioni @JmsListener .

Dobbiamo aggiungere l' annotazione @EnableJms a una delle nostre classi di configurazione per supportare i metodi annotati @JmsListener :

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

9. Gestore degli errori

Possiamo anche configurare un gestore di errori personalizzato per il nostro contenitore di listener di messaggi.

Per prima cosa implementiamo l' interfaccia org.springframework.util.ErrorHandler :

@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.

Puoi trovare l'implementazione del codice nel progetto GitHub.