Apache Camel - Guide rapide

Prenons une situation où une grande épicerie en ligne de votre ville, comme le Bigbasket en Inde, vous invite à concevoir une solution informatique pour elle. La solution stable et évolutive les aidera à surmonter les problèmes de maintenance logicielle auxquels ils sont confrontés aujourd'hui. Cette boutique en ligne mène ses activités depuis une dizaine d'années. Le magasin accepte les commandes en ligne de différentes catégories de produits de ses clients et les distribue aux fournisseurs respectifs. Par exemple, supposons que vous commandiez des savons, de l'huile et du lait; ces trois articles seront distribués aux trois fournisseurs respectifs. Les trois fournisseurs enverront ensuite leurs fournitures à un point de distribution commun d'où l'intégralité de la commande sera exécutée par le centre de livraison. Voyons maintenant le problème auquel ils sont confrontés aujourd'hui.

Lorsque ce magasin a démarré ses activités, il acceptait les commandes dans un fichier texte en clair séparées par des virgules. Au fil du temps, le magasin est passé au placement de commande basé sur les messages. Plus tard, un développeur de logiciels a suggéré un placement de commande basé sur XML. Finalement, le magasin a même adapté une interface de service Web. Maintenant, voici le vrai problème. Les commandes se présentent désormais sous différents formats. Evidemment, à chaque fois que l'entreprise a mis à niveau le format d'acceptation de commande, elle ne voulait pas casser l'interface précédemment déployée pour ne pas créer de confusion dans l'esprit du client.

Dans le même temps, alors que l'entreprise continuait de croître, le magasin ajoutait périodiquement de nouveaux fournisseurs à son répertoire. Chacun de ces fournisseurs avait son propre protocole d'acceptation des commandes. Une fois de plus, nous sommes confrontés au problème de l'intégration; notre architecture d'application doit être évolutive pour accueillir les nouveaux fournisseurs avec leur mécanisme unique de placement de commande.

La situation entière est illustrée dans la figure suivante -

Voyons maintenant comment Apache Camel peut venir à votre secours pour fournir une architecture de solution élégante, maintenable et évolutive pour le scénario décrit.

Avant de procéder à la solution, nous devons faire une petite hypothèse. Pour toutes les discussions de ce tutoriel, nous supposerons que les commandes en ligne sont passées au format XML. Un format typique du fichier de commande que nous utiliserons tout au long de nos discussions est présenté ici -

<?xml version = "1.0" encoding = "UTF-8"?>
<OrderID Order = "001">
   <order product = "soaps">
      <items>
         <item>
            <Brand>Cinthol</Brand>
            <Type>Original</Type>
            <Quantity>4</Quantity>
            <Price>25</Price>
         </item>
         <item>
            <Brand>Cinthol</Brand>
            <Type>Lime</Type>
            <Quantity>6</Quantity>
            <Price>30</Price>
         </item>
      </items>
   </order>
   
   <order product = "Oil">
      <items>
         <item>
            <Brand>Saffola</Brand>
            <Type>Gold</Type>
            <Quantity>2</Quantity>
            <Price>649</Price>
         </item>
         <item>
            <Brand>Fortune</Brand>
            <Type>Sunlite</Type>
            <Quantity>1</Quantity>
            <Price>525</Price>
         </item>
      </items>
   </order>
   
   <order product = "Milk">
      <items>
         <item>
            <Product>Milk</Product>
            <Brand>Amul</Brand>
            <Type>Pure</Type>
            <Quantity>2</Quantity>
            <Price>60</Price>
         </item>
      </items>
   </order>
</OrderID>

Nous utiliserons le modèle XML ci-dessus pour illustrer les exemples Camel de ce didacticiel.

Camel est une boîte noire qui reçoit les messages d'un point final et les envoie à un autre. Dans la boîte noire, les messages peuvent être traités ou simplement redirigés.

Alors pourquoi avoir un cadre pour cela? Dans les situations pratiques, comme le montre l'étude de cas d'introduction, il peut y avoir de nombreux expéditeurs et de nombreux récepteurs, chacun suivant son propre protocole tel que ftp, http et jms. Le système peut exiger de nombreuses règles complexes telles que le message de l'expéditeur A doit être livré uniquement à B & C. Dans certaines situations, vous devrez peut-être traduire le message dans un autre format que le destinataire attend. Cette traduction peut être soumise à certaines conditions en fonction du contenu du message. Donc, essentiellement, vous devrez peut-être traduire entre les protocoles, coller les composants ensemble, définir des règles de routage et fournir un filtrage basé sur le contenu des messages. Ceci est illustré dans la figure suivante -

