Introducción a Apache Camel

1. Información general

En este artículo, presentaremos Camel y exploraremos uno de sus conceptos centrales: el enrutamiento de mensajes .

Comenzaremos por cubrir estos conceptos y terminología fundamentales y luego presentaremos dos opciones principales para definir rutas: Java DSL y Spring DSL.

También los demostraremos en un ejemplo, definiendo una ruta que consume archivos de una carpeta y los mueve a otra mientras antepone una marca de tiempo a cada nombre de archivo.

2. Acerca de Apache Camel

Apache Camel es un marco de integración de código abierto diseñado para hacer que la integración de sistemas sea simple y fácil.

Permite a los usuarios finales integrar varios sistemas utilizando la misma API, brindando soporte para múltiples protocolos y tipos de datos, al tiempo que es extensible y permite la introducción de protocolos personalizados.

3. Dependencias de Maven

Para usar Camel, primero debemos agregar la dependencia de Maven:

 org.apache.camel camel-core 2.18.0 

La última versión del artefacto Camel se puede encontrar aquí.

3. Lenguaje específico del dominio

Las rutas y el motor de enrutamiento son la parte central de Camel. Las rutas contienen el flujo y la lógica de integración entre diferentes sistemas.

Para definir rutas más fáciles y limpias, Camel ofrece varios lenguajes específicos de dominio (DSL) diferentes para lenguajes de programación como Java o Groovy. Por otro lado, también proporciona la definición de rutas en XML con Spring DSL.

El uso de Java DSL o Spring DSL es principalmente una preferencia del usuario, ya que la mayoría de las funciones están disponibles en ambos.

Java DSL ofrece un poco más de funciones que no son compatibles con Spring DSL. Sin embargo, Spring DSL a veces es más beneficioso ya que XML se puede cambiar sin la necesidad de volver a compilar el código.

4. Terminología y arquitectura

Analicemos ahora la terminología y la arquitectura básicas de Camel.

Primero, echaremos un vistazo a los conceptos centrales de Camel aquí:

  • El mensaje contiene datos que se están transfiriendo a una ruta. Cada mensaje tiene un identificador único y se construye a partir de un cuerpo, encabezados y archivos adjuntos.
  • Exchange es el contenedor de un mensaje y se crea cuando un consumidor recibe un mensaje durante el proceso de enrutamiento. Exchange permite diferentes tipos de interacción entre sistemas: puede definir un mensaje unidireccional o un mensaje de solicitud-respuesta
  • El punto final es un canal a través del cual el sistema puede recibir o enviar un mensaje. Puede referirse a un URI de servicio web, URI de cola, archivo, dirección de correo electrónico, etc.
  • El componente actúa como una fábrica de puntos finales. En pocas palabras, los componentes ofrecen una interfaz para diferentes tecnologías utilizando el mismo enfoque y sintaxis. Camel ya admite muchos componentes en sus DSL para casi todas las tecnologías posibles, pero también brinda la capacidad de escribir componentes personalizados
  • El procesador es una interfaz Java simple que se utiliza para agregar lógica de integración personalizada a una ruta. Contiene un método de proceso único que se utiliza para realizar una lógica comercial personalizada en un mensaje recibido por un consumidor.

En un nivel alto, la arquitectura de Camel es simple. CamelContext representa el sistema de tiempo de ejecución de Camel y conecta diferentes conceptos como rutas, componentes o puntos finales.

Y debajo de eso, los procesadores manejan el enrutamiento y las transformaciones entre los puntos finales, mientras que los puntos finales integran diferentes sistemas.

5. Definición de una ruta

Las rutas se pueden definir con Java DSL o Spring DSL.

Ilustraremos ambos estilos definiendo una ruta que consume archivos de una carpeta y los mueve a otra carpeta mientras antepone una marca de tiempo a cada nombre de archivo.

5.1. Enrutamiento con Java DSL

Para definir una ruta con Java DSL, primero necesitaremos crear una instancia DefaultCamelContext . Después de eso, necesitamos extender la clase RouteBuilder e implementar el método de configuración que contendrá el flujo de ruta:

