Apache Camel - Kurzanleitung

Stellen Sie sich eine Situation vor, in der ein großes Online-Lebensmittelgeschäft in Ihrer Stadt wie der Bigbasket in Indien Sie einlädt, eine IT-Lösung für diese zu entwerfen. Die stabile und skalierbare Lösung hilft ihnen, die Probleme bei der Softwarewartung zu überwinden, mit denen sie heute konfrontiert sind. Dieser Online-Shop ist seit einem Jahrzehnt in Betrieb. Das Geschäft akzeptiert Online-Bestellungen für verschiedene Produktkategorien von seinen Kunden und verteilt diese an die jeweiligen Lieferanten. Angenommen, Sie bestellen Seifen, Öl und Milch. Diese drei Artikel werden an die drei jeweiligen Lieferanten verteilt. Die drei Lieferanten senden dann ihre Lieferungen an einen gemeinsamen Verteilungspunkt, von wo aus die gesamte Bestellung vom Lieferzentrum ausgeführt wird. Lassen Sie uns nun das Problem betrachten, mit dem sie heute konfrontiert sind.

Als dieses Geschäft seinen Betrieb aufnahm, nahm es Bestellungen in einer durch Kommas getrennten Nur-Text-Datei an. Im Laufe der Zeit wechselte das Geschäft zur nachrichtengesteuerten Auftragserteilung. Später schlugen einige Softwareentwickler eine XML-basierte Auftragserteilung vor. Schließlich hat der Laden sogar eine Web-Service-Oberfläche angepasst. Jetzt kommt das eigentliche Problem. Die Bestellungen kommen jetzt in verschiedenen Formaten. Offensichtlich wollte das Unternehmen jedes Mal, wenn es das Format der Auftragsannahme aktualisierte, die zuvor bereitgestellte Schnittstelle nicht beschädigen, um beim Kunden keine Verwirrung zu stiften.

Gleichzeitig, während das Geschäft weiter wuchs, erweiterte das Geschäft sein Repertoire regelmäßig um neue Lieferanten. Jeder dieser Lieferanten hatte sein eigenes Protokoll für die Annahme von Bestellungen. Wir stehen erneut vor dem Integrationsproblem. Unsere Anwendungsarchitektur muss skalierbar sein, um neuen Lieferanten mit ihrem einzigartigen Bestellungsmechanismus gerecht zu werden.

Die gesamte Situation ist in der folgenden Abbildung dargestellt -

Lassen Sie uns nun sehen, wie Apache Camel Ihnen helfen kann, eine elegante, wartbare und skalierbare Lösungsarchitektur für das beschriebene Szenario bereitzustellen.

Bevor wir mit der Lösung fortfahren, müssen wir eine kleine Annahme treffen. Bei allen Diskussionen in diesem Tutorial wird davon ausgegangen, dass die Online-Bestellungen im XML-Format erfolgen. Ein typisches Format für die Bestelldatei, die wir während unserer Diskussionen verwenden werden, wird hier gezeigt -

<?xml version = "1.0" encoding = "UTF-8"?>
<OrderID Order = "001">
   <order product = "soaps">
      <items>
         <item>
            <Brand>Cinthol</Brand>
            <Type>Original</Type>
            <Quantity>4</Quantity>
            <Price>25</Price>
         </item>
         <item>
            <Brand>Cinthol</Brand>
            <Type>Lime</Type>
            <Quantity>6</Quantity>
            <Price>30</Price>
         </item>
      </items>
   </order>
   
   <order product = "Oil">
      <items>
         <item>
            <Brand>Saffola</Brand>
            <Type>Gold</Type>
            <Quantity>2</Quantity>
            <Price>649</Price>
         </item>
         <item>
            <Brand>Fortune</Brand>
            <Type>Sunlite</Type>
            <Quantity>1</Quantity>
            <Price>525</Price>
         </item>
      </items>
   </order>
   
   <order product = "Milk">
      <items>
         <item>
            <Product>Milk</Product>
            <Brand>Amul</Brand>
            <Type>Pure</Type>
            <Quantity>2</Quantity>
            <Price>60</Price>
         </item>
      </items>
   </order>
</OrderID>

Wir werden die obige XML-Vorlage verwenden, um die Kamelbeispiele in diesem Tutorial zu veranschaulichen.

Camel ist eine Black Box, die Nachrichten von einem Endpunkt empfängt und an einen anderen sendet. Innerhalb der Black Box können die Nachrichten verarbeitet oder einfach umgeleitet werden.

