SlideShare una empresa de Scribd logo
1 de 74
Descargar para leer sin conexión
Abimael Desales López
Java Developers Mexico
www.facebook.com/JavaDevelopersMexico
Endpoints
Un endpoint es una abstracción que modela el extremo
de un canal de mensaje a través del cual un sistema
puede enviar o recibir mensajes.
En primer lugar vamos a ver cómo se pueden usar las
URIs para configurar Camel para comunicar sobre FTP y
JMS, los cuales son dos de los protocolos de transporte
más usados.
Trabajando con archivos sobre FTP
Una de las cosas que hace a Camel fácil de comprender
es la URI del endpoint. Especificando una URI, puedes
identificar el componente que quieres usar y cómo ese
componente está configurado. Puedes decidir entonces
ya sea enviar mensajes al componente configurado por
esta URI, o consumir mensajes de él.
Para comprender de una manera más clara, se ilustrarán
los conceptos a través de un ejemplo: Auto Partes Rider,
un negocio de partes de motocicletas ficticio, que provee
partes a fabricantes de motocicletas.
Al paso de los años, han cambiado la forma en que reciben
órdenes varias veces. Inicialmente colocaban órdenes
cargando archivos de valores separados por comas (CSV) a un
servidor FTP. El formato de mensaje fue cambiado a la postre
a XML. Actualmente proporcionan un sitio web a través del
cual las órdenes son emitidas como mensajes XML sobre
HTTP.
Auto Partes Rider solicita a los nuevos clientes usar la interfaz
web para colocar las órdenes, pero debido a los SLAs con los
clientes existentes, deben mantener todos los formatos e
interfaces de mensajes viejos en funcionamiento.
Todos estos mensajes son convertidos a un formato POJO
antes de ser procesado. En la siguiente figura se muestra una
lista de alto nivel del sistema de procesamiento de órdenes.
Fig. 1. Un cliente tiene dos formas de emitir órdenes al sistema de manejo de órdenes Auto Partes
Rider: ya sea cargando el archivo de órdenes plano a un servidor FTP o emitiendo una orden a
través de la tienda web de Auto Partes Rider. Eventualmente todas las órdenes son enviadas vía
JMS para procesarlas en Auto Partes Rider.
Como una primera asignación, necesitarás implementar el
módulo FTP en el sistema frontend de órdenes de Rider.
Implementar el módulo FTP involucrará los siguientes pasos:
1. Votear en el FTP server y descargar nuevas órdenes
2. Convertir los archivos de órdenes a mensajes JMS
3. Enviar el mensaje a la queue JMS incomingOrdenes
Para descargar nuevas órdenes del servidor FTP,
necesitas hacer lo siguiente:
1. Conectar al servidor FTP rider.com en el puerto FTP
default de 21
2. Proporcionar un username de “rider” y password de
“secret”
3. Cambiar el directorio a “ordenes”
4. Descargar cualesquiera archivos de órdenes nuevas
Camel buscará primero el esquema ftp en el registro de
componentes, el cual resolverá al FTPComponent. El
FTPComponent entonces funciona como una factory,
creando el FTPEndpoint basado en la ruta del contexto y las
opciones.
La ruta del contexto de rider.com/ordenes le dice al
FTPComponent que debe loguearse en el servidor FTP en
rider.com en el puerto FTP default y cambiar el directorio a
“ordenes”. Finalmente, las únicas opciones especificadas son
username y password, las cuales son usadas para
loguearse en el servidor FTP.
El FTPComponent no es parte del módulo camel-core, así
que tienes que agregar una dependencia adicional a tu
proyecto. Usando Maven sólo tienes que agregar la siguiente
dependencia a tu POM:
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-ftp</artifactId>
<version>2.5.0</version>
</dependency>
La URI de este endpoint se estará usando para descargar
órdenes del servidor FTP. Para hacerlo así, necesitas usarlo en
un nodo from del DSL de Camel:
from(“ftp://rider.com/ordenes?username=rider&password=secret”)
Lo anterior es todo lo que necesitas hacer para consumir
archivos desde un servidor FTP.
ftp://rider.com/ordenes?username=rider&password=secret
Esquema Ruta del contexto Opciones
Figura 2. La URI de un endpoint Camel consiste de tres partes: un esquema,
una ruta de contexto, y una lista de opciones.
Enviando a una Queue JMS
Camel proporciona soporte extensivo para conectar
proveedores habilitados para JMS. Por ahora sólo cubriremos
lo suficiente para que puedas completar tu primer tarea para
Auto Partes Rider. Recordemos que necesitas descargar
órdenes de un servidor FTP y enviarlas a una queue JMS.
JMS
Java Message Service es una API Java que te permite crear,
recibir, y leer mensajes. Además obliga que la mensajería sea
asíncrona y tenga elementos específicos de confiabilidad,
como entrega garantizada y una-y-solamente-una-vez. JMS
es la solución de facto en la comunidad Java.
En JMS, los consumidores y productores de mensajes se hablan uno
a otro a través de un intermediario –un destino JMS. Como se
muestra en la figura 3, un destino puede ser una queue o un topic.
Las Queues son estrictamente punto-a-punto, donde cada mensaje
tiene sólo un consumidor. Los Topics operan en un esquema
publish/subscribe; un sólo mensaje puede ser entregado a muchos
consumidores si ellos se han suscrito al topic.
JMS también proporciona una ConnectionFactory la cual los
clientes (como Camel) pueden usar para crear una conexión con un
proveedor JMS. A los proveedores JMS generalmente se les refiere
como brokers debido a que ellos gestionan la comunicación entre
el productor del mensaje y el consumidor del mensaje.
Cómo usar camel para usar un Proveedor JMS
Para conectar camel a un proveedor JMS específico, necesitas
configurar el componente JMS de Camel con una
ConnectionFactory apropiada.
Apache ActiveMQ es uno de los proveedores JMS open source más
populares; y es el broker JMS que el equipo de Camel usa para
probar el componente JMS. Por lo cual estaremos usándolo para
demostrar los conceptos JMS en el artículo.
Figura 3. Hay dos tipos de destinos
JMS: queues y topics. La queue es un
canal punto a punto, donde cada
mensaje tiene un sólo receptor. Un
topic entrega una copia del mensaje a
todos los clientes quienes se hayan
suscrito para recibirlo.
Así que en el caso de Apache ActiveMQ, puedes crear una
ActiveMQConnectionFactory que apunta a la ubicación del
broker ActiveMQ que está corriendo.
ConnectionFactory cf = new ActiveMQConnectionFactory(“vm://localhost”);
La URI vm:/localhost significa que debes conectarte a un
broker embebido llamado “localhost” corriendo dentro de la
JVM actual. El conector de transporte “vm” en ActiveMQ crea
un broker bajo demanda si uno no está corriendo aún. de
forma que es muy práctico para aplicaciones JMS de pruebas;
para escenarios de producción, se recomienda que conectes
un broker que ya esté en ejecución. Además, en escenarios de
producción se recomienda que se use un pool de conexiones
cuando se conecta a un broker JMS.
A continuación, cuando creas tu CamelContext puedes agregar el
componente JMS como sigue:
CamelContext context = new DefaultCamelContext();
context.addComponent(“jms”,
JmsComponent.jmsComponentAutoAcknowldge(connectionFactory));
El componente JMS y la connection factory específica de ActiveMQ
no son parte del módulo core de Camel. Con fines de usar este,
necesitarás agregar algunas dependencias a tu proyecto basado en
Maven. Para el componente JMS plano, todo lo que tienes que
hacer es esto:
<dependency>
<groupId>org.apache.camel</groupId>
<artefactId>camel-jms</artefactId>
<version>5.3.2</version>
</dependency>
La connection factory viene directamente de ActiveMQ, de forma
que tendrás que agregar la siguiente dependencia:
<dependency>
<groupId>org.apache.activemq</groupId>
<artefactId>activemq-core</artefactId>
<version>5.3.2</version>
</dependency>
Ahora que has configurado el componente JMS para conectar a un
broker JMS real, es hora de ver cómo las URIs pueden ser usadas
para especificar el destino.
Usando URIs para especificar el Destino
Una vez configurado el componente JMS, puedes enviar y recibir
mensajes JMS a tu gusto. Debido a que estás usando URIs es muy
fácil de configurar.
Digamos que quieres enviar un mensaje JMS a la queue llamada
incomingOrders. La URI en este caso sería:
jms:queue:incomingOrders
Esto es muy autoexplicatorio. El prefijo “jms” indica que estás
usando el componente JMS que configuraste antes. Especificando
“queue”, el componente JMS sabe que enviará a una queue llamada
incomingOrders. Aún pudiste haber omitido el calificador queue,
debido a que el comportamiento default es enviar a una queue más
que a un topic.
Usando el DSL Java de Camel puedes enviar un mensaje a la queue
incomingOrders usando la palabra clave to, como en este caso:
…to(“jms:queue:incomingOrders”)
Lo cual puede ser leído como enviando a la queue JMS llamada
incomingOrders.
Creando routes en Java
Antes de adentrarnos en los enrutamientos es necesario conocer
unos conceptos básicos de los mismos.
CamelContext
La figura 1.7 muestra los servicios más notables que mantiene
unidos el CamelContext. Estos servicios son descritos en la tabla 1.
Figura 1.7 El CamelContext provee acceso a
muchos servicios útiles, los más notables
siendo componentes, convertidores de tipo,
un registro, endpoints, routes, formatos de
datos, y lemguajes.
Servicio Descripción
Componentes Contiene los componentes usados. Camel es capaz de cargar
componentes en el aire, ya sea autodescubriendo en el claspath o
cuando un nuevo bundle es activado en un contenedor OSGi.
Endpoints Contiene los endpoints que han sido creados
Routes Contiene los routes que han sido agregados.
Convertidores de tipo Contiene los convertidores de tipo cargados. Camel tiene un
mecanismo que te permite convertir manual o automáticamente de
un tipo a otro.
Formatos de datos Contiene los formatos de datos cargados
Registro Contiene un registro que te permite localizar beans. Por default,
este será un registro JNDI. Si estás usando Camel desde Spring, será
el ApplicationContext. Puede ser un registro OSGi si usas Camel en
un contenedor OSGi.
Lenguajes Contiene los lenguajes cargados. Camel te permite usar diferentes
lenguajes para crear exprsiones.
Motor de Enrutamiento
El motor de enrutamiento de Camel es lo que realmente mueve los
mensajes tras bambalinas. Este motor no es expuesto al
desarrollador, pero debe estar consciente de que está ahí y hace el
trabajo pesado, asegurando que los mensajes sean enrutados
adecuadamente.
Routes
Las routes son obviamente una abstracción de Camel. La forma
más simple de definir una route es como una cadena de
procesadores. Hay muchas razones para usar routes en aplicaciones
de mensajería
Desacoplando los clientes de los servidores, y productores de
consumidores, routes puede:
 Decidir dinámicamente a qué servidor un cliente invocará
 Proporcionar una forma sensible de agregar procesamiento extra
 Permitir a los clientes y servidores ser desarrollados de forma
independiente
 Permitir a los clientes y servidores ser apagados (usando mocks)
por propósitos de prueba
 Promover mejores prácticas de diseño conectando sistemas
distintos que hacen una cosa bien
 Mejorar las características y funcionalidades de algunos sistemas
(tales como brokers de mensajes y ESBs)
Domain Specific Languaje (DSL)
Para vincular (cablear) procesadores y/a endpoints para formar
routes, camel define un DSL. En Camel, DSL significa una API Java
fluida que contiene métodos nombrados por téminos de EIP.
Considera este ejemplo:
from(“file:data/inbox”)
.filter().xpath(“/order[not(@test)]”)
.to(“jms:queue:order”)
Aquí, en una sola declaración Java, defines una route que consume
archivos de un endpoint de archivos . Los mensajes son luego
enrutados al filtro EIP, el cual usará un predicado XPath para
probar si el mensaje es una orden de prueba o no. Si un mensaje
pasa el test, es reenviado al endpoint JMS. Los mensajes que fallen
el filtro de prueba serán desechados.
Camel proporciona varios lenguajes DSL, de forma que puedas
definir la misma route usando el DSL de Spring, como en este caso:
<route>
<from uri=“file:data/inbox”>
<filter>
<xpath>/order[Not(@test)]</xpath>
<to uri=“jms:queue:order”>
</filter>
</route>
El DSL proporciona una buena abstracción para los usuarios de
Camel con las cuales construir aplicaciones. Aunque, tras
bambalinas, un route realmente está compuesto de un grafo de
processors.
Processor
El processor es un concepto de core de Camel que representa un
nodo capaz de usar, crear, o modificar un exchange entrante.
Durante el enrutamiento, los exchanges fluyen de un processor a
otro; como tal, puedes pensar de un route como un grafo teniendo
especializado processors como los nodos, y líneas que conectan las
salidas de un processor a la entrada de otro. Muchos de los
processors son implementaciones de EIPs, pero uno podría
fácilmente implementar su propio processor personalizado e
insertarlo en un route.
Así que, ¿cómo los exchanges entran o salen de este grafo
processor? Para descubrirlo necesitaremos ver los componentes y
endpoints.
Componente
Los componentes son los principales puntos de extensión en
Camel. Hasta la fecha, hay alrededor de 80 componentes en el
ecosistema de Camel que van del rango en función de protocolos de
datos, a DSLs, formatos de datos, etc. Además de que puedes crear
tus propios componentes para Camel.
Desde un punto de vista de programación, los componentes son
completamente simples: están asociados con un nombre, que es
usado en una URI, y actúan como una factory de endpoints. Por
ejemplo, un FileComponent es referenciado por un file en una
URI, y crea FileEndpoints. El endpoint es tal vez aún un
concepto más fundamental en Camel.
Endpoint
Un endpoint es la abstracción Camel que modela el extremo de un
canal a través del cual un sistema puede enviar o recibir mensajes.
Esto se ilustra en la figura 1.8
Figura 1.8 Un endpoint actúa como una interface neutral permitiendo a los
sistemas integrarse.
En Camel, puedes configurar endpoints usando URIs, como es
file:data/inbox?delay=5000, y puedes referirte a enpoints de esa
forma. En tiempo de ejecución, Camel buscará un endpoint basado
en la notación de URI.
Productor (Producer)
Un productor es la abstracción Camel que se refiere a una entidad
capaz de crear y enviar un mensaje a un endpoint. La figura 1.10
ilustra donde el productor se ajusta con otros conceptos Camel.
Cuando un mensaje necesita ser enviado a un endpoint, el
productor creará un exchange y lo llena con datos compatibles con
ese endpoint particular. Por ejemplo, un FileProducer escribirá el
body de un mensaje a un archivo. Por otro lado, un JMSProducer,
mapeará el mensaje Camel antes de enviarlo a un destino JMS.
Esta es una característica importante de Camel, ya que oculta la
complejidad de interactuar con transportes particulares .
crea
usa
crea
crea
crea
usa
usa
ProductorConsumidor
Figura 1.10 Cómo los endpoints trabajan
con productores, consumidores, y un
exchange
Consumidor
Un consumidor es el servicio que recibe mensajes producidos por
un productor, los envuelve en un exhange, y los envía a ser
procesados. Los consumidores son la fuente de los exchanges que
están siendo enrutados en Camel.
Para crear un nuevo exchange, un consumidor usará el endpoint
que envuelve el payload que está siendo consumido. Un processor
es luego usado para iniciar el enrutamiento del exchange en Camel
usando el motor de enrutamiento.
En Camel hay dos clases de consumidores: consumidores guiados
por eventos y consumidores de voteo. Las diferencias entre estos
consumidores son importantes, debido a que ellos ayudan a
resolver problemas diferentes.
Consumidor guiado por evento
El consumidor más familiar es probablemente el consumidor guiado por
evento, el cual se ilustra en la figura 1.11
Esta clase de consumidor está principalmente asociado con la arquitectura
cliente servidor y web services. También se le refiere como un receptor
asíncrono en el mundo EIP. Un consumidor guiado por evento escucha en
un canal de mensaje particular, usualmente un puerto TCP/IP o una
queue JMS, y espera para que un cliente le envíe mensajes. Cuando un
mensaje llega, el consumidor despierta y toma el mensaje para procesarlo.
Figura 1.1 Un consumidor guiado por evento
espera ocioso hasta que un mensaje llega,
punto en el cual despierta y consume el
mensaje.
Consumidor de voteo
La otra clase de consumidor es el consumidor de voteo, el cual se
ilustra en la figura 1.12.
En contraste al consumidor guiado por eventos, el consumidor de
voteo va activamente y obtiene mensajes desde una fuente
particular, como lo es un servidor FTP. El consumidor de voteo es
también conocido como receptor síncrono en la jerga EIP, debido a
que no voteará por más mensajes hasta que haya finalizado el
procesamiento del mensaje actual. Un sabor común del
consumidor de voteo es el consumidor de voteo programado, el
cual votea en intervalos programados. Todos los transportes de
File, FTP, y email usan consumidores de voteo programados.
Ahora que hemos cubierto todos los conceptos básicos de Camel,
es hora de proseguir con la creación de los routes.
El RouteBuilder no es el route final que el CamelContext usará
en tiempo de ejecución; es un builder para uno o más routes, los
cuales son luego agregados al CamelContext.
El método addRoutes del CamelContext acepta un RoutesBuilder,
no sólo un RouteBuilder. La interface RoutesBuilder tiene un sólo
método definido:
void addRoutesToCamelContext(CamelContext context) throws Exception;
Esto significa que podrías construir tu propia clase personalizada
para construir routes Camel. Aunque, la forma más común de
construir routes es usando la clase RouteBuilder, que
implementa RoutesBuilder. La clase RouteBuilder te da acceso
al DSL Java de camel para creación de route.
Figura 2.5 Los RoutesBuilders son usados para crear routes en Camel. Cada
RouteBuilder puede crear múltiples routes en Camel.
Usando el RouteBuilder
Para usar la clase org.camel.builder.RouteBuilder, extiendes de ella
una clase e implementas el método configure, como esto:
class MyRouteBuilder extends RouteBuilder{
public void configure() throws Exception{
…
}
}
Luego necesitas agregar la clase al CamelContext con el método
addRoutes:
CamelContext context = new DefaultCamelContext();
context.addRoutes(new MyRouteBuilder());
Alternativamente, puedes combinar el RouteBuilder y la
configuración del CamelContext agregando una clase RouteBuilder
anónima directamente en el CamelContext, como esta:
CamelContext context = new DefaultCamelContext();
context.addRoutes(new RouteBuilder(){
public void configure(){
…
}
});
En el método configure tú defines tus routes usando el DSL Java.
El método from acepta una URI de endpoint como argumento.
Puedes agregar la URI de un endpoint FTP para conectar al
servidor de órdenes de AutoPartes Rider de la siguiente forma:
from(“ftp://rider.com/orders?username=rider&password=secret”)
El método from retorna un objeto RouteDefinition, en el cual
puedes invocar un número de diferentes métodos que
implementan EIPs y otros conceptos de mensajería.
El DSL Java
Los lenguajes específicos de dominio (DSLs) son lenguajes de
computadora que se dirigen a problemas específicos de dominio, más que
a un dominio de propósito general como la mayoría de los lenguajes de
programación.
El dominio de Camel es la integración empresarial, de forma que el DSL
Java es esencialmente un conjunto de interfaces fluidas que contienen
métodos nombrados después de términos del libro EIP. En el editor de
Eclipse, toma una mirada a lo que está disponible usando autocompletar
después de un método from en el RouteBuilder. Por ahora, sólo selecciona
el método to y finaliza el route con un punto y coma. Cada declaración
Java que inicia con un método from en el RouteBuilder crea un nuevo
Route. Este nuevo route ahora completa tu primer tarea de AutoPartes
Rider –consumir órdenes de un servidor FTP y enviarlas a la queue JMS
incomingOrders.
Código 1. Voteando por mensajes FTP y enviándolos a la queue incomingOrders
import javax.jms.ConnectionFactory;
import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.camel.CamelContext;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.component.jms.JmsComponent;
import org.apache.camel.impl.DefaultCamelContext;
public class FtpToJMSExample {
public static void main(String args[]) throws Exception {
CamelContext context = new DefaultCamelContext();
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("vm://localhost");
context.addComponent("jms", JmsComponent.jmsComponentAutoAcknowledge(connectionFactory));
context.addRoutes(new RouteBuilder() {
public void configure() {
from("ftp://rider.com/orders?username=rider&password=secret")
.to("jms:incomingOrders");
}
});
context.start();
Thread.sleep(10000);
context.stop();
}
}
Sentencia Java que
forma una route
El flujo de mensajes en este route simple puede ser visualizado
como una tubería básica, donde la salida del consumidor es
alimentada en el productor como entrada. Esto se describe en la
figura 2.8:
Figura 2.8 El route mostrado en el código anterior forma una tubería simple.
La salida del consumidor FTP es alimentada en la entrada del productor JMS.
La conversión del payload de archivo a mensaje JMS es hecha automáticamente.
Una cosa que puedes haber notado es que no hicimos alguna
conversión del tipo de archivo FTP al tipo mensaje JMS – esto fue
hecho automáticamente por la facilidad TypeConverter de Camel.
Puedes forzar las conversiones de tipo para que ocurran en
cualquier momento durante una route, pero frecuentemente no
tienes que preocuparte de todo ello.
Agregando un Processor
La interface Processor en Camel es un bloque de construcción
importante de routes complejos. Es una interface simple que tiene
un sólo método:
public void process(Exchange exchange) throws Exception
Esto te da acceso completo al intercambio de mensajes,
permitiéndote hacer casi todo lo que quieras con el payload o
headers.
Todos los EIPs en Camel son implementados como processors. Aún
puedes agregar un processor simple a tu route inline, como esta:
from(“ftp://rider.com/orders?username=rider&password=secret”).
process(new processor(){
public void process(Exchange exchange) throws Exception{
System.out.println(“Solo has descargado: ”
+ exchange.getIn().getHeader(“CamelFileName”));
}
}
Esta route imprimirá el nombre de archivo de la orden que fue
descargada antes de enviarla a la queue JMS.
Agregando este processor en medio del route, efectivamente lo has
agregado al pipeline conceptual que mencionamos antes. La salida
del consumido FTP es alimentada en el processor como entrada; el
processor no modifica el payload o headers del mensaje, de forma
que el exchange se mueve en el productor JMS como entrada.
El método principal de Camel para crear routes es a través del DSL
Java. Esto está, después de todo, construido en el módulo camel-
core.
Figura 2.9 Con un processor en
la mezcla, la salida del consumidor
FTP es ahora alimentada en el
processor, y luego la salida del
processor es alimentada en el
productor JMS.
Creando routes con Spring
Spring es el contenedor Java de Inversión de Control (IoC) más
popular. El framework core te permite “vincular” beans para formas
aplicaciones. Esta vinculación es hecha a través de un archivo de
configuración XML.
Inyección de bean y Spring
Crear una aplicaciones desde beans usando Spring es muy simple.
Todo lo que necesitas son algunos beans Java (clases), un archivo de
configuración XML de Spring, y un ApplicationContext. El
ApplicationContext es similar al CamelContext, en que es el
contenedor de runtime para Spring. Vamos a ver un ejemplo muy
simple.
Considera una aplicación que imprime un saludo seguido por tu
username. En esta aplicación no quieres que el saludo sea
hardcodeado, de forma que puedas usar una interface para romper
esta dependencia. Considera la siguiente interface:
public interface Greeter{
public String diHola();
}
Esta interface es implementada por las siguientes clases:
public class EnglishGreeter implements Greeter{
public String diHola(){
return “Hello” + System.getProperty(“user.name”);
}
}
public class DanishGreeter implements Greeter{
public String diHola(){
return “Davs” + System.getProperty(“user.name”);
}
}
Ahora puedes crear una aplicación greeter como sigue:
public class GreeterMeBean{
public Greeter greeter;
public void setGreeter(Greeter greeter){
this.greeter = greeter;
}
public void execute(){
System.out.println(greeter.diHola());
}
}
Esta aplicación sacará un saludo diferente dependiendo de cómo lo
configures. Para configurar esta aplicación usando Spring, puedes hacer
algo como esto:
<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-3.0.xsd">
<bean id="myGreeter" class="camelinaction.EnglishGreeter"/>
<bean id="greetMeBean" class="camelinaction.GreetMeBean">
<property name="greeter" ref="myGreeter"/>
</bean>
</beans>
Este archivo XML instruye a Spring a hacer lo siguiente:
1. Crear una instancia de EnglishGreeter y nombrar al bean myGreeter
2. Crear una instancia de GreetMeBean y nombrar al bean greetMeBean
3. Asignar la referencia de la propiedad greeter del GreetMeBean al
bean llamado myGreeter
Esta configuración de beans es llamada wiring.
Ahora te toca cargar el archivo XML de configuración de Spring en tu
aplicación para poder hacer uso de los beans inyectados.
Para hacer las cosas más fáciles a los ojos, Camel utiliza los mecanismos
de extensión de Spring para proporcionar sintaxis XML personalizada
para conceptos Camel en el archivo XML de Spring. Para cargar un
CamelContext en Spring, puedes hacer lo siguiente:
<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-3.0.xsd
http://camel.apache.org/schema/spring
http://camel.apache.org/schema/spring/camel-spring.xsd">
...
<camelContext xmlns="http://camel.apache.org/schema/spring"/>
</beans>
Lo anterior automáticamente iniciará un SpringCamelContext, la
cual es una subclase del DefaultCamelContext que usaste para el
DSL Java. Además nota que tuviste que incluir la definición de
esquema XML http://camel.apache.org/schema/spring/camel-
spring.xsd en el archivo XML –que es necesario para importar los
elementos XML personalizados.
Este snippet no va a hacer nada por sí solo. Necesitas decirle a
Camel qué routes va a usar, como lo hiciste cuando usabas el DSL
Java. El siguiente código usa Spring para producir los mismos
resultados que el listado 2.1
<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-3.0.xsd
http://camel.apache.org/schema/spring
http://camel.apache.org/schema/spring/camel-spring.xsd">
<bean id="jms" class="org.apache.camel.component.jms.JmsComponent">
<property name="connectionFactory">
<bean class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="vm://localhost" />
</bean>
</property>
</bean>
<bean id="ftpToJmsRoute" class="camelinaction.FtpToJMSRoute"/>
<camelContext xmlns="http://camel.apache.org/schema/spring">
<routeBuilder ref="ftpToJmsRoute"/>
</camelContext>
</beans>
Puedes haber notado que nos estamos refiriendo a la clase
camelinaction.FtpToJMSRoute como un RouteBuilder. Con el fin
de reproducir el DSL Java del listado 2.1, tienes que factorizar el
RouteBuilder anónimo en su propia clase nombrada. La clase
FtpToJMSRoute se parece a la siguiente:
public class FtpToJMSRoute extends RouteBuilder {
public void configure() {
from("ftp://rider.com" +
"/orders?username=rider&password=secret")
.to("jms:incomingOrders");
}
}
Lo que hemos visto de la integración de Camel con Spring es
adecuado, pero no está tomando completa ventaja de la
metodología de Spring sin usar código. Para completamente
invertir el control de crear aplicaciones usando XML Spring, Camel
proporciona extensiones XML personalizadas a las que llamamos el
DSL Spring. El DSL Spring te permite hacer casi todo lo que puedes
hacer en el DSL Java.
Continuemos con el ejemplo de AutoPartes Rider mostrado en el
listado 2.2, pero esta vez especificarás las reglas de enrutamiento
definidas en el RouteBuilder puramente en XML. El siguiente XML
Spring hace esto.
Listado 2.3 Ejemplo DSL Spring que produce el mismo resultado que el listado 2.1
<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-3.0.xsd
http://camel.apache.org/schema/spring
http://camel.apache.org/schema/spring/camel-spring.xsd">
<bean id="jms" class="org.apache.camel.component.jms.JmsComponent">
<property name="connectionFactory">
<bean class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="vm://localhost" />
</bean>
</property>
</bean>
<camelContext xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="ftp://rider.com/orders?username=rider&password=secret"/>
<to uri="jms:incomingOrders"/>
</route>
</camelContext>
</beans>
En el listado anterior bajo el elemento camelContext remplazas el
routeBuilder con el elemento route. En el elemento route,
especificas el route usando elementos con nombres similares a
aquellos usados dentro del RouteBuilder del DSL Java. Este listado
es funcionalmente equivalente a la versión DSL de Java en el listado
2.1 y la combinación de Spring más el DSL Java.
El endpoint file cargará archivos de órdenes del directorio src/data
relativo. La propiedad noop configura el endpoint para que deje el
archivo como está después de procesarlo, esta opción es muy útil
para testing.
Este route no desplegará algo interesante aún. Necesitas agregar un
paso de procesamiento adicional para testing.
Agregando un Processor
Agregar pasos de procesamiento adicional es simple, como en el
DSL Java, aquí agregarás un procesador personalizado como lo
hiciste en la sección 2.3.2.
Debido a que no puedes referirte a una clase anónima en el XML
Spring, necesitas refactorizar el procesador anónimo en la siguiente
clase:
public class DownloadLogger implements Processor {
public void process(Exchange exchange) throws Exception {
System.out.println("We just downloaded: "
+ exchange.getIn().getHeader("CamelFileName"));
}
}
Puedes ahora usarla en el route de tu DSL Spring como sigue:
<bean id="downloadLogger" class="camelinaction.DownloadLogger"/>
<camelContext xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="file:src/data?noop=true"/>
<process ref="downloadLogger"/>
<to uri="jms:incomingOrders"/>
</route>
</camelContext>
Enrutamientos y EIPs
Usando un Enrutador Basado en Contenido (CBR)
Como su nombre lo implica, un Enrutador Basado en Contenido (CBR) es
un router de mensaje que enruta un mensaje a un destino basado en su
contenido. El contenido podría ser un header de mensaje, el tipo de dato
del payload, parte del mismo payload.
Para demostrar, vamos atrás a Autopartes Rider. Algunos clientes han
empezado a cargar órdenes al servidor FTP en el formato XML más nuevo
más que CSV. Lo que significa que tienes dos tipos de mensajes entrantes
a la queue incomingOrders. No hemos tocado esto antes, pero necesitas
convertir las órdenes entrantes en un formato POJO interno. Obviamente
necesitas hacer diferentes conversiones para los diferentes tipos de
órdenes entrantes.
Como una posible solución, podrías usar la extensión del nombre de
archivo si un mensaje de orden particular debe ser enviado a la queue para
órdenes CSV o a una queue para órdenes XML.
Enrutamientos y EIPs
Usando un Enrutador Basado en Contenido (CBR)
Figura 2.10. El CBR enruta mensajes basado en su contenido. En este caso, la
extensión filename (como un header del mensaje) es usado para determinar
a qué queue enrutar.
Enrutamientos y EIPs
Como lo viste antes, puedes usar el header CamelFileName
asignado por el consumidor FTP para obtener el nombre de archivo.
Para hacer el enrutamiento condicional requerido por el CBR,
Camel introduce algunas keywords en el DSL. El método choice
crea un processor CBR, y las condiciones son agregadas siguiendo
choice con una combinación de un método choice con una
combinación de un método when y un predicado.
from("jms:incomingOrders")
.choice()
.when(predicate)
.to("jms:xmlOrders")
.when(predicate)
.to("jms:csvOrders");
Enrutamientos y EIPs
Puedes haber notado que no llenamos el predicado requerido por
cada método when. Un predicado en Camel es una simple interface
que sólo tiene un método matches:
public interface Predicate {
boolean matches(Exchange exchange);
}
Por ejemplo, puedes pensar de un predicado como una condición
booleana en una sentencia if Java.
Probablemente no quieras buscar por ti mismo dentro del exchange
y hacer una comparación. Afortunadamente, los predicados son
construidos de expresiones, y las expresiones son usadas para
extraer resultados basados de un exchange basado en el contenido
de la expresión.
Enrutamientos y EIPs
Hay muchos lenguajes de expresión de los cuales elegir en Camel,
algunos de los cuales incluyen Simple, EL, JXPath, Mvel, OGNL,
PHP, BeanShell, JavaScript, Groovy, Python, Ruby, XPath y XQuery.
En el RouteBuilder, puedes comenzar usando el método header,
que retorna una expresión que evaluará al valor del header. Por
ejemplo, header(“CamelFileName”) creará una expresión que
resolverá al valor del header CamelFileName en el siguiente
exchange. En esta expresión puedes invocar muchos métodos para
crear un predicado. Así que verifica si la extensión del nombre del
archivo es .xml, puedes usar el siguiente predicado:
header(“CamelFileName”).endsWith(“.xml”);
Enrutamientos y EIPs
context.addRoutes(new RouteBuilder() {
public void configure() {
from("file:src/data?noop=true").to("jms:incomingOrders");
from("jms:incomingOrders")
.choice()
.when(header("CamelFileName")
.endsWith(".xml"))
.to("jms:xmlOrders")
.when(header("CamelFileName")
.endsWith(".csv"))
.to("jms:csvOrders");
from("jms:xmlOrders").process(new Processor() {
public void process(Exchange exchange) throws Exception {
System.out.println("Received XML order: "
+ exchange.getIn().getHeader("CamelFileName"));
}
});
from("jms:csvOrders").process(new Processor() {
public void process(Exchange exchange) throws Exception {
System.out.println("Received CSV order: "
+ exchange.getIn().getHeader("CamelFileName"));
}
});
}
});
Enrutamientos y EIPs
Usando Filtros de Mensajes
Figura 2.12. Un Filtro de Mensaje te permite filtrar los mensajes que no
importan basados en alguna condición. En este caso los mensajes de
prueba son filtrados.
Enrutamientos y EIPs
Usando filtros de mensajes
AutoPartes Rider ahora tiene un nuevo issue –su departamento de
QA ha expresado la necesidad de enviar órdenes de prueba en el
frontend web en vivo del sistema de órdenes. Tu solución actual
aceptaría estas órdenes como reales y enviarlas a los sistemas
externos para procesamiento. Tu has sugerido que QA pruebe en
un clon de desarrollo del sistema real, pero la gestión ha desechado
esa idea, alegando un presupuesto limitado. Lo que necesitas es
una solución que descarte estos mensajes de prueba mientras aún
se opera en las órdenes reales.
El EIP Message Filter, proporciona una buena forma de tratar con
esta clase de problemas. Los mensajes entrantes sólo pasan el filtro
si reúnen una cierta condición. Los mensajes que no reúnen la
condición son desechados.
Enrutamientos y EIPs
Usando filtros de mensajes
from("jms:xmlOrders").filter(xpath("/order[not(@test)]"))
.process(new Processor() {
public void process(Exchange exchange) throws Exception {
System.out.println("Received XML order: "
+ exchange.getIn().getHeader("CamelFileName"));
}
});
El anterior en el DSL Java, y el siguiente en el DSL de Spring
<route>
<from uri="jms:xmlOrders"/>
<filter>
<xpath>/order[not(@test)]</xpath>
<process ref="orderLogger"/>
</filter>
</route>
Enrutamientos y EIPs
Usando Multicasting
Figura 2.13. Un multicast envía un mensaje a un número de receptores
específicos.
Enrutamientos y EIPs
Usando Multicasting
Frecuentemente en las aplicaciones empresariales necesitarás
enviar una copia de un mensaje a varios destinos diferentes para
procesamiento. Cuando la lista de destinos es conocida adelante
del tiempo y es estática, puedes agregar un elemento al route que
consumirá mensajes desde un endpoint fuente y luego enviar el
mensaje a una lista de destinos.
Enrutamientos y EIPs
Usando lista de receptores
Figura 2.14. Una lista de receptores inspecciona los mensajes entrantes
y determina una lista de receptores basado en el contenido del
mensaje. En este caso, sólo es enviado a los destinos A, B, y D.
Enrutamientos y EIPs
Usando lista de receptores
Usando el EIP Recipient List. Una lista de receptores primero
inspecciona el mensaje entrante, luego genera una lista de
receptores deseados basados en el contenido del mensaje, y envía el
mensaje a esos receptores. Un receptor es especificado por una
URI. Nota que la lista de receptores es diferente que el multicast
debido a que la lista de receptores es dinámica.
Camel proporciona un método recipientList para implementar el
patrón EIP Recipient List. Por ejemplo, el siguiente route tomará la
lista de receptores desde un header llamado recipients, donde cada
recipiente es separado del siguiente por una coma:
from("jms:xmlOrders")
.recipientList(header("recipients"));
Enrutamientos y EIPs
En la versión DSL Java
from("jms:xmlOrders")
.setHeader("customer", xpath("/order/@customer"))
.process(new Processor() {
public void process(Exchange exchange) throws Exception {
String recipients = "jms:accounting";
String customer =
exchange.getIn().getHeader("customer", String.class);
if (customer.equals("honda")) {
recipients += ",jms:production";
}
exchange.getIn().setHeader("recipients", recipients);
}
})
.recipientList(header("recipients"));
Enrutamientos y EIPs
En la versión DSL Spring
<route>
<from uri="jms:xmlOrders" />
<setHeader headerName="customer">
<xpath>/order/@customer</xpath>
</setHeader>
<process ref="calculateRecipients" />
<recipientList>
<header>recipients</header>
</recipientList>
</route>
Enrutamientos y EIPs
Usando el método wireTap
Enrutamientos y EIPs
Usando el método wireTap
Frecuentemente en aplicaciones empresariales es útil y necesario
inspeccionar cómo los mensajes fluyen a través del sistema. Por
ejemplo, cuando una orden falla, necesitas una forma de buscar
qué mensajes fueron recibidos fueron recibidos para determinar la
causa de la falla.
Usando el método wireTap en el DSL Java, puedes enviar una copia
del exchange a un destino secundario sin afectar el
comportamiento del resto del route.
from("jms:incomingOrders")
.wireTap("jms:orderAudit")
.choice()
.when(header("CamelFileName").endsWith(".xml"))
.to("jms:xmlOrders")
.when(header("CamelFileName").regex("^.*(csv|csl)$"))
.to("jms:csvOrders")
.otherwise()
.to("jms:badOrders");
GRACIAS
Dudas y comentarios al email:
it.adesales@gmail.com
Y en la página
www.facebook.com/JavaDevelopersMexico
No olviden regalarnos un like.

Más contenido relacionado

La actualidad más candente

Deep Dive on Amazon Elastic Container Service (ECS) and Fargate
Deep Dive on Amazon Elastic Container Service (ECS) and FargateDeep Dive on Amazon Elastic Container Service (ECS) and Fargate
Deep Dive on Amazon Elastic Container Service (ECS) and FargateAmazon Web Services
 
Simple Object Access Protocol
Simple Object Access ProtocolSimple Object Access Protocol
Simple Object Access ProtocolSaatviga Sudhahar
 
Mule expression language
Mule expression languageMule expression language
Mule expression languagesathyaraj Anand
 
Top 50 MuleSoft interview questions
Top 50 MuleSoft interview questionsTop 50 MuleSoft interview questions
Top 50 MuleSoft interview questionstechievarsity
 
Architecting security and governance through policy guardrails in Amazon EKS ...
Architecting security and governance through policy guardrails in Amazon EKS ...Architecting security and governance through policy guardrails in Amazon EKS ...
Architecting security and governance through policy guardrails in Amazon EKS ...Amazon Web Services
 
Convert Your Code into a Microservice using AWS Lambda
Convert Your Code into a Microservice using AWS LambdaConvert Your Code into a Microservice using AWS Lambda
Convert Your Code into a Microservice using AWS LambdaAmazon Web Services
 
JMS-Java Message Service
JMS-Java Message ServiceJMS-Java Message Service
JMS-Java Message ServiceKasun Madusanke
 
Introduction to Amazon Web Services
Introduction to Amazon Web ServicesIntroduction to Amazon Web Services
Introduction to Amazon Web ServicesRobert Greiner
 
Best Practices for Getting Started with AWS
Best Practices for Getting Started with AWSBest Practices for Getting Started with AWS
Best Practices for Getting Started with AWSAmazon Web Services
 
AWS IAM and security
AWS IAM and securityAWS IAM and security
AWS IAM and securityErik Paulsson
 
API Testing Using REST Assured with TestNG
API Testing Using REST Assured with TestNGAPI Testing Using REST Assured with TestNG
API Testing Using REST Assured with TestNGSiddharth Sharma
 
Sesion 7 3 diseño diagramas de componentes
Sesion 7 3 diseño   diagramas de componentesSesion 7 3 diseño   diagramas de componentes
Sesion 7 3 diseño diagramas de componentesJulio Pari
 
UDA-Componentes RUP. Formulario
UDA-Componentes RUP. FormularioUDA-Componentes RUP. Formulario
UDA-Componentes RUP. FormularioAnder Martinez
 

La actualidad más candente (20)

Deep Dive on Amazon Elastic Container Service (ECS) and Fargate
Deep Dive on Amazon Elastic Container Service (ECS) and FargateDeep Dive on Amazon Elastic Container Service (ECS) and Fargate
Deep Dive on Amazon Elastic Container Service (ECS) and Fargate
 
Simple Object Access Protocol
Simple Object Access ProtocolSimple Object Access Protocol
Simple Object Access Protocol
 
REST & RESTful Web Services
REST & RESTful Web ServicesREST & RESTful Web Services
REST & RESTful Web Services
 
Mule expression language
Mule expression languageMule expression language
Mule expression language
 
Top 50 MuleSoft interview questions
Top 50 MuleSoft interview questionsTop 50 MuleSoft interview questions
Top 50 MuleSoft interview questions
 
Architecting security and governance through policy guardrails in Amazon EKS ...
Architecting security and governance through policy guardrails in Amazon EKS ...Architecting security and governance through policy guardrails in Amazon EKS ...
Architecting security and governance through policy guardrails in Amazon EKS ...
 
Convert Your Code into a Microservice using AWS Lambda
Convert Your Code into a Microservice using AWS LambdaConvert Your Code into a Microservice using AWS Lambda
Convert Your Code into a Microservice using AWS Lambda
 
JMS-Java Message Service
JMS-Java Message ServiceJMS-Java Message Service
JMS-Java Message Service
 
Introduction to Amazon Web Services
Introduction to Amazon Web ServicesIntroduction to Amazon Web Services
Introduction to Amazon Web Services
 
Best Practices for Getting Started with AWS
Best Practices for Getting Started with AWSBest Practices for Getting Started with AWS
Best Practices for Getting Started with AWS
 
Intro to Amazon ECS
Intro to Amazon ECSIntro to Amazon ECS
Intro to Amazon ECS
 
AWS IAM and security
AWS IAM and securityAWS IAM and security
AWS IAM and security
 
Web api
Web apiWeb api
Web api
 
Alice 11
Alice 11Alice 11
Alice 11
 
API Testing Using REST Assured with TestNG
API Testing Using REST Assured with TestNGAPI Testing Using REST Assured with TestNG
API Testing Using REST Assured with TestNG
 
Soap and Rest
Soap and RestSoap and Rest
Soap and Rest
 
Sesion 7 3 diseño diagramas de componentes
Sesion 7 3 diseño   diagramas de componentesSesion 7 3 diseño   diagramas de componentes
Sesion 7 3 diseño diagramas de componentes
 
Api Gateway
Api GatewayApi Gateway
Api Gateway
 
UDA-Componentes RUP. Formulario
UDA-Componentes RUP. FormularioUDA-Componentes RUP. Formulario
UDA-Componentes RUP. Formulario
 
Dependency Injection
Dependency InjectionDependency Injection
Dependency Injection
 

Destacado

Elegant Systems Integration w/ Apache Camel
Elegant Systems Integration w/ Apache CamelElegant Systems Integration w/ Apache Camel
Elegant Systems Integration w/ Apache CamelPradeep Elankumaran
 
Cooking with Apache Camel: Tips and Tricks - DevNation 2014
Cooking with Apache Camel: Tips and Tricks - DevNation 2014Cooking with Apache Camel: Tips and Tricks - DevNation 2014
Cooking with Apache Camel: Tips and Tricks - DevNation 2014Scott Cranton
 
Conceptos introductorios al diseño de Servicios SOA
Conceptos introductorios al diseño de Servicios SOAConceptos introductorios al diseño de Servicios SOA
Conceptos introductorios al diseño de Servicios SOAAbimael Desales López
 
Analisis ¿No es eso para personas poco inteligentes?
Analisis ¿No es eso para personas poco inteligentes?Analisis ¿No es eso para personas poco inteligentes?
Analisis ¿No es eso para personas poco inteligentes?Abimael Desales López
 
Arquitectura aplicaciones Patrones de diseño
Arquitectura aplicaciones Patrones de diseñoArquitectura aplicaciones Patrones de diseño
Arquitectura aplicaciones Patrones de diseñoGermania Rodriguez
 
Bases de Datos en Java - Intro a Hibernate
Bases de Datos en Java - Intro a HibernateBases de Datos en Java - Intro a Hibernate
Bases de Datos en Java - Intro a HibernateCarlos Hernando
 
Developing Microservices with Apache Camel
Developing Microservices with Apache CamelDeveloping Microservices with Apache Camel
Developing Microservices with Apache CamelClaus Ibsen
 
Microservices with Apache Camel
Microservices with Apache CamelMicroservices with Apache Camel
Microservices with Apache CamelClaus Ibsen
 
Integrating Microservices with Apache Camel
Integrating Microservices with Apache CamelIntegrating Microservices with Apache Camel
Integrating Microservices with Apache CamelChristian Posta
 
Diagrama de clases
Diagrama de clasesDiagrama de clases
Diagrama de clasesNedoww Haw
 
Orquestacion y Coreografia de Servicios Web
Orquestacion y Coreografia de Servicios WebOrquestacion y Coreografia de Servicios Web
Orquestacion y Coreografia de Servicios Webdaniel_lt
 
Patrones de diseño de software
Patrones de diseño de softwarePatrones de diseño de software
Patrones de diseño de softwareIker Canarias
 

Destacado (20)

Presentacion camel
Presentacion camelPresentacion camel
Presentacion camel
 
Elegant Systems Integration w/ Apache Camel
Elegant Systems Integration w/ Apache CamelElegant Systems Integration w/ Apache Camel
Elegant Systems Integration w/ Apache Camel
 
Cooking with Apache Camel: Tips and Tricks - DevNation 2014
Cooking with Apache Camel: Tips and Tricks - DevNation 2014Cooking with Apache Camel: Tips and Tricks - DevNation 2014
Cooking with Apache Camel: Tips and Tricks - DevNation 2014
 
Conceptos introductorios al diseño de Servicios SOA
Conceptos introductorios al diseño de Servicios SOAConceptos introductorios al diseño de Servicios SOA
Conceptos introductorios al diseño de Servicios SOA
 
Analisis ¿No es eso para personas poco inteligentes?
Analisis ¿No es eso para personas poco inteligentes?Analisis ¿No es eso para personas poco inteligentes?
Analisis ¿No es eso para personas poco inteligentes?
 
Orquestación de Servicios y SOA
Orquestación de Servicios y SOAOrquestación de Servicios y SOA
Orquestación de Servicios y SOA
 
Patrones de diseño
Patrones de diseñoPatrones de diseño
Patrones de diseño
 
Orquestación o coreografía
Orquestación o coreografíaOrquestación o coreografía
Orquestación o coreografía
 
Diseño de servicios ATM
Diseño de servicios ATMDiseño de servicios ATM
Diseño de servicios ATM
 
Arquitectura aplicaciones Patrones de diseño
Arquitectura aplicaciones Patrones de diseñoArquitectura aplicaciones Patrones de diseño
Arquitectura aplicaciones Patrones de diseño
 
Patrones diseño de software
Patrones diseño de softwarePatrones diseño de software
Patrones diseño de software
 
Integrando sonar
Integrando sonarIntegrando sonar
Integrando sonar
 
Bases de Datos en Java - Intro a Hibernate
Bases de Datos en Java - Intro a HibernateBases de Datos en Java - Intro a Hibernate
Bases de Datos en Java - Intro a Hibernate
 
Developing Microservices with Apache Camel
Developing Microservices with Apache CamelDeveloping Microservices with Apache Camel
Developing Microservices with Apache Camel
 
Microservices with Apache Camel
Microservices with Apache CamelMicroservices with Apache Camel
Microservices with Apache Camel
 
Integrating Microservices with Apache Camel
Integrating Microservices with Apache CamelIntegrating Microservices with Apache Camel
Integrating Microservices with Apache Camel
 
Diagrama de clases
Diagrama de clasesDiagrama de clases
Diagrama de clases
 
Tutorial - Ordenar listas Java
Tutorial   - Ordenar listas JavaTutorial   - Ordenar listas Java
Tutorial - Ordenar listas Java
 
Orquestacion y Coreografia de Servicios Web
Orquestacion y Coreografia de Servicios WebOrquestacion y Coreografia de Servicios Web
Orquestacion y Coreografia de Servicios Web
 
Patrones de diseño de software
Patrones de diseño de softwarePatrones de diseño de software
Patrones de diseño de software
 

Similar a Apache Camel

2. Java Servlets (J2EE) - Curso 2005-2006
2. Java Servlets (J2EE) - Curso 2005-20062. Java Servlets (J2EE) - Curso 2005-2006
2. Java Servlets (J2EE) - Curso 2005-2006Samuel Marrero
 
Web services-con-php
Web services-con-phpWeb services-con-php
Web services-con-phpLinkser SA.
 
Apache Tomcat 8: integración con Apache Server (con mod_jk)
Apache Tomcat 8: integración con Apache Server (con mod_jk)Apache Tomcat 8: integración con Apache Server (con mod_jk)
Apache Tomcat 8: integración con Apache Server (con mod_jk)pablozacrosuarez
 
Web inmobiliaria con word press y multilinkcrm
Web inmobiliaria con word press y multilinkcrmWeb inmobiliaria con word press y multilinkcrm
Web inmobiliaria con word press y multilinkcrmmultilinkcrm
 
Capitulo no3 parte_ii
Capitulo no3 parte_iiCapitulo no3 parte_ii
Capitulo no3 parte_iiJavier Juliac
 
Mq conceptos y programacion as400
Mq conceptos y programacion as400Mq conceptos y programacion as400
Mq conceptos y programacion as400Giovanny Guillen
 
hMailServer
hMailServerhMailServer
hMailServerVellidin
 
Mule Cloud Connectors-Instalacion
Mule Cloud Connectors-InstalacionMule Cloud Connectors-Instalacion
Mule Cloud Connectors-InstalacionSara Peralta
 
Mule Cloud Connectors-Instalacion1
Mule Cloud Connectors-Instalacion1Mule Cloud Connectors-Instalacion1
Mule Cloud Connectors-Instalacion1Sara Peralta
 
Mule Cloud Connectors-Instalacion
Mule Cloud Connectors-InstalacionMule Cloud Connectors-Instalacion
Mule Cloud Connectors-InstalacionManuel Antonio
 
Java WebServices JaxWS - JaxRs
Java WebServices JaxWS - JaxRsJava WebServices JaxWS - JaxRs
Java WebServices JaxWS - JaxRsHernan Rengifo
 

Similar a Apache Camel (20)

2. Java Servlets (J2EE) - Curso 2005-2006
2. Java Servlets (J2EE) - Curso 2005-20062. Java Servlets (J2EE) - Curso 2005-2006
2. Java Servlets (J2EE) - Curso 2005-2006
 
Web services-con-php
Web services-con-phpWeb services-con-php
Web services-con-php
 
Apache Tomcat 8: integración con Apache Server (con mod_jk)
Apache Tomcat 8: integración con Apache Server (con mod_jk)Apache Tomcat 8: integración con Apache Server (con mod_jk)
Apache Tomcat 8: integración con Apache Server (con mod_jk)
 
Web inmobiliaria con word press y multilinkcrm
Web inmobiliaria con word press y multilinkcrmWeb inmobiliaria con word press y multilinkcrm
Web inmobiliaria con word press y multilinkcrm
 
presenjava.ppt
presenjava.pptpresenjava.ppt
presenjava.ppt
 
Pdfwebservices
PdfwebservicesPdfwebservices
Pdfwebservices
 
Servlet
ServletServlet
Servlet
 
Capitulo no3 parte_ii
Capitulo no3 parte_iiCapitulo no3 parte_ii
Capitulo no3 parte_ii
 
Servicios web Extendido_error perl
Servicios web Extendido_error perlServicios web Extendido_error perl
Servicios web Extendido_error perl
 
JSP
JSPJSP
JSP
 
20001215 Programación de Servlets y WML
20001215   Programación de Servlets y WML20001215   Programación de Servlets y WML
20001215 Programación de Servlets y WML
 
Mq conceptos y programacion as400
Mq conceptos y programacion as400Mq conceptos y programacion as400
Mq conceptos y programacion as400
 
[Code Camp 2009] Aplicaciones de tiempo real con Silverlight y ASP.NET - COME...
[Code Camp 2009] Aplicaciones de tiempo real con Silverlight y ASP.NET - COME...[Code Camp 2009] Aplicaciones de tiempo real con Silverlight y ASP.NET - COME...
[Code Camp 2009] Aplicaciones de tiempo real con Silverlight y ASP.NET - COME...
 
hMailServer
hMailServerhMailServer
hMailServer
 
12integracion de tomcat con apache
12integracion de tomcat con apache12integracion de tomcat con apache
12integracion de tomcat con apache
 
Mule Cloud Connectors-Instalacion
Mule Cloud Connectors-InstalacionMule Cloud Connectors-Instalacion
Mule Cloud Connectors-Instalacion
 
Mule Cloud Connectors-Instalacion1
Mule Cloud Connectors-Instalacion1Mule Cloud Connectors-Instalacion1
Mule Cloud Connectors-Instalacion1
 
Mule Cloud Connectors-Instalacion
Mule Cloud Connectors-InstalacionMule Cloud Connectors-Instalacion
Mule Cloud Connectors-Instalacion
 
Java WebServices JaxWS - JaxRs
Java WebServices JaxWS - JaxRsJava WebServices JaxWS - JaxRs
Java WebServices JaxWS - JaxRs
 
Servidor web
Servidor webServidor web
Servidor web
 

Más de Abimael Desales López

Aprendiendo AWS Lambda con API Gateway y DynamoDB
Aprendiendo AWS Lambda con API Gateway y DynamoDBAprendiendo AWS Lambda con API Gateway y DynamoDB
Aprendiendo AWS Lambda con API Gateway y DynamoDBAbimael Desales López
 
Tareas Programadas de Oracle con Toad 10
Tareas Programadas de Oracle con Toad 10Tareas Programadas de Oracle con Toad 10
Tareas Programadas de Oracle con Toad 10Abimael Desales López
 
File Processing - Batch Process Execution
File Processing - Batch Process ExecutionFile Processing - Batch Process Execution
File Processing - Batch Process ExecutionAbimael Desales López
 
File Processing - Process Execution Solution
File Processing - Process Execution SolutionFile Processing - Process Execution Solution
File Processing - Process Execution SolutionAbimael Desales López
 
Patrones de Integración Empresariales
Patrones de Integración EmpresarialesPatrones de Integración Empresariales
Patrones de Integración EmpresarialesAbimael Desales López
 
El mejor enfoque para una arquitectura orientada a servicios
El mejor enfoque para una arquitectura orientada a serviciosEl mejor enfoque para una arquitectura orientada a servicios
El mejor enfoque para una arquitectura orientada a serviciosAbimael Desales López
 
SOA: Principios de Diseño de Servicios - Parte II
SOA: Principios de Diseño de Servicios - Parte IISOA: Principios de Diseño de Servicios - Parte II
SOA: Principios de Diseño de Servicios - Parte IIAbimael Desales López
 

Más de Abimael Desales López (10)

Aprendiendo AWS Lambda con API Gateway y DynamoDB
Aprendiendo AWS Lambda con API Gateway y DynamoDBAprendiendo AWS Lambda con API Gateway y DynamoDB
Aprendiendo AWS Lambda con API Gateway y DynamoDB
 
Tareas Programadas de Oracle con Toad 10
Tareas Programadas de Oracle con Toad 10Tareas Programadas de Oracle con Toad 10
Tareas Programadas de Oracle con Toad 10
 
File Processing - Batch Process Execution
File Processing - Batch Process ExecutionFile Processing - Batch Process Execution
File Processing - Batch Process Execution
 
File Processing - Process Execution Solution
File Processing - Process Execution SolutionFile Processing - Process Execution Solution
File Processing - Process Execution Solution
 
Tutorial - REST con java (JAX-RS 2.0)
Tutorial - REST con java (JAX-RS 2.0)Tutorial - REST con java (JAX-RS 2.0)
Tutorial - REST con java (JAX-RS 2.0)
 
Patrones de Integración Empresariales
Patrones de Integración EmpresarialesPatrones de Integración Empresariales
Patrones de Integración Empresariales
 
Jpa modelos de componentes
Jpa   modelos de componentesJpa   modelos de componentes
Jpa modelos de componentes
 
Integración de Aplicaciones
Integración de AplicacionesIntegración de Aplicaciones
Integración de Aplicaciones
 
El mejor enfoque para una arquitectura orientada a servicios
El mejor enfoque para una arquitectura orientada a serviciosEl mejor enfoque para una arquitectura orientada a servicios
El mejor enfoque para una arquitectura orientada a servicios
 
SOA: Principios de Diseño de Servicios - Parte II
SOA: Principios de Diseño de Servicios - Parte IISOA: Principios de Diseño de Servicios - Parte II
SOA: Principios de Diseño de Servicios - Parte II
 

Apache Camel

  • 1. Abimael Desales López Java Developers Mexico www.facebook.com/JavaDevelopersMexico
  • 2. Endpoints Un endpoint es una abstracción que modela el extremo de un canal de mensaje a través del cual un sistema puede enviar o recibir mensajes. En primer lugar vamos a ver cómo se pueden usar las URIs para configurar Camel para comunicar sobre FTP y JMS, los cuales son dos de los protocolos de transporte más usados.
  • 3. Trabajando con archivos sobre FTP Una de las cosas que hace a Camel fácil de comprender es la URI del endpoint. Especificando una URI, puedes identificar el componente que quieres usar y cómo ese componente está configurado. Puedes decidir entonces ya sea enviar mensajes al componente configurado por esta URI, o consumir mensajes de él. Para comprender de una manera más clara, se ilustrarán los conceptos a través de un ejemplo: Auto Partes Rider, un negocio de partes de motocicletas ficticio, que provee partes a fabricantes de motocicletas.
  • 4. Al paso de los años, han cambiado la forma en que reciben órdenes varias veces. Inicialmente colocaban órdenes cargando archivos de valores separados por comas (CSV) a un servidor FTP. El formato de mensaje fue cambiado a la postre a XML. Actualmente proporcionan un sitio web a través del cual las órdenes son emitidas como mensajes XML sobre HTTP. Auto Partes Rider solicita a los nuevos clientes usar la interfaz web para colocar las órdenes, pero debido a los SLAs con los clientes existentes, deben mantener todos los formatos e interfaces de mensajes viejos en funcionamiento.
  • 5. Todos estos mensajes son convertidos a un formato POJO antes de ser procesado. En la siguiente figura se muestra una lista de alto nivel del sistema de procesamiento de órdenes. Fig. 1. Un cliente tiene dos formas de emitir órdenes al sistema de manejo de órdenes Auto Partes Rider: ya sea cargando el archivo de órdenes plano a un servidor FTP o emitiendo una orden a través de la tienda web de Auto Partes Rider. Eventualmente todas las órdenes son enviadas vía JMS para procesarlas en Auto Partes Rider.
  • 6. Como una primera asignación, necesitarás implementar el módulo FTP en el sistema frontend de órdenes de Rider. Implementar el módulo FTP involucrará los siguientes pasos: 1. Votear en el FTP server y descargar nuevas órdenes 2. Convertir los archivos de órdenes a mensajes JMS 3. Enviar el mensaje a la queue JMS incomingOrdenes
  • 7. Para descargar nuevas órdenes del servidor FTP, necesitas hacer lo siguiente: 1. Conectar al servidor FTP rider.com en el puerto FTP default de 21 2. Proporcionar un username de “rider” y password de “secret” 3. Cambiar el directorio a “ordenes” 4. Descargar cualesquiera archivos de órdenes nuevas
  • 8. Camel buscará primero el esquema ftp en el registro de componentes, el cual resolverá al FTPComponent. El FTPComponent entonces funciona como una factory, creando el FTPEndpoint basado en la ruta del contexto y las opciones. La ruta del contexto de rider.com/ordenes le dice al FTPComponent que debe loguearse en el servidor FTP en rider.com en el puerto FTP default y cambiar el directorio a “ordenes”. Finalmente, las únicas opciones especificadas son username y password, las cuales son usadas para loguearse en el servidor FTP.
  • 9. El FTPComponent no es parte del módulo camel-core, así que tienes que agregar una dependencia adicional a tu proyecto. Usando Maven sólo tienes que agregar la siguiente dependencia a tu POM: <dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-ftp</artifactId> <version>2.5.0</version> </dependency> La URI de este endpoint se estará usando para descargar órdenes del servidor FTP. Para hacerlo así, necesitas usarlo en un nodo from del DSL de Camel: from(“ftp://rider.com/ordenes?username=rider&password=secret”)
  • 10. Lo anterior es todo lo que necesitas hacer para consumir archivos desde un servidor FTP. ftp://rider.com/ordenes?username=rider&password=secret Esquema Ruta del contexto Opciones Figura 2. La URI de un endpoint Camel consiste de tres partes: un esquema, una ruta de contexto, y una lista de opciones.
  • 11. Enviando a una Queue JMS Camel proporciona soporte extensivo para conectar proveedores habilitados para JMS. Por ahora sólo cubriremos lo suficiente para que puedas completar tu primer tarea para Auto Partes Rider. Recordemos que necesitas descargar órdenes de un servidor FTP y enviarlas a una queue JMS. JMS Java Message Service es una API Java que te permite crear, recibir, y leer mensajes. Además obliga que la mensajería sea asíncrona y tenga elementos específicos de confiabilidad, como entrega garantizada y una-y-solamente-una-vez. JMS es la solución de facto en la comunidad Java.
  • 12. En JMS, los consumidores y productores de mensajes se hablan uno a otro a través de un intermediario –un destino JMS. Como se muestra en la figura 3, un destino puede ser una queue o un topic. Las Queues son estrictamente punto-a-punto, donde cada mensaje tiene sólo un consumidor. Los Topics operan en un esquema publish/subscribe; un sólo mensaje puede ser entregado a muchos consumidores si ellos se han suscrito al topic. JMS también proporciona una ConnectionFactory la cual los clientes (como Camel) pueden usar para crear una conexión con un proveedor JMS. A los proveedores JMS generalmente se les refiere como brokers debido a que ellos gestionan la comunicación entre el productor del mensaje y el consumidor del mensaje.
  • 13. Cómo usar camel para usar un Proveedor JMS Para conectar camel a un proveedor JMS específico, necesitas configurar el componente JMS de Camel con una ConnectionFactory apropiada. Apache ActiveMQ es uno de los proveedores JMS open source más populares; y es el broker JMS que el equipo de Camel usa para probar el componente JMS. Por lo cual estaremos usándolo para demostrar los conceptos JMS en el artículo. Figura 3. Hay dos tipos de destinos JMS: queues y topics. La queue es un canal punto a punto, donde cada mensaje tiene un sólo receptor. Un topic entrega una copia del mensaje a todos los clientes quienes se hayan suscrito para recibirlo.
  • 14. Así que en el caso de Apache ActiveMQ, puedes crear una ActiveMQConnectionFactory que apunta a la ubicación del broker ActiveMQ que está corriendo. ConnectionFactory cf = new ActiveMQConnectionFactory(“vm://localhost”); La URI vm:/localhost significa que debes conectarte a un broker embebido llamado “localhost” corriendo dentro de la JVM actual. El conector de transporte “vm” en ActiveMQ crea un broker bajo demanda si uno no está corriendo aún. de forma que es muy práctico para aplicaciones JMS de pruebas; para escenarios de producción, se recomienda que conectes un broker que ya esté en ejecución. Además, en escenarios de producción se recomienda que se use un pool de conexiones cuando se conecta a un broker JMS.
  • 15. A continuación, cuando creas tu CamelContext puedes agregar el componente JMS como sigue: CamelContext context = new DefaultCamelContext(); context.addComponent(“jms”, JmsComponent.jmsComponentAutoAcknowldge(connectionFactory)); El componente JMS y la connection factory específica de ActiveMQ no son parte del módulo core de Camel. Con fines de usar este, necesitarás agregar algunas dependencias a tu proyecto basado en Maven. Para el componente JMS plano, todo lo que tienes que hacer es esto: <dependency> <groupId>org.apache.camel</groupId> <artefactId>camel-jms</artefactId> <version>5.3.2</version> </dependency>
  • 16. La connection factory viene directamente de ActiveMQ, de forma que tendrás que agregar la siguiente dependencia: <dependency> <groupId>org.apache.activemq</groupId> <artefactId>activemq-core</artefactId> <version>5.3.2</version> </dependency> Ahora que has configurado el componente JMS para conectar a un broker JMS real, es hora de ver cómo las URIs pueden ser usadas para especificar el destino.
  • 17. Usando URIs para especificar el Destino Una vez configurado el componente JMS, puedes enviar y recibir mensajes JMS a tu gusto. Debido a que estás usando URIs es muy fácil de configurar. Digamos que quieres enviar un mensaje JMS a la queue llamada incomingOrders. La URI en este caso sería: jms:queue:incomingOrders Esto es muy autoexplicatorio. El prefijo “jms” indica que estás usando el componente JMS que configuraste antes. Especificando “queue”, el componente JMS sabe que enviará a una queue llamada incomingOrders. Aún pudiste haber omitido el calificador queue, debido a que el comportamiento default es enviar a una queue más que a un topic.
  • 18. Usando el DSL Java de Camel puedes enviar un mensaje a la queue incomingOrders usando la palabra clave to, como en este caso: …to(“jms:queue:incomingOrders”) Lo cual puede ser leído como enviando a la queue JMS llamada incomingOrders.
  • 19. Creando routes en Java Antes de adentrarnos en los enrutamientos es necesario conocer unos conceptos básicos de los mismos. CamelContext La figura 1.7 muestra los servicios más notables que mantiene unidos el CamelContext. Estos servicios son descritos en la tabla 1. Figura 1.7 El CamelContext provee acceso a muchos servicios útiles, los más notables siendo componentes, convertidores de tipo, un registro, endpoints, routes, formatos de datos, y lemguajes.
  • 20. Servicio Descripción Componentes Contiene los componentes usados. Camel es capaz de cargar componentes en el aire, ya sea autodescubriendo en el claspath o cuando un nuevo bundle es activado en un contenedor OSGi. Endpoints Contiene los endpoints que han sido creados Routes Contiene los routes que han sido agregados. Convertidores de tipo Contiene los convertidores de tipo cargados. Camel tiene un mecanismo que te permite convertir manual o automáticamente de un tipo a otro. Formatos de datos Contiene los formatos de datos cargados Registro Contiene un registro que te permite localizar beans. Por default, este será un registro JNDI. Si estás usando Camel desde Spring, será el ApplicationContext. Puede ser un registro OSGi si usas Camel en un contenedor OSGi. Lenguajes Contiene los lenguajes cargados. Camel te permite usar diferentes lenguajes para crear exprsiones.
  • 21. Motor de Enrutamiento El motor de enrutamiento de Camel es lo que realmente mueve los mensajes tras bambalinas. Este motor no es expuesto al desarrollador, pero debe estar consciente de que está ahí y hace el trabajo pesado, asegurando que los mensajes sean enrutados adecuadamente. Routes Las routes son obviamente una abstracción de Camel. La forma más simple de definir una route es como una cadena de procesadores. Hay muchas razones para usar routes en aplicaciones de mensajería
  • 22. Desacoplando los clientes de los servidores, y productores de consumidores, routes puede:  Decidir dinámicamente a qué servidor un cliente invocará  Proporcionar una forma sensible de agregar procesamiento extra  Permitir a los clientes y servidores ser desarrollados de forma independiente  Permitir a los clientes y servidores ser apagados (usando mocks) por propósitos de prueba  Promover mejores prácticas de diseño conectando sistemas distintos que hacen una cosa bien  Mejorar las características y funcionalidades de algunos sistemas (tales como brokers de mensajes y ESBs)
  • 23. Domain Specific Languaje (DSL) Para vincular (cablear) procesadores y/a endpoints para formar routes, camel define un DSL. En Camel, DSL significa una API Java fluida que contiene métodos nombrados por téminos de EIP. Considera este ejemplo: from(“file:data/inbox”) .filter().xpath(“/order[not(@test)]”) .to(“jms:queue:order”) Aquí, en una sola declaración Java, defines una route que consume archivos de un endpoint de archivos . Los mensajes son luego enrutados al filtro EIP, el cual usará un predicado XPath para probar si el mensaje es una orden de prueba o no. Si un mensaje pasa el test, es reenviado al endpoint JMS. Los mensajes que fallen el filtro de prueba serán desechados.
  • 24. Camel proporciona varios lenguajes DSL, de forma que puedas definir la misma route usando el DSL de Spring, como en este caso: <route> <from uri=“file:data/inbox”> <filter> <xpath>/order[Not(@test)]</xpath> <to uri=“jms:queue:order”> </filter> </route> El DSL proporciona una buena abstracción para los usuarios de Camel con las cuales construir aplicaciones. Aunque, tras bambalinas, un route realmente está compuesto de un grafo de processors.
  • 25. Processor El processor es un concepto de core de Camel que representa un nodo capaz de usar, crear, o modificar un exchange entrante. Durante el enrutamiento, los exchanges fluyen de un processor a otro; como tal, puedes pensar de un route como un grafo teniendo especializado processors como los nodos, y líneas que conectan las salidas de un processor a la entrada de otro. Muchos de los processors son implementaciones de EIPs, pero uno podría fácilmente implementar su propio processor personalizado e insertarlo en un route. Así que, ¿cómo los exchanges entran o salen de este grafo processor? Para descubrirlo necesitaremos ver los componentes y endpoints.
  • 26. Componente Los componentes son los principales puntos de extensión en Camel. Hasta la fecha, hay alrededor de 80 componentes en el ecosistema de Camel que van del rango en función de protocolos de datos, a DSLs, formatos de datos, etc. Además de que puedes crear tus propios componentes para Camel. Desde un punto de vista de programación, los componentes son completamente simples: están asociados con un nombre, que es usado en una URI, y actúan como una factory de endpoints. Por ejemplo, un FileComponent es referenciado por un file en una URI, y crea FileEndpoints. El endpoint es tal vez aún un concepto más fundamental en Camel.
  • 27. Endpoint Un endpoint es la abstracción Camel que modela el extremo de un canal a través del cual un sistema puede enviar o recibir mensajes. Esto se ilustra en la figura 1.8 Figura 1.8 Un endpoint actúa como una interface neutral permitiendo a los sistemas integrarse.
  • 28. En Camel, puedes configurar endpoints usando URIs, como es file:data/inbox?delay=5000, y puedes referirte a enpoints de esa forma. En tiempo de ejecución, Camel buscará un endpoint basado en la notación de URI. Productor (Producer) Un productor es la abstracción Camel que se refiere a una entidad capaz de crear y enviar un mensaje a un endpoint. La figura 1.10 ilustra donde el productor se ajusta con otros conceptos Camel. Cuando un mensaje necesita ser enviado a un endpoint, el productor creará un exchange y lo llena con datos compatibles con ese endpoint particular. Por ejemplo, un FileProducer escribirá el body de un mensaje a un archivo. Por otro lado, un JMSProducer, mapeará el mensaje Camel antes de enviarlo a un destino JMS.
  • 29. Esta es una característica importante de Camel, ya que oculta la complejidad de interactuar con transportes particulares . crea usa crea crea crea usa usa ProductorConsumidor Figura 1.10 Cómo los endpoints trabajan con productores, consumidores, y un exchange
  • 30. Consumidor Un consumidor es el servicio que recibe mensajes producidos por un productor, los envuelve en un exhange, y los envía a ser procesados. Los consumidores son la fuente de los exchanges que están siendo enrutados en Camel. Para crear un nuevo exchange, un consumidor usará el endpoint que envuelve el payload que está siendo consumido. Un processor es luego usado para iniciar el enrutamiento del exchange en Camel usando el motor de enrutamiento. En Camel hay dos clases de consumidores: consumidores guiados por eventos y consumidores de voteo. Las diferencias entre estos consumidores son importantes, debido a que ellos ayudan a resolver problemas diferentes.
  • 31. Consumidor guiado por evento El consumidor más familiar es probablemente el consumidor guiado por evento, el cual se ilustra en la figura 1.11 Esta clase de consumidor está principalmente asociado con la arquitectura cliente servidor y web services. También se le refiere como un receptor asíncrono en el mundo EIP. Un consumidor guiado por evento escucha en un canal de mensaje particular, usualmente un puerto TCP/IP o una queue JMS, y espera para que un cliente le envíe mensajes. Cuando un mensaje llega, el consumidor despierta y toma el mensaje para procesarlo. Figura 1.1 Un consumidor guiado por evento espera ocioso hasta que un mensaje llega, punto en el cual despierta y consume el mensaje.
  • 32. Consumidor de voteo La otra clase de consumidor es el consumidor de voteo, el cual se ilustra en la figura 1.12. En contraste al consumidor guiado por eventos, el consumidor de voteo va activamente y obtiene mensajes desde una fuente particular, como lo es un servidor FTP. El consumidor de voteo es también conocido como receptor síncrono en la jerga EIP, debido a que no voteará por más mensajes hasta que haya finalizado el procesamiento del mensaje actual. Un sabor común del consumidor de voteo es el consumidor de voteo programado, el cual votea en intervalos programados. Todos los transportes de File, FTP, y email usan consumidores de voteo programados.
  • 33. Ahora que hemos cubierto todos los conceptos básicos de Camel, es hora de proseguir con la creación de los routes. El RouteBuilder no es el route final que el CamelContext usará en tiempo de ejecución; es un builder para uno o más routes, los cuales son luego agregados al CamelContext. El método addRoutes del CamelContext acepta un RoutesBuilder, no sólo un RouteBuilder. La interface RoutesBuilder tiene un sólo método definido: void addRoutesToCamelContext(CamelContext context) throws Exception; Esto significa que podrías construir tu propia clase personalizada para construir routes Camel. Aunque, la forma más común de construir routes es usando la clase RouteBuilder, que implementa RoutesBuilder. La clase RouteBuilder te da acceso al DSL Java de camel para creación de route.
  • 34. Figura 2.5 Los RoutesBuilders son usados para crear routes en Camel. Cada RouteBuilder puede crear múltiples routes en Camel.
  • 35. Usando el RouteBuilder Para usar la clase org.camel.builder.RouteBuilder, extiendes de ella una clase e implementas el método configure, como esto: class MyRouteBuilder extends RouteBuilder{ public void configure() throws Exception{ … } } Luego necesitas agregar la clase al CamelContext con el método addRoutes: CamelContext context = new DefaultCamelContext(); context.addRoutes(new MyRouteBuilder());
  • 36. Alternativamente, puedes combinar el RouteBuilder y la configuración del CamelContext agregando una clase RouteBuilder anónima directamente en el CamelContext, como esta: CamelContext context = new DefaultCamelContext(); context.addRoutes(new RouteBuilder(){ public void configure(){ … } }); En el método configure tú defines tus routes usando el DSL Java. El método from acepta una URI de endpoint como argumento. Puedes agregar la URI de un endpoint FTP para conectar al servidor de órdenes de AutoPartes Rider de la siguiente forma:
  • 37. from(“ftp://rider.com/orders?username=rider&password=secret”) El método from retorna un objeto RouteDefinition, en el cual puedes invocar un número de diferentes métodos que implementan EIPs y otros conceptos de mensajería.
  • 38. El DSL Java Los lenguajes específicos de dominio (DSLs) son lenguajes de computadora que se dirigen a problemas específicos de dominio, más que a un dominio de propósito general como la mayoría de los lenguajes de programación. El dominio de Camel es la integración empresarial, de forma que el DSL Java es esencialmente un conjunto de interfaces fluidas que contienen métodos nombrados después de términos del libro EIP. En el editor de Eclipse, toma una mirada a lo que está disponible usando autocompletar después de un método from en el RouteBuilder. Por ahora, sólo selecciona el método to y finaliza el route con un punto y coma. Cada declaración Java que inicia con un método from en el RouteBuilder crea un nuevo Route. Este nuevo route ahora completa tu primer tarea de AutoPartes Rider –consumir órdenes de un servidor FTP y enviarlas a la queue JMS incomingOrders.
  • 39. Código 1. Voteando por mensajes FTP y enviándolos a la queue incomingOrders import javax.jms.ConnectionFactory; import org.apache.activemq.ActiveMQConnectionFactory; import org.apache.camel.CamelContext; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.component.jms.JmsComponent; import org.apache.camel.impl.DefaultCamelContext; public class FtpToJMSExample { public static void main(String args[]) throws Exception { CamelContext context = new DefaultCamelContext(); ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("vm://localhost"); context.addComponent("jms", JmsComponent.jmsComponentAutoAcknowledge(connectionFactory)); context.addRoutes(new RouteBuilder() { public void configure() { from("ftp://rider.com/orders?username=rider&password=secret") .to("jms:incomingOrders"); } }); context.start(); Thread.sleep(10000); context.stop(); } } Sentencia Java que forma una route
  • 40. El flujo de mensajes en este route simple puede ser visualizado como una tubería básica, donde la salida del consumidor es alimentada en el productor como entrada. Esto se describe en la figura 2.8: Figura 2.8 El route mostrado en el código anterior forma una tubería simple. La salida del consumidor FTP es alimentada en la entrada del productor JMS. La conversión del payload de archivo a mensaje JMS es hecha automáticamente.
  • 41. Una cosa que puedes haber notado es que no hicimos alguna conversión del tipo de archivo FTP al tipo mensaje JMS – esto fue hecho automáticamente por la facilidad TypeConverter de Camel. Puedes forzar las conversiones de tipo para que ocurran en cualquier momento durante una route, pero frecuentemente no tienes que preocuparte de todo ello. Agregando un Processor La interface Processor en Camel es un bloque de construcción importante de routes complejos. Es una interface simple que tiene un sólo método: public void process(Exchange exchange) throws Exception
  • 42. Esto te da acceso completo al intercambio de mensajes, permitiéndote hacer casi todo lo que quieras con el payload o headers. Todos los EIPs en Camel son implementados como processors. Aún puedes agregar un processor simple a tu route inline, como esta: from(“ftp://rider.com/orders?username=rider&password=secret”). process(new processor(){ public void process(Exchange exchange) throws Exception{ System.out.println(“Solo has descargado: ” + exchange.getIn().getHeader(“CamelFileName”)); } } Esta route imprimirá el nombre de archivo de la orden que fue descargada antes de enviarla a la queue JMS.
  • 43. Agregando este processor en medio del route, efectivamente lo has agregado al pipeline conceptual que mencionamos antes. La salida del consumido FTP es alimentada en el processor como entrada; el processor no modifica el payload o headers del mensaje, de forma que el exchange se mueve en el productor JMS como entrada. El método principal de Camel para crear routes es a través del DSL Java. Esto está, después de todo, construido en el módulo camel- core. Figura 2.9 Con un processor en la mezcla, la salida del consumidor FTP es ahora alimentada en el processor, y luego la salida del processor es alimentada en el productor JMS.
  • 44. Creando routes con Spring Spring es el contenedor Java de Inversión de Control (IoC) más popular. El framework core te permite “vincular” beans para formas aplicaciones. Esta vinculación es hecha a través de un archivo de configuración XML. Inyección de bean y Spring Crear una aplicaciones desde beans usando Spring es muy simple. Todo lo que necesitas son algunos beans Java (clases), un archivo de configuración XML de Spring, y un ApplicationContext. El ApplicationContext es similar al CamelContext, en que es el contenedor de runtime para Spring. Vamos a ver un ejemplo muy simple.
  • 45. Considera una aplicación que imprime un saludo seguido por tu username. En esta aplicación no quieres que el saludo sea hardcodeado, de forma que puedas usar una interface para romper esta dependencia. Considera la siguiente interface: public interface Greeter{ public String diHola(); } Esta interface es implementada por las siguientes clases: public class EnglishGreeter implements Greeter{ public String diHola(){ return “Hello” + System.getProperty(“user.name”); } }
  • 46. public class DanishGreeter implements Greeter{ public String diHola(){ return “Davs” + System.getProperty(“user.name”); } } Ahora puedes crear una aplicación greeter como sigue: public class GreeterMeBean{ public Greeter greeter; public void setGreeter(Greeter greeter){ this.greeter = greeter; } public void execute(){ System.out.println(greeter.diHola()); } }
  • 47. Esta aplicación sacará un saludo diferente dependiendo de cómo lo configures. Para configurar esta aplicación usando Spring, puedes hacer algo como esto: <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-3.0.xsd"> <bean id="myGreeter" class="camelinaction.EnglishGreeter"/> <bean id="greetMeBean" class="camelinaction.GreetMeBean"> <property name="greeter" ref="myGreeter"/> </bean> </beans> Este archivo XML instruye a Spring a hacer lo siguiente: 1. Crear una instancia de EnglishGreeter y nombrar al bean myGreeter 2. Crear una instancia de GreetMeBean y nombrar al bean greetMeBean 3. Asignar la referencia de la propiedad greeter del GreetMeBean al bean llamado myGreeter
  • 48. Esta configuración de beans es llamada wiring. Ahora te toca cargar el archivo XML de configuración de Spring en tu aplicación para poder hacer uso de los beans inyectados. Para hacer las cosas más fáciles a los ojos, Camel utiliza los mecanismos de extensión de Spring para proporcionar sintaxis XML personalizada para conceptos Camel en el archivo XML de Spring. Para cargar un CamelContext en Spring, puedes hacer lo siguiente: <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-3.0.xsd http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd"> ... <camelContext xmlns="http://camel.apache.org/schema/spring"/> </beans>
  • 49. Lo anterior automáticamente iniciará un SpringCamelContext, la cual es una subclase del DefaultCamelContext que usaste para el DSL Java. Además nota que tuviste que incluir la definición de esquema XML http://camel.apache.org/schema/spring/camel- spring.xsd en el archivo XML –que es necesario para importar los elementos XML personalizados. Este snippet no va a hacer nada por sí solo. Necesitas decirle a Camel qué routes va a usar, como lo hiciste cuando usabas el DSL Java. El siguiente código usa Spring para producir los mismos resultados que el listado 2.1
  • 50. <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-3.0.xsd http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd"> <bean id="jms" class="org.apache.camel.component.jms.JmsComponent"> <property name="connectionFactory"> <bean class="org.apache.activemq.ActiveMQConnectionFactory"> <property name="brokerURL" value="vm://localhost" /> </bean> </property> </bean> <bean id="ftpToJmsRoute" class="camelinaction.FtpToJMSRoute"/> <camelContext xmlns="http://camel.apache.org/schema/spring"> <routeBuilder ref="ftpToJmsRoute"/> </camelContext> </beans>
  • 51. Puedes haber notado que nos estamos refiriendo a la clase camelinaction.FtpToJMSRoute como un RouteBuilder. Con el fin de reproducir el DSL Java del listado 2.1, tienes que factorizar el RouteBuilder anónimo en su propia clase nombrada. La clase FtpToJMSRoute se parece a la siguiente: public class FtpToJMSRoute extends RouteBuilder { public void configure() { from("ftp://rider.com" + "/orders?username=rider&password=secret") .to("jms:incomingOrders"); } }
  • 52. Lo que hemos visto de la integración de Camel con Spring es adecuado, pero no está tomando completa ventaja de la metodología de Spring sin usar código. Para completamente invertir el control de crear aplicaciones usando XML Spring, Camel proporciona extensiones XML personalizadas a las que llamamos el DSL Spring. El DSL Spring te permite hacer casi todo lo que puedes hacer en el DSL Java. Continuemos con el ejemplo de AutoPartes Rider mostrado en el listado 2.2, pero esta vez especificarás las reglas de enrutamiento definidas en el RouteBuilder puramente en XML. El siguiente XML Spring hace esto.
  • 53. Listado 2.3 Ejemplo DSL Spring que produce el mismo resultado que el listado 2.1 <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-3.0.xsd http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd"> <bean id="jms" class="org.apache.camel.component.jms.JmsComponent"> <property name="connectionFactory"> <bean class="org.apache.activemq.ActiveMQConnectionFactory"> <property name="brokerURL" value="vm://localhost" /> </bean> </property> </bean> <camelContext xmlns="http://camel.apache.org/schema/spring"> <route> <from uri="ftp://rider.com/orders?username=rider&password=secret"/> <to uri="jms:incomingOrders"/> </route> </camelContext> </beans>
  • 54. En el listado anterior bajo el elemento camelContext remplazas el routeBuilder con el elemento route. En el elemento route, especificas el route usando elementos con nombres similares a aquellos usados dentro del RouteBuilder del DSL Java. Este listado es funcionalmente equivalente a la versión DSL de Java en el listado 2.1 y la combinación de Spring más el DSL Java. El endpoint file cargará archivos de órdenes del directorio src/data relativo. La propiedad noop configura el endpoint para que deje el archivo como está después de procesarlo, esta opción es muy útil para testing. Este route no desplegará algo interesante aún. Necesitas agregar un paso de procesamiento adicional para testing.
  • 55. Agregando un Processor Agregar pasos de procesamiento adicional es simple, como en el DSL Java, aquí agregarás un procesador personalizado como lo hiciste en la sección 2.3.2. Debido a que no puedes referirte a una clase anónima en el XML Spring, necesitas refactorizar el procesador anónimo en la siguiente clase: public class DownloadLogger implements Processor { public void process(Exchange exchange) throws Exception { System.out.println("We just downloaded: " + exchange.getIn().getHeader("CamelFileName")); } }
  • 56. Puedes ahora usarla en el route de tu DSL Spring como sigue: <bean id="downloadLogger" class="camelinaction.DownloadLogger"/> <camelContext xmlns="http://camel.apache.org/schema/spring"> <route> <from uri="file:src/data?noop=true"/> <process ref="downloadLogger"/> <to uri="jms:incomingOrders"/> </route> </camelContext>
  • 57. Enrutamientos y EIPs Usando un Enrutador Basado en Contenido (CBR) Como su nombre lo implica, un Enrutador Basado en Contenido (CBR) es un router de mensaje que enruta un mensaje a un destino basado en su contenido. El contenido podría ser un header de mensaje, el tipo de dato del payload, parte del mismo payload. Para demostrar, vamos atrás a Autopartes Rider. Algunos clientes han empezado a cargar órdenes al servidor FTP en el formato XML más nuevo más que CSV. Lo que significa que tienes dos tipos de mensajes entrantes a la queue incomingOrders. No hemos tocado esto antes, pero necesitas convertir las órdenes entrantes en un formato POJO interno. Obviamente necesitas hacer diferentes conversiones para los diferentes tipos de órdenes entrantes. Como una posible solución, podrías usar la extensión del nombre de archivo si un mensaje de orden particular debe ser enviado a la queue para órdenes CSV o a una queue para órdenes XML.
  • 58. Enrutamientos y EIPs Usando un Enrutador Basado en Contenido (CBR) Figura 2.10. El CBR enruta mensajes basado en su contenido. En este caso, la extensión filename (como un header del mensaje) es usado para determinar a qué queue enrutar.
  • 59. Enrutamientos y EIPs Como lo viste antes, puedes usar el header CamelFileName asignado por el consumidor FTP para obtener el nombre de archivo. Para hacer el enrutamiento condicional requerido por el CBR, Camel introduce algunas keywords en el DSL. El método choice crea un processor CBR, y las condiciones son agregadas siguiendo choice con una combinación de un método choice con una combinación de un método when y un predicado. from("jms:incomingOrders") .choice() .when(predicate) .to("jms:xmlOrders") .when(predicate) .to("jms:csvOrders");
  • 60. Enrutamientos y EIPs Puedes haber notado que no llenamos el predicado requerido por cada método when. Un predicado en Camel es una simple interface que sólo tiene un método matches: public interface Predicate { boolean matches(Exchange exchange); } Por ejemplo, puedes pensar de un predicado como una condición booleana en una sentencia if Java. Probablemente no quieras buscar por ti mismo dentro del exchange y hacer una comparación. Afortunadamente, los predicados son construidos de expresiones, y las expresiones son usadas para extraer resultados basados de un exchange basado en el contenido de la expresión.
  • 61. Enrutamientos y EIPs Hay muchos lenguajes de expresión de los cuales elegir en Camel, algunos de los cuales incluyen Simple, EL, JXPath, Mvel, OGNL, PHP, BeanShell, JavaScript, Groovy, Python, Ruby, XPath y XQuery. En el RouteBuilder, puedes comenzar usando el método header, que retorna una expresión que evaluará al valor del header. Por ejemplo, header(“CamelFileName”) creará una expresión que resolverá al valor del header CamelFileName en el siguiente exchange. En esta expresión puedes invocar muchos métodos para crear un predicado. Así que verifica si la extensión del nombre del archivo es .xml, puedes usar el siguiente predicado: header(“CamelFileName”).endsWith(“.xml”);
  • 62. Enrutamientos y EIPs context.addRoutes(new RouteBuilder() { public void configure() { from("file:src/data?noop=true").to("jms:incomingOrders"); from("jms:incomingOrders") .choice() .when(header("CamelFileName") .endsWith(".xml")) .to("jms:xmlOrders") .when(header("CamelFileName") .endsWith(".csv")) .to("jms:csvOrders"); from("jms:xmlOrders").process(new Processor() { public void process(Exchange exchange) throws Exception { System.out.println("Received XML order: " + exchange.getIn().getHeader("CamelFileName")); } }); from("jms:csvOrders").process(new Processor() { public void process(Exchange exchange) throws Exception { System.out.println("Received CSV order: " + exchange.getIn().getHeader("CamelFileName")); } }); } });
  • 63. Enrutamientos y EIPs Usando Filtros de Mensajes Figura 2.12. Un Filtro de Mensaje te permite filtrar los mensajes que no importan basados en alguna condición. En este caso los mensajes de prueba son filtrados.
  • 64. Enrutamientos y EIPs Usando filtros de mensajes AutoPartes Rider ahora tiene un nuevo issue –su departamento de QA ha expresado la necesidad de enviar órdenes de prueba en el frontend web en vivo del sistema de órdenes. Tu solución actual aceptaría estas órdenes como reales y enviarlas a los sistemas externos para procesamiento. Tu has sugerido que QA pruebe en un clon de desarrollo del sistema real, pero la gestión ha desechado esa idea, alegando un presupuesto limitado. Lo que necesitas es una solución que descarte estos mensajes de prueba mientras aún se opera en las órdenes reales. El EIP Message Filter, proporciona una buena forma de tratar con esta clase de problemas. Los mensajes entrantes sólo pasan el filtro si reúnen una cierta condición. Los mensajes que no reúnen la condición son desechados.
  • 65. Enrutamientos y EIPs Usando filtros de mensajes from("jms:xmlOrders").filter(xpath("/order[not(@test)]")) .process(new Processor() { public void process(Exchange exchange) throws Exception { System.out.println("Received XML order: " + exchange.getIn().getHeader("CamelFileName")); } }); El anterior en el DSL Java, y el siguiente en el DSL de Spring <route> <from uri="jms:xmlOrders"/> <filter> <xpath>/order[not(@test)]</xpath> <process ref="orderLogger"/> </filter> </route>
  • 66. Enrutamientos y EIPs Usando Multicasting Figura 2.13. Un multicast envía un mensaje a un número de receptores específicos.
  • 67. Enrutamientos y EIPs Usando Multicasting Frecuentemente en las aplicaciones empresariales necesitarás enviar una copia de un mensaje a varios destinos diferentes para procesamiento. Cuando la lista de destinos es conocida adelante del tiempo y es estática, puedes agregar un elemento al route que consumirá mensajes desde un endpoint fuente y luego enviar el mensaje a una lista de destinos.
  • 68. Enrutamientos y EIPs Usando lista de receptores Figura 2.14. Una lista de receptores inspecciona los mensajes entrantes y determina una lista de receptores basado en el contenido del mensaje. En este caso, sólo es enviado a los destinos A, B, y D.
  • 69. Enrutamientos y EIPs Usando lista de receptores Usando el EIP Recipient List. Una lista de receptores primero inspecciona el mensaje entrante, luego genera una lista de receptores deseados basados en el contenido del mensaje, y envía el mensaje a esos receptores. Un receptor es especificado por una URI. Nota que la lista de receptores es diferente que el multicast debido a que la lista de receptores es dinámica. Camel proporciona un método recipientList para implementar el patrón EIP Recipient List. Por ejemplo, el siguiente route tomará la lista de receptores desde un header llamado recipients, donde cada recipiente es separado del siguiente por una coma: from("jms:xmlOrders") .recipientList(header("recipients"));
  • 70. Enrutamientos y EIPs En la versión DSL Java from("jms:xmlOrders") .setHeader("customer", xpath("/order/@customer")) .process(new Processor() { public void process(Exchange exchange) throws Exception { String recipients = "jms:accounting"; String customer = exchange.getIn().getHeader("customer", String.class); if (customer.equals("honda")) { recipients += ",jms:production"; } exchange.getIn().setHeader("recipients", recipients); } }) .recipientList(header("recipients"));
  • 71. Enrutamientos y EIPs En la versión DSL Spring <route> <from uri="jms:xmlOrders" /> <setHeader headerName="customer"> <xpath>/order/@customer</xpath> </setHeader> <process ref="calculateRecipients" /> <recipientList> <header>recipients</header> </recipientList> </route>
  • 72. Enrutamientos y EIPs Usando el método wireTap
  • 73. Enrutamientos y EIPs Usando el método wireTap Frecuentemente en aplicaciones empresariales es útil y necesario inspeccionar cómo los mensajes fluyen a través del sistema. Por ejemplo, cuando una orden falla, necesitas una forma de buscar qué mensajes fueron recibidos fueron recibidos para determinar la causa de la falla. Usando el método wireTap en el DSL Java, puedes enviar una copia del exchange a un destino secundario sin afectar el comportamiento del resto del route. from("jms:incomingOrders") .wireTap("jms:orderAudit") .choice() .when(header("CamelFileName").endsWith(".xml")) .to("jms:xmlOrders") .when(header("CamelFileName").regex("^.*(csv|csl)$")) .to("jms:csvOrders") .otherwise() .to("jms:badOrders");
  • 74. GRACIAS Dudas y comentarios al email: it.adesales@gmail.com Y en la página www.facebook.com/JavaDevelopersMexico No olviden regalarnos un like.