Erste Schritte mit Spring JMS

1. Übersicht

Spring bietet ein JMS-Integrationsframework, das die Verwendung der JMS-API vereinfacht. Dieser Artikel stellt die grundlegenden Konzepte einer solchen Integration vor.

2. Maven-Abhängigkeit

Um Spring JMS in unserer Anwendung verwenden zu können, müssen wir der pom.xml die erforderlichen Artefakte hinzufügen :

 org.springframework spring-jms 4.3.3.RELEASE  

Die neueste Version des Artefakts finden Sie hier.

3. Die JmsTemplate

Die JmsTemplate- Klasse verwaltet das Erstellen und Freigeben von Ressourcen beim Senden oder synchronen Empfangen von Nachrichten.

Daher muss die Klasse, die diese JmsTemplate verwendet, nur Rückrufschnittstellen implementieren, wie in der Methodendefinition angegeben.

Ab Spring 4.1 basiert das JmsMessagingTemplate auf JmsTemplate , das eine Integration in die Messaging-Abstraktion bietet, dh org.springframework.messaging.Message. Dies ermöglicht es uns wiederum, eine Nachricht zu erstellen, die generisch gesendet werden soll.

4. Verbindungsverwaltung

Um eine Verbindung herzustellen und Nachrichten senden / empfangen zu können, müssen wir eine ConnectionFactory konfigurieren .

Eine ConnectionFactory ist eines der von JMS verwalteten Objekte, die von einem Administrator vorkonfiguriert wurden . Ein Client stellt mithilfe der Konfiguration die Verbindung zu einem JMS-Anbieter her.

Spring bietet zwei Arten von ConnectionFactory :

  • SingleConnectionFactory - ist eine Implementierung der ConnectionFactory- Schnittstelle, die bei allen createConnection () -Aufrufendieselbe Verbindung zurückgibt und Aufrufe zum Schließen ()ignoriert.
  • CachingConnectionFactory - erweitert die Funktionalität der SingleConnectionFactory und erweitert sie um ein Caching von Sitzungen , MessageProducers und MessageConsumers

5. Zielverwaltung

Wie oben erläutert , sind Ziele zusammen mit der ConnectionFactory auch von JMS verwaltete Objekte und können von einem JNDI gespeichert und abgerufen werden.

Spring bietet generische Resolver wie DynamicDestinationResolver und spezifische Resolver wie JndiDestinationResolver .

Das JmsTemplate delegiert die Auflösung des Zielnamens an eine der Implementierungen, die auf unserer Auswahl basieren .

Es wird auch eine Eigenschaft namens defaultDestination bereitgestellt , die bei Sende- und Empfangsvorgängen verwendet wird, die sich nicht auf ein bestimmtes Ziel beziehen.

6. Nachrichtenkonvertierung

Spring JMS wäre ohne die Unterstützung von Message Converters unvollständig.

Die Standardkonvertierungsstrategie, die von JmsTemplate sowohl für ConvertAndSend () - als auch für ReceiveAndConvert () -Operationen verwendet wird, ist die SimpleMessageConverter- Klasse.

Der SimpleMessageConverter kann TextMessages , BytesMessages , MapMessages und ObjectMessages verarbeiten . Diese Klasse implementiert die MessageConverter- Schnittstelle.

Neben SimpleMessageConverter bietet Spring JMS einige andere MessageConverter- Klassen wie MappingJackson2MessageConverter , MarshallingMessageConverter und MessagingMessageConverter .

Darüber hinaus können wir benutzerdefinierte Nachrichtenkonvertierungsfunktionen erstellen, indem wir einfach die Methoden toMessage () und FromMessage () der MessageConverter- Schnittstelle implementieren .

Sehen wir uns ein Beispielcode-Snippet zur Implementierung eines benutzerdefinierten MessageConverter an .

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

7. Beispielfeder JMS

In diesem Abschnitt erfahren Sie , wie Sie mit einer JmsTemplate Nachrichten senden und empfangen.

The default method for sending the message is JmsTemplate.send(). It has two key parameters of which, the first parameter is the JMS destination and the second parameter is an implementation of MessageCreator. The JmsTemplate uses the MessageCreator‘s callback method createMessage() for constructing the message.

JmsTemplate.send() is good for sending plain text messages but in order to send custom messages, JmsTemplate has another method called convertAndSend().

We can see below the implementation of these methods:

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

Below is the message receiver class, we call it as Message-Driven POJO (MDP). We can see that the class SampleListener is implementing the MessageListener interface and provides the text specific implementation for the interface method onMessage().

Apart from onMessage() method, our SampleListener class also called a method receiveAndConvert() for receiving custom messages:

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

We saw how to implement MessageListener and below we see the configuration in Spring application context:

DefaultMessageListenerContainer is the default message listener container Spring provides along with many other specialized containers.

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.

Sie finden die Code-Implementierung im GitHub-Projekt.