Warum also einen Rahmen dafür haben? In praktischen Situationen, wie in der Fallstudie zur Einführung dargestellt, kann es viele Sender und Empfänger geben, die jeweils ihrem eigenen Protokoll wie ftp, http und jms folgen. Das System erfordert möglicherweise viele komplexe Regeln, z. B. sollte die Nachricht von Absender A nur an B & C übermittelt werden. In Situationen müssen Sie die Nachricht möglicherweise in ein anderes Format übersetzen, das der Empfänger erwartet. Diese Übersetzung kann bestimmten Bedingungen unterliegen, die auf dem Inhalt der Nachricht basieren. Daher müssen Sie möglicherweise zwischen Protokollen übersetzen, Komponenten zusammenkleben, Routing-Regeln definieren und Filterung basierend auf Nachrichteninhalten bereitstellen. Dies ist in der folgenden Abbildung dargestellt -

Um die oben genannten Anforderungen zu erfüllen und eine geeignete Softwarearchitektur für viele solcher Situationen zu entwerfen, wurden Enterprise Integration Patterns ( EIP ) 2003 von Gregor Hohpe und Bobby Woolf dokumentiert. Apache Camel bietet die Implementierung dieser Muster und der Zweck dieses Tutorials ist das Unterrichten Sie erfahren, wie Sie Camel in Situationen wie der in der Einführung beschriebenen verwenden.

Apache Camel ist ein Open Source Framework. Es handelt sich um eine nachrichtenorientierte Middleware, die eine regelbasierte Routing- und Mediations-Engine bereitstellt. Sie können Regeln definieren, z. B. ob es sich um eine Milchbestellung handelt, die an einen Milchverkäufer weitergeleitet wird, und ob es sich um eine Ölbestellung handelt, die an einen Ölverkäufer umgeleitet wird, und so weiter. Mit Camel können Sie diese Regeln implementieren und das Routing in einem vertrauten Java-Code durchführen. Dies bedeutet, dass Sie Ihre vertraute Java-IDE verwenden können, um diese Regeln in einer typsicheren Umgebung zu definieren. Wir müssen keine XML-Konfigurationsdateien verwenden, die normalerweise sperrig sind. Camel unterstützt jedoch die XML-Konfiguration über das Spring Framework, wenn Sie XML zum Konfigurieren der Regeln verwenden möchten. Sie können sogar Blueprint XML-Konfigurationsdateien und sogar eine Scala DSL verwenden, wenn Sie ein Scala-Liebhaber sind. Dies bedeutet auch, dass Sie Ihre bevorzugten Java-, Scala-IDE- oder sogar einen einfachen XML-Editor verwenden können, um die Regeln zu konfigurieren.

Die Eingabe für diese Engine kann eine durch Kommas getrennte Textdatei, ein POJO (Plain Old Java Object) und XML sein. XML ist eines der verschiedenen anderen von Camel unterstützten Formate. Ebenso kann die Ausgabe der Engine in eine Datei, in eine Nachrichtenwarteschlange oder sogar auf Ihren Monitorbildschirm umgeleitet werden, damit Sie die an die jeweiligen Lieferanten gesendeten Bestellungen anzeigen können. Diese werden als Endpunkte bezeichnet, und Camel unterstützt das EIP-Muster für Nachrichtenendpunkte . Die Kamelendpunkte werden später im Kapitel Endpunkte erläutert.

Camel wird normalerweise mit Apache ServiceMix , Apache ActiveMQ und Apache CXF verwendet , um serviceorientierte Architekturen zu implementieren.

Nachdem wir einen Überblick über Apache Camel erhalten haben, wollen wir uns nun mit seinen Funktionen befassen, um zu sehen, was es bietet. Wir wissen bereits, dass Apache Camel ein Open-Source-Java-Framework ist, das im Wesentlichen die Implementierung verschiedener EIPs bietet. Camel erleichtert die Integration, indem es Konnektivität zu einer Vielzahl von Transporten und APIs bietet. Beispielsweise können Sie JMS problemlos an JSON, JSON an JMS, HTTP an JMS, FTP an JMS, sogar HTTP an HTTP und Konnektivität an Microservices weiterleiten. Sie müssen lediglich an beiden Enden geeignete Endpunkte bereitstellen. Camel ist erweiterbar und daher können in Zukunft problemlos weitere Endpunkte zum Framework hinzugefügt werden.

Um EIPs und Transporte miteinander zu verbinden, verwenden Sie domänenspezifische Sprachen (DSLs) wie Java, Scala und Groovy. Eine typische Java-Routing-Regel könnte folgendermaßen aussehen:

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

