SlideShare una empresa de Scribd logo
1 de 83
Descargar para leer sin conexión
Abimael Desales López
Java Developers México
Contenido
1. Vista General de la Transformación de Datos
2. Transformando datos usando EIPs y Java
1. Usando el EIP Message Translator
2. Usando el EIP Content Enricher
3. Transformando XML
1. Transformando XML con XSLT
2. Transformando XML con marshalling de objetos
4. Transformando con formatos de datos
1. Formatos de datos provistos con Camel
2. Usando el formato de dato CSV de Camel
3. Usando el formato de dato Bindy de Camel
4. Usando el formato de dato JSON de Camel
5. Configurando formatos de datos Camel
6. Escribiendo tu propio formato de datos
Contenido
5. Transformando con plantillas
1. Usando Apache Velocity
6. A cerca de los convertidores de tipo Camel
5. Cómo funciona el mecanismo convertidor de tipo Camel
6. Usando los convertidores de tipo Camel
7. Escribiendo tu propio convertidor de tipo
1.Vista General de la Transformación de Datos
Camel proporciona muchas técnicas para transformación de datos.
La transformación de datos es un término amplio que cubre dos
tipos de transformación:
 Transformación de formatos de datos. El formato de datos del
cuerpo del mensaje es transformado de una forma a otra. Por
ejemplo, un registro CSV es formateado como XML.
 Transformación de tipo de datos. El tipo de datos del cuerpo del
mensaje es transformado de un tipo a otro. Por ejemplo, un
java.lang.String es transformado en un javax.jms.TextMessage.
La figura 3.1 ilustra el principio de transformar el cuerpo de un
mensaje de un formato a otro. Esta combinación puede involucrar
cualquier combinación de tipo y formato.
En la mayoría de los casos la transformación de datos con la que te
enfrentarás con Camel es transformación de formato, donde tienes
que mediar entre dos protocolos. Camel tiene un mecanismo
convertidor de tipo incorporado que puede convertir
automáticamente entre dos tipos, lo cual reduce mucho la
necesidad de tratar para los usuarios finales con transformaciones
de tipo.
1.Vista General de la Transformación de Datos
Figura 3.1. Camel ofrece
muchas características para
transformación de datos de un
formato a otro
Transformación de datos con Camel
En Camel la transformación de datos generalmente toma lugar en
las seis formas listadas en la tabla 3.1.
Transformación Descripción
Transformación de datos en
routes
Puedes explícitamente forzar la transformación en el route usando los EIPs
Message Translator o Content Enricher. Esto te da el poder de hacer mapeos
de datos usando código regular Java.
Transformación de datos
usando componentes
Camel proporciona un rango de componentes para transformación, como lo
es el componente XSLT para transformación XML.
Transformación de datos
usando formatos de datos
Los formatos de datos son transformadores Camel que vienen en pares para
transformar datos atrás y hacia adelante entre formatos bien conocidos
Transformación de datos
usando templates
Camel proporciona un rango de componentes para transformar usando
plantillas, como Apache Velocity.
Transformación de tipos de
datos usando el mecanismo
convertidor de tipos de Camel
Camel tiene un mecanismo convertidor de tipos elaborado que se activa bajo
demanda. Esto es conveniente cuando necesitas convertir de tipos comunes
como java.lang.Integer a java.lang.String o aún de java.io.File a
java.lang.String.
Transformación de mensajes
en adaptadores de
componentes
Muchos componentes de Camel se adaptan a varios protocolos comúnmente
usados y, como tal, necesita ser capaz de transformar mensajes en la medida
en que viajan a y desde estos protocolos. Frecuentemente estos componentes
usan una combinación de transformaciones de datos y convertidores de tipo
personalizadas.
2. Transformando datos usando EIPs y Java
Data Mapping es el proceso de mapear entre dos modelos de datos
distintos, y es un factor clave en la integración de datos. Hay
muchos estándares existentes para modelos de datos, gobernados
por varias organizaciones o comités. Por tal, frecuentemente te
encontrarás necesario mapear del modelo de datos personalizado
de una compañía a un modelo de datos estándar.
Camel proporciona gran libertad en el mapeo de datos debido a
que te permite usar código Java –no estás limitado a usar una
herramienta de mapeo de datos particular que en la primera podría
parecer elegante pero que torna a hacer las cosas imposibles.
Aquí veremos cómo mapear datos usando un Processor, el cual es
una API Camel. Camel también usa beans para mapear, lo cual es
una buena práctica, debido a que le permite a tu lógica de mapeo
ser independiente de la API de Camel.
Usando el EIP Message Translator
El EIP Mesage Translator es ilustrado en la figura 3.2
Este patrón cubre traducir un mensaje de un formato a otro. Es el
equivalente al patrón Adapter del libro Gang of Four.
Camel provee tres formas de usar este patrón:
 Usando un Processor
 Usando beans
 Usando <transform>
Transformando usando un Processor
El Processor de Camel es una interface definida en
org.apache.camel.Processor con un sólo método:
public void process(Exchange exchange) throws Exception;
El Processor es una API de bajo nivel donde trabajas directamente en la
instancia Exchange de Camel. Te da acceso completo a todas las partes de
Camel que se mueven del CamelContext, del cual puedes obtener del
Exchange usando el método getCamelContext.
Veamos un ejemplo. En Autopartes Rider se te ha solicitado generar
diariamente reportes de órdenes recientemente recibidas para ser sacadas a
un archivo CSV. La compañía usa un formato personalizado para entradas de
órdenes, pero hace las cosas fáciles, ellos ya tienen un servicio HTTP que
retorna una lista de órdenes para cualquier dato que ingreses. El reto al que
te enfrentas es mapear los datos retornados del servicio HTTP a un formato
CSV y escribir el reporte a un archivo.
Listado 3.1 Usando un Processor para traducir desde un formato personalizado a formato CSV
import org.apache.camel.Exchange;
import org.apache.camel.Processor;
public class OrderToCsvProcessor implements Processor {
public void process(Exchange exchange) throws Exception {
String custom = exchange.getIn().getBody(String.class);
String id = custom.substring(0, 9);
String customerId = custom.substring(10, 19);
String date = custom.substring(20, 29);
String items = custom.substring(30);
String[] itemIds = items.split("@");
StringBuilder csv = new StringBuilder();
csv.append(id.trim());
csv.append(",").append(date.trim());
csv.append(",").append(customerId.trim());
for (String item : itemIds) {
csv.append(",").append(item.trim());
}
exchange.getIn().setBody(csv.toString());
}
}
Obtiene payload
personalizado
Extrae datos a
variables locales
Mapea a
formato CSV
Remplaza payload
con payload CSV
Primero coges el payload de formato personalizado del exchange.
Es de tipo String, de forma que pasas una String como parametro
de entrada para tener el payload retornado como una String. Luego
extraes datos del formato personalizado a las variables locales. El
formato personalizado podría ser cualquier cosa, pero en este
ejemplo es un formato personalizado de longitud fija. Luego
mapeas el formato CSV construyendo una string con valores
separados por coma. Finalmente, remplaza el payload
personalizado con tu nuevo payload CSV.
Usar un processor tiene una desventaja, requieres hacer uso de la
API Camel.
Importante
Usando los métodos getIn y getOut en exchanges
El Exchange Camel define dos métodos para retomar mensajes: getIn y
getOut. El método getIn retorna el mensaje entrante, y el método getOut
accesa el mensaje saliente.
Hay dos escenarios donde el usuario final Camel tendrá que decidir entre usar
estos métodos:
 Un escenario de sólo lectura, como cuando envías a log el mensaje
entrante.
 Un escenario de escritura, como cuando estás transformando el mensaje
En el segundo escenario asumirías que se debería usar getOut. Eso es correcto
acorde a la teoría, pero en la práctica hay una trampa cuando se usa getOut:
los headers y attachments del mensaje entrante se perderán. Frecuentemente
esto no es lo que quieres, de forma que copiar los headers y attachments del
mensaje entrante al mensaje saliente, puede ser tedioso. La alternativa es
asignar los cambios directamente en el mensaje entrante usando getIn, y no
usar getOut en todo.
Transformando usando Beans
Usar beans es una buena práctica debido a que te permite usar
cualquier código Java y librerías que desees. Camel no impone
restricciones en ninguna cosa. Camel puede invocar cualquier bean
que elijas, de forma que puedes usar beans existentes sin tener que
rescribirlos o recompilarlos.
Listado 3.2 Usando un bean para traducir de un formato personalizado a formato CSV
public class OrderToCsvBean {
public static String map(String custom) {
String id = custom.substring(0, 9);
String customerId = custom.substring(10, 19);
String date = custom.substring(20, 29);
String items = custom.substring(30);
String[] itemIds = items.split("@");
StringBuilder csv = new StringBuilder();
csv.append(id.trim());
csv.append(",").append(date.trim());
csv.append(",").append(customerId.trim());
for (String item : itemIds) {
csv.append(",").append(item.trim());
}
return csv.toString();
}
}
Extrae datos a
variables locales
Mapea a
formato CSV
Retorna payload
CSV
La primer diferencia notable entre los listados 3.1 y 3.2 es que en el
listado 3.2 no se usa ningún import de Camel. Esto significa que tu
bean es totalmente independiente de la API Camel. La siguiente
diferencia es que puedes nombrar la firma del método en el listado
3.2 –en este caso es un método estático llamado map.
La firma del método define el contrato, lo cual significa que el
primer parámetro, (String custom), es el body del mensaje que
vas a usar para la traducción. El método retorna una String, lo
cual significa que los datos traducidos serán de tipo String. En
ejecución, Camel vincula a esta firma del método.
Una ventaja más de usar beans sobre processors para mapeos es
que las pruebas unitarias son mucho más fáciles.
Transformando usando el método transform() del DSL Java
Transform() es un método en el DSL Java que puede ser usado en
routes Camel para transformar mensajes. Permitiendo el uso de
expresiones, transform() permite gran flexibilidad, y usando
expresiones directamente en el DSL a veces puede ahorrar tiempo.
Supongamos que necesitas preparar algún texto para formateo
HTML remplazando todos los saltos de línea con una tag <br/>.
Esto puede hacerse con una expresión incorporada de Camel que
busca y remplaza utilizando expresiones regulares.
from("direct:start")
.transform(body().regexReplaceAll("n", "<br/>"))
.to("mock:result");
Lo que este route hace es usar el método transform() para decirle a
camel que el mensaje debe ser transformado usando una expresión.
Camel provee lo que es conocido como el patrón Builder para
construir expresiones desde expresiones individuales. Este se hace
encadenando llamadas a métodos, lo cual es la esencia del patrón
Builder.
En este ejemplo combinas body() y regexReplaceAll(). La
expresión debe ser leída como sigue: toma el body y ejecuta una
expresión regular que remplace todas las nuevas líneas (n) con
tags <br/>. Ahora hemos combinado dos métodos que conforman
a una expresión Camel compuesta.
Camel te permite usar tus propias expresiones personalizadas. Esto
es útil cuando necesitas tener control completo y tener código Java
en la punta de tus dedos. Por ejemplo, el ejemplo anterior podría
haber sido implementado de la forma siguiente:
from("direct:start")
.transform(new Expression() {
public <T> T evaluate(Exchange exchange, Class<T> type) {
String body = exchange.getIn().getBody(String.class);
body = body.replaceAll("n", "<br/>");
body = "<body>" + body + "</body>";
return (T) body;
}
}).to("mock:result");
Transformando usando <transform> de Spring XML
Usar <transform> de Spring XML es un poco diferente que el DSL
Java debido a que el DSL XML no es tan poderoso. No están
disponibles las expresiones del patrón Builder debido a que XML
no tiene un lenguaje de programación real tras él. Lo que puedes
hacer tras ello es invocar un método en un bean o usar lenguajes de
scripting.
Veamos cómo trabaja esto. El método del siguiente bean se usa
dentro del route como la expresión:
public class HtmlBean {
public static String toHtml(String body) {
body = body.replaceAll("n", "<br/>");
body = "<body>" + body + "</body>";
return body;
}
}
El route es el siguiente:
<bean id="htmlBean" class="camelinaction.HtmlBean"/>
<camelContext id="camel"
xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="direct:start"/>
<transform>
<method bean="htmlBean" method="toHtml"/>
</transform>
<to uri="mock:result"/>
</route>
</camelContext>
Primero declaras un bean regular de Spring para ser usado para
transformar el mensaje. Luego en el route, usas <transform> con
una expresión llamada <method> para invocar el bean.
Usando el patrón EIP Content Enricher
El EIP Content Enricher se ilustra en la figura 3.3. Este patrón
documenta el escenario donde un mensaje es enriquecido con
datos obtenidos de otro recurso.
Figura 3.3 En el EIP Content Enricher, un
mensaje existente tiene datos agregados
de otra fuente.
Para ayudar a comprender este patrón, regresaremos a Aupartes
Rider. Nos damos cuenta que el mapeo de datos que hicimos en el
listado 3.1 no era suficiente. Las órdenes también son acumuladas
en un servidor FTP, y tu job va de alguna manera a mezclar esta
información en el reporte existente. La figura 3.4 ilustra este
escenario.
En la figura 3.4, un consumidor calendarizado usando Quartz
inicia el route cada día a las 6:00 am 1. Luego obtiene datos de un
servidor FTP, el cual retorna órdenes en un formato personalizado
2, el cual luego es transformado en formato CSV 3. En este punto,
tienes que ejecutar el paso de enriquecimiento de contenido
adicional 4 con los datos obtenidos del servidor FTP 5. Después de
esto, el reporte final es escrito al servidor FTP 6.
Figura 3.4
Una vista general del route
que genera el reporte de
órdenes, ahora con el
enriquecedor de contenido
obteniendo datos de un
servidor FTP.
Antes de profundizarnos en el código y ver cómo implementar esto,
necesitamos ir un paso atrás y ver cómo el EIP Content Enricher es
implementado en Camel. Camel proporciona dos operaciones en el
DSL para implementar el patrón.
 pollEnrich – Esta operación mezcla datos retomados de otra
fuente usando un consumidor.
 enrich – Esta operación mezcla datos retomados de otra fuente
usando un productor.
Camel usa la interfaz org.apache.camel.processor.
AgregationStrategy para mezclar los resultados de la fuente con el
mensaje original, de la forma siguiente:
Exchange aggregate(Exchange oldExchange, Exchange newExchange);
Este método aggregate es una callback que debes implementar.
Este método tiene dos parámetros: el primero, llamado
oldExchange, contiene el exchange original; el segundo,
newExchange, es la fuente enriquecida. Tu tarea es enriquecer el
mensaje usando código Java y retornar el resultado mezclado. Esto
puede sonar un poco confuso, veámoslo en acción.
Para resolver el problema, necesitas usar pollEnrich debido a que
es capaz de votear por un archivo de un servidor FTP.
Enriqueciendo usando POLLENRICH.
El listado 3.3 muestra cómo puedes usar pollEnrich para retomar
las órdenes adicionales del servidor FTP remoto y agregar estos
datos con el mensaje existente usando AggregationStrategy de
Camel.
Listado 3.3 Usando pollEnrich para mezclar datos adicionales con un mensaje existente
from("quartz://report?cron=0+0+6+*+*+?")
.to("http://riders.com/orders/cmd=received")
.process(new OrderToCSVProcessor())
.pollEnrich("ftp://riders.com/orders/?username=rider&password=secret",
new AggregationStrategy() {
public Exchange aggregate(Exchange oldExchange, Exchange newExchange){
if (newExchange == null) {
return oldExchange;
}
String http = oldExchange.getIn().getBody(String.class);
String ftp = newExchange.getIn().getBody(String.class);
String body = http + "n" + ftp;
oldExchange.getIn().setBody(body);
return oldExchange;
}
})
.to("file://riders/orders");
1
2
Mezcla datos
usando
AggregationStrategy
3 Escribe la salida a archivo
Usa pollEnrich para leer un
archivo FTP
El route es disparado por Quartz para que corra todos los días a las
6 am. Invocas el servicio HTTP para retomar las órdenes y
transformarlas a formato CSV usando un processor.
En este punto, necesitas enriquecer los datos existentes con las
órdenes del servidor FTP remoto. Esto se hace usando pollEnrich 1,
lo cual consume el archivo remoto.
Para mezclar los datos, usas AggregationStrategy 2. Primero,
checas si algunos datos fueron o no consumidos. Si newExchange es
null, no hay archivo remoto para consumir, y sólo retornas los
datos existentes. Si hay un archivo remoto, mezclas los datos
concatenando los datos existentes con los nuevos datos y
asignándolos atrás en el oldExchange. Luego, retornas los datos
mezclados retornando el oldExchange. Para escribir el archivo de
reporte CSV, usas el componente file.
PollEnrich utiliza un consumidor de voteo para retomar mensajes,
y ofrece tres modos de timeout:
 pollEnrich(timeout=-1)- Votea el mensaje y espera hasta que un
