Spring Remoting avec JMS et ActiveMQ

Spring Remoting avec JMS et ActiveMQ

1. Vue d'ensemble

Nous avons vu dans unprevious article commentSpring Remoting pouvait être utilisé pour fournirRPC au-dessus d'un canal asynchrone en tant que file d'attenteAMQP. Cependant, nous pouvons également obtenir le même résultat en utilisantJMS.

Dans cet article, nous allons en fait explorer comment configurer l'appel à distance en utilisantSpring Remoting JMS etApache ActiveMQ comme middleware de messagerie.

2. Démarrage d'un courtier Apache ActiveMQ

Apache ActiveMQ est unopen source message broker qui permet aux applications d'échanger des informations de manière asynchrone, et il est entièrement compatible avec lesJava Message ServiceAPI.

Pour exécuter notre expérience, nous devons d'abord configurer une instance en cours d'exécution deActiveMQ. On peut choisir parmi plusieurs manières: en suivant les étapes décrites dans leofficial guide, en l'incorporant dans une applicationJava ou plus simplement en faisant tourner un conteneurDocker avec la commande suivante:

docker run -p 61616:61616 -p 8161:8161 rmohr/activemq:5.14.3

Cela démarrera un conteneurActiveMQ qui expose sur le port 8081 une interface graphique Web d'administration simple, à travers laquelle nous pouvons vérifier les files d'attente disponibles, les clients connectés et d'autres informations administratives. Les clients deJMS devront utiliser le port 61616 pour se connecter au courtier et échanger des messages à la place.

3. Dépendances Maven

Comme dans les articles précédents couvrantSpring Remoting, nous allons mettre en place un serveur et une application clientSpring Boot pour montrer comment fonctionneJMS Remoting.

Comme d'habitude, nous choisissons soigneusement les dépendances de démarrage deSpring Boot,as explained here:


    org.springframework.boot
    spring-boot-starter-activemq
    
        
            org.springframework.boot
            spring-boot-starter-tomcat
        
    

Nous avons explicitement exclu lesspring-boot-starter-tomcat afin de ne pas avoir les fichiers.jar liés àTomcat dans le chemin de classe.

Ceci, à son tour, empêchera le mécanisme d'autoconfiguration deSpring Boot de lancer un serveur Web intégré au démarrage de l'application car nous n'en avons pas besoin.

4. Application serveur

4.1. Exposez le service

Nous allons configurer une application serveur qui expose lesCabBookingService que les clients pourront appeler.

The first step is to declare a bean that implements the interface of the service we want to expose to the clients. C'est le bean qui exécutera la logique métier sur le serveur:

@Bean
CabBookingService bookingService() {
    return new CabBookingServiceImpl();
}

Définissons ensuite la file d’attente à partir de laquelle le serveur récupérera les appels, en spécifiant son nom dans le constructeur:

@Bean
Queue queue() {
    return new ActiveMQQueue("remotingQueue");
}

Comme nous le savons déjà dans les articles précédents,one of the main concepts of Spring Remoting is the Service Exporter, the component that collects the invocation requests from some source, dans ce cas, une file d'attenteApacheMQ ─ et invoque la méthode souhaitée sur l'implémentation du service.

Pour travailler avecJMS, nous définissons unJmsInvokerServiceExporter:

@Bean
JmsInvokerServiceExporter exporter(CabBookingService implementation) {
    JmsInvokerServiceExporter exporter = new JmsInvokerServiceExporter();
    exporter.setServiceInterface(CabBookingService.class);
    exporter.setService(implementation);
    return exporter;
}

Enfin, nous devons définir un auditeur ayant la responsabilité de consommer des messages. Lelistener acts as a bridge between ApacheMQ and the*JmsInvokerServiceExporter*, il écoute les messages d'appel disponibles dans la file d'attente, transmet l'appel à l'exportateur de service et sérialise les résultats:

@Bean SimpleMessageListenerContainer listener(
  ConnectionFactory factory,
  JmsInvokerServiceExporter exporter) {

    SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
    container.setConnectionFactory(factory);
    container.setDestinationName("remotingQueue");
    container.setConcurrentConsumers(1);
    container.setMessageListener(exporter);
    return container;
}

4.2. Configuration

Souvenons-nous de configurer le fichierapplication.properties pour permettre àSpring Boot de configurer certains objets de base, comme par exemple lesConnectionFactory nécessaires à l’auditeur. Les valeurs des différents paramètres dépendent principalement de la manière dont

Les valeurs des différents paramètres dépendent principalement de la façon dontApacheMQ a été installé, et la configuration suivante est une configuration raisonnable pour notre conteneurDocker fonctionnant sur la même machine où nous allons exécuter ces exemples:

spring.activemq.broker-url=tcp://localhost:61616
spring.activemq.packages.trusted=org.springframework.remoting.support,java.lang,com.example.api

Le paramètrespring.activemq.broker-url est une référence au portAMQ. Une explication plus approfondie est nécessaire pourspring.activemq.packages.trusted parameter à la place. Depuis la version 5.12.2, ActiveMQ refuse par défaut tout message de type

A partir de la version 5.12.2 ActiveMQ refuse par défaut tout message de typeObjectMessage, utilisé pour échanger un objetJava sérialisé car il est considéré comme un vecteur potentiel d'attaque de sécurité dans certains contextes.

Quoi qu'il en soit, il est possible de demander àAMQ d'accepter les objets sérialisés dans les packages spécifiés. org.springframework.remoting.support est le package qui contient les principaux messages qui représentent l'appel d'une méthode distante et son résultat. Le paquet

Le packagecom.example.api contient les paramètres et les résultats de notre service. java.lang est ajouté car l'objet qui représente le résultat de la réservation de cabine fait référence à unString, nous devons donc le sérialiser également.

5. Application client

5.1. Appeler le service distant

Attaquons-nous maintenant au client. Encore une fois, nous devons définir la file d'attente dans laquelle les messages d'appel seront écrits. Nous devons vérifier que le client et le serveur utilisent le même nom.

@Bean
Queue queue() {
    return new ActiveMQQueue("remotingQueue");
}

Nous devons ensuite mettre en place un exportateur:

@Bean
FactoryBean invoker(ConnectionFactory factory, Queue queue) {
    JmsInvokerProxyFactoryBean factoryBean = new JmsInvokerProxyFactoryBean();
    factoryBean.setConnectionFactory(factory);
    factoryBean.setServiceInterface(CabBookingService.class);
    factoryBean.setQueue(queue);
    return factoryBean;
}

Nous pouvons maintenant utiliser le service distant comme s'il était déclaré comme un bean local:

CabBookingService service = context.getBean(CabBookingService.class);
out.println(service.bookRide("13 Seagate Blvd, Key Largo, FL 33037"));

5.2. Exécutez l'exemple

Aussi pour l'application cliente, nous devons choisir correctement les valeurs dans le fichier.properties de l'application. Dans une configuration commune, ceux-ci correspondraient exactement à ceux utilisés côté serveur.

Cela devrait être suffisant pour démontrer l'invocation à distance viaApache AMQ. Commençons donc par démarrerApacheMQ, puis l’application serveur et enfin l’application cliente qui appellera le service distant.

6. Conclusion

Dans ce rapide tutoriel, nous avons vu comment nous pourrions utiliserSpring Remoting pour fournirRPC au-dessus d'un systèmeJMS en tant queAMQ.

Spring Remoting continue de démontrer à quel point il est facile de configurer rapidement un appel asynchrone quel que soit le canal sous-jacent.

Comme d'habitude, vous trouverez les sourcesover on GitHub.