Diese Routing-Regel lädt die Dateien aus dem order Verzeichnis, erstellt eine JMS-Nachricht mit dem Inhalt der Datei und sendet diese Nachricht an eine aufgerufene Warteschlange orderQueue.

Hier sind einige der wichtigsten Funktionen von Camel, die Sie bei der Entwicklung von Camel-Anwendungen nützlich finden würden:

  • Camel unterstützt steckbaren Datenformate und Typ - Wandler für eine solche Nachricht Transformationen, so neue Formate und Wandler können in Zukunft hinzugefügt werden. Derzeit werden mehrere gängige Formate und Konverter unterstützt. um nur einige zu nennen - CSV, EDI, JAXB, JSON, XmlBeans, XStream, Flatpack, Zip.

  • Camel unterstützt steckbare Sprachen zum Schreiben von Prädikaten in DSL. Einige der unterstützten Sprachen umfassen JavaScript, Groovy, Python, PHP, Ruby, SQL, XPath und XQuery.

  • Camel unterstützt das POJO-Modell, sodass Sie Javabeans an verschiedenen Stellen anschließen können.

  • Camel erleichtert das Testen derart großer verteilter und asynchroner Systeme mithilfe von Messaging.

Lassen Sie uns nun die Architektur von Camel verstehen und sehen, wie die verschiedenen Funktionen implementiert werden.

Die Camel-Architektur besteht aus drei Komponenten: Integration Engine und Router, Prozessoren und Komponenten. Dies ist in der folgenden Abbildung dargestellt -

Der Kamelkern selbst ist sehr klein und enthält 13 wesentliche Komponenten. Die restlichen 80+ Komponenten befinden sich außerhalb des Kerns. Dies trägt dazu bei, eine geringe Abhängigkeit von der Bereitstellung aufrechtzuerhalten, und fördert zukünftige Erweiterungen. DasComponents Modul bietet eine EndpointSchnittstelle zur Außenwelt. Die Endpunkte werden durch URIs angegeben, zfile:/order und jms:orderQueue das haben Sie im letzten Kapitel gesehen.

Das ProcessorsDas Modul wird zum Bearbeiten und Vermitteln von Nachrichten zwischen Endpunkten verwendet. Die zuvor erwähnten EIPs sind in diesem Modul implementiert. Derzeit werden mehr als 40 Muster unterstützt, wie im EIP-Buch und anderen nützlichen Verarbeitungseinheiten dokumentiert .

Das Processors und Endpoints sind miteinander verdrahtet Integration Engine and RouterModul mit DSLs. Während Sie diese verkabeln, können Sie Filter verwenden, um Nachrichten basierend auf benutzerdefinierten Kriterien zu filtern. Wie bereits erwähnt, haben Sie beim Schreiben dieser Regeln mehrere Möglichkeiten. Sie können hierfür Java, Scala, Groovy oder sogar XML verwenden.

Nun kommen wir zu der wichtigsten Komponente von Camel, die als Kern betrachtet werden kann - der CamelContext.

CamelContext bietet Zugriff auf alle anderen Dienste in Camel, wie in der folgenden Abbildung dargestellt -

Schauen wir uns die verschiedenen Dienstleistungen an. DasRegistryDas Modul ist standardmäßig eine JNDI-Registrierung, die den Namen der verschiedenen Javabeans enthält, die Ihre Anwendung verwendet. Wenn Sie Camel mit Spring verwenden, ist dies der SpringApplicationContext. Wenn Sie Camel im OSGI-Container verwenden, ist dies der FallOSGI registry. DasType convertersWie der Name schon sagt, enthält es die verschiedenen geladenen Typkonverter, die Ihre Eingabe von einem Format in ein anderes konvertieren. Sie können die integrierten Konverter verwenden oder Ihren eigenen Konvertierungsmechanismus bereitstellen. DasComponentsModul enthält die von Ihrer Anwendung verwendeten Komponenten. Die Komponenten werden durch automatische Erkennung auf die geladenclasspathdass Sie angeben. Im Falle des OSGI-Containers werden diese geladen, wenn ein neues Bundle aktiviert wird. Wir haben das bereits besprochenEndpoints und Routesin den vorherigen Kapiteln. DasData formats Modul enthält die geladenen Datenformate und schließlich die Languages Modul repräsentiert die geladenen Sprachen.

Das Code-Snippet hier gibt Ihnen einen Einblick, wie a CamelContext wird in einer Kamelanwendung erstellt -

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

