Apache Camel - Guía rápida

Considere una situación en la que una gran tienda de comestibles en línea en su ciudad, como Bigbasket en India, lo invita a diseñar una solución de TI para ellos. La solución estable y escalable les ayudará a superar los problemas de mantenimiento de software que enfrentan hoy. Esta tienda en línea ha estado operando su negocio durante la última década. La tienda acepta pedidos en línea para diferentes categorías de productos de sus clientes y los distribuye a los respectivos proveedores. Por ejemplo, suponga que pide jabones, aceite y leche; estos tres artículos se distribuirán a los tres proveedores respectivos. Luego, los tres proveedores enviarán sus suministros a un punto de distribución común desde donde el centro de entrega cumplirá el pedido completo. Ahora, veamos el problema que enfrentan hoy.

Cuando esta tienda inició su negocio, aceptaba pedidos en un archivo de texto sin formato separado por comas. Durante un período de tiempo, la tienda cambió a la colocación de pedidos basada en mensajes. Más tarde, algún desarrollador de software sugirió una colocación de pedidos basada en XML. Finalmente, la tienda incluso adaptó una interfaz de servicio web. Ahora, aquí viene el verdadero problema. Los pedidos ahora vienen en diferentes formatos. Obviamente, cada vez que la empresa actualizaba el formato de aceptación de pedidos, no quería romper la interfaz previamente implementada para no causar confusiones en la mente del cliente.

Al mismo tiempo, a medida que el negocio seguía creciendo, la tienda agregaba periódicamente nuevos proveedores a su repertorio. Cada uno de esos proveedores tenía su propio protocolo para aceptar pedidos. Una vez más, nos enfrentamos al tema de la integración; nuestra arquitectura de aplicaciones debe ser escalable para adaptarse a nuevos proveedores con su mecanismo único de colocación de pedidos.

La situación completa se muestra en la siguiente figura:

Ahora, veamos cómo Apache Camel puede acudir a su rescate para brindarle una arquitectura de solución elegante, fácil de mantener y escalable para el escenario descrito.

Antes de continuar con la solución, debemos hacer una pequeña suposición. Para todas las discusiones en este tutorial, asumiremos que los pedidos en línea se realizan en formato XML. Aquí se muestra un formato típico para el archivo de pedido que usaremos a lo largo de nuestras discusiones:

<?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>

Usaremos la plantilla XML anterior para ilustrar los ejemplos de Camel en este tutorial.

Camel es una caja negra que recibe mensajes de algún endpoint y los envía a otro. Dentro de la caja negra, los mensajes se pueden procesar o simplemente redirigir.

Entonces, ¿por qué tener un marco para esto? En situaciones prácticas, como se ve en el estudio de caso de introducción, puede haber muchos remitentes y muchos receptores, cada uno siguiendo su propio protocolo, como ftp, http y jms. El sistema puede requerir muchas reglas complejas, como que el mensaje del remitente A se envíe solo a B & C. En situaciones, es posible que deba traducir el mensaje a otro formato que el receptor espera. Esta traducción puede estar sujeta a ciertas condiciones basadas en el contenido del mensaje. Por lo tanto, es posible que deba traducir entre protocolos, unir componentes, definir reglas de enrutamiento y proporcionar filtrado según el contenido del mensaje. Esto se ilustra en la siguiente figura:

Para cumplir con los requisitos anteriores y diseñar una arquitectura de software adecuada para muchas de estas situaciones, Gregor Hohpe y Bobby Woolf documentaron los patrones de integración empresarial ( EIP ) en 2003. Apache Camel proporciona la implementación de estos patrones y el propósito de este tutorial es enseñar cómo usar Camel en situaciones como la descrita en la introducción.

