Freie Integrations-Frameworks auf der Java-Plattform

Seite 2: Unterschiede

Inhaltsverzeichnis

Trotz vieler Gemeinsamkeiten gibt es durchaus auch einige Unterschiede. Am deutlichsten variieren die Produkte hinsichtlich der verfügbaren Konnektoren und DSLs. Daher soll im Folgenden der Fokus auf diesen beiden Kriterien liegen. Für die drei Frameworks wird als Code-Beispiel das EIP "Content-based Router" umgesetzt, das eine Nachricht abhängig von ihrem Inhalt an ein unterschiedliches Ziel weiterleitet. Dabei werden Bestellungen aus einem Dateiverzeichnis gelesen und die einzelnen Bestellpositionen passend weiterverarbeitet. DVDs werden in ein anderes Verzeichnis kopiert, Videospiele gehen in eine JMS
Queue, und andere Bestellungen werden (vorübergehend) nur geloggt. Jede andere Technik – beispielsweise FTP, Mail, MongoDB, Amazon SQS, RMI (Remote Method Invocation) oder etwa 100 weitere – ließen sich auf die gleiche Weise nutzen.

Das Framework baut auf dem Spring-Portfolio auf und erweitert dessen Programmiermodell um Integrationsaspekte. Die bekannten Spring-Funktionen wie Dependency Injection, Transaktionen oder Security werden wie gewohnt verwendet. Spring Integration ist vor allem gut geeignet, wenn die restliche Anwendung ebenfalls auf Spring aufsetzt. Das Zusammenspiel ist einfach, und für Spring-erfahrene Entwickler ist dieses Framework nahezu ohne zusätzlichen Lernaufwand nutzbar.

Spring Integration bietet hauptsächlich Unterstützung für einige im Java-Umfeld weitverbreitete Techniken wie File, FTP, JMS, TCP, HTTP und Webservices an. Mule und Camel dagegen bieten eine deutlich größere Anzahl an Konnektoren. Eigene lassen sich in Spring Integration zwar ebenfalls erstellen, allerdings ist der Prozess nicht dokumentiert, daher aufwendig und umständlich.

Integrationen setzt der Entwickler mit XML-Quellcode ohne eine richtige DSL um:

<file:inbound-channel-adapter 
id="incomingOrders"
directory="file:incomingOrders"/>

<payload-type-router input-channel="incomingOrders">
<mapping type="com.kw.DvdOrder" channel="dvdOrders" />
<mapping type="com.kw.VideogameOrder"
channel="videogameOrders" />
<mapping type="com.kw.OtherOrder" channel="otherOrders" />
</payload-type-router>

<file:outbound-channel-adapter
id="dvdOrders"
directory="dvdOrders"/>

<jms:outbound-channel-adapter
id="videogamesOrders"
destination="videogameOrdersQueue"
channel="videogamesOrders"/>

<logging-channel-adapter id="otherOrders" level="INFO"/>

Mittlerweile lässt sich dank Annotationen auch mit Spring viel Logik in Java-Code auslagern; die eigentliche Integrationslogik ist jedoch in XML umzusetzen. Während XML wiederum für Konfigurationen gut geeignet ist, trifft das bei der Integrationslogik nur bedingt zu. Zumindest bei komplexeren, größeren Integrationsaufgaben ist eine DSL mit guter Lesbarkeit eine enorme Erleichterung für Entwickler. Komplexere Spring-Integration-Beispiele sind daher deutlich schwerer nachzuvollziehen als bei den Konkurrenten. Positiv ist daher zu bewerten, dass sich derzeit auch eine Scala- und Groovy-DSL in einem frühen Stadium in Arbeit befinden.

Das in Eclipse integrierte visuelle Werkzeug namens Integration Graph funktioniert, ist aber weniger intuitiv als die Tools der anderen Frameworks. Außerdem fehlt bisher jegliche Dokumentation oder zusätzliche Features wie die oben genannten Live-Monitoring oder Performance-Analysen.

Wie es der Name sagt, ist Mule ESB nicht nur ein Integrations-Framework, sondern auch ein ESB inklusive zusätzlicher Funktionen. Dennoch lässt sich Mule auch als Integrations-Framework einsetzen, indem man nur die benötigten Bibliotheken wie bei Camel oder Spring Integration in die Anwendung einfügt. Auf ESB-Features wie Monitoring oder Business Process Management (BPM) wird im Artikel deshalb verzichtet.