Das DefaultCamelContext Klasse bietet eine konkrete Implementierung von CamelContext. ImaddRoutes Methode erstellen wir eine anonyme Instanz von RouteBuilder. Sie können mehrere erstellenRouteBuilderInstanzen, um mehr als ein Routing zu definieren. Jede Route im selben Kontext muss eine eindeutige ID haben. Routen können zur Laufzeit dynamisch hinzugefügt werden. Eine Route mit der gleichen ID wie die zuvor definierte ersetzt die ältere Route.

Was geht in die RouteBuilder Instanz wird als nächstes beschrieben.

Routen

Der Router definiert die Regel zum Verschieben der Nachricht from zu einem toLage. Sie verwendenRouteBuilderum eine Route in Java DSL zu definieren. Sie erstellen eine Route, indem Sie die integrierte Route erweiternRouteBuilderKlasse. Die Route beginnt mit afromEndpunkt und endet an einem oder mehreren Endpunkten. Dazwischen implementieren Sie die Verarbeitungslogik. Sie können eine beliebige Anzahl von Routen innerhalb einer einzelnen konfigurierenconfigure Methode.

Hier ist ein typisches Beispiel für die Erstellung einer Route:

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

Wir überschreiben die Konfigurationsmethode von RouteBuilderklassifizieren und implementieren Sie unseren Routing- und Filtermechanismus darin. Im aktuellen Fall leiten wir die vom Endpunkt empfangenen Eingaben umDistributeOrderDSL an die Konsole, die vom Endpunkt angegeben wird stream:out.

Sprachwahl

Sie können die Routen in verschiedenen Sprachen erstellen. Hier einige Beispiele, wie dieselbe Route in drei verschiedenen Sprachen definiert wird:

Java DSL

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

Frühling DSL

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

Scala DSL

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

Filter

Sie verwenden Filter, um einen Teil des Eingabeinhalts auszuwählen. Um einen Filter einzurichten, verwenden Sie eine beliebige Predicate- Implementierung. Die gefilterte Eingabe wird dann an Ihren gewünschten Zielendpunkt gesendet. In diesem Beispiel filtern wir alle Bestellungen für die Seife heraus, damit diese gemeinsam an einen Seifenlieferanten gesendet werden können.

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

Im Beispiel haben wir verwendet xpathPrädikat für die Filterung. Wenn Sie die Java-Klasse zum Filtern bevorzugen, verwenden Sie den folgenden Code:

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

Das Order ist Ihre benutzerdefinierte Java-Klasse mit Ihrem eigenen Filtermechanismus.

Sie können wie hier mehrere Prädikate in einem einzigen Routing kombinieren -

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

Jetzt gehen alle "Öl" -Bestellungen an den Ölverkäufer, "Milch" -Bestellungen an den Milchverkäufer und der Rest an einen gemeinsamen Pool.

Benutzerdefinierter Prozessor

Sie können auch die benutzerdefinierte Verarbeitung verwenden. Im folgenden Beispiel wird ein benutzerdefinierter Prozessor mit dem Namen erstelltmyCustomProcessor und verwendet es im Route Builder.

Processor myCustomProcessor = new Processor() {
   public void process(Exchange exchange) {
      // implement your custom processing
   }
};
RouteBuilder builder = new RouteBuilder() {
   public void configure() {
      from("direct:DistributeOrderDSL")
      .process(myProcessor);
   }
};

Sie können benutzerdefinierte Prozessoren zusammen mit Auswahl und Filterung verwenden, um eine bessere Kontrolle über Ihre Mediation und Ihr Routing zu erhalten.

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

Verwenden von XML

Die Routen können in sperrigerem XML definiert werden, wenn Sie dies bevorzugen. Das folgende XML-Snippet zeigt, wie Sie eine Route zusammen mit einer Filterung über Spring XML erstellen.

<camelContext xmlns = "http://camel.apache.org/schema/spring">
   <route>
      <from uri = "direct:DistributeOrderXML"/>
      <log message = "Split by Distribute Order"/>
      <split>
         <xpath>//order[@product = 'Oil']/items</xpath>
         <to uri = "file:src/main/resources/order/"/>
         <to uri = "stream:out"/>
      </split>
   </route>
</camelContext>

Nachdem wir gesehen haben, wie Routen erstellt werden, werden wir nun die verschiedenen Techniken zum Erstellen von Endpunkten sehen.