mensaje llegue. Este modo bloqueará hasta un mensaje exista.
 pollEnrich(timeout=0)- Inmediatamente votea el mensaje si
alguno existe; de otra forma se retornará null. Nunca esperará
para que los mensajes lleguen, así que este modo nunca
bloqueará. Este es el modo default.
 pollEnrich(timeout>0)- Votea el mensaje, si no existe mensaje,
esperará por uno, esperando a lo más hasta que el timeout se
dispare. Este modo potencialmente bloqueará.
Es una mejor práctica usar timeout=0 o asignar un valor de
timeout cuando se usa pollEnrich para evitar esperar
indefinidamente si no llegan mensajes.
Enriqueciendo usando ENRICH
Enrich es usado cuando necesitas enriquecer el mensaje actual con
datos de otra fuente usando mensajería request-response. Un primer
ejemplo sería enriquecer el mensaje actual con la respuesta de una
llamada a web service. Pero veremos otro ejemplo, usando Spring XML
para enriquecer el mensaje actual usando el transporte TCP:
<bean id="quoteStrategy“ class="camelinaction.QuoteStrategy"/>
<route>
<from uri="activemq:queue:quotes"/>
<enrich url="mina:tcp://riders.com:9876?textline=true&sync=true"
strategyRef="quoteStrategy"/>
<to uri="log:quotes"/>
</route>
Aquí usas el componente mina de Camel para transporte TCP,
configurado para usar mensajería request-response usando la opción
sync=true.
1
Bean implementando AggregationStrategy
Para mezclar el mensaje original con datos del servidor remoto,
<enrich> debe referir a una AggregationStrategy. Esto se hace
usando el atributo strategyRef. Como lo puedes ver en el ejemplo,
la quoteStrategy a la que está siendo referida es el id de un bean
1, el cual contiene la implementación real de la
AggregationStrategy, donde la mezcla toma lugar.
3.3 Transformando XML
Camel proporciona dos formas de ejecutar transformaciones XML.
 Componente XSLT –Para transformar un payload XML en otro
formato usando hojas de estilo XSLT.
 Marshaling XML –Para serializar y deserializar objetos a y desde
XML.
Transformando XML con XSLT
XSL Transformations (XSLT) es un lenguaje XML declarativo usado
para transformar documentos XML en otros documentos. Por
ejemplo, XSLT puede ser usado para transformar XML en HTML
para páginas web o para transformar un documento XML en otro
documento XML con una estructura diferente. XSLT es poderoso y
versátil, pero también es un lenguaje complejo y toma tiempo y
esfuerzo comprenderlo y dominarlo. Hay que pensarlo dos veces.
Camel provee XSLT como un componente en camel-spring.jar
debido a que aprovecha la carga de recursos de Spring. Esto
significa mayor flexibilidad en la carga de hojas de estilo debido a
que Spring les permite ser cargadas de diferentes ubicaciones,
como lo es del classpath, rutas de archivos, y sobre HTTP.
Figura 3.5 Un Camel route usando un componente XSLT para transformar un
documento XML antes de que sea enviado a una queue JMS
Usar el componente XSLT es sencillo, debido a que es sólo otro
componente Camel. El siguiente route muestra un ejemplo de cómo
podrías usarlo; este route también es ilustrado en la figura 3.5.
from("file://rider/inbox")
.to("xslt://camelinaction/transform.xsl")
.to("activemq:queue:transformed")
El consumidor de archivos selecciona los nuevos archivos y los
enruta al componente XSLT, el cual transforma el payload usando la
hoja de estilos. Después de la transformación, el mensaje es
enrutado a un productor JMS. Nota en el código anterior como es
definida la URL para el componente XSLT:
xslt://camelinaction/transform.xsl. La parte posterior del esquema
es la ubicación URI de la hoja de estilo a usar. Por default Camel
buscará en el classpath.
El componente XSLT aprovecha Spring para cargar la hoja de
estilos. Puedes prefijar el nombre del recurso con cualquiera de los
tres prefijos listados en la tabla 3.2.
Prefijo Ejemplo Descripción
<ninguno> xslt://camelinaction/transform.xsl Si no se proporciona prefijo, camel
carga el recurso del classpath
classpath xslt://classpath:com/mycompany/tra
nsform.xsl
Carga el recurso del classpath
file xslt://file:/rider/config/transform.xsl Carga el recurso del sistema de
archivos local
http: xslt://http://rider.com/styles/transfor
m.xsl
Carga el recurso de una URL
Transformando XML con Marshalling de Objetos
Cualquier ingeniero de software quien ha trabajado con XML sabe
que es un reto usar la API XML de bajo nivel que ofrece Java. En
lugar de eso, la gente frecuentemente prefiere trabajar con objetos
Java regulares y usar marshalling para transformar entre objetos
Java y representaciones XML.
En Camel este proceso de marshalling es provisto en componentes
listos-para-usar conocidos como formatos de datos.
Transformando usando XStream
XStream es una simple librería para serializar objetos a XML y hacia
atrás. Para usarla, necesitas el camel-xstream.jar en el classpath y la
misma librería de XStream.
Supón que necesitas enviar mensajes en formato XML a una queue
JMS compartida, la cual luego es usada para integrar dos sistemas.
Transformando usando Marshalling de Objetos
Listado 3.4 Usando XStream para transformar un mensaje en XML
<camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
<dataFormats>
<xstream id="myXstream"/>
</dataFormats>
<route>
<from uri="direct:foo"/>
<marshal ref="myXstream"/>
<to uri="activemq:queue:foo"/>
</route>
</camelContext>
Cuando usas el DSL XML, puedes declarar los formatos de datos
usados arriba 1 del <CamelContext>. Haciendo esto, puedes
compartir los formatos de datos en múltiples routes. En este primer
route, donde envías mensajes a una queue JMS, usas marshall 2, lo
cual se refiere al id de 1,, de forma que Camel sabe que el formato
de datos XStream está siendo usado.
Especifica formato de datos XStream
Transforma a XML
Transformando usando Marshalling de Objetos
También puedes usar directamente en el route, lo cual puede
acortar un poco la sintaxis, como esto:
<route>
<from uri="direct:foo"/>
<marshal> <xstream/> </marshall>
<to uri="activemq:queue:foo"/>
</route>
</camelContext>
El mismo route es un poco más acortador para escribir en el DSL
Java, debido a que puedes hacerlo con una línea por route:
from("direct:foo").marshal().xstream().to("uri:activemq:queue:foo");
Sí, usar Xstream es tan fácil. Y la operación inversa, unmarshalling
de XML a un objeto, es tan simple:
Transformando usando Marshalling de Objetos
<route>
<from uri="activemq:queue:foo"/>
<unmarshal ref="myXstream"/>
<to uri="direct:handleFoo"/>
</route>
Ya has visto cuan fácil es usar XStream con Camel.
Transformando usando JAXB
JAXB (Java Architecture for XML Binding) es una especificación
estándar para XML binding, y es provista lista en el runtime Java.
Como XStream, te permite serializar objetos a XML y hacia atrás
otra vez. No es tan simple, pero ofrece más opciones para controlar
la salida XML. Y debido a que es distribuido en Java, no necesitas
algunos archivos Jars especiales en el classpath.
A diferencia de XStream, JAXB requiere que hagas un poco de
trabajo para declarar el binding entre objetos Java y el formato
XML. Esto frecuentemente se hace usando anotaciones. Supón que
defines un modelo de bean para representar una orden, como se
muestra en el listado 3.5, y quieres transformar esto en XML antes
de enviarlo a una queue JMS. Luego quieres transformarlo atrás al
bean de orden otra vez, cuando consumes de la queue JMS. Esto
puede hacerse como se muestra en los listados 3.5 y 3.6.
Transformando usando JAXB
package com.acme.order;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class PurchaseOrder {
@XmlAttribute
private String name;
@XmlAttribute
private double price;
@XmlAttribute
private double amount;
}
1
PurchaseOrder en una clase JAXB anotada
Listado 3.5 Anotando un bean con JAXB de
forma que pueda ser transformado a y desde XML
Transformando usando JAXB
El listado 3.5 muestra como usar anotaciones JAXB para decorar tu objeto
modelo (omitiendo los getters y setters usuales). Primero define
@XmlRootElement 1 como una anotación a nivel de clase para indicar que
esta clase es un elemento XML. Luego defines el @XmlAccessorType
para permitir que JAXB accese los campos directamente. Para exponer los
campos de este objeto modelo como atributos XML, los marcas con la
anotación @XmlAttribute.
Usando JAXB, debes ser capaz de serializar un objeto modelo en una
representación XML como esta:
<purchaseOrder name="Camel in Action" price="4995" amount="1"/>
El listado 3.6 muestra como puedes usar JAXB en routes para transformar
el objeto PurchaseOrder a XML antes de que sea enviado a una queue
JMS, y luego atrás otra vez de XML al objeto PurchaseOrder cuando se
consume de la misma queue JMS.
Transformando usando JAXB
Listado 3.5 Usando JAXB para serializar objetos a y desde XML
<camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
<dataFormats>
<jaxb id="jaxb" contextPath="camelinaction"/>
</dataFormats>
<route>
<from uri="direct:order"/>
<marshal ref="jaxb"/>
<to uri="activemq:queue:order"/>
</route>
<route>
<from uri="activemq:queue:order"/>
<unmarshal ref="jaxb"/>
<to uri="direct:doSomething"/>
</route>
</camelContext>
1
Declara formato de datos JAXB
2
Transforma de modelo a XML
3
Transforma de XML a modelo
Transformando usando JAXB
Primero necesitas declarar el formato de datos JAXB 1. Nota que también
se define un atributo contextPath en el formato de datos JAXB –este es un
nombre de package que instruye a JAXB que busque en este package
clases que son anotadas de JAXB.
El primer route luego serializa a XML 2 y el segundo route deserializa para
transformar el XML atrás al objeto PurchaseOrder 3.
Nota: Para decirle a JAXB qué clases son anotadas de JAXB, necesitas
arrastrar un archivo especial jaxb.index en la ruta del contexto. Es un
archivo de texto plano en el cual cada línea lista el nombre de la clase. En
el ejemplo anterior, el archivo contiene una sola línea con el texto
PurchaseOrder.
3.4 Transformando con formatos de datos
En Camel, los formatos de datos son transformadores pluggables que
pueden transformar mensajes de un formato a otro y viceversa. Cada
formato de dato es representado en Camel como una interface
org.apache.camel.spi.DataFormat conteniendo dos métodos:
 marshall – Para serializar un objeto en otro formato, tal como serializar
objetos Java a XML, CSV, EDI, HL7, u otros modelos de datos conocidos.
 unmarshall – Para ejecutar la operación inversa, la cual transforma datos de