private static final long DURATION_MILIS = 10000; private static final String SOURCE_FOLDER = "src/test/source-folder"; private static final String DESTINATION_FOLDER = "src/test/destination-folder"; @Test public void moveFolderContentJavaDSLTest() throws Exception { CamelContext camelContext = new DefaultCamelContext(); camelContext.addRoutes(new RouteBuilder() { @Override public void configure() throws Exception { from("file://" + SOURCE_FOLDER + "?delete=true").process( new FileProcessor()).to("file://" + DESTINATION_FOLDER); } }); camelContext.start(); Thread.sleep(DURATION_MILIS); camelContext.stop(); }

El método de configuración se puede leer así: leer archivos de la carpeta de origen, procesarlos con FileProcessor y enviar el resultado a una carpeta de destino. Establecer delete = true significa que el archivo se eliminará de la carpeta de origen después de que se procese correctamente.

Para iniciar Camel, necesitamos llamar al método de inicio en CamelContext . Se invoca Thread.sleep para permitirle a Camel el tiempo necesario para mover los archivos de una carpeta a otra.

FileProcessor implementa la interfaz del procesador y contiene un método de proceso único que contiene lógica para modificar los nombres de los archivos:

public class FileProcessor implements Processor { public void process(Exchange exchange) throws Exception { String originalFileName = (String) exchange.getIn().getHeader( Exchange.FILE_NAME, String.class); Date date = new Date(); SimpleDateFormat dateFormat = new SimpleDateFormat( "yyyy-MM-dd HH-mm-ss"); String changedFileName = dateFormat.format(date) + originalFileName; exchange.getIn().setHeader(Exchange.FILE_NAME, changedFileName); } }

Para recuperar el nombre del archivo, tenemos que recuperar un mensaje entrante de un intercambio y acceder a su encabezado. De manera similar, para modificar el nombre del archivo, tenemos que actualizar el encabezado del mensaje.

5.2. Enrutamiento con Spring DSL

Al definir una ruta con Spring DSL, usamos un archivo XML para configurar nuestras rutas y procesadores. Esto nos permite configurar rutas sin código utilizando Spring y, en última instancia, nos brinda el beneficio de una inversión total del control.

Esto ya se cubrió en un artículo existente, por lo que nos centraremos en usar Spring DSL junto con Java DSL, que es comúnmente una forma preferida de definir rutas.

En esta disposición, CamelContext se define en el archivo Spring XML usando una sintaxis XML personalizada para Camel, pero sin la definición de ruta como en el caso de Spring DSL "puro" usando XML:

De esta manera le decimos a Camel que use la clase FileRouter que contiene la definición de nuestra ruta en Java DSL:

public class FileRouter extends RouteBuilder { private static final String SOURCE_FOLDER = "src/test/source-folder"; private static final String DESTINATION_FOLDER = "src/test/destination-folder"; @Override public void configure() throws Exception { from("file://" + SOURCE_FOLDER + "?delete=true").process( new FileProcessor()).to("file://" + DESTINATION_FOLDER); } }

Para probar esto, tenemos que crear una instancia de ClassPathXmlApplicationContext que cargará nuestro CamelContext en Spring:

@Test public void moveFolderContentSpringDSLTest() throws InterruptedException { ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("camel-context.xml"); Thread.sleep(DURATION_MILIS); applicationContext.close(); }

Al usar este enfoque, obtenemos flexibilidad y beneficios adicionales proporcionados por Spring, así como todas las posibilidades del lenguaje Java al usar Java DSL.

6. Conclusión

En este artículo rápido, presentamos una introducción a Apache Camel y demostramos los beneficios de usar Camel para tareas de integración como enrutar archivos de una carpeta a otra.

En nuestro ejemplo, vimos que Camel le permite concentrarse en la lógica empresarial y reduce la cantidad de código repetitivo.

El código de este artículo se puede encontrar en GitHub.