Wir haben gelernt, wie die Endpunkte in unserem Integrationscode aussehen. Die Ausdrücke, die wir bisher verwendet haben, wie zfile:/order, jms:orderQueue, direct:distributeOrderDSLsind die Endpunkte. Wie Sie sehen, folgen sie den URI-Spezifikationsformaten. Bei der Auswertung dieser URI wird dieCamelContext schafft die EndpointBeispiel; Sie brauchen sich keine Sorgen um die Instanziierung zu machenEndpoint Implementierung in Ihrem DSL.

Anhand unserer früheren Beispiele geben Sie Endpunkte in Java DSL wie folgt an:

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

Und im Frühling wie hier -

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

In beiden Fällen ist der Endpunkt eine konstante Zeichenfolge. In bestimmten Fällen möchten Sie diese Zeichenfolge möglicherweise zur Laufzeit erstellen. Sie können dies mit Java tunStringFormatierungsmethoden. Camel bietet einen weiteren einfacheren Ansatz zum Erstellen dieser URI-Zeichenfolgen zur Laufzeit. Zu diesem Zweck stellt Camel zur VerfügungfromF und toFMethoden, die die Argumente mit den benutzerdefinierten Parametern akzeptieren. Die folgende Anweisung veranschaulicht die Verwendung vontoF Methode -

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

Aufgrund dieser Methoden ist die Verwendung des integrierten Java erforderlich String Formatierungsmethoden werden vermieden.

Camel verwendet standardmäßig die einfache Sprache, um den Endpunktausdruck zu berechnen. DasSimple Sprache wurde in erster Linie zur Bewertung entwickelt Expressions und Predicatesohne sich um die Feinheiten von zu kümmern XPath. Zur Auswertung von Prädikaten können Sie eine andere Sprache kombinieren, zxpath mit der Standardeinstellung SimpleSprache. Verwenden Sie dazu das Pluszeichen, um die andere Sprache zu trennen. Das Code-Snippet hier zeigt, wie man verkettetxpath Zeichenfolge zu dem in geschriebenen Ausdruck Simple.

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

Im Springkönnen Sie das gleiche wie hier erreichen -

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

Sie können so viele Sprachen verketten, wie Sie möchten, wobei jede durch ein Pluszeichen von der vorherigen getrennt ist. Die Liste der unterstützten Sprachen finden Sie hier .

Camel bietet mehrere vorgefertigte Komponenten.

In diesem Kapitel werden einige wichtige Komponenten aus dem camel-core Modul.

Bohne

Das BeanKomponente bindet Beans an den Austausch von Camel-Nachrichten. Der URI zum Erstellen eines Endpunkts wird als angegebenbean:beanID, wo beanID ist der Name der Bean, wie in der Registry.

JndiContext jndiContext = new JndiContext();
jndiContext.bind("MilkOrder", new MilkOrderProcessor());
CamelContext camelContext = new DefaultCamelContext(jndiContext);

camelContext.addRoutes(new RouteBuilder() {
   public void configure() {
      from("direct:bigBasket")
         .to("bean:MilkOrder?method=placeOrder");
   }
});

Beachten Sie, wie der Endpunkt mit dem angegeben wird bean:Protokoll. Sie können optional die Bean-Methode angeben, die aufgerufen werden soll. In diesem Fall wird die Methode aufgerufenplaceOrderwird beim Auswerten des Endpunktausdrucks aufgerufen. DasMilkOrder ist ein JNDI-Name für die MilkOrderProcessorJavabean wie in den ersten beiden Zeilen des Code-Snippets registriert. Die Definition vonMilkOrderProcessor selbst wird hier der Kürze halber weggelassen.

Direkte

Sie müssen die Verwendung von bemerkt haben Directin unseren vorherigen Beispielen. Um eine Bestellung an einen Ölhändler zu senden, haben wir verwendetdirect:oilin der Endpunktspezifikation. Die Verwendung vonDirectMit der Komponente können Sie einen Endpunkt synchron aufrufen. Die folgenden zwei Codefragmente aus unseren vorherigen Beispielen veranschaulichen die Verwendung vonDirect - -

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

Und,

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

Datei

Das FileKomponente bietet Zugriff auf das Dateisystem auf Ihrem Computer. Mit dieser Komponente können Sie Nachrichten von anderen Komponenten auf einer lokalen Festplatte speichern. Darüber hinaus können andere Camel-Komponenten die lokalen Dateien verarbeiten. Sie können entweder verwendenfile:directoryName[?options] oder file://directoryName[?options]als URI-Format bei Verwendung der Dateikomponente. Sie haben bereits die Verwendung dieser Komponente gesehen -

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