formatos bien conocidos atrás en un mensaje.
Figura 3.6 Un objeto es
serializado a una
representación binaria;
unmarshall puede utilizarse
para llevar el objeto atrás.
Ya pudiste haberte dado cuenta que estas dos funciones son
opuestas, significando que una es capaz de hacer lo inverso de lo
que la otra ha hecho, como lo ilustra la figura 3.6.
En esta sección cubriremos los formatos de datos en más
profundidad y usando otros tipos de datos diferentes a XML, como
es CSV y JSON. Aún también veremos cómo puedes crear tus
propios formatos de datos.
Comenzaremos nuestra jornada checando los formatos de datos
Camel provistos listos para usar.
Formatos de datos provistos con Camel
Camel provee formatos de datos para un rango de modelos de datos
bien conocidos, como se lista en la tabla 3.3.
Tabla 3.3 Formatos de datos provistos listos con Camel
Formato
de dato
Modelo de
dato
Artefacto Descripción
Bindy CSV, FIX,
longitud fija
camel-bindy Vincula varios modelos de datos para modelar objetos usando
anotaciones
Castor XML camel-castor Usa Castor para vincular a y desde objetos Java
Crypto Cualquiera camel-crypto Encripta y desencripta datos usando la Java Cryotography
Extension
CSV CSV camel-csv Transforma a y desde CSV usando la librería Apache Commons
CSV
Flatpack CSV camel-flatpack Transforma a y desde CSV usando la librería FlatPack
GZip Cualquiera camel-gzip Comprime y descomprime archivos (compatible con las populares
herramientas gzip/gunzip)
HL7 HL7 camel-hl7 Transforma a y desde HL7, el cual es un formato de datos bien
conocido en la industria del cuidado de la salud
JAXB XML camel-jaxb Usa el estándar JAXB 2.x para vincular XML a y desde objetos Java
Jackson JSON camel-jackson Transforma a y desde JSON usando la ultrarrápida librería Jackson
Tabla 3.3 Formatos de datos provistos listos con Camel (cont)
Formato de
dato
Modelo de
dato
Artefacto Descripción
Protobuf XML camel-
protobuf
Transforma a y desde XML usando la librería Google Protocol
Buffers
SOAP XML camel-soap Transforma a y desde SOAP
Serialization Objeto camel-core Usa serialización de objetos para transformar objetos a y desde
un stream serializado
TidyMarkup HTML camel-tagsoup
xmalBeans XML camel-
xmlsbeans
Usa XmlBeans para vincular XML a y desde objetos Java
XMLSecurity XML camel-
xmlsecurity
Facilita la encripción y desencripción de documentos XML
XStream XML camel-xstream Usa XStream para vinculación XML a y desde objetos Java
XStream JSON camel-xstream Transforma a y desde JSON usando la librería XStream
Zip Cualquiera camel-core Usa el estándar JAXB 2.x para vincular XML a y desde objetos
Java
Como puedes ver, Camel proporciona 18 formatos de datos listos
para usar. Aquí estaremos viendo 3 de ellos. Ellos son los formatos
más comúnmente usados, y lo que aprendas sobre estos aplicarán
también para los restantes formatos de datos.
Usando el formato de datos CSV de Camel
El formato de datos camel-csv es capaz de transformar a y desde
formato CSV. Aprovecha Apache Commons CSV para hacer el
trabajo real.
Supón que necesitas consumir archivos CSV, dividir cada fila, y
enviarla a una queue JMS. Suena difícil de hacer, pero es posible
con poco esfuerzo en un route Camel:
from.(“file://rider/csvfiles”)
.unmarshall().csv()
.split(body()).to(“activemq:queue.csv.record”);
Todo lo que tienes que hacer es unmarshall los archivos CSV, lo
cual leerá el archivo línea por línea y almacenará todas las líneas en
el cuerpo del mensaje como un tipo java.util.List<List>. Luego
usas el splitter para dividir el cuerpo, lo cual fraccionará la
java.util.List<List<String>> en filas (cada fila representada
como otra List<String> conteniendo los campos) y enviar la fila a
la queue JMS. Podrías no querer enviar cada fila como un tipo List
a la queue JMS, de forma que puedes transformar la fila antes de
enviarla, quizás usando un processor.
El mismo ejemplo en Spring XML es un poco diferente, como se
muestra aquí:
<camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="file://rider/csvfiles"/>
<unmarshal><csv/></unmarshal>
<split>
<simple>body</simple>
<to uri="activemq:queue.csv.record"/>
</split>
</route>
</camelContext>
La notable diferencia es como le dices a <split> que debe dividir el cuerpo
del mensaje. Para hacer esto necesitas proveerle a <split> con una
Expression, qué es lo que el splitter debe iterar cuando ejecute el splitting.
Para hacerlo así, puedes usar el lenguaje de expresión incorporado de Camel
llamado Simple, el cual sabe cómo hacer eso.
A la primera, los tipos de datos que el formato de datos usa pueden
parecer un poco confusos. Estos son listados en la tabla 3.4.
Un problema con camel-csv es que usa tipos de datos genéricos, como
Maps o Lists, para representar registros CSV. Frecuentemente ya tienes
modelos de datos para representar tus datos en memoria.
Operación De tipo A tipo Descripción
marshall Map<String,
Object>
OutputStream Contiene una sola fila en formato CSV
marshall List<Map<String,
Object>>
OutputStream Contiene múltiples filas en formato
CSV donde cada fila está separada por
n (nueva línea)
unmarshall InputStream List<List<String>> Contiene una List de filas donde
cada fila es otra List de campos
Usando el formato de datos Bidy de Camel
Los dos formatos de datos existentes relacionados a CSV (camel-csv
y camel-flatpack) son librerías más viejas que no toman ventaja de
las nuevas características de Java 1.5, tales como anotaciones y
generics. A la luz de esta deficiencia, Charles Moulliard salió y
escribió el componente camel-bindy para tomar ventaja de estas
nuevas posibilidades. Es capaz de vincular CSV, FIX, y formatos de
datos de longitud fija a modelos de objetos existentes usando
anotaciones. Esto es similar a lo que hace JAXB para XML.
Supón que tienes un objeto modelo que representa una orden de
compra. Anotando el objeto modelo con anotaciones camel-bindy,
puedes fácilmente transformar mensajes entre CSV y objetos
modelo Java.
package camelinaction.bindy;
import java.math.BigDecimal;
import org.apache.camel.dataformat.bindy.annotation.CsvRecord;
import org.apache.camel.dataformat.bindy.annotation.DataField;
@CsvRecord(separator = ",", crlf = "UNIX")
public class PurchaseOrder {
@DataField(pos = 1)
private String name;
@DataField(pos = 2, precision = 2)
private BigDecimal price;
@DataField(pos = 3)
private int amount;
}
Mapea a registro CSV
1
2 Mapea a columna en
registro registro CSV
Primero marcas la clase con la anotación @CsvRecord 1 para indicar
que representa un registro en formato CSV. Entonces anotas los
campos con @DateField acorde al layout del registro CSV 2.
Usando el atributo pos, puedes dictar la orden en la cual son
sacados en formato CSV; pos inicia con un valor de 1. Para campos
numéricos, puedes adicionalmente declarar precision, la cual en
este ejemplo es asignada a 2, indicando que el precio debe usar dos
dígitos por centavo. Bindy tiene atributos para layout de grano fino
de los campos, tales como pattern, trim y length. Puedes usar
pattern para indicar el patrón de datos, trim para recortar la
entrada, y length para restringir la descripción de un texto a un
cierto número de caracteres.
Antes de ver cómo usar Bindy en routes Camel, necesitamos ir un
paso atrás y checar los tipos de datos que Bindy espera usar. Ellos
son listados en la tabla 3.5.
Tabla 3.5 Tipos de datos que Bindy usa cuando transforma a y desde formato CSV
Operación De tipo A tipo Descripción de la salida
marshall List<Map<String,
Object>>
OutputStream Contiene múltiples filas en formato CSV donde
cada fila es separada por una n (nueva línea)
unmarshall InputStream List<Map<String,
Object>>
Contiene una List de filas donde cada fila
contiene 1..n modelos de datos contenidos en un
Map
La cosa importante a notar en la tabla 3.5 es que Bindy usa un
Map<String, Object> para representar una fila CSV. A la primera puede
parecer extraño. ¿Por qué no sólo usa un único objeto modelo para eso?
La respuesta es que puedes tener múltiples objetos modelo con el registro
CSV que está siendo dispersado a través de estos objetos. Por ejemplo,
podrías tener los campos 1 a 3 en un objeto modelo, los campos 4 a 9 en
otro, y los campos 10 al 12 en un tercero.
La entrada del map <String, Object> es destilada como sigue:
 Map key (String) –Debe contener el nombre de la clase
completamente cualificado del objeto modelo.
 Map value (Object) –Debe contener el objeto modelo.
Si te parece ser un poco confuso, no te preocupes. El siguiente ejemplo
debe hacerlo más claro:
Listado 3.8 Usando Bindy para transformar un objeto modelo a formato CSV
public class PurchaseOrderBindyTest extends TestCase {
public void testBindy() throws Exception {
CamelContext context = new DefaultCamelContext();
context.addRoutes(createRoute());
context.start();
MockEndpoint mock = context.getEndpoint("mock:result",
MockEndpoint.class);
mock.expectedBodiesReceived("Camel in Action,49.95,1n");
PurchaseOrder order = new PurchaseOrder();
order.setAmount(1);
order.setPrice(new BigDecimal("49.95"));
order.setName("Camel in Action");
ProducerTemplate template = context.createProducerTemplate();
template.sendBody("direct:toCsv", order);
mock.assertIsSatisfied();
}
public RouteBuilder createRoute() {
return new RouteBuilder() {
public void configure() throws Exception {
from("direct:toCsv")
.marshal().bindy(BindyType.Csv, "camelinaction.bindy")
.to("mock:result");
}
};
}
}
Crea el objeto modelo
como es usual1
Inicia el test
2
Transforma
el objeto
modelo a
CSV
En este listado, primero creas y llenas el modelo de orden usando
setters Java regulares 1. Luego envías el modelo de orden al route
enviándolo al endpoint direct:toCsv 2 que es usado en el route. El
route luego serializará el modelo de orden a CSV usando Bindy 3.
Nota cómo Bindy es configurado para usar modo CSV vía
BindyType.Csv. Para permitirle a Bindy saber cómo mapear a objeto
modelo orden, necesitas proporcionar un nombre de package que
será escaneado para clases anotadas con anotaciones Bindy. Esta es
la misma solución que ofrece JAXB.
Nota: El listado 3.8 usa MockEndpoint para probar fácilmente que
el registro CSV está como se espera.
Usando el formato de datos JSON de Camel
JSON (JavaScript Jason Notation) es un formato de intercambio de datos,
y Camel proporciona dos componentes que soportan el formato de datos
JSON: camel-xstream y camel-jackson. En esta sección nos enfocaremos
en camel-jackson debido a que Jackson es una librería JSON muy popular.
Yendo atrás a Autopartes Rider, ahora tienes que implementar un nuevo
servicio que retorna resúmenes de órdenes entregadas en formato JSON.
Hacer esto con Camel es muy fácil, debido a que Camel tiene todos los
ingredientes necesarios fabricar este servicio. El listado 3.9 muestra cómo
puedes subir a un prototipo.
<bean id="orderService" class="camelinaction.OrderServiceBean"/>
<camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
<dataFormats>
<json id="json" library="Jackson"/>
</dataFormats>
<route>
<from uri="jetty://http://0.0.0.0:8080/order"/>
<bean ref="orderService" method="lookup"/>
<marshal ref="json"/>
</route>
</camelContext>
Primero necesitas montar el formato de datos JSON y especificar que la
librería Jackson debe ser usada 1. Luego defines un route que expone el
servicio HTTP usando el endpoint Jetty. Este ejemplo expone el endpoint Jetty
directamente en la URL. Usando http://0.0.0.0:8080/order , le dices a Jetty
que cualquier cliente puede alcanzar este servicio en el puerto 8080.
Monta un formato de datos JSON
1
2
Invoca bean para retomar datos
para respuesta
Siempre que una request golpee este servicio HTTP, es enrutado al bean
orderService 2 y el método lookup es invocado en ese bean. El resultado
de la invocación a este bean es luego serializado a formato JSON y
retornado atrás al cliente HTTP.
El bean order service podría tener una firma de método como esta:
public PurchaseOrder lookup(@Header(name = "id") String id)
Esta firma te permite implementar la lógica de lookup como desees.
Nota que el bean del servicio puede retornar un POJO que la librería
JSON es capaz de serializar. Por ejemplo, supón que usaste el
PurchaseOrder del listado 3.7, y tuviste salida JSON como la siguente:
{"name":"Camel in Action","amount":1.0,"price":49.95}
El mismo servicio HTTP puede ser invocado por una request HTTP Get
con el id de la orden como parámetro:
http://0.0.0.0:8080/order/service?id=123.
Configurando formatos de datos de Camel
En secciones anteriores utilizaste el formato de datos CSV, pero este
formato de datos ofrece muchas configuraciones adicionales. Este listado
muestra como puedes configurar el formato de datos CSV.
public void configure() {
CSVConfig custom = new CSVConfig();
custom.setDelimiter(';');
custom.setEndTrimmed(true);
custom.addField(new CSVField("id"));
custom.addField(new CSVField("customerId"));
custom.addField(new CSVField("date"));
custom.addField(new CSVField("item"));
custom.addField(new CSVField("amount"));
custom.addField(new CSVField("description"));
CsvDataFormat myCsv = new CsvDataFormat();
myCsv.setConfig(custom);
myCsv.setAutogenColumns(false);
from("direct:toCsv").marshal(myCsv).to("file://acme/outbox/csv");
}
Configura formato de datos
CSV personalizado
1
Crea el formato de datos
CSV personalizado
2
3
Usa el formato de datos CSV
Configurar formatos de datos en Camel se hace usando código Java
regular; usas la API que proporciona el formato de datos. En el
listado 3.10, el formato de datos CSV ofrece un objeto CSVConfig 1
que es usado para asignar el punto y coma como delimitador y para
especificar el orden de los campos. El mismo formato de datos es
luego creado 2 y asignado para usar la configuración. El uso del
formato de datos sigue siendo el mismo, así que todo lo que
necesitas hacer es referirte a él desde los métodos marshall y
unmarshall. Este mismo principio aplica a todos los formatos de
datos en Camel. Puedes configurarlos usando las APIs que ellos
proveen.
Ahora que sabes como usar los formatos de datos, vamos a ver
como puedes escribir tus propios formatos de datos.
Escribiendo tu propio formato de datos
Pudieras encontrarte necesario transformar datos a y desde un formato de
datos personalizado. En esta sección, veremos cómo puedes desarrollar
un formato de datos que puede reversar strings.
Desarrollar tu propio formato de datos es muy fácil, debido a que Camel
provee una sola API que debes implementar:
org.apache.camel.spi.DataFormat. Vamos a ver cómo podrías
implementar un formato de dato de reversa de string.
El formato de datos personalizado debe implementar la interface
DataFormat, la cual te forza a desarrollar dos métodos: marshall 1 y
unmarshall 2. Eso no es sorpresa, ya que ellos son los mismos métodos
que usas en el route. El método marshall 1 necesita sacar el resultado al
OutputStream. Para hacer esto necesitas obtener el payload del mensaje
como un byte[], y luego reversarlo con un método helper. Luego escribes
los datos al OutputStream.
Nota que utilizas os convertidores de tipo de Camel para retornar el
payload del mensaje como un byte[]. Esto es muy poderoso y te ahorra de
hacer un typecast manual en Java o intentar convertir el payload por ti
mismo.
El método unmarshall es cercanamente el mismo. Usas el mecanismo
convertidor de tipo de Camel otra vez para proporcionar el payload del
mensaje como un byte[]. unmarshall también reversa los bytes para
obtener los datos atrás en su orden original. Nota que en este método
retornas los datos en vez de escribirlos a un stream.
TIP: Como mejor práctica usa los convertidores de tipo Camel en vez del
typecasting o convertirlos entre tipos por ti mismo.
Para usar este nuevo formato de datos en un route, todo lo que tienes que
hacer es definirlo como un bean de Spring y referirte a él desde
<marshall> y <unmarshall> de la forma siguiente:
<bean id="reverse" class="camelinaction.ReverseDataFormat"/>
<camelContext id="camel"
xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="direct:marshal"/>
<marshal ref="reverse"/>
<to uri="log:marshal"/>
</route>
<route>
<from uri="direct:unmarshal"/>
<unmarshal ref="reverse"/>
<to uri="log:unmarshal"/>
</route>
</camelContext>
3.5 Transformando con templates
Camel proporciona una hábil integración con dos diferentes lenguajes de
plantillas:
 Apache Velocity-Probablemente el lenguaje de plantillas más conocido
 FreeMarker –Otro lenguaje de plantillas popular que puede ser un poco
más avanzado que Velocity.
Los dos lenguajes de plantilla son muy similares de usar, así que con
Velocity nos basta.
Usando Apache Velocity
Autopartes Rider ha implementado un nuevo sistema de órdenes que
debe enviar una respuesta de email cuando un cliente ha emitido una
orden. Tu trabajo es implementar esta característica.
El email de respuesta podría parecerse a este:
Querido cliente
Gracias por ordenar X pieza(s) de XXX a un costo de XXX.
Este es un email automatizado, por favor no responda.
Hay tres piezas de información en el email que deben ser remplazadas en
tiempo de ejecución con valores reales. Lo que necesitas hacer es ajustar
el email para usar el lenguaje de plantillas Velocity, y luego colocarlas en
el repositorio de fuentes como /src/test/resources/email.vm:
Querido cliente
Gracias por ordenar ${body.amount} de ${body.name} a un
costo de ${body.price}.
Este es un email automatizado, por favor no responda.
Nota que hemos insertado placeholders ${} en la plantilla, lo cual instruye
a Velocity que las evalúe y las remplace en tiempo de ejecución. Camel
prellena el contexto de Velocity con un número de entidades que luego
están disponibles a Velocity. Estas entidades son listadas en la tabla 3.6.
NOTA: Las entidades en la tabla 3.6 también aplican para otros lenguajes de
plantilla como FreeMarker.
Entidad Tipo Descripción
camelContext org.apache.camel.CamelContext El Contexto de Camel
exchange org.apache.camel.Exchange El exchange actual
in org.apache.camel.Message El mensaje de entrada. Este puede chocar con
alguna palabra reservada en algunos lenguajes. En
su lugar usa request.
request org.apache.camel.Message El mensaje de entrada
body java.lang.Object El cuerpo del mensaje de entrada
headers java.util.Map Los headers del mensaje de entrada
response org.apache.camel.Message El mensaje de salida
out org.apache.camel.Message El mensaje de salida. Este puede chocar con alguna
palabra reservada en algunos lenguajes. En su lugar
usa response.
3.6 A cerca de los convertidores de tipo de Camel
Camel proporciona un sistema conversor de tipo incorporado que
convierte automáticamente entre tipos bien conocidos. Este sistema le
permite a los componentes de Camel trabajar juntos fácilmente sin tener
diferencias de tipos. Y desde la perspectiva del usuario Camel, las
conversiones de tipo están incorporadas en la API en muchos lugares sin
ser invasivas. Por ejemplo, has usado en el listado 3.1:
String custom = exchange.getIn().getBody(String.class);
Al método getBody le es pasado el tipo que quieres que se le retorne. Tras
bambalinas, el sistema conversor de tipo convierte el tipo retornado a un
String si es necesario.
Aquí se explicará cómo Camel escanea el classpath al arranque para
registrar dinámicamente los convertidores de tipo. También mostraremos
cómo puedes usarlo desde un route Camel, y cómo construir tus propios
convertidores de tipo.
Cómo funciona el mecanismo convertidor de tipo de Camel
Para comprender el sistema conversor de tipo, primero necesitamos saber
qué es un convertidor de tipo en Camel. La figura 3.7 ilustra la relación
entre el TypeConverterRegistry y los TypeConverters que contiene.
El TypeConverteRegistry es donde todos los conversores de tipos son
registrados cuando Camel inicia. En tiempo de ejecución, Camel usa el
método lookup de TypeConverterRegistry para buscar un
TypeConverter adecuado.
TypeConverter lookup(Class<?> toType, Class<?> fromType);
Figura 3.7
El TypeConverterRegistry contiene
muchos TypeConverter
Usando el TypeConverter, Camel entonces puede convertir un tipo a
otro usando el método convertTo de TpeConverter, el cual está
definido de la siguiente forma:
<T> T convertTo(Class<T> type, Object value);
Nota: Camel implementa alrededor de 150 o más conversores de tipo listos
para usar, los cuales son capaces de convertir a y desde los tipos más
comúnmente usados.
CARGA DE CONVERTIDORES DE TIPO EN EL REGSITRO
Al arranque, Camel carga todos los convertidores de tipo en el
TypeConverterRegistry usando una solución de escaneo del classpath.
Esto le permite a Camel elegir no sólo un conversor de tipo de camel-core
sino también desde cualesquier a otros componentes de Camel.
Para escanear y cargar los conversores de tipo, Camel usa
org.apache.camel.impl.converter.AnnotationTypeConverterLoader.
Para evitar cargar silos de clases, lee un archivo de descubrimiento de
servicio en la carpeta META-INF: META-
INF/services/org/apache/camel/TypeConverter. Este es un archivo de
texto plano que tiene una lista de paquetes que contiene conversores de
tipo Camel. El archivo especial es necesario para evitar escanear cada JAR
posible y todos sus packeges, lo cual sería consumidor de tiempo. El
archivo especial le dice a Camel si el archivo JAR contiene o no
conversores de tipo. Por ejemplo, el archivo en camel-core contiene las
siguientes tres entradas:
org.apache.camel.converter
org.apache.camel.component.bean
org.apache.camel.component.file
La AnnotationTypeConverterLoader escaneará estos packages y sus
subpackages para clases que han sido anotadas con @Converter, y busca
en ellas métodos públicos que son anotados con @Converter. Cada uno de
estos métodos es considerado un conversor de tipo.
Esto es mejor ilustrado con un ejemplo. El siguiente código es un snippet de la
clase IOConverter del JAR camel-core:
@Converter
public final class IOConverter {
@Converter
public static InputStream toInputStream(URL url) throws IOException {
return url.openStream();
}
}
Camel irá sobre cada método anotado con @Converter y buscará la firma del
método. El primer parámetro es del tipo from, y el tipo de retorno es del tipo to
–en este ejemplo tienes un TypeConverter que puede convertir desde una URL
a un InputStream. Haciendo esto, Camel carga todos los conversores de tipo
incorporados, incluyendo aquellos de los componentes Camel en uso.
Usando convertidores de tipo Camel
Podrías querer usar los convertidores de tipo para forzar un tipo específico
para que sea usado en un route, como antes enviando datos atrás a un
llamante o a un destino JMS. Vamos a ver cómo hacer eso:
Supón que necesitas enrutar archivos a una queue JMS usando
java.jms.TextMessage. Para hacer lo así, puedes convertir cada archivo a
una String, lo cual forza al componente JMS a usar TextMessage. Esto es
fácil de hacer en Camel –puedes usar el método convertBodyTo, como es
mostrado aquí:
from("file://riders/inbox")
.convertBodyTo(String.class)
.to("activemq:queue:inbox");
Si estás usando Spring XML. en vez de ello proporcionas el tipo como un
atributo, como lo siguiente:
<route>
<from uri="file://riders/inbox"/>
<convertBodyTo type="java.lang.String"/>
<to uri="activemq:queue:inbox"/>
</route>
Puedes omitir el prefijo java.lang en el tipo, lo cual puede acortar la
sintaxis un poco:
<convertBodyTo type="java.lang.String"/>
Otra razón para usar convertBodyTo es leer archivos usando un
encoding fijo como UTF-8. Esto se hace pasando el encoding el segundo
parámetro de entrada:
from("file://riders/inbox")
.convertBodyTo(String.class, "UTF-8")
.to("activemq:queue:inbox");
Escribiendo tu propio convertidor de tipo
Escribir tu propio convertidor de tipo es fácil en Camel. Ya has visto como un
conversor de tipo se ve en la sección 3.6.1, cuando viste cómo funcionan los
conversores de tipo.
Supón que necesitaras escribir un conversor de tipo personalizado que puede
convertir un byte en un objeto modelo PurchaseOrder (un objeto que usaste
en el listado 3.7). Como lo viste anteriormente, necesitas crear una clase
@Converter conteniendo el método conversor de tipo:
Listado 3.12 Un conversor de tipo personalizado para convertir de tipo byte[] a
PurchaseOrden
@Converter
public final class PurchaseOrderConverter
@Converter
public static PurchaseOrder toPurchaseOrder(byte[] data,
Exchange exchange) {
TypeConverter converter = exchange.getContext()
.getTypeConverter();
Coge el TypeConverter a
reutilizar
1
String s = converter.convertTo(String.class, data);
if (s == null || s.length() < 30) {
throw new IllegalArgumentException("data is invalid");
}
s = s.replaceAll("##START##", "");
s = s.replaceAll("##END##", "");
String name = s.substring(0, 9).trim();
String s2 = s.substring(10, 19).trim();
BigDecimal price = new BigDecimal(s2);
price.setScale(2);
String s3 = s.substring(20).trim();
Integer amount = converter.convertTo(Integer.class, s3);
return new PurchaseOrder(name, price, amount);
}
}
Convierte de String
a PurchaseOrden
2
En el listado 3.12 el Exchange te da acceso al CamelContext y así al padre
TypeConverter 1, el cual usas en este método para convertir entre
cadenas y números. El resto del código. El resto del código es la lógica
para parsear el protocolo personalizado y retornar el PurchaseOrder 2.
Nota como puedes usar el converter para convertir fácilmente entre
tipos bien conocidos.
Todo lo que necesitas hacer es agregar el archivo de descubrimiento de
servicio, llamado TypeConverter, en el directorio META-INF. Como se
explicó anteriormente, este archivo contiene una línea identificando cada
package para ser escaneado por las clases @Converter.
GRACIAS
www.facebook.com/JavaDevelopersMexico
No olvides regalarnos un like.
Dudas y comentarios no dudes en escribir en la página o
al siguiente correo
it.adesales@gmail.com