Apache Camel es un marco de código abierto. Es un middleware orientado a mensajes que proporciona un motor de mediación y enrutamiento basado en reglas. Puede definir reglas como, por ejemplo, si se trata de un pedido de "leche", redirigirlo a un proveedor de leche y si es un pedido de "aceite", redirigirlo a un proveedor de aceite, etc. Con Camel, podrá implementar estas reglas y realizar el enrutamiento en un código Java familiar. Significa que puede utilizar su IDE de Java familiar para definir estas reglas en un entorno de tipo seguro. No necesitamos utilizar archivos de configuración XML, que suelen ser voluminosos. Sin embargo, Camel admite la configuración XML a través del marco Spring, si prefiere usar XML para configurar las reglas. Incluso puede usar archivos de configuración Blueprint XML e incluso un DSL de Scala, si es un amante de Scala. También significa que puede usar su Java, Scala IDE favorito o incluso un simple editor XML para configurar las reglas.

La entrada a este motor puede ser un archivo de texto delimitado por comas, un POJO (Plain Old Java Object), XML son cualquiera de los otros formatos soportados por Camel. Del mismo modo, la salida del motor se puede redirigir a un archivo, a una cola de mensajes o incluso a la pantalla de su monitor para que pueda ver los pedidos enviados a los respectivos proveedores. Estos se denominan puntos finales y Camel admite el patrón EIP de punto final de mensaje . Los puntos finales de Camel se describen más adelante en el capítulo Puntos finales.

Camel se utiliza normalmente con Apache ServiceMix , Apache ActiveMQ y Apache CXF para implementar arquitecturas orientadas a servicios.

Habiendo visto una descripción general de Apache Camel, profundicemos en sus características para ver qué ofrece. Ya sabemos que Apache Camel es un marco Java de código abierto que esencialmente proporciona una implementación de varios EIP. Camel facilita la integración al proporcionar conectividad a una gran variedad de transportes y API. Por ejemplo, puede enrutar fácilmente JMS a JSON, JSON a JMS, HTTP a JMS, FTP a JMS, incluso HTTP a HTTP y conectividad a microservicios. Simplemente necesita proporcionar puntos finales apropiados en ambos extremos. Camel es extensible y, por lo tanto, en el futuro se pueden agregar fácilmente más puntos finales al marco.

Para conectar EIP y transportes juntos, utilice lenguajes específicos de dominio (DSL) como Java, Scala y Groovy. Una regla de enrutamiento típica de Java puede verse así:

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

Esta regla de enrutamiento carga los archivos del order directorio, crea un mensaje JMS con el contenido del archivo y envía ese mensaje a una cola llamada orderQueue.

Estas son algunas de las características más importantes de Camel que le resultarían útiles en el desarrollo de aplicaciones Camel:

  • Camel admite formatos de datos conectables y convertidores de tipos para tales transformaciones de mensajes, por lo que se pueden agregar nuevos formatos y convertidores en el futuro. Actualmente, es compatible con varios formatos y convertidores populares; por nombrar algunos: CSV, EDI, JAXB, JSON, XmlBeans, XStream, Flatpack, Zip.

  • Camel admite lenguajes conectables para escribir predicados en DSL. Algunos de los lenguajes admitidos incluyen JavaScript, Groovy, Python, PHP, Ruby, SQL, XPath, XQuery.

  • Camel admite el modelo POJO para que pueda conectar Javabeans en varios puntos.

  • Camel facilita las pruebas de sistemas grandes distribuidos y asincrónicos mediante el uso de mensajería.

Entendamos ahora la arquitectura de Camel y veamos cómo se implementan las diversas funciones.

La arquitectura Camel consta de tres componentes: motor de integración y enrutador, procesadores y componentes. Esto se ilustra en la siguiente figura:

El núcleo de Camel en sí es muy pequeño y contiene 13 componentes esenciales. El resto de más de 80 componentes están fuera del núcleo. Esto ayuda a mantener una baja dependencia de dónde se implementa y promueve extensiones en el futuro. losComponents módulo proporciona un Endpointinterfaz con el mundo exterior. Los puntos finales se especifican mediante URI, comofile:/order y jms:orderQueue que has visto en el último capítulo.