Notiere dass der FileKomponente nimmt standardmäßig den Verzeichnisnamen. Daher wird der Inhalt des Auftragsverzeichnisses als Eingabeinhalt verwendet. Um eine bestimmte Datei in der anzugebenorder Verzeichnis verwenden Sie die folgende Anweisung -

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

Log

Das LogMit der Komponente können Sie Nachrichten im zugrunde liegenden Protokollierungsmechanismus protokollieren. Camel verwendet Simple Logging Facade für Java (SLF4J) als Abstraktion für verschiedene Protokollierungsframeworks. Sie können verwendenjava.util.logging, logback, log4jzur Protokollierung. Dieses Code-Snippet veranschaulicht die Verwendung vonLog Komponente -

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

SEDA

Das SEDA Mit der Komponente können Sie einen anderen Endpunkt in derselben asynchron aufrufen CamelContext. Wenn Sie über CamelContext-Instanzen hinweg aufrufen möchten, müssen Sie verwendenVMKomponente. Die Verwendung von SEDA wird hier veranschaulicht -

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

Auf dieser Route leiten wir einfach die Bestellungen an weiter nextOrderasynchrone Warteschlange. Ein Client, der diese Warteschlange abonniert hat, holt die Nachrichten aus dieser Warteschlange ab.

Timer

Das TimerDie Komponente wird zum Versenden von Nachrichten in regelmäßigen Abständen verwendet und kann daher beim Testen von Camel-Anwendungen sehr nützlich sein. Das Code-Snippet hier löst alle zwei Sekunden eine Testnachricht an die Konsole aus -

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

Die meisten Integrationsprojekte verwenden Messaging, da es bei der Erstellung einer lose gekoppelten Anwendungsarchitektur hilft. Messaging kann entweder synchron oder asynchron sein. JMS unterstützt beidepoint-to-point und publish-subscribeModelle. Sie verwenden eineQueue für Punkt zu Punkt und Topicfür ein Publish-Subscribe-Modell. Auf einer Java-Plattform bietet JMS - Java Messaging Service eine Schnittstelle zu einem Messaging-Server. Apache activeMQ ist ein solcher Open Source JMS-Anbieter. Camel wird nicht mit einem JMS-Anbieter geliefert. Es kann jedoch für die Verwendung von activeMQ konfiguriert werden. Um diese Komponente verwenden zu können, müssen Sie die folgenden Gläser in Ihr Projekt aufnehmen - activemq, camel-spring und camel-jms.

Das folgende Code-Snippet zeigt, wie Camel für activeMQ konfiguriert wird.

<bean id = "jms" class = "org.apache.camel.component.jms.JmsComponent">
   <property name = "connectionFactory">
      <bean class="org.apache.activemq.ActiveMQConnectionFactory">
         <property name = "orderQueue" value = "tcp://localhost:61000" />
      </bean>
   </property>
</bean>

Hier beginnt die Camel-Anwendung, eine aufgerufene Warteschlange abzuhören orderQueue. Die Warteschlange selbst wird auf dem ActiveMQ-Nachrichtenserver eingerichtet, der auf dem lokalen Host ausgeführt wird und an Port 61000 aufgelistet ist. Anschließend kann Ihre Anwendung von jedem in Ihrer Anwendung definierten Endpunkt aus eine Nachricht an diese Warteschlange senden oder empfangen.

Schließlich ist es jetzt an der Zeit, alles in einem Projekt zusammenzufassen, um ein tieferes Verständnis dafür zu erhalten, wie Camel-Anwendungen erstellt werden.

Wir werden Maven verwenden, um ein Kamelprojekt zu bauen. Wir verwenden jedoch vorzugsweise IntelliJ IDE für die Entwicklung. Sie können für dieses Projekt eine beliebige IDE Ihrer Wahl verwenden.

Neues Projekt erstellen

Erstelle eine neue Maven Projekt und geben Sie Folgendes an -

GroupId: Basket
ArtifactId: Basket

Wählen Sie den Standardspeicherort für Ihr Projekt oder geben Sie bei Bedarf das Verzeichnis Ihrer Wahl an.

Abhängigkeiten hinzufügen

Sie müssen einige Abhängigkeiten hinzufügen, um Camel verwenden zu können. Die Abhängigkeiten werden hinzugefügtpom.xml. Öffnen Sie also pom.xml und fügen Sie die folgenden zwei Abhängigkeiten hinzu:

