© OPITZ CONSULTING GmbH 2010 Seite 1Integration mit Apache Camel
Dr. Ralf Sigmund, Bereichsleiter
OPITZ CONSULTING Hamburg GmbH
Hamburg, 02.03.2011
Integration mit Apache Camel
© OPITZ CONSULTING GmbH 2010 Seite 2Integration mit Apache Camel
Agenda
1. Enterprise Integration Patterns
2. Einführung in Apache Camel
3. Ein Beispiel
4. Weitere Patterns
5. Beans
© OPITZ CONSULTING GmbH 2010 Seite 3Integration mit Apache Camel
1 Enterprise Integration Patterns
© OPITZ CONSULTING GmbH 2010 Seite 4Integration mit Apache Camel
Enterprise Integration Patterns (EIP) (1)
Bewährte Lösungsschablonen für Integrationsszenarien auf Basis asynchronen Nachrichtenaustauschs
Muster beschreiben Lösung von Problemen, die bei der Integration heterogener Anwendungen auf unterschiedlichen Plattformen auftreten.
Definition einer grafischen Notation
Titel: Enterprise Integration Patterns
Autor: Gregor Hohpe, Bobby Woolf
Verlag: Addison-Wesley
ISBN: 0321200683
© OPITZ CONSULTING GmbH 2010 Seite 5Integration mit Apache Camel
Enterprise Integration Patterns (2)
Musterkatalog besteht aus 65 Integration Patterns
Die Muster lassen sich in verschiedenen Kategorien unterteilen Message Construction Message Endpoints Message Channels Message Routing Message Transformation System Management
© OPITZ CONSULTING GmbH 2010 Seite 6Integration mit Apache Camel
2 Einführung in Apache Camel
© OPITZ CONSULTING GmbH 2010 Seite 7Integration mit Apache Camel
Enterprise Integration mit Apache Camel
Open Source Integrations Framework
Subprojekt von ApacheMQ
Umsetzung eines Großteils der Enterprise Integration Patterns
Ermöglicht die Definition von Routing- und Konvertierungsregeln in Java oder Scala auf Basis einer domänenpezifischen Sprache (DSL) bzw. Spring basierter XML-Konfiguration
Titel: Camel In Action Autor: Claus Ibsen, Jonathan
Anstey Verlag: Manning ISBN: 9781935182368
© OPITZ CONSULTING GmbH 2010 Seite 8Integration mit Apache Camel
Apache Camel (Architektur)
Zentraler Punkt der Camel-Architektur: CamelContext
Hier registrieren sich sämtliche Komponenten und erhalten eine eindeutige Adresse in Form einer URI
Aus: Ibsen, Anstey: Camel in Action, Manning 2010
© OPITZ CONSULTING GmbH 2010 Seite 9Integration mit Apache Camel
Apache Camel (Komponenten)
Camel stellt eine Vielzahl an Komponenten zur Verfügung (über 80), die unterschiedliche Transportprotokolle und –formate sowie eine Reihe von Bindings anbieten http://camel.apache.org/components.html
Beispiele für Komponenten: JMS-Komponente: erlaubt das Senden (bzw. Konsumieren) von Nachrichten
an eine JMS-Queue oder –Topic JDBC-Komponente: Verbindung mit Datenbanken via JDBC und Absetzen
von SQL-Statements JPA-Komponente: erlaubt das Speichern und Abfragen von Objekten (ORM) File-Komponente: ermöglicht das Laden und Speichern im Dateisystem FTP-Komponente: erlaubt den Zugriff auf entfernte Dateisysteme über FTP HTTP-Komponente: Http-Client für den Aufruf externer Server Direct-Komponente: direkter, synchroner Aufruf eines beliebigen Endpunktes
© OPITZ CONSULTING GmbH 2010 Seite 10Integration mit Apache Camel
Apache Camel (Endpunkte)
Endpunkte arbeiten wahlweise als Consumer (in-only) oder Producer (out)
Consumer nehmen Nachrichten entgegen
Producer erzeugen Nachrichten
es ist aber auch möglich beide Rollen einzunehmen (in-out)
Endpunkte werden durch protokollspezifische Factories erzeugt und im Laufzeit-Container registriert (CamelContext).
© OPITZ CONSULTING GmbH 2010 Seite 11Integration mit Apache Camel
Camel (Routenbildung)
Routenbildung (Camel-Route) erfolgt über eine bestimmte Anzahl von RouteBuildern, die dem CamelContext hinzugefügt werden
Zur Festlegung der Routen zwei Möglichkeiten: Definition über Java-basierte domänenspezifische Sprache (DSL) Spring basierte XML
Bei der DSL handelt es sich um eine Inline DSL, der das Builder-Pattern zugrunde liegt
Durch Verkettung von Methoden wird eine Route (Nachrichtenfluss) definiert.
© OPITZ CONSULTING GmbH 2010 Seite 12Integration mit Apache Camel
3 Ein Beispiel
© OPITZ CONSULTING GmbH 2010 Seite 13Integration mit Apache Camel
Beispielmuster: Message-Filter
spezielle Art eines Routers es werden nur Nachrichten weitergeleitet, deren Inhalt
bestimmte Kriterien erfüllt hat nur einen output-Channel
Nachricht Typ A
Nachricht Typ A
Nachricht Typ ANachricht
Typ ANachricht
Typ BMessage
Fiilter
© OPITZ CONSULTING GmbH 2010 Seite 14Integration mit Apache Camel
Beispielmuster: Message Filter (Java)
Java-Klassen müssen die Basisklasse org.apache.camel.builder.RouteBuilder erweitern und die Routenlogik in der configure-Methode bereitstellen
public class MyRouteBuilder extends RouteBuilder {public void configure() throws Exception {from("activemq:topic:Quotes").filter().
xpath("/quote/product='widget'").to("mqseries:WidgeQuotes");
} }
© OPITZ CONSULTING GmbH 2010 Seite 15Integration mit Apache Camel
Beispielmuster: Message Filter (Java)
Endpunkt A nimmt eine Nachricht aus einer Queue entgegen (from). Diese wird anschließend verarbeitet und an den Endpunkt B weitergeleitet (to).
public class MyRouteBuilder extends RouteBuilder {public void configure() throws Exception {
Endpoint A = endpoint("activemq:topic:Quotes");
Endpoint B = endpoint("mqseries:WidgeQuotes");Predicate isWidget = xpath("/quote/product=
'widget'");from(A).filter(isWidget).to(B);
}}
© OPITZ CONSULTING GmbH 2010 Seite 16Integration mit Apache Camel
Beispielmuster: Message Filter (Spring XML)
Der CamelContext wird innerhalb des Beans-Tags in den ApplicationContext eingtragen
in der XML-Definition finden sich den Methoden der Java-DSL entsprechende Tags wieder
<camelContext xmlns="http://camel.apache.org/schema/spring"><route>
<from uri="activemq:topic:Quotes"><filter>
<xpath>/quote/product='widget'</xpath>
</filter></from><to uri="mqseries:WidgeQuotes"></to>
</route></camelContext>
© OPITZ CONSULTING GmbH 2010 Seite 17Integration mit Apache Camel
Ausführung in einer Java-Anwendung
CamelContext kann programmatisch erzeugt werden
Keine zusätzlichen Bibliotheken / Frameworks notwendig
CamelContext context = new DefaultCamelContext();context.addRoutes(new MyRouteBuilder());context.start();
© OPITZ CONSULTING GmbH 2010 Seite 18Integration mit Apache Camel
CamelContext in Spring
Package-Tag: Package, in dem nach Route-Buildern gesucht werden soll => Routendefinition in Java ist auch möglich, wenn Spring genutzt wird
PropertyPlaceholder-Tag: Verweis auf eine properties-Datei, auf die in Routendefinitionen zugegriffen werden kann
<camelContext xmlns="http://camel.apache.org/schema/spring"><propertyPlaceholder id="properties"
location="classpath:camel-prod.properties"/><package>com.acme.quotes</package>
</camelContext>
© OPITZ CONSULTING GmbH 2010 Seite 19Integration mit Apache Camel
4 Weitere Patterns
© OPITZ CONSULTING GmbH 2010 Seite 20Integration mit Apache Camel
Content Based Router
Untersuchen des Inhaltes der Nachricht
Weiterleitung in verschiedene Kanäle in Abhängigkeit von ihrem Inhalt
Kann auf verschiedenen Kriterien basieren (z.B. Vorhandensein bestimmter Felder, Inhalt von Feldern…)
Neuer Auftrag
Router
Endpunkt A
Endpunkt B
© OPITZ CONSULTING GmbH 2010 Seite 21Integration mit Apache Camel
Content Based Router
Abarbeiten eines Auftrags aus der Queue
Überprüfen der Nachricht (XML) anhand eines XPath-Ausdrucks
RouteBuilder builder = new RouteBuilder() {public void configure() {
from("activemq:Auftraege").choice().when(xpath("/order/
product").isEqualTo("produktA")).to("direct:A").when(xpath("/order/
product")
.isEqualTo("produktB")).to("direct:B").otherwise().to("direct:C");
}};
© OPITZ CONSULTING GmbH 2010 Seite 22Integration mit Apache Camel
Content Based Router<camelContext xmlns="http://camel.apache.org/schema/spring">
<route><from uri="activemq:Auftraege" /><choice>
<when><xpath>/order/product =
'produktA'</xpath><to uri="direct:A" />
</when><when>
<xpath>/order/product = 'produktB'</xpath>
<to uri="direct:B" /></when><otherwise>
<to uri="direct:C" /></otherwise>
</choice></route></camelContext>
© OPITZ CONSULTING GmbH 2010 Seite 23Integration mit Apache Camel
Splitter
Empfängt eine Nachricht mit wiederkehrenden Elementen, die separat verarbeitet werden können
Für jedes Element (oder jede Teilmenge) der Ursprungsnachricht wird eine neue Nachricht erzeugt
Neuer Auftrag Splitter
Auftragsposition
1
Auftragsposition
2
Auftragsposition
3
© OPITZ CONSULTING GmbH 2010 Seite 24Integration mit Apache Camel
Splitter
Laden von Aufträgen aus dem Dateisystem
Nachricht (als String) wird zeilenweise zerlegt
Entstehende Nachrichten werden an eine Queue gesandt
RouteBuilder builder = new RouteBuilder() {public void configure() {
from("file://Auftraege").split(body(String.class).tokenize("\
n")).to("activemq:Auftraege.Positionen");
}};
© OPITZ CONSULTING GmbH 2010 Seite 25Integration mit Apache Camel
Splitter
Laden von Nachrichten aus dem Dateisystem
Nachricht (XML-Format) wird anhand eines XPath-Ausdrucks zerlegt
Senden an eine Queue
<camelContext xmlns="http://camel.apache.org/schema/spring"><route>
<from uri="file://Auftraege" /><split>
<xpath>/auftrag/positionen</xpath><to
uri="activemq:Auftraege.Positionen /></split>
</route></camelContext>
© OPITZ CONSULTING GmbH 2010 Seite 26Integration mit Apache Camel
Message Translator
Ermöglicht Kommunikation zwischen Systemen mit verschiedenen Datenformaten
Konvertiert eine Nachricht in das Format eines Partners
Eingehende Nachricht
Umgeformte NachrichtTranslator
© OPITZ CONSULTING GmbH 2010 Seite 27Integration mit Apache Camel
Message Translator
Transformation einer XML-Nachricht mithilfe eines XSL-Templates
XSLT-Komponente erhält als Parameter den Pfad zum XSL-Template
RouteBuilder builder = new RouteBuilder() {public void configure() {
from("file://Auftraege").to("xslt:com/acme/mytransform.xsl").to("activemq:Auftraege");
}};
© OPITZ CONSULTING GmbH 2010 Seite 28Integration mit Apache Camel
Message Translator
Transformation kann alternativ durch (hier anonyme) Implementierung eines Processors geschehen
Durch Parameter exchange Zugriff auf eingehende (In) und ausgehende (Out) Nachricht
Beliebige Ausführung von Java-Code möglich
from("file://Auftraege").process(new Processor() {public void process(Exchange exchange) {
Message in = exchange.getIn();in.setBody(in.getBody(String.class) + "
World!");}
}).to("activemq:Auftraege");
© OPITZ CONSULTING GmbH 2010 Seite 29Integration mit Apache Camel
Message Translator
Anhängen von ‚extra data!‘ im transform-tag
Statt Simple kann eine Vielzahl weiterer Expression Languages genutzt werden, wie beispielsweise Java Script, Groovy, EL, XPath
<camelContext xmlns="http://camel.apache.org/schema/spring"><route>
<from uri="file://Auftraege" /><transform>
<simple>${in.body} extra data!</simple></transform><to uri="activemq:Auftraege" />
</route></camelContext>
© OPITZ CONSULTING GmbH 2010 Seite 30Integration mit Apache Camel
5 Beans
© OPITZ CONSULTING GmbH 2010 Seite 31Integration mit Apache Camel
Message Translator: Bean
Nutzung einer Java Bean, falls komplexe Logik für Transformation benötigt (z.B. DB-Zugriff, Schleifen)
Vorteil: Routenbeschreibung bleibt übersichtlich und deklarativ, Logik wird ausgelagert
Bean-Komponente erhält als Parameter den Namen der Bean und den Methodennamen Ist kein Methodenname angegeben oder wurde die Methode überladen, wird
versucht, anhand der Nachricht die richtige Methode zu ermitteln
Bean muss im Spring-Context oder im JNDI-Context registriert werden
from("file://Auftraege").to("bean:ConverterBean?method=convertOrder").to("activemq:Auftraege");
© OPITZ CONSULTING GmbH 2010 Seite 32Integration mit Apache Camel
Die Bean
Rückgabe der convertOrder-Methode wird an den Body der Nachricht gebunden
Mittels der @Header-Annotation wird der Header ‚headerName‘ an den Parameter header gebunden
Mittels der @XPath-Annotation wird die Nachricht mit einem XPath-Ausdruck ausgewertet und das Ergebnis an den Parameter auftragsNummer gebunden
public class ConverterBean {@Consume(uri = "activemq:Auftraege")public String convertOrder(@Header(value =
"headerName") String header, @XPath(value = "/auftrag/nummer")
String auftragsNummer) {return header + auftragsNummer;
}}
© OPITZ CONSULTING GmbH 2010 Seite 33Integration mit Apache Camel
Typ-Konvertierung
Camel unterstützt eine ganze Reihe von Konvertierungen „out of the box“
Bei Bedarf können eigene Konverter implementiert werden Hinzufügen der @Converter-Annotation zur Klasse und Methode Eintragen der Packages mit Konverter-Klassen in
META-INF/services/org/apache/camel/TypeConverter
@Converterpublic class IOConverter {
@Converterpublic static InputStream toInputStream(File file)
throws FileNotFoundException {return new BufferedInputStream(new
FileInputStream(file));}
}
© OPITZ CONSULTING GmbH 2010 Seite 34Integration mit Apache Camel
Beans an Endpunkte binden
Eine einfache Alternative zur Definition einer kompletten Route
Durch die @Consume-Annotation wird die Methode an den als Parameter übergebenen Endpunkt gebunden
Beim Eintreffen einer neuen Nachricht wird die Methode mit der Nachricht als Parameter aufgerufen
public class AuftragsBean {@Consume(uri = "activemq:Auftraege")public void pruefeAuftrag(String body) {
...}
}
© OPITZ CONSULTING GmbH 2010 Seite 35Integration mit Apache Camel
Nachrichten an Endpunkte senden
Durch die @Produce-Annotation wird der Bean ein Producer-Template injiziert, mit dessen Hilfe Nachrichten an den jeweiligen Endpunkt gesendet werden können
Weitere Methoden verfügbar (z.B. senden von Headern)
(Nachteil: Aufrufer wird vom Camel-API abhängig; kann durch ein Interface versteckt werden)
public class SenderBean {@Produce(uri = "activemq:Auftraege")ProducerTemplate template;
public void sendeNachricht() {template.sendBody("Nachricht");
}}
© OPITZ CONSULTING GmbH 2010 Seite 36Integration mit Apache Camel
Testen
Spezielle Komponente: Mock-Endpoints
Abstrakte Klasse CamelTestSupport
Formulieren von Erwartungen und Assertions für Mock-Endpunkte
Zugriff auf Nachrichten, die an Mock-Endpunkten eingegangen sind
© OPITZ CONSULTING GmbH 2010 Seite 37Integration mit Apache Camel
Testen: Testklassepublic class FilterTest extends CamelTestSupport {
@EndpointInject(uri = "mock:result")protected MockEndpoint resultEndpoint;
@Produce(uri = "direct:start")protected ProducerTemplate template;
@Overrideprotected RouteBuilder createRouteBuilder() {
return new RouteBuilder() {public void configure() {
from("direct:start").filter(
header("auftragsNummer").isEqualTo("1")).to("mock:result");
}};
}}
© OPITZ CONSULTING GmbH 2010 Seite 38Integration mit Apache Camel
Testen: Testmethoden
public void testSendMatchingMessage() throws Exception {String expectedBody = "<matched/>";resultEndpoint.expectedBodiesReceived(expectedBody);template.sendBodyAndHeader(expectedBody,
"auftragsNummer", "1");resultEndpoint.assertIsSatisfied();
}
public void testSendNotMatchingMessage() throws Exception {resultEndpoint.expectedMessageCount(0);template.sendBodyAndHeader("<notMatched/>",
"auftragsNummer", "2");
resultEndpoint.assertIsSatisfied();}
© OPITZ CONSULTING GmbH 2010 Seite 39Integration mit Apache Camel
Quellen und weiterführende Links
http://camel.apache.org/enterprise-integration-patterns.html
http://www.enterpriseintegrationpatterns.com/
http://camel.apache.org/components.html
© OPITZ CONSULTING GmbH 2010 Seite 40Integration mit Apache Camel
Fragen und Antworten