los ProcessorsEl módulo se utiliza para manipular y mediar mensajes entre Endpoints. Los EIP que mencioné anteriormente se implementan en este módulo. Actualmente admite más de 40 patrones como se documenta en el libro EIP y otras unidades de procesamiento útiles.

los Processors y Endpoints están conectados juntos en Integration Engine and Routermódulo mediante DSL. Mientras los conecta, puede usar filtros para filtrar mensajes según los criterios definidos por el usuario. Como se mencionó anteriormente, tiene varias opciones para escribir estas reglas. Puede usar Java, Scala, Groovy o incluso XML para esto.

Ahora, llegamos al componente más importante de Camel, que puede considerarse como el núcleo: el CamelContext.

CamelContext proporciona acceso a todos los demás servicios en Camel como se muestra en la siguiente figura:

Echemos un vistazo a los distintos servicios. losRegistryEl módulo por defecto es un registro JNDI, que contiene el nombre de los distintos Javabeans que utiliza su aplicación. Si usa Camel con Spring, esta será la primaveraApplicationContext. Si usa Camel en un contenedor OSGI, esto seráOSGI registry. losType converterscomo su nombre indica, contiene los diversos convertidores de tipo cargados, que convierten su entrada de un formato a otro. Puede utilizar los convertidores de tipo integrados o proporcionar su propio mecanismo de conversión. losComponentsEl módulo contiene los componentes utilizados por su aplicación. Los componentes se cargan mediante descubrimiento automático en elclasspathque especifique. En el caso del contenedor OSGI, estos se cargan cada vez que se activa un nuevo paquete. Ya hemos discutido elEndpoints y Routesen los capítulos anteriores. losData formats contiene los formatos de datos cargados y finalmente el Languages módulo representa los idiomas cargados.

El fragmento de código aquí le dará una idea de cómo un CamelContext se crea en una aplicación Camel -

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

los DefaultCamelContext La clase proporciona una implementación concreta de CamelContext. EnaddRoutes método, creamos una instancia anónima de RouteBuilder. Puede crear variosRouteBuilderinstancias para definir más de un enrutamiento. Cada ruta en el mismo contexto debe tener un ID único. Las rutas se pueden agregar dinámicamente en el tiempo de ejecución. Una ruta con la misma ID que la definida anteriormente reemplazará a la ruta anterior.

¿Qué va dentro del RouteBuilder La instancia se describe a continuación.

Rutas

El enrutador define la regla para mover el mensaje from a un toubicación. Tu usasRouteBuilderpara definir una ruta en Java DSL. Creas una ruta extendiendo el incorporadoRouteBuilderclase. La ruta comienza con unfrompunto final y termina en uno o más puntos finales. Entre los dos, implementa la lógica de procesamiento. Puede configurar cualquier cantidad de rutas dentro de una solaconfigure método.

Aquí hay un ejemplo típico de cómo se crea una ruta:

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

Anulamos el método de configuración de RouteBuilderclass e implementar nuestro mecanismo de enrutamiento y filtrado en él. En el caso actual, redirigimos la entrada recibida del EndpointDistributeOrderDSL a la consola, que es especificada por el Endpoint stream:out.

Elección de idioma

Puede crear las rutas en diferentes idiomas. A continuación se muestran algunos ejemplos de cómo se define la misma ruta en tres idiomas diferentes:

DSL de Java

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

DSL de primavera

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

Scala DSL

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

Filtros

Utiliza el filtro para seleccionar una parte del contenido de entrada. Para configurar un filtro, usa cualquier implementación de Predicado arbitraria . La entrada filtrada se envía a su punto final de destino deseado. En este ejemplo, filtramos todos los pedidos de jabón para que puedan enviarse colectivamente a un proveedor de jabón.

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

