Erste Schritte mit Spring JMS

Erste Schritte mit Spring JMS

1. Überblick

Spring bietet ein JMS-Integrationsframework, das die Verwendung der JMS-API vereinfacht. Dieser Artikel führt in die grundlegenden Konzepte einer solchen Integration ein.

2. Maven-Abhängigkeit

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


    org.springframework
    spring-jms
    4.3.3.RELEASE

Die neueste Version des Artefakts kannfound here sein.

3. DieJmsTemplate

Die KlasseJmsTemplateübernimmt das Erstellen und Freigeben von Ressourcen beim Senden oder synchronen Empfangen von Nachrichten.

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

Ab Spring 4.1 wirdJmsMessagingTemplate aufJmsTemplate aufgebaut, was eine Integration in die Messaging-Abstraktion ermöglicht, dhorg.springframework.messaging.Message.. Auf diese Weise können wir wiederum eine zu sendende Nachricht erstellen in einer generischen Weise.

4. Verbindungsmanagement

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

A ConnectionFactory is one of the JMS administered objects which are preconfigured by an administrator. Ein Client stellt mit Hilfe der Konfiguration die Verbindung zu einem JMS-Provider her.

Die Feder bietet zwei Arten vonConnectionFactory:

  • SingleConnectionFactory – ist eine Implementierung derConnectionFactory-Schnittstelle, die bei allencreateConnection () -Aufrufen dieselbe Verbindung zurückgibt und Aufrufe anclose () ignoriert.

  • CachingConnectionFactory erweitert die Funktionalität vonSingleConnectionFactory und fügt sie mit einem Caching vonSessions,MessageProducers undMessageConsumers hinzu

5. Zielverwaltung

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

Spring bietet generische Resolver wieDynamicDestinationResolver und spezifische Resolver wieJndiDestinationResolver.

DieJmsTemplate delegieren die Auflösung des Zielnamens an eine der Implementierungen, die auf unserer Auswahl basieren.

Es wird auch eine Eigenschaft namensdefaultDestination bereitgestellt, die mitsend- undreceive-Operationen verwendet wird, die sich nicht auf ein bestimmtes Ziel beziehen.

6. Nachrichtenkonvertierung

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

Die Standardkonvertierungsstrategie, die vonJmsTemplate sowohl fürConvertAndSend() als auch fürReceiveAndConvert() verwendet wird, ist dieSimpleMessageConverter-Klasse.

The SimpleMessageConverter kannTextMessages,BytesMessages,MapMessages undObjectMessages verarbeiten. Diese Klasse implementiert dieMessageConverter-Schnittstelle.

Abgesehen vonSimpleMessageConverter bietet Spring JMS einige andereMessageConverter-Klassen wieMappingJackson2MessageConverter,MarshallingMessageConverter,MessagingMessageConverter.

Darüber hinaus können wir benutzerdefinierte Nachrichtenkonvertierungsfunktionen erstellen, indem wir einfach die MethodentoMessage() undFromMessage()der SchnittstelleMessageConverterimplementieren.

Lassen Sie uns ein Beispielcode-Snippet zur Implementierung eines benutzerdefiniertenMessageConverter sehen.

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 mitJmsTemplate Nachrichten senden und empfangen.

Die Standardmethode zum Senden der Nachricht istJmsTemplate.send(). Es hat zwei Schlüsselparameter, von denen der erste Parameter das JMS-Ziel und der zweite Parameter eine Implementierung vonMessageCreator. The JmsTemplateist. Er verwendet die RückrufmethodecreateMessage()vonMessageCreatorzum Erstellen der Nachricht.

JmsTemplate.send() eignet sich zum Senden von Nur-Text-Nachrichten. Um benutzerdefinierte Nachrichten zu senden, verfügtJmsTemplate über eine andere Methode namens convertAndSend().

Nachfolgend sehen wir die Implementierung dieser Methoden:

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

Nachfolgend finden Sie die Nachrichtenempfängerklasse, die wir als Message-Driven POJO (MDP) bezeichnen. We can see that the class SampleListener is implementing the MessageListener interface and provides the text specific implementation for the interface method onMessage().

Abgesehen von der MethodeonMessage()wird unsere KlasseSampleListenerauch als MethodereceiveAndConvert() bezeichnet, um benutzerdefinierte Nachrichten zu empfangen:

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

Wir haben gesehen, wieMessageListener implementiert werden, und unten sehen wir die Konfiguration im Kontext der Spring-Anwendung:




    
    
    

DefaultMessageListenerContainer ist der Standard-Nachrichten-Listener-Container, den Spring zusammen mit vielen anderen spezialisierten Containern bereitstellt.

8. Grundkonfiguration mit Java Annotations

The @JmsListener is the only annotation required to convert a method of a normal bean into a JMS listener endpoint. Spring JMS bietet viel mehr Anmerkungen, um die JMS-Implementierung zu vereinfachen.

Wir können einige der unten angegebenen Beispielklassen sehen:

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

Um einer einzelnen Methode mehrere Listener hinzuzufügen, müssen nur mehrere@JmsListener-Anmerkungen hinzugefügt werden.

Wir müssen die Annotation@EnableJmszu einer unserer Konfigurationsklassen hinzufügen, um die annotierten Methoden von@JmsListenerzu unterstützen:

@Configuration
@EnableJms
public class AppConfig {

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

9. Fehlerbehandler

Wir können auch einen benutzerdefinierten Fehlerhandler für unseren Nachrichtenlistener-Container konfigurieren.

Implementieren wir zuerst dieorg.springframework.util.ErrorHandler-Schnittstelle:

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

}

Beachten Sie, dass wir die MethodehandleError()überschrieben haben, die einfach die Fehlermeldung protokolliert.

Und dann müssen wir unseren Fehlerbehandlungsdienst inDefaultJmsListenerConnectionFactory mit der MethodesetErrorHandler() referenzieren:

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

Damit erkennt unser konfigurierter Fehlerbehandler jetzt alle nicht behandelten Ausnahmen und protokolliert die Nachricht.

Optional können wir den Fehlerhandler auch mithilfe der einfachen alten XML-Konfigurationen konfigurieren, indem wir unsereappContext.xml: aktualisieren




    
    
    
    

10. Fazit

In diesem Tutorial haben wir die Konfiguration und die grundlegenden Konzepte von Spring JMS erläutert. Wir haben uns auch kurz die spring-spezifischenJmsTemplate-Klassen angesehen, die zum Senden und Empfangen von Nachrichten verwendet werden.

Sie finden die Code-Implementierung inGitHub project.