Pour répondre aux exigences ci-dessus et concevoir une architecture logicielle appropriée pour de nombreuses situations de ce type, les modèles d'intégration d'entreprise ( EIP ) ont été documentés par Gregor Hohpe et Bobby Woolf en 2003. Apache Camel fournit la mise en œuvre de ces modèles et le but de ce tutoriel est d'enseigner vous comment utiliser Camel dans des situations comme celle décrite dans l'introduction.

Apache Camel est un framework open source. Il s'agit d'un middleware orienté message qui fournit un moteur de routage et de médiation basé sur des règles. Vous pouvez définir des règles telles que s'il s'agit d'une commande «lait», la rediriger vers un vendeur de lait et s'il s'agit d'une commande «huile», la rediriger vers un vendeur d'huile, etc. En utilisant Camel, vous pourrez implémenter ces règles et effectuer le routage dans un code Java familier. Cela signifie que vous pouvez utiliser votre IDE Java familier pour définir ces règles dans un environnement de type sécurisé. Nous n'avons pas besoin d'utiliser des fichiers de configuration XML, qui ont généralement tendance à être volumineux. Camel prend en charge la configuration XML via Spring Framework, si vous préférez utiliser XML pour configurer les règles. Vous pouvez même utiliser des fichiers de configuration XML Blueprint et même un DSL Scala, si vous êtes un amoureux de Scala. Cela signifie également que vous pouvez utiliser votre Java préféré, votre IDE Scala ou même un simple éditeur XML pour configurer les règles.

L'entrée de ce moteur peut être un fichier texte délimité par des virgules, un POJO (Plain Old Java Object), XML sont l'un des nombreux autres formats pris en charge par Camel. De même, la sortie du moteur peut être redirigée vers un fichier, une file d'attente de messages ou même votre écran de contrôle pour vous permettre de visualiser les commandes envoyées aux fournisseurs respectifs. Ceux-ci sont appelés les points de terminaison et Camel prend en charge le modèle EIP de point de terminaison de message . Les points de terminaison Camel sont abordés plus loin dans le chapitre Points de terminaison.

Camel est généralement utilisé avec Apache ServiceMix , Apache ActiveMQ et Apache CXF pour implémenter des architectures orientées services.

Après avoir vu un aperçu d'Apache Camel, passons maintenant à ses fonctionnalités pour voir ce qu'il offre. Nous savons déjà qu'Apache Camel est un framework Java open source qui fournit essentiellement une implémentation de divers EIP. Camel facilite l'intégration en fournissant une connectivité à une très grande variété de transports et d'API. Par exemple, vous pouvez facilement acheminer JMS vers JSON, JSON vers JMS, HTTP vers JMS, FTP vers JMS, même HTTP vers HTTP, et la connectivité aux microservices. Vous devez simplement fournir des points de terminaison appropriés aux deux extrémités. Camel est extensible et donc à l'avenir, plus de points de terminaison peuvent être ajoutés facilement au framework.

Pour câbler les EIP et les transports ensemble, vous utilisez des langages spécifiques au domaine (DSL) tels que Java, Scala et Groovy. Une règle de routage Java typique peut ressembler à -

from ("file:/order").to("jms:orderQueue");

Cette règle de routage charge les fichiers du order répertoire, crée un message JMS avec le contenu du fichier et envoie ce message à une file d'attente appelée orderQueue.

Voici quelques-unes des fonctionnalités les plus importantes de Camel qui vous seraient utiles pour développer des applications Camel -

  • Camel prend en charge les formats de données enfichables et les convertisseurs de type pour de telles transformations de messages, de sorte que de nouveaux formats et convertisseurs peuvent être ajoutés à l'avenir. Actuellement, il prend en charge plusieurs formats et convertisseurs populaires; pour n'en nommer que quelques-uns - CSV, EDI, JAXB, JSON, XmlBeans, XStream, Flatpack, Zip.

  • Camel prend en charge les langages enfichables pour écrire des prédicats en DSL. Certains des langages pris en charge incluent JavaScript, Groovy, Python, PHP, Ruby, SQL, XPath, XQuery.

  • Camel prend en charge le modèle POJO afin que vous puissiez brancher des Javabeans à différents endroits.

  • Camel facilite les tests de ces grands systèmes distribués et asynchrones en utilisant la messagerie.