Más contenido relacionado

La actualidad más candente

SPA Editor - Adobe Experience Manager Sites
SPA Editor - Adobe Experience Manager SitesSPA Editor - Adobe Experience Manager Sites
SPA Editor - Adobe Experience Manager SitesGabriel Walt
 
Message Oriented Middleware (MOM)
Message Oriented Middleware (MOM)Message Oriented Middleware (MOM)
Message Oriented Middleware (MOM)drewenut
 
ABAP Message, Debugging, File Transfer and Type Group
ABAP Message, Debugging, File Transfer and Type GroupABAP Message, Debugging, File Transfer and Type Group
ABAP Message, Debugging, File Transfer and Type Groupsapdocs. info
 
AEM (CQ) Dispatcher Security and CDN+Browser Caching
AEM (CQ) Dispatcher Security and CDN+Browser CachingAEM (CQ) Dispatcher Security and CDN+Browser Caching
AEM (CQ) Dispatcher Security and CDN+Browser CachingAndrew Khoury
 
Ab1011 module pool programming
Ab1011   module pool programmingAb1011   module pool programming
Ab1011 module pool programmingSatheesh Kanna
 
AEM & Single Page Applications (SPAs) 101
AEM & Single Page Applications (SPAs) 101AEM & Single Page Applications (SPAs) 101
AEM & Single Page Applications (SPAs) 101Adobe
 
Microservices with Apache Camel
Microservices with Apache CamelMicroservices with Apache Camel
Microservices with Apache CamelClaus Ibsen
 
Node js Modules and Event Emitters
Node js Modules and Event EmittersNode js Modules and Event Emitters
Node js Modules and Event EmittersTheCreativedev Blog
 
Maximizing SAP ABAP Performance
Maximizing SAP ABAP PerformanceMaximizing SAP ABAP Performance
Maximizing SAP ABAP PerformancePeterHBrown
 
Coding Standards & Best Practices for iOS/C#
Coding Standards & Best Practices for iOS/C#Coding Standards & Best Practices for iOS/C#
Coding Standards & Best Practices for iOS/C#Asim Rais Siddiqui
 
Spring + WebSocket integration
Spring + WebSocket integrationSpring + WebSocket integration
Spring + WebSocket integrationOleksandr Semenov
 
Four approaches to integrate aem with external systems by Jan Kuzniak
Four approaches to integrate aem with external systems by Jan KuzniakFour approaches to integrate aem with external systems by Jan Kuzniak
Four approaches to integrate aem with external systems by Jan KuzniakAEM HUB
 
Microservices Architecture for AEM
Microservices Architecture for AEMMicroservices Architecture for AEM
Microservices Architecture for AEMMaciej Majchrzak
 
Ppt of soap ui
Ppt of soap uiPpt of soap ui
Ppt of soap uipkslide28
 

La actualidad más candente (20)

SPA Editor - Adobe Experience Manager Sites
SPA Editor - Adobe Experience Manager SitesSPA Editor - Adobe Experience Manager Sites
SPA Editor - Adobe Experience Manager Sites
 
Asp.net controls
Asp.net controlsAsp.net controls
Asp.net controls
 
Message Oriented Middleware (MOM)
Message Oriented Middleware (MOM)Message Oriented Middleware (MOM)
Message Oriented Middleware (MOM)
 
ABAP Message, Debugging, File Transfer and Type Group
ABAP Message, Debugging, File Transfer and Type GroupABAP Message, Debugging, File Transfer and Type Group
ABAP Message, Debugging, File Transfer and Type Group
 
Siebel Web Service
Siebel Web ServiceSiebel Web Service
Siebel Web Service
 
AEM (CQ) Dispatcher Security and CDN+Browser Caching
AEM (CQ) Dispatcher Security and CDN+Browser CachingAEM (CQ) Dispatcher Security and CDN+Browser Caching
AEM (CQ) Dispatcher Security and CDN+Browser Caching
 
Module pool programming
Module pool programmingModule pool programming
Module pool programming
 
Ab1011 module pool programming
Ab1011   module pool programmingAb1011   module pool programming
Ab1011 module pool programming
 
AEM & Single Page Applications (SPAs) 101
AEM & Single Page Applications (SPAs) 101AEM & Single Page Applications (SPAs) 101
AEM & Single Page Applications (SPAs) 101
 
Microservices with Apache Camel
Microservices with Apache CamelMicroservices with Apache Camel
Microservices with Apache Camel
 
Node js Modules and Event Emitters
Node js Modules and Event EmittersNode js Modules and Event Emitters
Node js Modules and Event Emitters
 
Maximizing SAP ABAP Performance
Maximizing SAP ABAP PerformanceMaximizing SAP ABAP Performance
Maximizing SAP ABAP Performance
 
Coding Standards & Best Practices for iOS/C#
Coding Standards & Best Practices for iOS/C#Coding Standards & Best Practices for iOS/C#
Coding Standards & Best Practices for iOS/C#
 
Ajax
AjaxAjax
Ajax
 
Get to Know AtoM's Codebase
Get to Know AtoM's CodebaseGet to Know AtoM's Codebase
Get to Know AtoM's Codebase
 
Weblogic12 c installation guide
Weblogic12 c installation guideWeblogic12 c installation guide
Weblogic12 c installation guide
 
Spring + WebSocket integration
Spring + WebSocket integrationSpring + WebSocket integration
Spring + WebSocket integration
 
Four approaches to integrate aem with external systems by Jan Kuzniak
Four approaches to integrate aem with external systems by Jan KuzniakFour approaches to integrate aem with external systems by Jan Kuzniak
Four approaches to integrate aem with external systems by Jan Kuzniak
 
Microservices Architecture for AEM
Microservices Architecture for AEMMicroservices Architecture for AEM
Microservices Architecture for AEM
 
Ppt of soap ui
Ppt of soap uiPpt of soap ui
Ppt of soap ui
 

Destacado

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
 
Easy Integration with Apache Camel and Fuse IDE
Easy Integration with Apache Camel and Fuse IDEEasy Integration with Apache Camel and Fuse IDE
Easy Integration with Apache Camel and Fuse IDEJBUG London
 
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
 
Integrating Microservices with Apache Camel
Integrating Microservices with Apache CamelIntegrating Microservices with Apache Camel
Integrating Microservices with Apache CamelChristian Posta
 
Planeación de Capital Humano
Planeación de Capital HumanoPlaneación de Capital Humano
Planeación de Capital HumanoUVM
 
Consideraciones para el Desarrollo de Aplicaciones Móviles
Consideraciones para el Desarrollo de Aplicaciones MóvilesConsideraciones para el Desarrollo de Aplicaciones Móviles
Consideraciones para el Desarrollo de Aplicaciones MóvilesSorey García
 
Orquestacion y Coreografia de Servicios Web
Orquestacion y Coreografia de Servicios WebOrquestacion y Coreografia de Servicios Web
Orquestacion y Coreografia de Servicios Webdaniel_lt
 

Destacado (20)

Presentacion camel
Presentacion camelPresentacion camel
Presentacion 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?
 
Estructuras TI,cap5
Estructuras TI,cap5Estructuras TI,cap5
Estructuras TI,cap5
 
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
 
Easy Integration with Apache Camel and Fuse IDE
Easy Integration with Apache Camel and Fuse IDEEasy Integration with Apache Camel and Fuse IDE
Easy Integration with Apache Camel and Fuse IDE
 
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
 
Integrating Microservices with Apache Camel
Integrating Microservices with Apache CamelIntegrating Microservices with Apache Camel
Integrating Microservices with Apache Camel
 
Planeación de Capital Humano
Planeación de Capital HumanoPlaneación de Capital Humano
Planeación de Capital Humano
 
Consideraciones para el Desarrollo de Aplicaciones Móviles
Consideraciones para el Desarrollo de Aplicaciones MóvilesConsideraciones para el Desarrollo de Aplicaciones Móviles
Consideraciones para el Desarrollo de Aplicaciones Móviles
 
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
 

Similar a Transformación de datos en Camel

Similar a Transformación de datos en Camel (20)

Java WebServices JaxWS - JaxRs
Java WebServices JaxWS - JaxRsJava WebServices JaxWS - JaxRs
Java WebServices JaxWS - JaxRs
 
Desarrollo de Apps Web en Ruby on Rails
Desarrollo de Apps Web en Ruby on RailsDesarrollo de Apps Web en Ruby on Rails
Desarrollo de Apps Web en Ruby on Rails
 
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
 
Formularios web
Formularios webFormularios web
Formularios web
 
Servicio web
Servicio web Servicio web
Servicio web
 
Curso Java Avanzado 3 Js Ps
Curso Java Avanzado   3 Js PsCurso Java Avanzado   3 Js Ps
Curso Java Avanzado 3 Js Ps
 
Servicios web
Servicios webServicios web
Servicios web
 
ADO
ADOADO
ADO
 
Presentacion comunicaciones
Presentacion comunicacionesPresentacion comunicaciones
Presentacion comunicaciones
 
Presentacion comunicaciones
Presentacion comunicacionesPresentacion comunicaciones
Presentacion comunicaciones
 
Web services-con-php
Web services-con-phpWeb services-con-php
Web services-con-php
 
bd.net.pptx
bd.net.pptxbd.net.pptx
bd.net.pptx
 
Servlet
ServletServlet
Servlet
 
Taller programación web ajax con jquery
Taller programación web  ajax con jqueryTaller programación web  ajax con jquery
Taller programación web ajax con jquery
 
AJAX EN CURSO PHP
AJAX EN CURSO PHPAJAX EN CURSO PHP
AJAX EN CURSO PHP
 
Ruby y las arquitecturas orientadas a servicios
Ruby y las arquitecturas orientadas a servicios Ruby y las arquitecturas orientadas a servicios
Ruby y las arquitecturas orientadas a servicios
 
Diapositivas de acceso a datos ado.net
Diapositivas de acceso a datos ado.netDiapositivas de acceso a datos ado.net
Diapositivas de acceso a datos ado.net
 
Clase 4 routing
Clase 4 routingClase 4 routing
Clase 4 routing
 
ADO .NET
ADO .NETADO .NET
ADO .NET
 
Frameworks de templates y xml
Frameworks de templates y xmlFrameworks de templates y xml
Frameworks de templates y xml
 

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
 

Último

AREA TECNOLOGIA E INFORMATICA TRABAJO EN EQUIPO
AREA TECNOLOGIA E INFORMATICA TRABAJO EN EQUIPOAREA TECNOLOGIA E INFORMATICA TRABAJO EN EQUIPO
AREA TECNOLOGIA E INFORMATICA TRABAJO EN EQUIPOnarvaezisabella21
 