<dependencies>
   <dependency>
      <groupId>org.apache.camel</groupId>
      <artifactId>camel-core</artifactId>
      <version>2.20.0</version>
   </dependency>
   <dependency>
      <groupId>org.apache.camel</groupId>
      <artifactId>camel-stream</artifactId>
      <version>2.20.0</version>
   </dependency>
</dependencies>

Note- Wir benötigen die Mindestabhängigkeiten für unsere Anwendung. Wenn Sie mehr Camel-Komponenten aus den Bibliotheken verwenden, müssen Sie die entsprechenden Abhängigkeiten in diese Datei pom.xml einfügen.

Java DSL erstellen

Als Nächstes schreiben Sie Ihren Filter- und Routing-Code in Java DSL. Erstellen Sie eine neue Java-Klasse mit dem NamenDistributeOrderDSL. Fügen Sie den folgenden Code hinzu:

public class DistributeOrderDSL {
   public static void main(String[] args) throws Exception {
      CamelContext context = new DefaultCamelContext();
      try {
         context.addRoutes(new RouteBuilder() {
            @Override
            public void configure() throws Exception {
               from("direct:DistributeOrderDSL")
                  .split(xpath("//order[@product='soaps']/items")).to("stream:out");
               
               // .to("file:src/main/resources/order/");
            }
         });
         context.start();
         ProducerTemplate orderProducerTemplate = context.createProducerTemplate();
         InputStream orderInputStream = new FileInputStream(ClassLoader.getSystemClassLoader()
            .getResource("order.xml").getFile());
         orderProducerTemplate.sendBody("direct:DistributeOrderDSL", orderInputStream);
      } finally {
         context.stop();
      }
   }
}

In dem main Methode erstellen wir zuerst CamelContext durch Instanziieren einer Standardimplementierung in DefaultCamelContext Klasse.

CamelContext context = new DefaultCamelContext();

Als Nächstes fügen wir eine Route hinzu, indem wir eine anonyme erstellen RouteBuilder Instanz -