En el ejemplo, hemos utilizado xpathpredicado para el filtrado. Si prefiere usar la clase Java para el filtrado, use el siguiente código:

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

los Order es su clase Java personalizada con su propio mecanismo de filtrado.

Puede combinar varios predicados en un solo enrutamiento como aquí:

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

Así que ahora todos los pedidos de "aceite" irán al vendedor de aceite, los pedidos de "leche" irán al vendedor de leche y el resto a un grupo común.

Procesador personalizado

También puede utilizar el procesamiento personalizado. El siguiente ejemplo crea un procesador personalizado llamadomyCustomProcessor y lo usa en el generador de rutas.

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

Puede usar procesadores personalizados junto con opciones y filtros para obtener un mejor control de su mediación y enrutamiento.

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

Usando XML

Las rutas pueden definirse en XML más voluminoso, si lo prefiere. El siguiente fragmento de XML muestra cómo crear una ruta junto con algunos filtros a través de 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>

Habiendo visto cómo se construyen las rutas, ahora veremos las diversas técnicas de creación de Endpoints.

Hemos aprendido cómo se ven los puntos finales en nuestro código de integración. Las expresiones que hemos utilizado hasta ahora comofile:/order, jms:orderQueue, direct:distributeOrderDSLson los puntos finales. Como puede ver, siguen los formatos de especificación de URI. Al evaluar este URI, elCamelContext crea el Endpointejemplo; no necesitas preocuparte por instanciarEndpoint implementación en su DSL.

Tomando nuestros ejemplos anteriores, especifica los puntos finales en Java DSL como aquí:

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

Y en primavera como aquí ...

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

En ambos casos, el punto final es una cadena constante. En ciertos casos, es posible que desee crear esta cadena en tiempo de ejecución. Puedes hacerlo usando JavaStringmétodos del formateador. Camel proporciona otro enfoque más simple para crear estas cadenas de URI en tiempo de ejecución. Para ello, Camel proporcionafromF y toFmétodos que aceptan los argumentos con los parámetros especificados por el usuario. La siguiente declaración ilustra el uso detoF método -

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

Debido a estos métodos, la necesidad de utilizar Java integrado String Se obvia los métodos del formateador.

Camel usa lenguaje simple de forma predeterminada para calcular la expresión del punto final. losSimple El lenguaje fue diseñado principalmente para evaluar Expressions y Predicatessin preocuparse mucho por las complejidades de XPath. Para evaluar predicados, puede combinar otro lenguaje comoxpath con el predeterminado Simpleidioma. Esto se hace usando el signo más para separar el otro idioma. El fragmento de código aquí muestra cómo concatenarxpath cadena a la expresión escrita en Simple.

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

En Spring, puedes lograr lo mismo que aquí -

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

Puede concatenar tantos idiomas como desee, cada uno separado con un signo más del anterior. La lista de idiomas admitidos se puede encontrar aquí .

Camel proporciona varios componentes prefabricados.

En este capítulo, discutiremos algunos componentes importantes del camel-core módulo.

Frijol

los BeanEl componente une beans a los intercambios de mensajes de Camel. El URI para crear un punto final se especifica comobean:beanID, dónde beanID es el nombre del bean como se especifica en el 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");
   }
});

Observe cómo se especifica el punto final mediante el bean:protocolo. Opcionalmente, puede especificar el método bean que se invocará; en este caso, el método llamadoplaceOrderse invocará al evaluar la expresión de Endpoint. losMilkOrder es un nombre JNDI para el MilkOrderProcessorJavabean registrado en las dos primeras líneas del fragmento de código. La definición deMilkOrderProcessor sí mismo se omite aquí por brevedad.

Directo

Debes haber notado el uso de Directen nuestros ejemplos anteriores. Para enviar un pedido a un proveedor de aceite, usamosdirect:oilen la especificación de Endpoint. El uso deDirectEl componente le permite invocar sincrónicamente un punto final. Los siguientes dos fragmentos de código de nuestros ejemplos anteriores ilustran el uso deDirect -

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