Mapa-conceptual-del-Origen-del-Universo-3.pptx
Mapa-conceptual-del-Origen-del-Universo-3.pptxMapa-conceptual-del-Origen-del-Universo-3.pptx
Mapa-conceptual-del-Origen-del-Universo-3.pptxMidwarHenryLOZAFLORE
 
Modelo de Presentacion Feria Robotica Educativa 2024 - Versión3.pptx
Modelo de Presentacion Feria Robotica Educativa 2024 - Versión3.pptxModelo de Presentacion Feria Robotica Educativa 2024 - Versión3.pptx
Modelo de Presentacion Feria Robotica Educativa 2024 - Versión3.pptxtjcesar1
 
El uso de las TIC's en la vida cotidiana.
El uso de las TIC's en la vida cotidiana.El uso de las TIC's en la vida cotidiana.
El uso de las TIC's en la vida cotidiana.241514949
 
Crear un recurso multimedia. Maricela_Ponce_DomingoM1S3AI6-1.pptx
Crear un recurso multimedia. Maricela_Ponce_DomingoM1S3AI6-1.pptxCrear un recurso multimedia. Maricela_Ponce_DomingoM1S3AI6-1.pptx
Crear un recurso multimedia. Maricela_Ponce_DomingoM1S3AI6-1.pptxNombre Apellidos
 
tarea de exposicion de senati zzzzzzzzzz
tarea de exposicion de senati zzzzzzzzzztarea de exposicion de senati zzzzzzzzzz
tarea de exposicion de senati zzzzzzzzzzAlexandergo5
 
El_Blog_como_herramienta_de_publicacion_y_consulta_de_investigacion.pptx
El_Blog_como_herramienta_de_publicacion_y_consulta_de_investigacion.pptxEl_Blog_como_herramienta_de_publicacion_y_consulta_de_investigacion.pptx
El_Blog_como_herramienta_de_publicacion_y_consulta_de_investigacion.pptxAlexander López
 
Presentación inteligencia artificial en la actualidad
Presentación inteligencia artificial en la actualidadPresentación inteligencia artificial en la actualidad
Presentación inteligencia artificial en la actualidadMiguelAngelVillanuev48
 
tics en la vida cotidiana prepa en linea modulo 1.pptx
tics en la vida cotidiana prepa en linea modulo 1.pptxtics en la vida cotidiana prepa en linea modulo 1.pptx
tics en la vida cotidiana prepa en linea modulo 1.pptxazmysanros90
 
Red Dorsal Nacional de Fibra Óptica y Redes Regionales del Perú
Red Dorsal Nacional de Fibra Óptica y Redes Regionales del PerúRed Dorsal Nacional de Fibra Óptica y Redes Regionales del Perú
Red Dorsal Nacional de Fibra Óptica y Redes Regionales del PerúCEFERINO DELGADO FLORES
 
Medidas de formas, coeficiente de asimetría y coeficiente de curtosis.pptx
Medidas de formas, coeficiente de asimetría y coeficiente de curtosis.pptxMedidas de formas, coeficiente de asimetría y coeficiente de curtosis.pptx
Medidas de formas, coeficiente de asimetría y coeficiente de curtosis.pptxaylincamaho
 
LUXOMETRO EN SALUD OCUPACIONAL(FINAL).ppt
LUXOMETRO EN SALUD OCUPACIONAL(FINAL).pptLUXOMETRO EN SALUD OCUPACIONAL(FINAL).ppt
LUXOMETRO EN SALUD OCUPACIONAL(FINAL).pptchaverriemily794
 
La Electricidad Y La Electrónica Trabajo Tecnología.pdf
La Electricidad Y La Electrónica Trabajo Tecnología.pdfLa Electricidad Y La Electrónica Trabajo Tecnología.pdf
La Electricidad Y La Electrónica Trabajo Tecnología.pdfjeondanny1997
 
Trabajo de tecnología excel avanzado.pdf
Trabajo de tecnología excel avanzado.pdfTrabajo de tecnología excel avanzado.pdf
Trabajo de tecnología excel avanzado.pdfedepmariaperez
 
TEMA 2 PROTOCOLO DE EXTRACCION VEHICULAR.ppt
TEMA 2 PROTOCOLO DE EXTRACCION VEHICULAR.pptTEMA 2 PROTOCOLO DE EXTRACCION VEHICULAR.ppt
TEMA 2 PROTOCOLO DE EXTRACCION VEHICULAR.pptJavierHerrera662252
 
Los Microcontroladores PIC, Aplicaciones
Los Microcontroladores PIC, AplicacionesLos Microcontroladores PIC, Aplicaciones
Los Microcontroladores PIC, AplicacionesEdomar AR
 
LAS_TIC_COMO_HERRAMIENTAS_EN_LA_INVESTIGACIÓN.pptx
LAS_TIC_COMO_HERRAMIENTAS_EN_LA_INVESTIGACIÓN.pptxLAS_TIC_COMO_HERRAMIENTAS_EN_LA_INVESTIGACIÓN.pptx
LAS_TIC_COMO_HERRAMIENTAS_EN_LA_INVESTIGACIÓN.pptxAlexander López
 
El uso de las tic en la vida ,lo importante que son
El uso de las tic en la vida ,lo importante  que sonEl uso de las tic en la vida ,lo importante  que son
El uso de las tic en la vida ,lo importante que son241514984
 
Tecnologias Starlink para el mundo tec.pptx
Tecnologias Starlink para el mundo tec.pptxTecnologias Starlink para el mundo tec.pptx
Tecnologias Starlink para el mundo tec.pptxGESTECPERUSAC
 
Excel (1) tecnologia.pdf trabajo Excel taller
Excel  (1) tecnologia.pdf trabajo Excel tallerExcel  (1) tecnologia.pdf trabajo Excel taller
Excel (1) tecnologia.pdf trabajo Excel tallerValentinaTabares11
 

Último (20)

AREA TECNOLOGIA E INFORMATICA TRABAJO EN EQUIPO
AREA TECNOLOGIA E INFORMATICA TRABAJO EN EQUIPOAREA TECNOLOGIA E INFORMATICA TRABAJO EN EQUIPO
AREA TECNOLOGIA E INFORMATICA TRABAJO EN EQUIPO
 
Mapa-conceptual-del-Origen-del-Universo-3.pptx
Mapa-conceptual-del-Origen-del-Universo-3.pptxMapa-conceptual-del-Origen-del-Universo-3.pptx
Mapa-conceptual-del-Origen-del-Universo-3.pptx
 
Modelo de Presentacion Feria Robotica Educativa 2024 - Versión3.pptx
Modelo de Presentacion Feria Robotica Educativa 2024 - Versión3.pptxModelo de Presentacion Feria Robotica Educativa 2024 - Versión3.pptx
Modelo de Presentacion Feria Robotica Educativa 2024 - Versión3.pptx
 
El uso de las TIC's en la vida cotidiana.
El uso de las TIC's en la vida cotidiana.El uso de las TIC's en la vida cotidiana.
El uso de las TIC's en la vida cotidiana.
 
Crear un recurso multimedia. Maricela_Ponce_DomingoM1S3AI6-1.pptx
Crear un recurso multimedia. Maricela_Ponce_DomingoM1S3AI6-1.pptxCrear un recurso multimedia. Maricela_Ponce_DomingoM1S3AI6-1.pptx
Crear un recurso multimedia. Maricela_Ponce_DomingoM1S3AI6-1.pptx
 
tarea de exposicion de senati zzzzzzzzzz
tarea de exposicion de senati zzzzzzzzzztarea de exposicion de senati zzzzzzzzzz
tarea de exposicion de senati zzzzzzzzzz
 
El_Blog_como_herramienta_de_publicacion_y_consulta_de_investigacion.pptx
El_Blog_como_herramienta_de_publicacion_y_consulta_de_investigacion.pptxEl_Blog_como_herramienta_de_publicacion_y_consulta_de_investigacion.pptx
El_Blog_como_herramienta_de_publicacion_y_consulta_de_investigacion.pptx
 
Presentación inteligencia artificial en la actualidad
Presentación inteligencia artificial en la actualidadPresentación inteligencia artificial en la actualidad
Presentación inteligencia artificial en la actualidad
 
tics en la vida cotidiana prepa en linea modulo 1.pptx
tics en la vida cotidiana prepa en linea modulo 1.pptxtics en la vida cotidiana prepa en linea modulo 1.pptx
tics en la vida cotidiana prepa en linea modulo 1.pptx
 
Red Dorsal Nacional de Fibra Óptica y Redes Regionales del Perú
Red Dorsal Nacional de Fibra Óptica y Redes Regionales del PerúRed Dorsal Nacional de Fibra Óptica y Redes Regionales del Perú
Red Dorsal Nacional de Fibra Óptica y Redes Regionales del Perú
 
Medidas de formas, coeficiente de asimetría y coeficiente de curtosis.pptx
Medidas de formas, coeficiente de asimetría y coeficiente de curtosis.pptxMedidas de formas, coeficiente de asimetría y coeficiente de curtosis.pptx
Medidas de formas, coeficiente de asimetría y coeficiente de curtosis.pptx
 
LUXOMETRO EN SALUD OCUPACIONAL(FINAL).ppt
LUXOMETRO EN SALUD OCUPACIONAL(FINAL).pptLUXOMETRO EN SALUD OCUPACIONAL(FINAL).ppt
LUXOMETRO EN SALUD OCUPACIONAL(FINAL).ppt
 
La Electricidad Y La Electrónica Trabajo Tecnología.pdf
La Electricidad Y La Electrónica Trabajo Tecnología.pdfLa Electricidad Y La Electrónica Trabajo Tecnología.pdf
La Electricidad Y La Electrónica Trabajo Tecnología.pdf
 
Trabajo de tecnología excel avanzado.pdf
Trabajo de tecnología excel avanzado.pdfTrabajo de tecnología excel avanzado.pdf
Trabajo de tecnología excel avanzado.pdf
 
TEMA 2 PROTOCOLO DE EXTRACCION VEHICULAR.ppt
TEMA 2 PROTOCOLO DE EXTRACCION VEHICULAR.pptTEMA 2 PROTOCOLO DE EXTRACCION VEHICULAR.ppt
TEMA 2 PROTOCOLO DE EXTRACCION VEHICULAR.ppt
 
Los Microcontroladores PIC, Aplicaciones
Los Microcontroladores PIC, AplicacionesLos Microcontroladores PIC, Aplicaciones
Los Microcontroladores PIC, Aplicaciones
 
LAS_TIC_COMO_HERRAMIENTAS_EN_LA_INVESTIGACIÓN.pptx
LAS_TIC_COMO_HERRAMIENTAS_EN_LA_INVESTIGACIÓN.pptxLAS_TIC_COMO_HERRAMIENTAS_EN_LA_INVESTIGACIÓN.pptx
LAS_TIC_COMO_HERRAMIENTAS_EN_LA_INVESTIGACIÓN.pptx
 
El uso de las tic en la vida ,lo importante que son
El uso de las tic en la vida ,lo importante  que sonEl uso de las tic en la vida ,lo importante  que son
El uso de las tic en la vida ,lo importante que son
 
Tecnologias Starlink para el mundo tec.pptx
Tecnologias Starlink para el mundo tec.pptxTecnologias Starlink para el mundo tec.pptx
Tecnologias Starlink para el mundo tec.pptx
 
Excel (1) tecnologia.pdf trabajo Excel taller
Excel  (1) tecnologia.pdf trabajo Excel tallerExcel  (1) tecnologia.pdf trabajo Excel taller
Excel (1) tecnologia.pdf trabajo Excel taller
 