Mule bietet für die Integration leider nur eine XML-DSL an. Immerhin bietet die Entwicklungsumgebung Mule Studio aber einen guten und intuitiven Visual Designer. Der folgende Codeschnipsel zeigt die Umsetzung des Beispiels mit Mule. Im Vergleich zum Spring-Integration-Beispiel ist der DSL-Code deutlich besser lesbar. Das ist insbesondere bei komplexerer Integrationslogik wichtig:

<flow name="muleFlow">
<file:inbound-endpoint path="incomingOrders"/>
<choice>
<when expression="payload instanceof com.kw.DvdOrder"
evaluator="groovy">
<file:outbound-endpoint
path="incoming/dvdOrders"/>
</when>
<when expression="payload instanceof com.kw.DvdOrder"
evaluator="groovy">
<jms:outbound-endpoint
queue="videogameOrdersQueue"/>
</when>
<otherwise>
<logger level="INFO"/>
</otherwise>
</choice>
</flow>

Der größte Pluspunkt von Mule sind die zahlreichen Konnektoren zu wichtigen proprietären Schnittstellen wie SAP, Tibco Rendevous, Oracle Siebel CRM oder IBMs CICS Transaction Gateway. Sofern also das Integrationsprojekt einen der proprietären Konnektoren benötigt, ist Mule die beste Wahl. Existiert noch kein Konnektor, lässt sich einfach ein eigener erstellen. Dabei erzeugt ein Maven-Archetype das Grundgerüst, sodass der Entwickler nur mehr die eigene Logik zur Integration der gewünschten Technik hinzufügen muss. Ein Nachteil für manche Projekte ist hingegen, dass Mule keine Unterstützung für OSGi anbietet und das auch in Zukunft nicht geplant ist.

Camel ist in vielerlei Hinsicht nahezu identisch zu Mule. Es bietet ebenfalls viele Konnektoren für fast jede denkbare Technik, auch eigene Konnektoren sind leicht erstellbar. Zudem bietet Camel eine starke Integration in das Spring Framework an. Das folgende Beispiel zeigt die XML-DSL, die auf Spring aufsetzt:

<route>
<from uri="file:incomingOrders"/>
<choice>
<when>
<simple>${in.header.type} is 'com.kw.DvdOrder'</simple>
<to uri="file:incoming/dvdOrders"/>
</when>
<when>
<simple>${in.header.type} is
'com.kw.VideogameOrder'</simple>
<to uri="jms:videogameOrdersQueue"/>
</when>
<otherwise>
<to uri="log:OtherOrders"/>
</otherwise>
</choice>
</route>

Die DSL ist nahezu identisch zu Mule und deutlich besser lesbar als bei Spring Integration. FuseSource bietet darüber hinaus den kommerziellen – sich in Eclipse integrierende – grafischen Designer Fuse IDE an, der XML-DSL-Quellcode generiert.

Nichtsdestoweniger ist letztlich viel XML zu erzeugen und zu warten. Camel bietet im Gegensatz zu den Konkurrenten daher noch ein weiteres Feature: programmatische DSLs für Java, Groovy und Scala. Auch für den Neuling unter den JVM-Sprachen Kotlin ist bereits eine DSL in Arbeit.

Der folgende Codeschnipsel zeigt die Java-DSL:

from("file:incomingOrders ")
.choice()
.when(body().isInstanceOf(com.kw.DvdOrder.class))
.to("file:incoming/dvdOrders")
.when(body().isInstanceOf(com.kw.VideogameOrder.class))
.to("jms:videogameOrdersQueue ")
.otherwise()
.to("mock:OtherOrders ");

Dadurch lässt sich auf XML vollständig verzichten. Die fließende DSL ist deutlich besser lesbar und bietet gewohnte Funktionen der Entwicklungsumgebung wie automatische Code-Vervollständigung oder Refactoring. Übrigens bietet Talend ein visuelles Werkzeug an, das eine Java-DSL generiert. Allerdings erzeugt es, im Gegensatz zur Fuse IDE, noch viel zusätzlichen unnötigen Boilerplate-Code. Außerdem kann man vice versa diesen nicht bearbeiten, der generierte Quellcode lässt sich nicht editieren. Da Talend mit seiner Produkt-Suite einen "Zero-Coding"-Ansatz anbietet, ist das Editieren aber auch nicht notwendig.

Der Einsatz mehrerer DSLs ist ebenfalls möglich. In der Praxis wird oftmals eine programmatische DSL für die Integrationslogik eingesetzt, während XML bei der Konfiguration zum Einsatz kommt – beispielsweise zur Spezifikation von JMS Connection Factories oder JDBC Properties.

Nach der Vorstellung der Integrations-Frameworks erläutert der Autor nun, in welchen Projekten sich diese statt eines mächtigeren, aber eben auch komplexeren ESB sinnvoll einsetzen lassen.