Comprenons maintenant l'architecture de Camel et voyons comment les différentes fonctionnalités sont implémentées.

L'architecture Camel se compose de trois composants: moteur d'intégration et routeur, processeurs et composants. Ceci est illustré dans la figure suivante -

Le noyau Camel lui-même est très petit et contient 13 composants essentiels. Les 80 autres composants sont en dehors du noyau. Cela aide à maintenir une faible dépendance à l'endroit où il est déployé et favorise les extensions à l'avenir. leComponents module fournit un Endpointinterface avec le monde extérieur. Les points de terminaison sont spécifiés par des URI, tels quefile:/order et jms:orderQueue que vous avez vu dans le dernier chapitre.

le ProcessorsLe module est utilisé pour la manipulation et la médiation des messages entre les points de terminaison. Les EIP que j'ai mentionnés précédemment sont implémentés dans ce module. Il prend actuellement en charge plus de 40 modèles tels que documentés dans le livre EIP et d'autres unités de traitement utiles.

le Processors et Endpoints sont câblés ensemble dans Integration Engine and Routermodule utilisant des DSL. Lors de leur câblage, vous pouvez utiliser des filtres pour filtrer les messages en fonction de critères définis par l'utilisateur. Comme mentionné précédemment, vous avez plusieurs options pour rédiger ces règles. Vous pouvez utiliser Java, Scala, Groovy ou même XML pour cela.

Maintenant, nous arrivons au composant le plus important de Camel, qui peut être considéré comme le noyau - le CamelContext.

CamelContext donne accès à tous les autres services de Camel comme indiqué dans la figure suivante -

Regardons les différents services. leRegistrymodule par défaut est un registre JNDI, qui contient le nom des différents Javabeans que votre application utilise. Si vous utilisez Camel avec Spring, ce sera le printempsApplicationContext. Si vous utilisez Camel dans un conteneur OSGI, ce seraOSGI registry. leType converterscomme son nom l'indique, contient les différents convertisseurs de type chargés, qui convertissent votre entrée d'un format à un autre. Vous pouvez utiliser les convertisseurs de type intégrés ou fournir votre propre mécanisme de conversion. leComponentsmodule contient les composants utilisés par votre application. Les composants sont chargés par détection automatique sur leclasspathque vous spécifiez. Dans le cas du conteneur OSGI, ceux-ci sont chargés chaque fois qu'un nouveau bundle est activé. Nous avons déjà discuté de laEndpoints et Routesdans les chapitres précédents. leData formats module contient les formats de données chargés et enfin le Languages module représente les langues chargées.

L'extrait de code ici vous donnera un aperçu de la façon dont un CamelContext est créé dans une application Camel -

CamelContext context = new DefaultCamelContext();
try {
   context.addRoutes(new RouteBuilder() {
      // Configure filters and routes
   }
}
);

le DefaultCamelContext class fournit une implémentation concrète de CamelContext. DansaddRoutes méthode, nous créons une instance anonyme de RouteBuilder. Vous pouvez créer plusieursRouteBuilderinstances pour définir plus d'un routage. Chaque route dans le même contexte doit avoir un ID unique. Les itinéraires peuvent être ajoutés dynamiquement au moment de l'exécution. Un itinéraire avec le même ID que celui précédemment défini remplacera l'ancien itinéraire.

Ce qui se passe à l'intérieur RouteBuilder l'instance est décrite ci-après.

Itinéraires

Le routeur définit la règle de déplacement du message from à un toemplacement. Tu utilisesRouteBuilderpour définir une route dans Java DSL. Vous créez un itinéraire en étendant leRouteBuilderclasse. L'itinéraire commence par unfrompoint final et se termine à un ou plusieurs points finaux. Entre les deux, vous implémentez la logique de traitement. Vous pouvez configurer n'importe quel nombre d'itinéraires dans un mêmeconfigure méthode.

Voici un exemple typique de la façon dont l'itinéraire est créé -