context.addRoutes(new RouteBuilder() {

Wir überschreiben die configure Methode zum Hinzufügen einer Route von einem direkten URI DistributeOrderDSLan die Systemkonsole. Wir bieten einige Filter mithilfe der xpath-Abfrage.

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

Nach dem Hinzufügen der Route starten wir den Kontext -

context.start();

Als nächstes fügen wir den Code zum Erstellen unserer direkten URI hinzu - DistributeOrderDSL.

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

Schließlich starten wir die Verarbeitung -

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

Nachdem Ihr Java-DSL-Code fertiggestellt ist, müssen Sie vor dem Testen der Anwendung nur noch den Code hinzufügen order.xmlDatei zu Ihrem Projekt. Zu diesem Zweck können Sie das im Kapitel Einführung gezeigte XML-Beispiel verwenden.

Testergebnisse

Wenn Sie die Anwendung ausführen, wird die folgende Ausgabe angezeigt:

<items>
   <item>
      <Brand>Cinthol</Brand>
      <Type>Original</Type>
      <Quantity>4</Quantity>
      <Price>25</Price>
   </item>
   <item>
      <Brand>Cinthol</Brand>
      <Type>Lime</Type>
      <Quantity>6</Quantity>
      <Price>30</Price>
   </item>
</items>

Beachten Sie, dass hier nur Bestellungen für Seifen aufgeführt sind. Wenn Sie dies in einer lokalen Datei speichern möchten, kommentieren Sie einfach diestream.out Zeile und kommentieren Sie die folgende Zeile in Ihrem configure Methode -

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

In unserem folgenden Abschnitt erfahren Sie, wie Sie Camel mit Spring verwenden.

Wir werden nun die Anwendung aus dem vorherigen Kapitel mit Spring neu erstellen. Dies gibt uns eine Vorstellung davon, wie Camel-Routing in XML anstatt in DSL erstellt wird.

Neues Projekt erstellen

Erstelle eine neue Maven Projekt und geben Sie Folgendes an -

GroupId: BasketWithSpring
ArtifactId: BasketWithSpring

Wählen Sie den Standardspeicherort für Ihr Projekt oder geben Sie bei Bedarf das Verzeichnis Ihrer Wahl an.

Abhängigkeiten hinzufügen

Zusätzlich zu den Kernabhängigkeiten, die Sie in der früheren Anwendung verwendet haben, müssen Sie einige weitere Abhängigkeiten hinzufügen, um Spring zu verwenden. Die Abhängigkeiten werden in pom.xml hinzugefügt. Öffnen Sie nun pom.xml und fügen Sie die folgenden Abhängigkeiten hinzu:

<dependencies>
   ...
   <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.1.3.RELEASE</version>
   </dependency>
   
   <dependency>
      <groupId>org.apache.activemq</groupId>
      <artifactId>activemq-pool</artifactId>
      <version>5.15.2</version>
   </dependency>
   
   <dependency>
      <groupId>org.apache.activemq</groupId>
      <artifactId>activemq-pool</artifactId>
      <version>5.15.1</version>
   </dependency>
   
   <dependency>
      <groupId>org.apache.camel</groupId>
      <artifactId>camel-spring</artifactId>
      <version>2.15.1</version>
   </dependency>
</dependencies>

Erstellen von Java DSL für Spring

Lassen Sie uns nun eine neue Java-Klasse namens erstellen DistributeOrderXML. Fügen Sie den folgenden Code hinzu:

public class DistributeOrderXML {
   public static void main(String[] args) throws Exception {
      ApplicationContext appContext = new ClassPathXmlApplicationContext(
         "SpringRouteContext.xml");
      CamelContext camelContext = SpringCamelContext.springCamelContext(appContext, false);
      try {
         camelContext.start();
         ProducerTemplate orderProducerTemplate = camelContext.createProducerTemplate();
         InputStream orderInputStream = new FileInputStream(ClassLoader.getSystemClassLoader()
            .getResource("order.xml").getFile());
         
         orderProducerTemplate.sendBody("direct:DistributeOrderXML", orderInputStream);
      } finally {
         camelContext.stop();
      }
   }
}

In dem main Methode erstellen wir zuerst eine Instanz von ApplicationContextDies ist die zentrale Schnittstelle innerhalb einer Spring-Anwendung. In seinem Konstruktor geben wir den Namen der XML-Datei an, die unsere Routing- und Filterinformationen enthält.

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

Als nächstes erstellen wir CamelContext Angabe der oben erstellten ApplicationContext in seinem Parameter.

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

Zu diesem Zeitpunkt ist unser Routing und Filtern eingerichtet. Deshalb starten wir dieCamelContext mit seiner startMethode. Wie im vorherigen Fall definieren wir den Endpunkt zum Laden der Datei order.xml und starten die Verarbeitung. Lassen Sie uns nun verstehen, wie Routing in XML definiert ist.

Anwendungskontext erstellen

Fügen Sie dem Projekt eine neue XML-Datei hinzu und rufen Sie sie auf SpringRouteContext.xml. Schneiden Sie den folgenden Inhalt aus und fügen Sie ihn in diese Datei ein.

<?xml version = "1.0" encoding = "UTF-8"?>
<beans xmlns = "http://www.springframework.org/schema/beans"
   xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation = "
      http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans.xsd
      http://camel.apache.org/schema/spring
      http://camel.apache.org/schema/spring/camel-spring.xsd ">
   <camelContext xmlns = "http://camel.apache.org/schema/spring">
      <route>
         <from uri = "direct:DistributeOrderXML"/>
         <log message = "Split by Distribute Order"/>
         <split>
            <xpath>//order[@product = 'Oil']/items</xpath>
            <to uri = "file:src/main/resources/order/"/>
            <to uri = "stream:out"/>
         </split>
      </route>
   </camelContext>
</beans>

Hier definieren wir die xpath-Abfrage wie folgt. Beachten Sie, dass wir jetzt alle Bestellungen für „Öl“ auswählen.

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

Die Ausgabeendpunkte sind mehrfach. Der erste Endpunkt gibt die anorder Ordner und der zweite gibt die Konsole an.

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

Führen Sie die Anwendung aus.

Testergebnisse

Wenn Sie die Anwendung ausführen, wird die folgende Ausgabe auf dem Bildschirm angezeigt.

<items>
   <item>
      <Brand>Cinthol</Brand>
      <Type>Original</Type>
      <Quantity>4</Quantity>
      <Price>25</Price>
   </item>
   <item>
      <Brand>Cinthol</Brand>
      <Type>Lime</Type>
      <Quantity>6</Quantity>
      <Price>30</Price>
   </item>
</items>

Probier das aus orderOrdner in dem von Ihnen angegebenen Pfad. Sie finden eine neu erstellte Datei, die den obigen XML-Code enthält.

Fazit

Camel bietet ein sofort einsatzbereites Framework, das EIPs implementiert, um Ihre Integrationsprojekte zu vereinfachen. Es unterstützt die Codierung in domänenspezifischen Sprachen sowie die Verwendung von XML.