Premiers pas avec Spring JMS
1. Vue d'ensemble
Spring fournit une infrastructure d’intégration JMS qui simplifie l’utilisation de l’API JMS. Cet article présente les concepts de base d’une telle intégration.
2. Dépendance Maven
Afin d'utiliser Spring JMS dans notre application, nous devons ajouter les artefacts nécessaires dans lespom.xml:
org.springframework
spring-jms
4.3.3.RELEASE
La dernière version de l'artefact peut êtrefound here.
3. LesJmsTemplate
La classeJmsTemplate gère la création et la libération des ressources lors de l'envoi ou de la réception synchrone de messages.
Par conséquent, la classe qui utilise ceJmsTemplate n'a besoin que d'implémenter des interfaces de rappel comme spécifié dans la définition de la méthode.
À partir de Spring 4.1, leJmsMessagingTemplate est construit au-dessus deJmsTemplate qui fournit une intégration avec l'abstraction de la messagerie, c'est-à-direorg.springframework.messaging.Message. Ceci, à son tour, nous permet de créer un message à envoyer de manière générique.
4. Gestion des connexions
Pour nous connecter et pouvoir envoyer / recevoir des messages, nous devons configurer unConnectionFactory.
A ConnectionFactory is one of the JMS administered objects which are preconfigured by an administrator. Un client à l'aide de la configuration établira la connexion avec un fournisseur JMS.
Spring fournit 2 types deConnectionFactory:
-
SingleConnectionFactory – est une implémentation de l'interfaceConnectionFactory, qui retournera la même connexion sur tous les appelscreateConnection () et ignorera les appels àclose ()
-
CachingConnectionFactory – étend la fonctionnalité duSingleConnectionFactory et l'ajoute l'améliore avec une mise en cache deSessions,MessageProducers etMessageConsumers
5. Gestion des destinations
Comme indiqué ci-dessus, avec lesConnectionFactory, les destinations sont également des objets administrés par JMS et peuvent être stockées et récupérées à partir d'un JNDI.
Spring fournit des résolveurs génériques tels queDynamicDestinationResolver et des résolveurs spécifiques tels queJndiDestinationResolver.
LesJmsTemplate délégueront la résolution du nom de destination à l'une des implémentations en fonction de notre sélection.
Il fournira également une propriété appeléedefaultDestination - qui sera utilisée avec les opérationssend etreceive qui ne font pas référence à une destination spécifique.
6. Conversion de message
Spring JMS serait incomplet sans le support des convertisseurs de messages.
La stratégie de conversion par défaut utilisée parJmsTemplate pour les opérationsConvertAndSend() etReceiveAndConvert() est la classeSimpleMessageConverter.
The SimpleMessageConverter est capable de gérerTextMessages,BytesMessages,MapMessages etObjectMessages. Cette classe implémente l'interfaceMessageConverter.
En dehors deSimpleMessageConverter, Spring JMS fournit d'autres classesMessageConverter prêtes à l'emploi commeMappingJackson2MessageConverter,MarshallingMessageConverter,MessagingMessageConverter.
De plus, nous pouvons créer une fonctionnalité de conversion de message personnalisée simplement en implémentant les méthodestoMessage() etFromMessage() de l'interfaceMessageConverter.
Voyons un exemple d'extrait de code sur l'implémentation d'unMessageConverter personnalisé,
public class SampleMessageConverter implements MessageConverter {
public Object fromMessage(Message message)
throws JMSException, MessageConversionException {
//...
}
public Message toMessage(Object object, Session session)
throws JMSException, MessageConversionException {
//...
}
}
7. Exemple de JMS Spring
Dans cette section, nous verrons comment utiliser unJmsTemplate pour envoyer et recevoir des messages.
La méthode par défaut pour envoyer le message estJmsTemplate.send(). Il a deux paramètres clés dont, le premier paramètre est la destination JMS et le second paramètre est une implémentation deMessageCreator. The JmsTemplate utilise la méthode de rappel deMessageCreatorcreateMessage() pour construire le message.
JmsTemplate.send() est bon pour envoyer des messages en texte brut, mais pour envoyer des messages personnalisés,JmsTemplate a une autre méthode appelée convertAndSend().
Nous pouvons voir ci-dessous la mise en œuvre de ces méthodes:
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);
}
}
Ci-dessous la classe de récepteur de message, nous l'appelons comme POJO (MDP) Message-Driven. We can see that the class SampleListener is implementing the MessageListener interface and provides the text specific implementation for the interface method onMessage().
Outre la méthodeonMessage(), notre classeSampleListener a également appelé une méthodereceiveAndConvert() pour recevoir des messages personnalisés:
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"));
}
}
Nous avons vu comment implémenterMessageListener et ci-dessous, nous voyons la configuration dans le contexte de l'application Spring:
DefaultMessageListenerContainer est le conteneur d'écoute de messages par défaut que Spring fournit avec de nombreux autres conteneurs spécialisés.
8. Configuration de base avec annotations Java
The @JmsListener is the only annotation required to convert a method of a normal bean into a JMS listener endpoint. Spring JMS fournit beaucoup plus d'annotations pour faciliter l'implémentation JMS.
Nous pouvons voir quelques exemples de classes annotées ci-dessous:
@JmsListener(destination = "myDestination")
public void SampleJmsListenerMethod(Message order) { ... }
Afin d'ajouter plusieurs écouteurs à une seule méthode, nous devons simplement ajouter plusieurs annotations@JmsListener.
Nous devons ajouter l'annotation@EnableJms à l'une de nos classes de configuration pour prendre en charge les méthodes annotées@JmsListener:
@Configuration
@EnableJms
public class AppConfig {
@Bean
public DefaultJmsListenerContainerFactory jmsListenerContainerFactory() {
DefaultJmsListenerContainerFactory factory
= new DefaultJmsListenerContainerFactory();
factory.setConnectionFactory(connectionFactory());
return factory;
}
}
9. Gestionnaire d'erreur
Nous pouvons également configurer un gestionnaire d’erreurs personnalisé pour notre conteneur d’écoute de messages.
Commençons par implémenter l’interfaceorg.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());
}
}
Notez que nous avons remplacé la méthodehandleError(), qui enregistre simplement le message d'erreur.
Et puis, nous devons référencer notre service de gestionnaire d'erreurs dans leDefaultJmsListenerConnectionFactory en utilisant la méthodesetErrorHandler():
@Bean
public DefaultJmsListenerContainerFactorybjmsListenerContainerFactory() {
DefaultJmsListenerContainerFactory factory
= new DefaultJmsListenerContainerFactory();
factory.setConnectionFactory(connectionFactory());
factory.setErrorHandler(sampleJmsErrorHandler);
return factory;
}
Avec cela, notre gestionnaire d'erreurs configuré interceptera désormais toutes les exceptions non gérées et enregistrera le message.
En option, nous pouvons également configurer le gestionnaire d'erreurs en utilisant les anciennes configurations XML en mettant à jour nosappContext.xml:
10. Conclusion
Dans ce didacticiel, nous avons abordé la configuration et les concepts de base de Spring JMS. Nous avons également examiné brièvement les classesJmsTemplate spécifiques à Spring qui sont utilisées pour envoyer et recevoir des messages.
Vous pouvez trouver l'implémentation du code dans lesGitHub project.