context.addRoutes(new RouteBuilder() {
   @Override
   public void configure() throws Exception {
      from("direct:DistributeOrderDSL")
      .to("stream:out");
   }
}

Nous remplaçons la méthode de configuration de RouteBuilderclasse et implémentez notre mécanisme de routage et de filtrage. Dans le cas actuel, nous redirigeons les entrées reçues du EndpointDistributeOrderDSL à la console, qui est spécifiée par le point de terminaison stream:out.

Choix de la langue

Vous pouvez créer les itinéraires dans différentes langues. Voici quelques exemples de la façon dont le même itinéraire est défini dans trois langues différentes -

Java DSL

from ("file:/order").to("jms:orderQueue");

DSL de printemps

<route>
   <from uri = "file:/order"/>
   <to uri = "jms:orderQueue"/>
</route>

Scala DSL

from "file:/order" -> "jms:orderQueue"

Filtres

Vous utilisez le filtre pour sélectionner une partie du contenu d'entrée. Pour configurer un filtre, vous utilisez n'importe quelle implémentation arbitraire de Predicate . L'entrée filtrée est ensuite envoyée à votre point de terminaison de destination souhaité. Dans cet exemple, nous filtrons toutes les commandes de savon afin que celles-ci puissent être envoyées collectivement à un fournisseur de savon.

from("direct:DistributeOrderDSL")
   .split(xpath("//order[@product = 'soaps']/items"))
      .to("stream:out");

Dans l'exemple, nous avons utilisé xpathprédicat pour le filtrage. Si vous préférez utiliser la classe Java pour le filtrage, utilisez le code suivant -

from("direct:DistributeOrderDSL")
   .filter()
      .method(new Order(),"filter")
         .to("stream:out");

le Order est votre classe Java personnalisée avec votre propre mécanisme de filtrage.

Vous pouvez combiner plusieurs prédicats dans un seul routage comme ici -

from("direct:DistributeOrderDSL")
   .choice()
      .when(header("order").isEqualTo("oil"))
         .to("direct:oil")
      .when(header("order").isEqualTo("milk"))
         .to("direct:milk")
      .otherwise()
         .to("direct:d");

Alors maintenant, toutes les commandes «d'huile» iront au vendeur de pétrole, les commandes de «lait» iront au vendeur de lait et le reste à un pool commun.

Processeur personnalisé

Vous pouvez également utiliser un traitement personnalisé. L'exemple ci-dessous crée un processeur personnalisé appelémyCustomProcessor et l'utilise dans le générateur d'itinéraire.

Processor myCustomProcessor = new Processor() {
   public void process(Exchange exchange) {
      // implement your custom processing
   }
};
RouteBuilder builder = new RouteBuilder() {
   public void configure() {
      from("direct:DistributeOrderDSL")
      .process(myProcessor);
   }
};

Vous pouvez utiliser des processeurs personnalisés avec le choix et le filtrage pour obtenir un meilleur contrôle sur votre médiation et votre routage -

from("direct:DistributeOrderDSL")
   .filter(header("order").isEqualTo("milk"))
      .process(myProcessor);

Utilisation de XML

Les routes peuvent être définies en XML plus volumineux, si vous le préférez. L'extrait de code XML suivant montre comment créer une route avec un filtrage via Spring XML -

<camelContext xmlns = "http://camel.apache.org/schema/spring">
   <route>
      <from uri = "direct:DistributeOrderXML"/>
      <log message = "Split by Distribute Order"/>
      <split>
         <xpath>//order[@product = 'Oil']/items</xpath>
         <to uri = "file:src/main/resources/order/"/>
         <to uri = "stream:out"/>
      </split>
   </route>
</camelContext>

Après avoir vu comment les routes sont construites, nous allons maintenant voir les différentes techniques de création de points de terminaison.

Nous avons appris à quoi ressemblent les points de terminaison dans notre code d'intégration. Les expressions que nous avons utilisées jusqu'à présent telles quefile:/order, jms:orderQueue, direct:distributeOrderDSLsont les points de terminaison. Comme vous le voyez, ils suivent les formats de spécification URI. Lors de l'évaluation de cet URI, leCamelContext crée le Endpointexemple; vous n'avez pas à vous soucier de l'instanciationEndpoint mise en œuvre dans votre DSL.

En prenant nos exemples précédents, vous spécifiez les points de terminaison dans Java DSL comme ici -

from ("file:/order").to("jms:orderQueue");

Et au printemps comme ici -

<route>
   <from uri = "file:/order"/>
   <to uri = "jms:orderQueue"/>
</route>

Dans les deux cas, le point de terminaison est une chaîne constante. Dans certains cas, vous souhaiterez peut-être créer cette chaîne lors de l'exécution. Vous pouvez le faire en utilisant JavaStringméthodes de mise en forme. Camel fournit une autre approche plus simple pour créer ces chaînes URI lors de l'exécution. A cet effet, Camel fournitfromF et toFméthodes qui acceptent les arguments avec les paramètres spécifiés par l'utilisateur. La déclaration suivante illustre l'utilisation detoF méthode -

from("direct:distributeOrderDSL”).toF("file://%s?fileName=%s", path, name);

En raison de ces méthodes, la nécessité d'utiliser le Java intégré String les méthodes de mise en forme sont évitées.

Camel utilise le langage Simple par défaut pour calculer l'expression du point de terminaison. leSimple la langue a été conçue principalement pour évaluer Expressions et Predicatessans trop se soucier des subtilités de XPath. Pour évaluer les prédicats, vous pouvez combiner un autre langage tel quexpath avec la valeur par défaut SimpleLangue. Cela se fait en utilisant le signe plus pour séparer l'autre langue. L'extrait de code ici montre comment concaténerxpath chaîne à l'expression écrite dans Simple.

from("direct:start")
.toD("jms:${orderQueue}+language:xpath:/order/@id");

Dans Spring, vous pouvez réaliser la même chose qu'ici -

<route>
   <from uri = "direct:start"/>
   <toD uri = "jms:${orderQueue}+language:xpath:/order/@id"/>
</route>

Vous pouvez concaténer autant de langues que vous le souhaitez, chacune séparée par un signe plus de la précédente. La liste des langues prises en charge peut être trouvée ici .

Camel fournit plusieurs composants pré-construits.

Dans ce chapitre, nous aborderons quelques composants importants du camel-core module.

Haricot

le BeanLe composant lie les beans aux échanges de messages Camel. L'URI pour créer un point de terminaison est spécifié commebean:beanID, où beanID est le nom du bean tel que spécifié dans le Registry.

JndiContext jndiContext = new JndiContext();
jndiContext.bind("MilkOrder", new MilkOrderProcessor());
CamelContext camelContext = new DefaultCamelContext(jndiContext);

camelContext.addRoutes(new RouteBuilder() {
   public void configure() {
      from("direct:bigBasket")
         .to("bean:MilkOrder?method=placeOrder");
   }
});

Notez comment le point de terminaison est spécifié à l'aide du bean:protocole. Vous pouvez éventuellement spécifier la méthode bean à invoquer; dans ce cas, la méthode appeléeplaceOrdersera appelée lors de l'évaluation de l'expression Endpoint. leMilkOrder est un nom JNDI au MilkOrderProcessorJavabean comme enregistré dans les deux premières lignes de l'extrait de code. La définition deMilkOrderProcessor lui-même est omis ici par souci de concision.

Direct

Vous devez avoir remarqué l'utilisation de Directdans nos exemples précédents. Pour envoyer une commande à un vendeur de pétrole, nous avons utilisédirect:oildans la spécification Endpoint. L'utilisation deDirectLe composant vous permet d'appeler de manière synchrone un point de terminaison. Les deux extraits de code suivants de nos exemples précédents illustrent l'utilisation deDirect -

.when(header("order").isEqualTo("oil"))
   .to("direct:oil")

Et,

from("direct:DistributeOrderDSL")
   .process(myProcessor);

Fichier

le FileLe composant permet d'accéder au système de fichiers de votre machine. À l'aide de ce composant, vous pourrez enregistrer les messages d'autres composants sur un disque local. De plus, il permet à d'autres composants Camel de traiter les fichiers locaux. Vous pouvez utiliser soitfile:directoryName[?options] ou file://directoryName[?options]comme format URI lors de l'utilisation du composant File. Vous avez déjà vu l'utilisation de ce composant -

from ("file:/order").to("jms:orderQueue");

Notez que le FileLe composant par défaut prend le nom du répertoire. Par conséquent, le contenu du répertoire de commande sera pris comme contenu d'entrée. Pour spécifier un fichier particulier dans leorder répertoire, vous utiliserez l'instruction suivante -

from ("file:/order?fileName = order.xml").to("jms:orderQueue");

Journal

le LogLe composant vous permet de consigner les messages dans le mécanisme de journalisation sous-jacent. Camel utilise Simple Logging Facade pour Java (SLF4J) comme abstraction de divers frameworks de journalisation. Vous pouvez utiliserjava.util.logging, logback, log4jpour la journalisation. Cet extrait de code illustre l'utilisation duLog composant -

from("direct:DistributeOrderDSL")
   .to("bean:MilkOrder?method = placeOrder")
   .to("log:com.example.com?level = INFO&showBody = true");

SEDA

le SEDA Le composant vous permet d'appeler de manière asynchrone un autre point de terminaison dans le même CamelContext. Si vous souhaitez appeler sur des instances CamelContext, vous devez utiliserVMcomposant. L'utilisation de SEDA est illustrée ici -

from("direct:DistributeOrderDSL")
// send it to the seda queue that is async
   .to("seda:nextOrder")

Dans cet itinéraire, nous acheminerons simplement les commandes vers nextOrderfile d'attente asynchrone. Un client qui s'est abonné à cette file d'attente récupérera les messages de cette file d'attente.

Minuteur

le TimerLe composant est utilisé pour envoyer des messages à intervalles réguliers et peut donc être très utile lors du test des applications Camel. L'extrait de code déclenche ici un message de test vers la console toutes les deux secondes -

from("timer://testTimer?period = 2000")
   .setBody()
   .simple("This is a test message ${header.timer}")
      .to("stream:out");

La plupart des projets d'intégration utilisent la messagerie car elle aide à créer une architecture d'application faiblement couplée. La messagerie peut être synchrone ou asynchrone. JMS prend en charge les deuxpoint-to-point et publish-subscribedes modèles. Vous utilisez unQueue pour point à point et Topicpour un modèle de publication-abonnement. Sur une plate-forme Java, JMS - Java Messaging Service fournit une interface avec un serveur de messagerie. Apache activeMQ est l'un de ces fournisseurs JMS open source. Camel n'est pas livré avec un fournisseur JMS; cependant, il peut être configuré pour utiliser activeMQ. Pour utiliser ce composant, vous devez inclure les fichiers JAR suivants dans votre projet - activemq, camel-spring et camel-jms.

L'extrait de code suivant montre comment configurer Camel pour activeMQ.

<bean id = "jms" class = "org.apache.camel.component.jms.JmsComponent">
   <property name = "connectionFactory">
      <bean class="org.apache.activemq.ActiveMQConnectionFactory">
         <property name = "orderQueue" value = "tcp://localhost:61000" />
      </bean>
   </property>
</bean>

Ici, l'application Camel commencera à écouter une file d'attente appelée orderQueue. La file d'attente elle-même est configurée dans le serveur de messagerie activeMQ s'exécutant sur l'hôte local et répertoriant sur le port 61000. Une fois que cela est fait, votre application peut envoyer ou recevoir un message à cette file d'attente à partir de n'importe lequel des points de terminaison définis dans votre application.

Enfin, il est maintenant temps de tout rassembler dans un projet pour mieux comprendre comment les applications Camel sont créées.

Nous utiliserons Maven pour construire un projet Camel. Cependant, nous préférons utiliser IntelliJ IDE pour le développement. Vous pouvez utiliser n'importe quel IDE de votre choix pour ce projet.

Créer un nouveau projet

Créer un nouveau Maven projet et précisez ce qui suit -

GroupId: Basket
ArtifactId: Basket

Sélectionnez l'emplacement par défaut de votre projet ou, si vous préférez, spécifiez le répertoire de votre choix.

Ajouter des dépendances

Vous devez ajouter quelques dépendances pour utiliser Camel. Les dépendances sont ajoutées danspom.xml. Alors ouvrez pom.xml et ajoutez les deux dépendances suivantes -

<dependencies>
   <dependency>
      <groupId>org.apache.camel</groupId>
      <artifactId>camel-core</artifactId>
      <version>2.20.0</version>
   </dependency>
   <dependency>
      <groupId>org.apache.camel</groupId>
      <artifactId>camel-stream</artifactId>
      <version>2.20.0</version>
   </dependency>
</dependencies>

Note- Nous avons besoin du strict minimum de dépendances pour notre application. Au fur et à mesure que vous utiliserez plus de composants Camel de ses bibliothèques, vous devrez ajouter les dépendances correspondantes dans ce fichier pom.xml.

Création de Java DSL

Ensuite, vous écrirez votre code de filtrage et de routage dans un Java DSL. Créez une nouvelle classe Java appeléeDistributeOrderDSL. Ajoutez-y le code suivant -

public class DistributeOrderDSL {
   public static void main(String[] args) throws Exception {
      CamelContext context = new DefaultCamelContext();
      try {
         context.addRoutes(new RouteBuilder() {
            @Override
            public void configure() throws Exception {
               from("direct:DistributeOrderDSL")
                  .split(xpath("//order[@product='soaps']/items")).to("stream:out");
               
               // .to("file:src/main/resources/order/");
            }
         });
         context.start();
         ProducerTemplate orderProducerTemplate = context.createProducerTemplate();
         InputStream orderInputStream = new FileInputStream(ClassLoader.getSystemClassLoader()
            .getResource("order.xml").getFile());
         orderProducerTemplate.sendBody("direct:DistributeOrderDSL", orderInputStream);
      } finally {
         context.stop();
      }
   }
}

dans le main méthode, nous créons d'abord CamelContext en instanciant une implémentation par défaut fournie dans DefaultCamelContext classe.

CamelContext context = new DefaultCamelContext();

Ensuite, nous ajoutons une route en créant un RouteBuilder instance -

context.addRoutes(new RouteBuilder() {

Nous remplaçons le configure méthode pour ajouter une route à partir d'un URI direct DistributeOrderDSLà la console système. Nous fournissons un filtrage en utilisant la requête xpath.

public void configure() throws Exception {
   from("direct:DistributeOrderDSL")
      .split(xpath("//order[@product = 'soaps']/items")).to("stream:out");
   // .to("file:src/main/resources/order/");
}

Après avoir ajouté la route, nous commençons le contexte -

context.start();

Ensuite, nous ajoutons le code pour créer notre URI direct - DistributeOrderDSL.

ProducerTemplate orderProducerTemplate = context.createProducerTemplate();
InputStream orderInputStream = new FileInputStream(ClassLoader.getSystemClassLoader()
   .getResource("order.xml").getFile());

Enfin, nous commençons le traitement -

orderProducerTemplate.sendBody("direct:DistributeOrderDSL", orderInputStream);

Maintenant que votre code Java DSL est terminé, la seule chose qui reste avant de tester l'application est d'ajouter le order.xmlfichier à votre projet. Vous pouvez utiliser l'exemple XML présenté dans le chapitre Introduction à cette fin.

Résultats de test

Lorsque vous exécutez l'application, vous verrez la sortie suivante -

<items>
   <item>
      <Brand>Cinthol</Brand>
      <Type>Original</Type>
      <Quantity>4</Quantity>
      <Price>25</Price>
   </item>
   <item>
      <Brand>Cinthol</Brand>
      <Type>Lime</Type>
      <Quantity>6</Quantity>
      <Price>30</Price>
   </item>
</items>

Notez que seules les commandes de savons sont répertoriées ici. Si vous souhaitez stocker ceci dans un fichier local, commentez simplement lestream.out et décommentez la ligne suivante dans votre configure méthode -

// .to("file:src/main/resources/order/");

Dans notre section suivante, nous apprendrons à utiliser Camel avec Spring.

Nous allons maintenant recréer l'application du chapitre précédent en utilisant Spring. Cela nous donnera une idée de la façon de créer un routage Camel en XML plutôt qu'en DSL.

Créer un nouveau projet

Créer un nouveau Maven projet et précisez ce qui suit -

GroupId: BasketWithSpring
ArtifactId: BasketWithSpring

Sélectionnez l'emplacement par défaut de votre projet ou, si vous préférez, spécifiez le répertoire de votre choix.

Ajouter des dépendances

En plus des dépendances principales que vous avez utilisées dans l'application précédente, vous devez ajouter quelques dépendances supplémentaires pour utiliser Spring. Les dépendances sont ajoutées dans pom.xml. Maintenant, ouvrez pom.xml et ajoutez les dépendances suivantes -

<dependencies>
   ...
   <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.1.3.RELEASE</version>
   </dependency>
   
   <dependency>
      <groupId>org.apache.activemq</groupId>
      <artifactId>activemq-pool</artifactId>
      <version>5.15.2</version>
   </dependency>
   
   <dependency>
      <groupId>org.apache.activemq</groupId>
      <artifactId>activemq-pool</artifactId>
      <version>5.15.1</version>
   </dependency>
   
   <dependency>
      <groupId>org.apache.camel</groupId>
      <artifactId>camel-spring</artifactId>
      <version>2.15.1</version>
   </dependency>
</dependencies>

Création de Java DSL pour Spring

Créons maintenant une nouvelle classe Java appelée DistributeOrderXML. Ajoutez-y le code suivant -

public class DistributeOrderXML {
   public static void main(String[] args) throws Exception {
      ApplicationContext appContext = new ClassPathXmlApplicationContext(
         "SpringRouteContext.xml");
      CamelContext camelContext = SpringCamelContext.springCamelContext(appContext, false);
      try {
         camelContext.start();
         ProducerTemplate orderProducerTemplate = camelContext.createProducerTemplate();
         InputStream orderInputStream = new FileInputStream(ClassLoader.getSystemClassLoader()
            .getResource("order.xml").getFile());
         
         orderProducerTemplate.sendBody("direct:DistributeOrderXML", orderInputStream);
      } finally {
         camelContext.stop();
      }
   }
}

dans le main méthode, nous créons d'abord une instance de ApplicationContext, qui est l'interface centrale d'une application Spring. Dans son constructeur, nous spécifions le nom du fichier XML qui contient nos informations de routage et de filtrage.

ApplicationContext appContext = new ClassPathXmlApplicationContext(
   "SpringRouteContext.xml");

Ensuite, nous créons CamelContext en spécifiant les éléments créés ci-dessus ApplicationContext dans son paramètre.

CamelContext camelContext = SpringCamelContext.springCamelContext(appContext, false);

À ce stade, notre routage et notre filtrage sont configurés. Par conséquent, nous commençons leCamelContext en utilisant son startméthode. Comme dans le cas précédent, nous définissons le point de terminaison pour charger le fichier order.xml et commençons le traitement. Voyons maintenant comment le routage est défini en XML.

Créer un contexte d'application

Ajoutez un nouveau fichier XML au projet et appelez-le SpringRouteContext.xml. Coupez-collez le contenu suivant dans ce fichier.

<?xml version = "1.0" encoding = "UTF-8"?>
<beans xmlns = "http://www.springframework.org/schema/beans"
   xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation = "
      http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans.xsd
      http://camel.apache.org/schema/spring
      http://camel.apache.org/schema/spring/camel-spring.xsd ">
   <camelContext xmlns = "http://camel.apache.org/schema/spring">
      <route>
         <from uri = "direct:DistributeOrderXML"/>
         <log message = "Split by Distribute Order"/>
         <split>
            <xpath>//order[@product = 'Oil']/items</xpath>
            <to uri = "file:src/main/resources/order/"/>
            <to uri = "stream:out"/>
         </split>
      </route>
   </camelContext>
</beans>

Ici, nous définissons la requête xpath comme suit, notez que nous sélectionnons maintenant toutes les commandes pour «pétrole».

<xpath>//order[@product = 'Oil']/items</xpath>

Les points de terminaison de sortie sont multiples. Le premier point de terminaison spécifie leorder dossier et le second spécifie la console.

<to uri = "file:src/main/resources/order/"/>
<to uri = "stream:out"/>

Exécutez l'application.

Résultats de test

Lorsque vous exécutez l'application, vous verrez la sortie suivante à l'écran.

<items>
   <item>
      <Brand>Cinthol</Brand>
      <Type>Original</Type>
      <Quantity>4</Quantity>
      <Price>25</Price>
   </item>
   <item>
      <Brand>Cinthol</Brand>
      <Type>Lime</Type>
      <Quantity>6</Quantity>
      <Price>30</Price>
   </item>
</items>

Vérifiez orderdossier dans le chemin spécifié par vous. Vous trouverez un fichier nouvellement créé contenant le code XML ci-dessus.

Conclusion

Camel fournit un framework prêt à l'emploi qui implémente des EIP pour faciliter vos projets d'intégration. Il prend en charge le codage dans des langages spécifiques au domaine et également l'utilisation de XML.