Y,

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

Archivo

los FileEl componente proporciona acceso al sistema de archivos de su máquina. Con este componente, podrá guardar mensajes de otros componentes en un disco local. Además, permite que otros componentes de Camel procesen los archivos locales. Puedes usar cualquierafile:directoryName[?options] o file://directoryName[?options]como formato URI mientras se usa el componente Archivo. Ya ha visto el uso de este componente:

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

Tenga en cuenta que el FileEl componente por defecto toma el nombre del directorio. Por lo tanto, el contenido del directorio de pedidos se tomará como contenido de entrada. Para especificar un archivo en particular en elorder directorio, utilizará la siguiente declaración:

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

Iniciar sesión

los LogEl componente le permite registrar mensajes en el mecanismo de registro subyacente. Camel utiliza Simple Logging Facade para Java (SLF4J) como una abstracción de varios marcos de registro. Puedes utilizarjava.util.logging, logback, log4jpara la tala. Este fragmento de código ilustra el uso deLog componente -

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

SEDA

los SEDA El componente le permite llamar asincrónicamente a otro punto final en el mismo CamelContext. Si desea llamar a través de instancias de CamelContext, debe usarVMcomponente. El uso de SEDA se ilustra aquí:

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

En esta ruta, simplemente enrutaremos los pedidos a nextOrdercola asincrónica. Un cliente que se haya suscrito a esta cola recogerá los mensajes de esta cola.

Temporizador

los TimerEl componente se utiliza para enviar mensajes a intervalos regulares y, por lo tanto, puede ser muy útil al probar aplicaciones Camel. El fragmento de código aquí dispara un mensaje de prueba a la consola cada dos segundos:

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

La mayoría de los proyectos de integración utilizan la mensajería, ya que ayuda a crear una arquitectura de aplicaciones poco acoplada. La mensajería puede ser sincrónica o asincrónica. JMS admite ambospoint-to-point y publish-subscribemodelos. Usas unQueue para punto a punto y Topicpara un modelo de publicación-suscripción. En una plataforma Java, JMS - Java Messaging Service proporciona una interfaz para un servidor de mensajería. Apache activeMQ es uno de esos proveedores de JMS de código abierto. Camel no se envía con un proveedor de JMS; sin embargo, se puede configurar para utilizar activeMQ. Para utilizar este componente, debe incluir los siguientes frascos en su proyecto: activemq, camel-spring y camel-jms.

El siguiente fragmento de código muestra cómo configurar Camel para 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>

Aquí, la aplicación Camel comenzará a escuchar una cola llamada orderQueue. La cola en sí se configura en el servidor de mensajería activeMQ que se ejecuta en el host local y se enumera en el puerto 61000. Una vez hecho esto, su aplicación puede enviar o recibir mensajes a esta cola desde cualquiera de los puntos finales definidos en su aplicación.

Finalmente, ha llegado el momento de poner todo junto en un proyecto para obtener una comprensión más profunda de cómo se crean las aplicaciones Camel.

Usaremos Maven para construir un proyecto Camel. Aunque, es preferible utilizar IntelliJ IDE para el desarrollo. Puede utilizar cualquier IDE de su elección para este proyecto.

Crear nuevo proyecto

Crear un nuevo Maven proyecto y especifique lo siguiente:

GroupId: Basket
ArtifactId: Basket

Seleccione la ubicación predeterminada para su proyecto o, si lo prefiere, especifique el directorio de su elección.

Agregar dependencias

Necesita agregar algunas dependencias para usar Camel. Las dependencias se agregan enpom.xml. Entonces abra pom.xml y agregue las siguientes dos dependencias:

<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- Necesitamos las dependencias mínimas para nuestra aplicación. A medida que utilice más componentes de Camel de sus bibliotecas, deberá agregar las dependencias correspondientes en este archivo pom.xml.