Transformación de datos en Camel

  • 1. Abimael Desales López Java Developers México
  • 2. Contenido 1. Vista General de la Transformación de Datos 2. Transformando datos usando EIPs y Java 1. Usando el EIP Message Translator 2. Usando el EIP Content Enricher 3. Transformando XML 1. Transformando XML con XSLT 2. Transformando XML con marshalling de objetos 4. Transformando con formatos de datos 1. Formatos de datos provistos con Camel 2. Usando el formato de dato CSV de Camel 3. Usando el formato de dato Bindy de Camel 4. Usando el formato de dato JSON de Camel 5. Configurando formatos de datos Camel 6. Escribiendo tu propio formato de datos
  • 3. Contenido 5. Transformando con plantillas 1. Usando Apache Velocity 6. A cerca de los convertidores de tipo Camel 5. Cómo funciona el mecanismo convertidor de tipo Camel 6. Usando los convertidores de tipo Camel 7. Escribiendo tu propio convertidor de tipo
  • 4. 1.Vista General de la Transformación de Datos Camel proporciona muchas técnicas para transformación de datos. La transformación de datos es un término amplio que cubre dos tipos de transformación:  Transformación de formatos de datos. El formato de datos del cuerpo del mensaje es transformado de una forma a otra. Por ejemplo, un registro CSV es formateado como XML.  Transformación de tipo de datos. El tipo de datos del cuerpo del mensaje es transformado de un tipo a otro. Por ejemplo, un java.lang.String es transformado en un javax.jms.TextMessage. La figura 3.1 ilustra el principio de transformar el cuerpo de un mensaje de un formato a otro. Esta combinación puede involucrar cualquier combinación de tipo y formato.
  • 5. En la mayoría de los casos la transformación de datos con la que te enfrentarás con Camel es transformación de formato, donde tienes que mediar entre dos protocolos. Camel tiene un mecanismo convertidor de tipo incorporado que puede convertir automáticamente entre dos tipos, lo cual reduce mucho la necesidad de tratar para los usuarios finales con transformaciones de tipo. 1.Vista General de la Transformación de Datos Figura 3.1. Camel ofrece muchas características para transformación de datos de un formato a otro
  • 6. Transformación de datos con Camel En Camel la transformación de datos generalmente toma lugar en las seis formas listadas en la tabla 3.1.
  • 7. Transformación Descripción Transformación de datos en routes Puedes explícitamente forzar la transformación en el route usando los EIPs Message Translator o Content Enricher. Esto te da el poder de hacer mapeos de datos usando código regular Java. Transformación de datos usando componentes Camel proporciona un rango de componentes para transformación, como lo es el componente XSLT para transformación XML. Transformación de datos usando formatos de datos Los formatos de datos son transformadores Camel que vienen en pares para transformar datos atrás y hacia adelante entre formatos bien conocidos Transformación de datos usando templates Camel proporciona un rango de componentes para transformar usando plantillas, como Apache Velocity. Transformación de tipos de datos usando el mecanismo convertidor de tipos de Camel Camel tiene un mecanismo convertidor de tipos elaborado que se activa bajo demanda. Esto es conveniente cuando necesitas convertir de tipos comunes como java.lang.Integer a java.lang.String o aún de java.io.File a java.lang.String. Transformación de mensajes en adaptadores de componentes Muchos componentes de Camel se adaptan a varios protocolos comúnmente usados y, como tal, necesita ser capaz de transformar mensajes en la medida en que viajan a y desde estos protocolos. Frecuentemente estos componentes usan una combinación de transformaciones de datos y convertidores de tipo personalizadas.
  • 8. 2. Transformando datos usando EIPs y Java Data Mapping es el proceso de mapear entre dos modelos de datos distintos, y es un factor clave en la integración de datos. Hay muchos estándares existentes para modelos de datos, gobernados por varias organizaciones o comités. Por tal, frecuentemente te encontrarás necesario mapear del modelo de datos personalizado de una compañía a un modelo de datos estándar. Camel proporciona gran libertad en el mapeo de datos debido a que te permite usar código Java –no estás limitado a usar una herramienta de mapeo de datos particular que en la primera podría parecer elegante pero que torna a hacer las cosas imposibles. Aquí veremos cómo mapear datos usando un Processor, el cual es una API Camel. Camel también usa beans para mapear, lo cual es una buena práctica, debido a que le permite a tu lógica de mapeo ser independiente de la API de Camel.
  • 9. Usando el EIP Message Translator El EIP Mesage Translator es ilustrado en la figura 3.2 Este patrón cubre traducir un mensaje de un formato a otro. Es el equivalente al patrón Adapter del libro Gang of Four. Camel provee tres formas de usar este patrón:  Usando un Processor  Usando beans  Usando <transform>
  • 10. Transformando usando un Processor El Processor de Camel es una interface definida en org.apache.camel.Processor con un sólo método: public void process(Exchange exchange) throws Exception; El Processor es una API de bajo nivel donde trabajas directamente en la instancia Exchange de Camel. Te da acceso completo a todas las partes de Camel que se mueven del CamelContext, del cual puedes obtener del Exchange usando el método getCamelContext. Veamos un ejemplo. En Autopartes Rider se te ha solicitado generar diariamente reportes de órdenes recientemente recibidas para ser sacadas a un archivo CSV. La compañía usa un formato personalizado para entradas de órdenes, pero hace las cosas fáciles, ellos ya tienen un servicio HTTP que retorna una lista de órdenes para cualquier dato que ingreses. El reto al que te enfrentas es mapear los datos retornados del servicio HTTP a un formato CSV y escribir el reporte a un archivo.
  • 11. Listado 3.1 Usando un Processor para traducir desde un formato personalizado a formato CSV import org.apache.camel.Exchange; import org.apache.camel.Processor; public class OrderToCsvProcessor implements Processor { public void process(Exchange exchange) throws Exception { String custom = exchange.getIn().getBody(String.class); String id = custom.substring(0, 9); String customerId = custom.substring(10, 19); String date = custom.substring(20, 29); String items = custom.substring(30); String[] itemIds = items.split("@"); StringBuilder csv = new StringBuilder(); csv.append(id.trim()); csv.append(",").append(date.trim()); csv.append(",").append(customerId.trim()); for (String item : itemIds) { csv.append(",").append(item.trim()); } exchange.getIn().setBody(csv.toString()); } } Obtiene payload personalizado Extrae datos a variables locales Mapea a formato CSV Remplaza payload con payload CSV
  • 12. Primero coges el payload de formato personalizado del exchange. Es de tipo String, de forma que pasas una String como parametro de entrada para tener el payload retornado como una String. Luego extraes datos del formato personalizado a las variables locales. El formato personalizado podría ser cualquier cosa, pero en este ejemplo es un formato personalizado de longitud fija. Luego mapeas el formato CSV construyendo una string con valores separados por coma. Finalmente, remplaza el payload personalizado con tu nuevo payload CSV. Usar un processor tiene una desventaja, requieres hacer uso de la API Camel.
  • 13. Importante Usando los métodos getIn y getOut en exchanges El Exchange Camel define dos métodos para retomar mensajes: getIn y getOut. El método getIn retorna el mensaje entrante, y el método getOut accesa el mensaje saliente. Hay dos escenarios donde el usuario final Camel tendrá que decidir entre usar estos métodos:  Un escenario de sólo lectura, como cuando envías a log el mensaje entrante.  Un escenario de escritura, como cuando estás transformando el mensaje En el segundo escenario asumirías que se debería usar getOut. Eso es correcto acorde a la teoría, pero en la práctica hay una trampa cuando se usa getOut: los headers y attachments del mensaje entrante se perderán. Frecuentemente esto no es lo que quieres, de forma que copiar los headers y attachments del mensaje entrante al mensaje saliente, puede ser tedioso. La alternativa es asignar los cambios directamente en el mensaje entrante usando getIn, y no usar getOut en todo.
  • 14. Transformando usando Beans Usar beans es una buena práctica debido a que te permite usar cualquier código Java y librerías que desees. Camel no impone restricciones en ninguna cosa. Camel puede invocar cualquier bean que elijas, de forma que puedes usar beans existentes sin tener que rescribirlos o recompilarlos.
  • 15. Listado 3.2 Usando un bean para traducir de un formato personalizado a formato CSV public class OrderToCsvBean { public static String map(String custom) { String id = custom.substring(0, 9); String customerId = custom.substring(10, 19); String date = custom.substring(20, 29); String items = custom.substring(30); String[] itemIds = items.split("@"); StringBuilder csv = new StringBuilder(); csv.append(id.trim()); csv.append(",").append(date.trim()); csv.append(",").append(customerId.trim()); for (String item : itemIds) { csv.append(",").append(item.trim()); } return csv.toString(); } } Extrae datos a variables locales Mapea a formato CSV Retorna payload CSV
  • 16. La primer diferencia notable entre los listados 3.1 y 3.2 es que en el listado 3.2 no se usa ningún import de Camel. Esto significa que tu bean es totalmente independiente de la API Camel. La siguiente diferencia es que puedes nombrar la firma del método en el listado 3.2 –en este caso es un método estático llamado map. La firma del método define el contrato, lo cual significa que el primer parámetro, (String custom), es el body del mensaje que vas a usar para la traducción. El método retorna una String, lo cual significa que los datos traducidos serán de tipo String. En ejecución, Camel vincula a esta firma del método. Una ventaja más de usar beans sobre processors para mapeos es que las pruebas unitarias son mucho más fáciles.
  • 17. Transformando usando el método transform() del DSL Java Transform() es un método en el DSL Java que puede ser usado en routes Camel para transformar mensajes. Permitiendo el uso de expresiones, transform() permite gran flexibilidad, y usando expresiones directamente en el DSL a veces puede ahorrar tiempo. Supongamos que necesitas preparar algún texto para formateo HTML remplazando todos los saltos de línea con una tag <br/>. Esto puede hacerse con una expresión incorporada de Camel que busca y remplaza utilizando expresiones regulares. from("direct:start") .transform(body().regexReplaceAll("n", "<br/>")) .to("mock:result");
  • 18. Lo que este route hace es usar el método transform() para decirle a camel que el mensaje debe ser transformado usando una expresión. Camel provee lo que es conocido como el patrón Builder para construir expresiones desde expresiones individuales. Este se hace encadenando llamadas a métodos, lo cual es la esencia del patrón Builder. En este ejemplo combinas body() y regexReplaceAll(). La expresión debe ser leída como sigue: toma el body y ejecuta una expresión regular que remplace todas las nuevas líneas (n) con tags <br/>. Ahora hemos combinado dos métodos que conforman a una expresión Camel compuesta.
  • 19. Camel te permite usar tus propias expresiones personalizadas. Esto es útil cuando necesitas tener control completo y tener código Java en la punta de tus dedos. Por ejemplo, el ejemplo anterior podría haber sido implementado de la forma siguiente: from("direct:start") .transform(new Expression() { public <T> T evaluate(Exchange exchange, Class<T> type) { String body = exchange.getIn().getBody(String.class); body = body.replaceAll("n", "<br/>"); body = "<body>" + body + "</body>"; return (T) body; } }).to("mock:result");
  • 20. Transformando usando <transform> de Spring XML Usar <transform> de Spring XML es un poco diferente que el DSL Java debido a que el DSL XML no es tan poderoso. No están disponibles las expresiones del patrón Builder debido a que XML no tiene un lenguaje de programación real tras él. Lo que puedes hacer tras ello es invocar un método en un bean o usar lenguajes de scripting. Veamos cómo trabaja esto. El método del siguiente bean se usa dentro del route como la expresión: public class HtmlBean { public static String toHtml(String body) { body = body.replaceAll("n", "<br/>"); body = "<body>" + body + "</body>"; return body; } }
  • 21. El route es el siguiente: <bean id="htmlBean" class="camelinaction.HtmlBean"/> <camelContext id="camel" xmlns="http://camel.apache.org/schema/spring"> <route> <from uri="direct:start"/> <transform> <method bean="htmlBean" method="toHtml"/> </transform> <to uri="mock:result"/> </route> </camelContext> Primero declaras un bean regular de Spring para ser usado para transformar el mensaje. Luego en el route, usas <transform> con una expresión llamada <method> para invocar el bean.
  • 22.
  • 23. Usando el patrón EIP Content Enricher El EIP Content Enricher se ilustra en la figura 3.3. Este patrón documenta el escenario donde un mensaje es enriquecido con datos obtenidos de otro recurso. Figura 3.3 En el EIP Content Enricher, un mensaje existente tiene datos agregados de otra fuente.
  • 24. Para ayudar a comprender este patrón, regresaremos a Aupartes Rider. Nos damos cuenta que el mapeo de datos que hicimos en el listado 3.1 no era suficiente. Las órdenes también son acumuladas en un servidor FTP, y tu job va de alguna manera a mezclar esta información en el reporte existente. La figura 3.4 ilustra este escenario. En la figura 3.4, un consumidor calendarizado usando Quartz inicia el route cada día a las 6:00 am 1. Luego obtiene datos de un servidor FTP, el cual retorna órdenes en un formato personalizado 2, el cual luego es transformado en formato CSV 3. En este punto, tienes que ejecutar el paso de enriquecimiento de contenido adicional 4 con los datos obtenidos del servidor FTP 5. Después de esto, el reporte final es escrito al servidor FTP 6.
  • 25. Figura 3.4 Una vista general del route que genera el reporte de órdenes, ahora con el enriquecedor de contenido obteniendo datos de un servidor FTP.
  • 26. Antes de profundizarnos en el código y ver cómo implementar esto, necesitamos ir un paso atrás y ver cómo el EIP Content Enricher es implementado en Camel. Camel proporciona dos operaciones en el DSL para implementar el patrón.  pollEnrich – Esta operación mezcla datos retomados de otra fuente usando un consumidor.  enrich – Esta operación mezcla datos retomados de otra fuente usando un productor. Camel usa la interfaz org.apache.camel.processor. AgregationStrategy para mezclar los resultados de la fuente con el mensaje original, de la forma siguiente: Exchange aggregate(Exchange oldExchange, Exchange newExchange);
  • 27. Este método aggregate es una callback que debes implementar. Este método tiene dos parámetros: el primero, llamado oldExchange, contiene el exchange original; el segundo, newExchange, es la fuente enriquecida. Tu tarea es enriquecer el mensaje usando código Java y retornar el resultado mezclado. Esto puede sonar un poco confuso, veámoslo en acción. Para resolver el problema, necesitas usar pollEnrich debido a que es capaz de votear por un archivo de un servidor FTP. Enriqueciendo usando POLLENRICH. El listado 3.3 muestra cómo puedes usar pollEnrich para retomar las órdenes adicionales del servidor FTP remoto y agregar estos datos con el mensaje existente usando AggregationStrategy de Camel.
  • 28. Listado 3.3 Usando pollEnrich para mezclar datos adicionales con un mensaje existente from("quartz://report?cron=0+0+6+*+*+?") .to("http://riders.com/orders/cmd=received") .process(new OrderToCSVProcessor()) .pollEnrich("ftp://riders.com/orders/?username=rider&password=secret", new AggregationStrategy() { public Exchange aggregate(Exchange oldExchange, Exchange newExchange){ if (newExchange == null) { return oldExchange; } String http = oldExchange.getIn().getBody(String.class); String ftp = newExchange.getIn().getBody(String.class); String body = http + "n" + ftp; oldExchange.getIn().setBody(body); return oldExchange; } }) .to("file://riders/orders"); 1 2 Mezcla datos usando AggregationStrategy 3 Escribe la salida a archivo Usa pollEnrich para leer un archivo FTP
  • 29. El route es disparado por Quartz para que corra todos los días a las 6 am. Invocas el servicio HTTP para retomar las órdenes y transformarlas a formato CSV usando un processor. En este punto, necesitas enriquecer los datos existentes con las órdenes del servidor FTP remoto. Esto se hace usando pollEnrich 1, lo cual consume el archivo remoto. Para mezclar los datos, usas AggregationStrategy 2. Primero, checas si algunos datos fueron o no consumidos. Si newExchange es null, no hay archivo remoto para consumir, y sólo retornas los datos existentes. Si hay un archivo remoto, mezclas los datos concatenando los datos existentes con los nuevos datos y asignándolos atrás en el oldExchange. Luego, retornas los datos mezclados retornando el oldExchange. Para escribir el archivo de reporte CSV, usas el componente file.
  • 30. PollEnrich utiliza un consumidor de voteo para retomar mensajes, y ofrece tres modos de timeout:  pollEnrich(timeout=-1)- Votea el mensaje y espera hasta que un mensaje llegue. Este modo bloqueará hasta un mensaje exista.  pollEnrich(timeout=0)- Inmediatamente votea el mensaje si alguno existe; de otra forma se retornará null. Nunca esperará para que los mensajes lleguen, así que este modo nunca bloqueará. Este es el modo default.  pollEnrich(timeout>0)- Votea el mensaje, si no existe mensaje, esperará por uno, esperando a lo más hasta que el timeout se dispare. Este modo potencialmente bloqueará. Es una mejor práctica usar timeout=0 o asignar un valor de timeout cuando se usa pollEnrich para evitar esperar indefinidamente si no llegan mensajes.
  • 31. Enriqueciendo usando ENRICH Enrich es usado cuando necesitas enriquecer el mensaje actual con datos de otra fuente usando mensajería request-response. Un primer ejemplo sería enriquecer el mensaje actual con la respuesta de una llamada a web service. Pero veremos otro ejemplo, usando Spring XML para enriquecer el mensaje actual usando el transporte TCP: <bean id="quoteStrategy“ class="camelinaction.QuoteStrategy"/> <route> <from uri="activemq:queue:quotes"/> <enrich url="mina:tcp://riders.com:9876?textline=true&sync=true" strategyRef="quoteStrategy"/> <to uri="log:quotes"/> </route> Aquí usas el componente mina de Camel para transporte TCP, configurado para usar mensajería request-response usando la opción sync=true. 1 Bean implementando AggregationStrategy
  • 32. Para mezclar el mensaje original con datos del servidor remoto, <enrich> debe referir a una AggregationStrategy. Esto se hace usando el atributo strategyRef. Como lo puedes ver en el ejemplo, la quoteStrategy a la que está siendo referida es el id de un bean 1, el cual contiene la implementación real de la AggregationStrategy, donde la mezcla toma lugar.
  • 33. 3.3 Transformando XML Camel proporciona dos formas de ejecutar transformaciones XML.  Componente XSLT –Para transformar un payload XML en otro formato usando hojas de estilo XSLT.  Marshaling XML –Para serializar y deserializar objetos a y desde XML. Transformando XML con XSLT XSL Transformations (XSLT) es un lenguaje XML declarativo usado para transformar documentos XML en otros documentos. Por ejemplo, XSLT puede ser usado para transformar XML en HTML para páginas web o para transformar un documento XML en otro documento XML con una estructura diferente. XSLT es poderoso y versátil, pero también es un lenguaje complejo y toma tiempo y esfuerzo comprenderlo y dominarlo. Hay que pensarlo dos veces.
  • 34. Camel provee XSLT como un componente en camel-spring.jar debido a que aprovecha la carga de recursos de Spring. Esto significa mayor flexibilidad en la carga de hojas de estilo debido a que Spring les permite ser cargadas de diferentes ubicaciones, como lo es del classpath, rutas de archivos, y sobre HTTP. Figura 3.5 Un Camel route usando un componente XSLT para transformar un documento XML antes de que sea enviado a una queue JMS
  • 35. Usar el componente XSLT es sencillo, debido a que es sólo otro componente Camel. El siguiente route muestra un ejemplo de cómo podrías usarlo; este route también es ilustrado en la figura 3.5. from("file://rider/inbox") .to("xslt://camelinaction/transform.xsl") .to("activemq:queue:transformed") El consumidor de archivos selecciona los nuevos archivos y los enruta al componente XSLT, el cual transforma el payload usando la hoja de estilos. Después de la transformación, el mensaje es enrutado a un productor JMS. Nota en el código anterior como es definida la URL para el componente XSLT: xslt://camelinaction/transform.xsl. La parte posterior del esquema es la ubicación URI de la hoja de estilo a usar. Por default Camel buscará en el classpath.
  • 36. El componente XSLT aprovecha Spring para cargar la hoja de estilos. Puedes prefijar el nombre del recurso con cualquiera de los tres prefijos listados en la tabla 3.2. Prefijo Ejemplo Descripción <ninguno> xslt://camelinaction/transform.xsl Si no se proporciona prefijo, camel carga el recurso del classpath classpath xslt://classpath:com/mycompany/tra nsform.xsl Carga el recurso del classpath file xslt://file:/rider/config/transform.xsl Carga el recurso del sistema de archivos local http: xslt://http://rider.com/styles/transfor m.xsl Carga el recurso de una URL
  • 37. Transformando XML con Marshalling de Objetos Cualquier ingeniero de software quien ha trabajado con XML sabe que es un reto usar la API XML de bajo nivel que ofrece Java. En lugar de eso, la gente frecuentemente prefiere trabajar con objetos Java regulares y usar marshalling para transformar entre objetos Java y representaciones XML. En Camel este proceso de marshalling es provisto en componentes listos-para-usar conocidos como formatos de datos. Transformando usando XStream XStream es una simple librería para serializar objetos a XML y hacia atrás. Para usarla, necesitas el camel-xstream.jar en el classpath y la misma librería de XStream. Supón que necesitas enviar mensajes en formato XML a una queue JMS compartida, la cual luego es usada para integrar dos sistemas.
  • 38. Transformando usando Marshalling de Objetos Listado 3.4 Usando XStream para transformar un mensaje en XML <camelContext id="camel" xmlns="http://camel.apache.org/schema/spring"> <dataFormats> <xstream id="myXstream"/> </dataFormats> <route> <from uri="direct:foo"/> <marshal ref="myXstream"/> <to uri="activemq:queue:foo"/> </route> </camelContext> Cuando usas el DSL XML, puedes declarar los formatos de datos usados arriba 1 del <CamelContext>. Haciendo esto, puedes compartir los formatos de datos en múltiples routes. En este primer route, donde envías mensajes a una queue JMS, usas marshall 2, lo cual se refiere al id de 1,, de forma que Camel sabe que el formato de datos XStream está siendo usado. Especifica formato de datos XStream Transforma a XML
  • 39. Transformando usando Marshalling de Objetos También puedes usar directamente en el route, lo cual puede acortar un poco la sintaxis, como esto: <route> <from uri="direct:foo"/> <marshal> <xstream/> </marshall> <to uri="activemq:queue:foo"/> </route> </camelContext> El mismo route es un poco más acortador para escribir en el DSL Java, debido a que puedes hacerlo con una línea por route: from("direct:foo").marshal().xstream().to("uri:activemq:queue:foo"); Sí, usar Xstream es tan fácil. Y la operación inversa, unmarshalling de XML a un objeto, es tan simple:
  • 40. Transformando usando Marshalling de Objetos <route> <from uri="activemq:queue:foo"/> <unmarshal ref="myXstream"/> <to uri="direct:handleFoo"/> </route> Ya has visto cuan fácil es usar XStream con Camel.
  • 41. Transformando usando JAXB JAXB (Java Architecture for XML Binding) es una especificación estándar para XML binding, y es provista lista en el runtime Java. Como XStream, te permite serializar objetos a XML y hacia atrás otra vez. No es tan simple, pero ofrece más opciones para controlar la salida XML. Y debido a que es distribuido en Java, no necesitas algunos archivos Jars especiales en el classpath. A diferencia de XStream, JAXB requiere que hagas un poco de trabajo para declarar el binding entre objetos Java y el formato XML. Esto frecuentemente se hace usando anotaciones. Supón que defines un modelo de bean para representar una orden, como se muestra en el listado 3.5, y quieres transformar esto en XML antes de enviarlo a una queue JMS. Luego quieres transformarlo atrás al bean de orden otra vez, cuando consumes de la queue JMS. Esto puede hacerse como se muestra en los listados 3.5 y 3.6.
  • 42. Transformando usando JAXB package com.acme.order; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class PurchaseOrder { @XmlAttribute private String name; @XmlAttribute private double price; @XmlAttribute private double amount; } 1 PurchaseOrder en una clase JAXB anotada Listado 3.5 Anotando un bean con JAXB de forma que pueda ser transformado a y desde XML
  • 43. Transformando usando JAXB El listado 3.5 muestra como usar anotaciones JAXB para decorar tu objeto modelo (omitiendo los getters y setters usuales). Primero define @XmlRootElement 1 como una anotación a nivel de clase para indicar que esta clase es un elemento XML. Luego defines el @XmlAccessorType para permitir que JAXB accese los campos directamente. Para exponer los campos de este objeto modelo como atributos XML, los marcas con la anotación @XmlAttribute. Usando JAXB, debes ser capaz de serializar un objeto modelo en una representación XML como esta: <purchaseOrder name="Camel in Action" price="4995" amount="1"/> El listado 3.6 muestra como puedes usar JAXB en routes para transformar el objeto PurchaseOrder a XML antes de que sea enviado a una queue JMS, y luego atrás otra vez de XML al objeto PurchaseOrder cuando se consume de la misma queue JMS.
  • 44. Transformando usando JAXB Listado 3.5 Usando JAXB para serializar objetos a y desde XML <camelContext id="camel" xmlns="http://camel.apache.org/schema/spring"> <dataFormats> <jaxb id="jaxb" contextPath="camelinaction"/> </dataFormats> <route> <from uri="direct:order"/> <marshal ref="jaxb"/> <to uri="activemq:queue:order"/> </route> <route> <from uri="activemq:queue:order"/> <unmarshal ref="jaxb"/> <to uri="direct:doSomething"/> </route> </camelContext> 1 Declara formato de datos JAXB 2 Transforma de modelo a XML 3 Transforma de XML a modelo
  • 45. Transformando usando JAXB Primero necesitas declarar el formato de datos JAXB 1. Nota que también se define un atributo contextPath en el formato de datos JAXB –este es un nombre de package que instruye a JAXB que busque en este package clases que son anotadas de JAXB. El primer route luego serializa a XML 2 y el segundo route deserializa para transformar el XML atrás al objeto PurchaseOrder 3. Nota: Para decirle a JAXB qué clases son anotadas de JAXB, necesitas arrastrar un archivo especial jaxb.index en la ruta del contexto. Es un archivo de texto plano en el cual cada línea lista el nombre de la clase. En el ejemplo anterior, el archivo contiene una sola línea con el texto PurchaseOrder.
  • 46. 3.4 Transformando con formatos de datos En Camel, los formatos de datos son transformadores pluggables que pueden transformar mensajes de un formato a otro y viceversa. Cada formato de dato es representado en Camel como una interface org.apache.camel.spi.DataFormat conteniendo dos métodos:  marshall – Para serializar un objeto en otro formato, tal como serializar objetos Java a XML, CSV, EDI, HL7, u otros modelos de datos conocidos.  unmarshall – Para ejecutar la operación inversa, la cual transforma datos de formatos bien conocidos atrás en un mensaje. Figura 3.6 Un objeto es serializado a una representación binaria; unmarshall puede utilizarse para llevar el objeto atrás.
  • 47. Ya pudiste haberte dado cuenta que estas dos funciones son opuestas, significando que una es capaz de hacer lo inverso de lo que la otra ha hecho, como lo ilustra la figura 3.6. En esta sección cubriremos los formatos de datos en más profundidad y usando otros tipos de datos diferentes a XML, como es CSV y JSON. Aún también veremos cómo puedes crear tus propios formatos de datos. Comenzaremos nuestra jornada checando los formatos de datos Camel provistos listos para usar. Formatos de datos provistos con Camel Camel provee formatos de datos para un rango de modelos de datos bien conocidos, como se lista en la tabla 3.3.
  • 48. Tabla 3.3 Formatos de datos provistos listos con Camel Formato de dato Modelo de dato Artefacto Descripción Bindy CSV, FIX, longitud fija camel-bindy Vincula varios modelos de datos para modelar objetos usando anotaciones Castor XML camel-castor Usa Castor para vincular a y desde objetos Java Crypto Cualquiera camel-crypto Encripta y desencripta datos usando la Java Cryotography Extension CSV CSV camel-csv Transforma a y desde CSV usando la librería Apache Commons CSV Flatpack CSV camel-flatpack Transforma a y desde CSV usando la librería FlatPack GZip Cualquiera camel-gzip Comprime y descomprime archivos (compatible con las populares herramientas gzip/gunzip) HL7 HL7 camel-hl7 Transforma a y desde HL7, el cual es un formato de datos bien conocido en la industria del cuidado de la salud JAXB XML camel-jaxb Usa el estándar JAXB 2.x para vincular XML a y desde objetos Java Jackson JSON camel-jackson Transforma a y desde JSON usando la ultrarrápida librería Jackson
  • 49. Tabla 3.3 Formatos de datos provistos listos con Camel (cont) Formato de dato Modelo de dato Artefacto Descripción Protobuf XML camel- protobuf Transforma a y desde XML usando la librería Google Protocol Buffers SOAP XML camel-soap Transforma a y desde SOAP Serialization Objeto camel-core Usa serialización de objetos para transformar objetos a y desde un stream serializado TidyMarkup HTML camel-tagsoup xmalBeans XML camel- xmlsbeans Usa XmlBeans para vincular XML a y desde objetos Java XMLSecurity XML camel- xmlsecurity Facilita la encripción y desencripción de documentos XML XStream XML camel-xstream Usa XStream para vinculación XML a y desde objetos Java XStream JSON camel-xstream Transforma a y desde JSON usando la librería XStream Zip Cualquiera camel-core Usa el estándar JAXB 2.x para vincular XML a y desde objetos Java
  • 50. Como puedes ver, Camel proporciona 18 formatos de datos listos para usar. Aquí estaremos viendo 3 de ellos. Ellos son los formatos más comúnmente usados, y lo que aprendas sobre estos aplicarán también para los restantes formatos de datos. Usando el formato de datos CSV de Camel El formato de datos camel-csv es capaz de transformar a y desde formato CSV. Aprovecha Apache Commons CSV para hacer el trabajo real. Supón que necesitas consumir archivos CSV, dividir cada fila, y enviarla a una queue JMS. Suena difícil de hacer, pero es posible con poco esfuerzo en un route Camel:
  • 51. from.(“file://rider/csvfiles”) .unmarshall().csv() .split(body()).to(“activemq:queue.csv.record”); Todo lo que tienes que hacer es unmarshall los archivos CSV, lo cual leerá el archivo línea por línea y almacenará todas las líneas en el cuerpo del mensaje como un tipo java.util.List<List>. Luego usas el splitter para dividir el cuerpo, lo cual fraccionará la java.util.List<List<String>> en filas (cada fila representada como otra List<String> conteniendo los campos) y enviar la fila a la queue JMS. Podrías no querer enviar cada fila como un tipo List a la queue JMS, de forma que puedes transformar la fila antes de enviarla, quizás usando un processor. El mismo ejemplo en Spring XML es un poco diferente, como se muestra aquí:
  • 52. <camelContext id="camel" xmlns="http://camel.apache.org/schema/spring"> <route> <from uri="file://rider/csvfiles"/> <unmarshal><csv/></unmarshal> <split> <simple>body</simple> <to uri="activemq:queue.csv.record"/> </split> </route> </camelContext> La notable diferencia es como le dices a <split> que debe dividir el cuerpo del mensaje. Para hacer esto necesitas proveerle a <split> con una Expression, qué es lo que el splitter debe iterar cuando ejecute el splitting. Para hacerlo así, puedes usar el lenguaje de expresión incorporado de Camel llamado Simple, el cual sabe cómo hacer eso.
  • 53. A la primera, los tipos de datos que el formato de datos usa pueden parecer un poco confusos. Estos son listados en la tabla 3.4. Un problema con camel-csv es que usa tipos de datos genéricos, como Maps o Lists, para representar registros CSV. Frecuentemente ya tienes modelos de datos para representar tus datos en memoria. Operación De tipo A tipo Descripción marshall Map<String, Object> OutputStream Contiene una sola fila en formato CSV marshall List<Map<String, Object>> OutputStream Contiene múltiples filas en formato CSV donde cada fila está separada por n (nueva línea) unmarshall InputStream List<List<String>> Contiene una List de filas donde cada fila es otra List de campos
  • 54. Usando el formato de datos Bidy de Camel Los dos formatos de datos existentes relacionados a CSV (camel-csv y camel-flatpack) son librerías más viejas que no toman ventaja de las nuevas características de Java 1.5, tales como anotaciones y generics. A la luz de esta deficiencia, Charles Moulliard salió y escribió el componente camel-bindy para tomar ventaja de estas nuevas posibilidades. Es capaz de vincular CSV, FIX, y formatos de datos de longitud fija a modelos de objetos existentes usando anotaciones. Esto es similar a lo que hace JAXB para XML. Supón que tienes un objeto modelo que representa una orden de compra. Anotando el objeto modelo con anotaciones camel-bindy, puedes fácilmente transformar mensajes entre CSV y objetos modelo Java.
  • 55. package camelinaction.bindy; import java.math.BigDecimal; import org.apache.camel.dataformat.bindy.annotation.CsvRecord; import org.apache.camel.dataformat.bindy.annotation.DataField; @CsvRecord(separator = ",", crlf = "UNIX") public class PurchaseOrder { @DataField(pos = 1) private String name; @DataField(pos = 2, precision = 2) private BigDecimal price; @DataField(pos = 3) private int amount; } Mapea a registro CSV 1 2 Mapea a columna en registro registro CSV
  • 56. Primero marcas la clase con la anotación @CsvRecord 1 para indicar que representa un registro en formato CSV. Entonces anotas los campos con @DateField acorde al layout del registro CSV 2. Usando el atributo pos, puedes dictar la orden en la cual son sacados en formato CSV; pos inicia con un valor de 1. Para campos numéricos, puedes adicionalmente declarar precision, la cual en este ejemplo es asignada a 2, indicando que el precio debe usar dos dígitos por centavo. Bindy tiene atributos para layout de grano fino de los campos, tales como pattern, trim y length. Puedes usar pattern para indicar el patrón de datos, trim para recortar la entrada, y length para restringir la descripción de un texto a un cierto número de caracteres. Antes de ver cómo usar Bindy en routes Camel, necesitamos ir un paso atrás y checar los tipos de datos que Bindy espera usar. Ellos son listados en la tabla 3.5.
  • 57. Tabla 3.5 Tipos de datos que Bindy usa cuando transforma a y desde formato CSV Operación De tipo A tipo Descripción de la salida marshall List<Map<String, Object>> OutputStream Contiene múltiples filas en formato CSV donde cada fila es separada por una n (nueva línea) unmarshall InputStream List<Map<String, Object>> Contiene una List de filas donde cada fila contiene 1..n modelos de datos contenidos en un Map La cosa importante a notar en la tabla 3.5 es que Bindy usa un Map<String, Object> para representar una fila CSV. A la primera puede parecer extraño. ¿Por qué no sólo usa un único objeto modelo para eso? La respuesta es que puedes tener múltiples objetos modelo con el registro CSV que está siendo dispersado a través de estos objetos. Por ejemplo, podrías tener los campos 1 a 3 en un objeto modelo, los campos 4 a 9 en otro, y los campos 10 al 12 en un tercero.
  • 58. La entrada del map <String, Object> es destilada como sigue:  Map key (String) –Debe contener el nombre de la clase completamente cualificado del objeto modelo.  Map value (Object) –Debe contener el objeto modelo. Si te parece ser un poco confuso, no te preocupes. El siguiente ejemplo debe hacerlo más claro: Listado 3.8 Usando Bindy para transformar un objeto modelo a formato CSV public class PurchaseOrderBindyTest extends TestCase { public void testBindy() throws Exception { CamelContext context = new DefaultCamelContext(); context.addRoutes(createRoute()); context.start(); MockEndpoint mock = context.getEndpoint("mock:result", MockEndpoint.class);
  • 59. mock.expectedBodiesReceived("Camel in Action,49.95,1n"); PurchaseOrder order = new PurchaseOrder(); order.setAmount(1); order.setPrice(new BigDecimal("49.95")); order.setName("Camel in Action"); ProducerTemplate template = context.createProducerTemplate(); template.sendBody("direct:toCsv", order); mock.assertIsSatisfied(); } public RouteBuilder createRoute() { return new RouteBuilder() { public void configure() throws Exception { from("direct:toCsv") .marshal().bindy(BindyType.Csv, "camelinaction.bindy") .to("mock:result"); } }; } } Crea el objeto modelo como es usual1 Inicia el test 2 Transforma el objeto modelo a CSV
  • 60. En este listado, primero creas y llenas el modelo de orden usando setters Java regulares 1. Luego envías el modelo de orden al route enviándolo al endpoint direct:toCsv 2 que es usado en el route. El route luego serializará el modelo de orden a CSV usando Bindy 3. Nota cómo Bindy es configurado para usar modo CSV vía BindyType.Csv. Para permitirle a Bindy saber cómo mapear a objeto modelo orden, necesitas proporcionar un nombre de package que será escaneado para clases anotadas con anotaciones Bindy. Esta es la misma solución que ofrece JAXB. Nota: El listado 3.8 usa MockEndpoint para probar fácilmente que el registro CSV está como se espera.
  • 61. Usando el formato de datos JSON de Camel JSON (JavaScript Jason Notation) es un formato de intercambio de datos, y Camel proporciona dos componentes que soportan el formato de datos JSON: camel-xstream y camel-jackson. En esta sección nos enfocaremos en camel-jackson debido a que Jackson es una librería JSON muy popular. Yendo atrás a Autopartes Rider, ahora tienes que implementar un nuevo servicio que retorna resúmenes de órdenes entregadas en formato JSON. Hacer esto con Camel es muy fácil, debido a que Camel tiene todos los ingredientes necesarios fabricar este servicio. El listado 3.9 muestra cómo puedes subir a un prototipo.
  • 62. <bean id="orderService" class="camelinaction.OrderServiceBean"/> <camelContext id="camel" xmlns="http://camel.apache.org/schema/spring"> <dataFormats> <json id="json" library="Jackson"/> </dataFormats> <route> <from uri="jetty://http://0.0.0.0:8080/order"/> <bean ref="orderService" method="lookup"/> <marshal ref="json"/> </route> </camelContext> Primero necesitas montar el formato de datos JSON y especificar que la librería Jackson debe ser usada 1. Luego defines un route que expone el servicio HTTP usando el endpoint Jetty. Este ejemplo expone el endpoint Jetty directamente en la URL. Usando http://0.0.0.0:8080/order , le dices a Jetty que cualquier cliente puede alcanzar este servicio en el puerto 8080. Monta un formato de datos JSON 1 2 Invoca bean para retomar datos para respuesta
  • 63. Siempre que una request golpee este servicio HTTP, es enrutado al bean orderService 2 y el método lookup es invocado en ese bean. El resultado de la invocación a este bean es luego serializado a formato JSON y retornado atrás al cliente HTTP. El bean order service podría tener una firma de método como esta: public PurchaseOrder lookup(@Header(name = "id") String id) Esta firma te permite implementar la lógica de lookup como desees. Nota que el bean del servicio puede retornar un POJO que la librería JSON es capaz de serializar. Por ejemplo, supón que usaste el PurchaseOrder del listado 3.7, y tuviste salida JSON como la siguente: {"name":"Camel in Action","amount":1.0,"price":49.95} El mismo servicio HTTP puede ser invocado por una request HTTP Get con el id de la orden como parámetro: http://0.0.0.0:8080/order/service?id=123.
  • 64. Configurando formatos de datos de Camel En secciones anteriores utilizaste el formato de datos CSV, pero este formato de datos ofrece muchas configuraciones adicionales. Este listado muestra como puedes configurar el formato de datos CSV. public void configure() { CSVConfig custom = new CSVConfig(); custom.setDelimiter(';'); custom.setEndTrimmed(true); custom.addField(new CSVField("id")); custom.addField(new CSVField("customerId")); custom.addField(new CSVField("date")); custom.addField(new CSVField("item")); custom.addField(new CSVField("amount")); custom.addField(new CSVField("description")); CsvDataFormat myCsv = new CsvDataFormat(); myCsv.setConfig(custom); myCsv.setAutogenColumns(false); from("direct:toCsv").marshal(myCsv).to("file://acme/outbox/csv"); } Configura formato de datos CSV personalizado 1 Crea el formato de datos CSV personalizado 2 3 Usa el formato de datos CSV
  • 65. Configurar formatos de datos en Camel se hace usando código Java regular; usas la API que proporciona el formato de datos. En el listado 3.10, el formato de datos CSV ofrece un objeto CSVConfig 1 que es usado para asignar el punto y coma como delimitador y para especificar el orden de los campos. El mismo formato de datos es luego creado 2 y asignado para usar la configuración. El uso del formato de datos sigue siendo el mismo, así que todo lo que necesitas hacer es referirte a él desde los métodos marshall y unmarshall. Este mismo principio aplica a todos los formatos de datos en Camel. Puedes configurarlos usando las APIs que ellos proveen. Ahora que sabes como usar los formatos de datos, vamos a ver como puedes escribir tus propios formatos de datos.
  • 66. Escribiendo tu propio formato de datos Pudieras encontrarte necesario transformar datos a y desde un formato de datos personalizado. En esta sección, veremos cómo puedes desarrollar un formato de datos que puede reversar strings. Desarrollar tu propio formato de datos es muy fácil, debido a que Camel provee una sola API que debes implementar: org.apache.camel.spi.DataFormat. Vamos a ver cómo podrías implementar un formato de dato de reversa de string. El formato de datos personalizado debe implementar la interface DataFormat, la cual te forza a desarrollar dos métodos: marshall 1 y unmarshall 2. Eso no es sorpresa, ya que ellos son los mismos métodos que usas en el route. El método marshall 1 necesita sacar el resultado al OutputStream. Para hacer esto necesitas obtener el payload del mensaje como un byte[], y luego reversarlo con un método helper. Luego escribes los datos al OutputStream.
  • 67. Nota que utilizas os convertidores de tipo de Camel para retornar el payload del mensaje como un byte[]. Esto es muy poderoso y te ahorra de hacer un typecast manual en Java o intentar convertir el payload por ti mismo. El método unmarshall es cercanamente el mismo. Usas el mecanismo convertidor de tipo de Camel otra vez para proporcionar el payload del mensaje como un byte[]. unmarshall también reversa los bytes para obtener los datos atrás en su orden original. Nota que en este método retornas los datos en vez de escribirlos a un stream. TIP: Como mejor práctica usa los convertidores de tipo Camel en vez del typecasting o convertirlos entre tipos por ti mismo. Para usar este nuevo formato de datos en un route, todo lo que tienes que hacer es definirlo como un bean de Spring y referirte a él desde <marshall> y <unmarshall> de la forma siguiente:
  • 68. <bean id="reverse" class="camelinaction.ReverseDataFormat"/> <camelContext id="camel" xmlns="http://camel.apache.org/schema/spring"> <route> <from uri="direct:marshal"/> <marshal ref="reverse"/> <to uri="log:marshal"/> </route> <route> <from uri="direct:unmarshal"/> <unmarshal ref="reverse"/> <to uri="log:unmarshal"/> </route> </camelContext>
  • 69. 3.5 Transformando con templates Camel proporciona una hábil integración con dos diferentes lenguajes de plantillas:  Apache Velocity-Probablemente el lenguaje de plantillas más conocido  FreeMarker –Otro lenguaje de plantillas popular que puede ser un poco más avanzado que Velocity. Los dos lenguajes de plantilla son muy similares de usar, así que con Velocity nos basta. Usando Apache Velocity Autopartes Rider ha implementado un nuevo sistema de órdenes que debe enviar una respuesta de email cuando un cliente ha emitido una orden. Tu trabajo es implementar esta característica.
  • 70. El email de respuesta podría parecerse a este: Querido cliente Gracias por ordenar X pieza(s) de XXX a un costo de XXX. Este es un email automatizado, por favor no responda. Hay tres piezas de información en el email que deben ser remplazadas en tiempo de ejecución con valores reales. Lo que necesitas hacer es ajustar el email para usar el lenguaje de plantillas Velocity, y luego colocarlas en el repositorio de fuentes como /src/test/resources/email.vm: Querido cliente Gracias por ordenar ${body.amount} de ${body.name} a un costo de ${body.price}. Este es un email automatizado, por favor no responda.
  • 71. Nota que hemos insertado placeholders ${} en la plantilla, lo cual instruye a Velocity que las evalúe y las remplace en tiempo de ejecución. Camel prellena el contexto de Velocity con un número de entidades que luego están disponibles a Velocity. Estas entidades son listadas en la tabla 3.6. NOTA: Las entidades en la tabla 3.6 también aplican para otros lenguajes de plantilla como FreeMarker.
  • 72. Entidad Tipo Descripción camelContext org.apache.camel.CamelContext El Contexto de Camel exchange org.apache.camel.Exchange El exchange actual in org.apache.camel.Message El mensaje de entrada. Este puede chocar con alguna palabra reservada en algunos lenguajes. En su lugar usa request. request org.apache.camel.Message El mensaje de entrada body java.lang.Object El cuerpo del mensaje de entrada headers java.util.Map Los headers del mensaje de entrada response org.apache.camel.Message El mensaje de salida out org.apache.camel.Message El mensaje de salida. Este puede chocar con alguna palabra reservada en algunos lenguajes. En su lugar usa response.
  • 73. 3.6 A cerca de los convertidores de tipo de Camel Camel proporciona un sistema conversor de tipo incorporado que convierte automáticamente entre tipos bien conocidos. Este sistema le permite a los componentes de Camel trabajar juntos fácilmente sin tener diferencias de tipos. Y desde la perspectiva del usuario Camel, las conversiones de tipo están incorporadas en la API en muchos lugares sin ser invasivas. Por ejemplo, has usado en el listado 3.1: String custom = exchange.getIn().getBody(String.class); Al método getBody le es pasado el tipo que quieres que se le retorne. Tras bambalinas, el sistema conversor de tipo convierte el tipo retornado a un String si es necesario. Aquí se explicará cómo Camel escanea el classpath al arranque para registrar dinámicamente los convertidores de tipo. También mostraremos cómo puedes usarlo desde un route Camel, y cómo construir tus propios convertidores de tipo.
  • 74. Cómo funciona el mecanismo convertidor de tipo de Camel Para comprender el sistema conversor de tipo, primero necesitamos saber qué es un convertidor de tipo en Camel. La figura 3.7 ilustra la relación entre el TypeConverterRegistry y los TypeConverters que contiene. El TypeConverteRegistry es donde todos los conversores de tipos son registrados cuando Camel inicia. En tiempo de ejecución, Camel usa el método lookup de TypeConverterRegistry para buscar un TypeConverter adecuado. TypeConverter lookup(Class<?> toType, Class<?> fromType); Figura 3.7 El TypeConverterRegistry contiene muchos TypeConverter
  • 75. Usando el TypeConverter, Camel entonces puede convertir un tipo a otro usando el método convertTo de TpeConverter, el cual está definido de la siguiente forma: <T> T convertTo(Class<T> type, Object value); Nota: Camel implementa alrededor de 150 o más conversores de tipo listos para usar, los cuales son capaces de convertir a y desde los tipos más comúnmente usados. CARGA DE CONVERTIDORES DE TIPO EN EL REGSITRO Al arranque, Camel carga todos los convertidores de tipo en el TypeConverterRegistry usando una solución de escaneo del classpath. Esto le permite a Camel elegir no sólo un conversor de tipo de camel-core sino también desde cualesquier a otros componentes de Camel. Para escanear y cargar los conversores de tipo, Camel usa org.apache.camel.impl.converter.AnnotationTypeConverterLoader.
  • 76. Para evitar cargar silos de clases, lee un archivo de descubrimiento de servicio en la carpeta META-INF: META- INF/services/org/apache/camel/TypeConverter. Este es un archivo de texto plano que tiene una lista de paquetes que contiene conversores de tipo Camel. El archivo especial es necesario para evitar escanear cada JAR posible y todos sus packeges, lo cual sería consumidor de tiempo. El archivo especial le dice a Camel si el archivo JAR contiene o no conversores de tipo. Por ejemplo, el archivo en camel-core contiene las siguientes tres entradas: org.apache.camel.converter org.apache.camel.component.bean org.apache.camel.component.file La AnnotationTypeConverterLoader escaneará estos packages y sus subpackages para clases que han sido anotadas con @Converter, y busca en ellas métodos públicos que son anotados con @Converter. Cada uno de estos métodos es considerado un conversor de tipo.
  • 77. Esto es mejor ilustrado con un ejemplo. El siguiente código es un snippet de la clase IOConverter del JAR camel-core: @Converter public final class IOConverter { @Converter public static InputStream toInputStream(URL url) throws IOException { return url.openStream(); } } Camel irá sobre cada método anotado con @Converter y buscará la firma del método. El primer parámetro es del tipo from, y el tipo de retorno es del tipo to –en este ejemplo tienes un TypeConverter que puede convertir desde una URL a un InputStream. Haciendo esto, Camel carga todos los conversores de tipo incorporados, incluyendo aquellos de los componentes Camel en uso.
  • 78. Usando convertidores de tipo Camel Podrías querer usar los convertidores de tipo para forzar un tipo específico para que sea usado en un route, como antes enviando datos atrás a un llamante o a un destino JMS. Vamos a ver cómo hacer eso: Supón que necesitas enrutar archivos a una queue JMS usando java.jms.TextMessage. Para hacer lo así, puedes convertir cada archivo a una String, lo cual forza al componente JMS a usar TextMessage. Esto es fácil de hacer en Camel –puedes usar el método convertBodyTo, como es mostrado aquí: from("file://riders/inbox") .convertBodyTo(String.class) .to("activemq:queue:inbox");
  • 79. Si estás usando Spring XML. en vez de ello proporcionas el tipo como un atributo, como lo siguiente: <route> <from uri="file://riders/inbox"/> <convertBodyTo type="java.lang.String"/> <to uri="activemq:queue:inbox"/> </route> Puedes omitir el prefijo java.lang en el tipo, lo cual puede acortar la sintaxis un poco: <convertBodyTo type="java.lang.String"/> Otra razón para usar convertBodyTo es leer archivos usando un encoding fijo como UTF-8. Esto se hace pasando el encoding el segundo parámetro de entrada: from("file://riders/inbox") .convertBodyTo(String.class, "UTF-8") .to("activemq:queue:inbox");
  • 80. Escribiendo tu propio convertidor de tipo Escribir tu propio convertidor de tipo es fácil en Camel. Ya has visto como un conversor de tipo se ve en la sección 3.6.1, cuando viste cómo funcionan los conversores de tipo. Supón que necesitaras escribir un conversor de tipo personalizado que puede convertir un byte en un objeto modelo PurchaseOrder (un objeto que usaste en el listado 3.7). Como lo viste anteriormente, necesitas crear una clase @Converter conteniendo el método conversor de tipo: Listado 3.12 Un conversor de tipo personalizado para convertir de tipo byte[] a PurchaseOrden @Converter public final class PurchaseOrderConverter @Converter public static PurchaseOrder toPurchaseOrder(byte[] data, Exchange exchange) { TypeConverter converter = exchange.getContext() .getTypeConverter(); Coge el TypeConverter a reutilizar 1
  • 81. String s = converter.convertTo(String.class, data); if (s == null || s.length() < 30) { throw new IllegalArgumentException("data is invalid"); } s = s.replaceAll("##START##", ""); s = s.replaceAll("##END##", ""); String name = s.substring(0, 9).trim(); String s2 = s.substring(10, 19).trim(); BigDecimal price = new BigDecimal(s2); price.setScale(2); String s3 = s.substring(20).trim(); Integer amount = converter.convertTo(Integer.class, s3); return new PurchaseOrder(name, price, amount); } } Convierte de String a PurchaseOrden 2
  • 82. En el listado 3.12 el Exchange te da acceso al CamelContext y así al padre TypeConverter 1, el cual usas en este método para convertir entre cadenas y números. El resto del código. El resto del código es la lógica para parsear el protocolo personalizado y retornar el PurchaseOrder 2. Nota como puedes usar el converter para convertir fácilmente entre tipos bien conocidos. Todo lo que necesitas hacer es agregar el archivo de descubrimiento de servicio, llamado TypeConverter, en el directorio META-INF. Como se explicó anteriormente, este archivo contiene una línea identificando cada package para ser escaneado por las clases @Converter.
  • 83. GRACIAS www.facebook.com/JavaDevelopersMexico No olvides regalarnos un like. Dudas y comentarios no dudes en escribir en la página o al siguiente correo it.adesales@gmail.com