Creando Java DSL

A continuación, escribirá su código de filtrado y enrutamiento en un DSL de Java. Crea una nueva clase de Java llamadaDistributeOrderDSL. Agregue el siguiente código:

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

En el main método, primero creamos CamelContext instanciando una implementación predeterminada proporcionada en DefaultCamelContext clase.

CamelContext context = new DefaultCamelContext();

A continuación, agregamos una ruta creando un anónimo RouteBuilder instancia -

context.addRoutes(new RouteBuilder() {

Anulamos el configure método para agregar una ruta desde un URI directo DistributeOrderDSLa la consola del sistema. Proporcionamos algunos filtros mediante la consulta xpath.

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

Después de agregar la ruta, comenzamos el contexto -

context.start();

A continuación, agregamos el código para crear nuestro URI directo: DistributeOrderDSL.

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

Finalmente, comenzamos el procesamiento -

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

Ahora, cuando se complete su código DSL de Java, lo único que queda antes de probar la aplicación es agregar el order.xmlarchivo a su proyecto. Puede utilizar el XML de muestra que se muestra en el capítulo Introducción para este propósito.

Resultados de la prueba

Cuando ejecute la aplicación, verá el siguiente resultado:

<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>

Tenga en cuenta que aquí solo se enumeran los pedidos de jabones. Si desea almacenar esto en un archivo local, simplemente comente elstream.out línea y descomente la siguiente línea en su configure método -

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

En nuestra siguiente sección, aprenderemos cómo usar Camel con Spring.

Ahora recrearemos la aplicación del capítulo anterior usando Spring. Esto nos dará una idea de cómo crear enrutamiento Camel en XML en lugar de DSL.

Crear nuevo proyecto

Crear un nuevo Maven proyecto y especifique lo siguiente:

GroupId: BasketWithSpring
ArtifactId: BasketWithSpring

Seleccione la ubicación predeterminada para su proyecto o, si lo prefiere, especifique el directorio de su elección.

Agregar dependencias

Además de las dependencias centrales que usó en la aplicación anterior, necesita agregar algunas dependencias más para usar Spring. Las dependencias se agregan en pom.xml. Ahora, abra pom.xml y agregue las siguientes dependencias:

<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>

Creando Java DSL para Spring

Creemos ahora una nueva clase Java llamada DistributeOrderXML. Agregue el siguiente código:

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

En el main método, primero creamos una instancia de ApplicationContext, que es la interfaz central dentro de una aplicación Spring. En su constructor, especificamos el nombre del archivo XML que contiene nuestra información de enrutamiento y filtrado.

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

A continuación, creamos CamelContext especificando lo anterior creado ApplicationContext en su parámetro.

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

En este punto, nuestro enrutamiento y filtrado está configurado. Por lo tanto, comenzamosCamelContext usando su startmétodo. Como en el caso anterior, definimos el Endpoint para cargar el archivo order.xml e iniciamos el procesamiento. Ahora, entendamos cómo se define el enrutamiento en XML.

Crear contexto de aplicación

Agregue un nuevo archivo XML al proyecto y llámelo SpringRouteContext.xml. Corta y pega el siguiente contenido en este archivo.

<?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>

Aquí, definimos la consulta xpath de la siguiente manera, tenga en cuenta que ahora seleccionamos todos los pedidos para "aceite".

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

Los puntos finales de salida son múltiples. El primer punto final especifica elorder carpeta y el segundo especifica la consola.

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

Ejecute la aplicación.

Resultados de la prueba

Cuando ejecute la aplicación, verá el siguiente resultado en la pantalla.

<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>

Revisar la ordercarpeta en la ruta especificada por usted. Encontrará un archivo recién creado que contiene el código XML anterior.

Conclusión

Camel proporciona un marco listo para usar que implementa EIP para facilitar sus proyectos de integración. Admite la codificación en lenguajes específicos de dominio y también el uso de XML.