Java Magazin 7.2014 Java Mag Der Tod der Java Application Server: Sind sie noch zeitgemäß? 55 Deutschland € 9,80 Österreich € 10,80 Schweiz sFr 19,50 Luxemburg € 11,15 7.2014 magazin Java • Architekturen • Web • Agile Clojure RoboVM ServiceMix iOS-Apps mit Java entwickeln 115 Schlanke Systemintegration 91 www.javamagazin.de Application Server ramminfos Erste Prog 7! ab Seite 4 RoboVM ServiceMix Clojure REST und HATEOAS Quo vadis Clojure 1.6 14 IoT mit Java 8 und Tinkerforge Zugriff auf relationale Datenbanken 32 Polyglotte Entwicklung mit Clojure und Java 24 © iStockphoto.com/sololos Ceph-Storage-Cluster Fieldings Vermächtnis: Wer REST will, muss mit HATEOAS ernst machen 64 IoT mit Java 8 und Tinkerforge: Baukasten für große Kinder 38 Mächtig flexibel: Konzepte des ­ Ceph-StorageClusters 103 ServiceMix Web Schlanke Systemintegration in der Praxis Integration lösen Wer Websysteme entwickelt, kennt die wachsenden Mühen und damit verbundenen Unwägbarkeiten bei einer zunehmenden Zahl an Systemintegrationen. In einem sich stetig wandelnden und beschleunigten Geschäftsumfeld sind aber weniger Anstrengungen und Risiken gefragt. Apache ServiceMix [1] ist ein Open Source Enterprise Service Bus (ESB), der heute für hochgradig skalierbare Systeme geeignet ist. Lesen Sie, wie er eingesetzt wird, um einen verteilten Geschäftsprozess zu realisieren, der von Kunden über das Web ausgelöst wird. von Daniel Takai, Raúl Kripalani und Matthias Rothe Stellen Sie sich vor, Sie arbeiten für ein Einzelhandelsunternehmen, das Produkte auf der ganzen Welt verkauft. Der Hauptsitz der Firma befindet sich in Deutschland, aber es gibt regionales Marketing sowie Finanz- und HR-Abteilungen in jedem wichtigen Markt (EMEA, APAC, US, LATAM etc.). Zudem betreibt die Firma pro Land eine eigene Logistik, Warenlager und CustomerRelationship-Management-Systeme (CRM). In diesem Beispiel nutzen Kunden die Website des Unternehmens zur Produktbestellung. Die Produkte werden dann von der jeweiligen Länderorganisation versandt. An der Ausführung dieses Shopping-Workflows ist eine Reihe von Systemen beteiligt: •Product-Information-Management-(PIM-) und Inventory-Control-Systeme (ICS) werden eingesetzt, um einen Artikel zu finden; beide sind Java-EnterpriseApplikationen. •Ein Warenkorbsystem (eine .NET-Anwendung) nimmt Artikel auf, während der Nutzer den Einkauf fortsetzt. •Ein E-Commerce-Payment-Gateway (B2B-Transaktion) ist am Check-out beteiligt. Es handelt sich um eine SaaS-Anwendung. •(Mainframe-)Logistiksysteme übernehmen dann das Zepter, um den Versand an den Kunden in Gang zu setzen. •Versandpartner und ihre Tracking-Systeme sind ­ständig an der Auslieferung beteiligt (B2B). •CRM-Systeme halten aktuelle Informationen ­während des gesamten Prozesses bereit. Betrachtet man das Szenario sorgfältig, dann sieht man eine Geschichte der Integration: Diverse Geschäftseinheiten, alle mit ihren spezifischen Applikationen, www.JAXenter.de schließen sich zusammen, um eine Reihe von Geschäftstransaktionen zu erledigen. Dabei spielen die Orchestrierung und Choreografie der Applikationen eine Schlüsselrolle. Wir benötigen einen Dirigenten, der die Vorgänge koordiniert: Sowohl Datentransformationen sind auszuführen, als auch Validierung, Auditing, Security, Fehlerbehandlung etc. Wobei immer in Betracht zu ziehen ist, dass Systeme vermutlich mit heterogener Technologie gebaut wurden, etwa mit .NET, Java, Cobol, Mainframe etc. Um diese vielfältigen Herausforderungen zu bewältigen, setzen wir auf Apache ServiceMix als ESB. Der Apache Integration Stack Apache ServiceMix ist eine Open Source und auf Standards basierende Integrationsplattform, zugeschnitten auf Echtzeitintegration in einem heterogenen System­ umfeld. Es wird durch mehrere Apache-Projekte unterstützt, die in der Middleware-Industrie als Best of Breed bekannt sind: •Apache ActiveMQ, ein stabiler JMS-Broker [2]. •Apache Camel [3], das bekannte Integrationsframework mit mehr als 200 Konnektoren und über vierzig unterstützten Datenformaten, basiert auf dem Konzept der Enterprise Integration Patterns [4]. •Apache CXF, der Apache Web Services Stack [5]. •Apache Karaf, ein OSGi Container als Laufzeitumgebung [6]. Abbildung 1 zeigt die Details des Technologiestacks. ServiceMix-Bausteine Wenn man Systemintegrationen in hoher Qualität herstellen möchte, dann ergibt es Sinn, eine Technologie einzusetzen, die hierfür entworfen wurde. Das OpenSource-Lizensierungsmodell und die schlanke, stabile javamagazin 7 | 2014 91 Web ServiceMix Abb. 1: Der ServiceMix Technologie-Stack Abb. 2: Exemplarische Bausteine der Architektur Architektur von ServiceMix machen es zu einem guten Kandidaten – in kleinen wie auch in größeren Systemen. Die Grundarchitektur, die wir hier zeigen möchten, besteht aus einem Consumer, einem Business- oder DataService sowie ServiceMix in der Mitte (Abb. 2). Innerhalb von ServiceMix nutzen wir drei Schichten, um unsere Integrationsziele zu erreichen. Die Trennung bewirkt eine klare Teilung der Verantwortlichkeiten und damit die Entkopplung der einzelnen Schichten. Wie immer ist das Ziel, dass Änderungen an einer Schicht nicht notwendigerweise Änderungen in anderen Schichten nach sich ziehen. Das Frontend-Servicemodul nimmt Anfragen vom Consumer entgegen und kann für jedwedes Protokoll geschrieben werden; gewöhnlich ist dies REST mit einer JSON Payload für die Nachrichten, da JSON mit dem JavaScript-Code im Browser kompatibel ist. Das Frontend-Modul validiert die ankommenden Requests und leitet sie an das richtige Businessmodul weiter. Es ist zudem verantwortlich für Authentifizierung und (soweit 92 javamagazin 7 | 2014 möglich) Autorisierung. Das Frontend-Modul transformiert außerdem eine hereinkommende Anfrage in das kanonische Datenmodell (siehe unten). Das Businessservicemodul wird benötigt, wenn eine anspruchsvollere Integration erforderlich ist. Das Modul kann eine Batchverarbeitung von Nachrichten durchführen, Nachrichten teilen oder ist sogar für Serviceorchestrierung zuständig. In den meisten dedizierten Integrationsschichten, denen wir während der Entwicklung von Websystemen begegnen, ist dies der Ort, wo wir auch den Geschäftsprozess ansiedeln. Somit ist der Businessservice oft auch damit beauftragt, qualifizierte Geschäftsfehler zu erzeugen, die im Error Catalogue dokumentiert werden (siehe unten). Ein Backend-Servicemodul sendet eine Anfrage an den externen Service und validiert die Antwort. Da es eng an das Backend-System gekoppelt ist, versteht es dessen Datenmodell und kann dieses in das kanonische Datenmodell übersetzen. Daher muss allerdings die Version genau passen, da Backend-Systeme sich meistens in andauernder Entwicklung befinden und sich auch ihre Schnittstellen verändern. Das Backend-Modul stellt in unserer Architektur die Zuverlässigkeit und Stabilität sicher. Synchrone Services, die versagen oder willkürlich antworten, machen die Architektur anfällig. Dieser Layer hat die Verantwortung, solches Verhalten zu erkennen und sicherzustellen, dass es nicht die Gesamtstabilität beeinträchtigt. Wer mit vielen unzuverlässigen Services zu tun hat, kann sich als Alternative überlegen, einen asynchronen Weg einzuschlagen, wenn dies der Geschäftsprozess gestattet. Semantische Integration Zwei bedeutende Artefakte werden für die Integration auf der semantischen Ebene benötigt: www.JAXenter.de ServiceMix Web Abb. 3: Verteilte ServiceMix-Architektur Das Canonical Data Model (CDM): Es ist für gewöhnlich eine Teilmenge des Domänenmodells der Zielorganisation. Es enthält die Konzepte, die an der Integration beteiligt sind, sowie ihre Beziehungen untereinander. Wir nutzen dieses Modell als gemeinsame Sprache unserer Integrationsgeschichten. Wenn sich eine Integration in dieser Sprache ausdrücken lässt, dann lässt sie sich auch implementieren. Jede eingehende Payload wird in Konzepte unseres Modells übersetzt und an Business- und Backend-Mo­ dule weitergeleitet, die somit von den Consumer-Systemen entkoppelt werden: Sie arbeiten nur noch mit Nachrichten in unserer Sprache, die Sprache des Consumers spielt keine Rolle mehr. Dies ist eine Umsetzung des Normalizer Patterns, wie es in Enterprise Integration Patterns [4] definiert wird. Das Modell sorgt also für die konzeptuelle Integrität, die Frontend- und Businesskomponenten von Änderungen in den Backend-Systemen abschirmt (semantische Entkopplung). Zudem begünstigt das CDM die Datenwiederverwendbarkeit im Kontext der Serviceorchestrierung. Der Common Error Catalogue ist das zweite Artefakt, das wir benötigen. Der Katalog ist eine Systematik aller Fehlersituationen, die während des Integrationsprozesses auftauchen könnten, bspw. Business Errors, Validation Errors, Communication Errors etc. Das Backend-Servicemodul übersetzt alle Fehler jeglicher nativen Form (bspw. SOAP Fault, HTTP Status Code, TCP Byte Marker etc.) in Error-Catalogue-Codes, damit alle Upstream-Teilnehmer die Situation erfolgreich interpretieren können. Unter vielen Vorteilen erlaubt dies den Auslieferungskanälen (in Websystemen oft ein CMS) diesen Error-Code zu nutzen, um eine korrekt übersetzte und passende Antwort für den Endkunden zu erzeugen. www.JAXenter.de Federated SOA mit ServiceMix Kehren wir nach diesem Ausflug in die Theorie nun in die Praxis zurück. Wir behalten unsere Basisarchitektur, erweitern diese aber nun noch um den Aspekt der weltweiten Verteilung und Multikanalfähigkeit (Abb. 3). Im Beispiel ist die Verteilung wichtig, da die Organisation ihre Bestände global bewirtschaftet. Ziel ist es, ein Produkt aus dem Warenlager in Atlanta an einen Schweizer Kunden schicken zu können, falls dieses im regionalen Lager nicht vorrätig ist. Doch dazu müssen verschiedene geografische Regionen miteinander kooperieren und ihre Daten hinsichtlich der verfügbaren Bestände teilen. ServiceMix erlaubt den Aufbau einer Föderation von Instanzen. Gelöst wird dies durch ein Broker-Netzwerk auf Basis von ActiveMQ. Im Beispiel stöbern die Kunden im globalen Store und geben ihre Bestellungen entweder über eine Website oder eine App auf. Dazu einige technische Details: •Die Website und die Smartphone-Apps kommunizieren mit einem Cluster von ServiceMix-Instanzen mittels REST-Aufruf mit JSON Payload. •Die ServiceMix-Instanzen enthalten jeweils einen ActiveMQ JMS Broker für die Verteilung von Nachrichten untereinander. •Jede geografische Zone nutzt ServiceMix auf Regionen- und Länderebene. Sie sind miteinander in einer baumähnlichen Form verbunden, entsprechend der geografischen Hierarchie. •Kernanwendungen (wie ein globales Abrechnungssystem) sind mit einer zentralen ServiceMix-Instanz verbunden, wohingegen regionale Applikationen mit regionalen ServiceMix-Instanzen verbunden sind. •Die Integrationslogik wird mit Camel Routes umgesetzt. javamagazin 7 | 2014 93 Web ServiceMix Eine Camel Route ist eine Abfolge von Schritten, die bei der Bearbeitung von Nachrichten angewandt wird. Zu dem Nachrichtenfluss gehören Routing-Regeln, Deci­ sions, Transformations, Mediation, Security, Logging usw. Camel unterstützt über 200 Integrationstechnologien out of the box, dazu gehören WS-*, REST, JMS, TCP, FTP, File, Caches, SQL, NoSQL usw. Listing 1 // (2) .to("validator:stock-availability.xsd") // (3) .to("xslt:stock-availability-request.xsl") // (4) .to("jms:organization.processes.stock.availability")) // (5) .to("xslt:stock-availability-response.xsl") // (6) .marshal().xmljson(); // (7) Listing 2 from("jms:organization.processes.stock.availability") // (1) .onException(Exception.class) .setBody(simple("<error>${exception}</error>")) // (2) .end() .multicast().parallelProcessing() // (3) .aggregationStrategy(new MergeStockAvailabilityStrategy()) .to("jms:organization.services.emea.germany.stock.availability")) // (4) .to("jms:organization.services.us.atlanta.stock.availability")) // (5) .to("jms:organization.services.apac.singapore.availability")) // (6) .end(); Listing 3 from("jms:organization.processes.stock.emea.germany.availability") .to("xslt:stock-availability-emea-germany-request.xsl") .to("cxf:http://inventory.orga.de/StockService?dataFormat=PAYLOAD") .to("xslt:stock-availability-emea-germany-response.xsl"); 94 javamagazin 7 | 2014 Unsere erste Camel Route nimmt Einkäufe von der Website oder der App an, validiert diese und übersetzt sie in unser CDM, damit sie an das Businessmodul gesendet werden können (Listing 1). Mit nur wenigen Zeilen Code haben wir nun Folgendes erreicht: 1.Einen HTTP GET per Camel-Restlet-Komponente angenommen, in diesem Fall mit dem dynamischen Pfadparameter {productId}, der als Camel-Header weitergereicht wird 2.Transformation der Request Payload von JSON nach XML (Camel-XML-JSON-Datenformat) 3.Validierung des Inputs per XML-Schema (CamelValidator-Komponente) 4.Normalisierung des Aufrufs in unser CDM (CamelXSLT-Komponente) 5.Senden der Nachricht an unser Businessmodul via JMS (Camel-JMS-Komponente) 6.Übersetzung der Antwort des Businessmoduls in das spezifische Datenmodell unseres Channel-Systems (Camel-XSLT-Komponente) 7.Transformation der Antwort von XML nach JSON, damit sie im Browser oder der App gut ausgewertet werden kann from("restlet:http://0.0.0.0:9090/products/{productid}/ stock?method=GET") // (1) .unmarshal().xmljson() Beispiel 1: Lagerinformationen aus föderierten Warenwirtschaftssystemen Unser Businessmodul holt sich dann den Aufruf ab, der in Schritt 5 gesendet wurde und wendet eine Orchestrierung an, um die Daten aus drei verschiedenen Quellen einzusammeln (Listing 2). Und das geschieht dabei: 1. Wir nutzen einen Camel-JMS-Endpunkt, um die Nachricht aus der JMS Queue abzuholen. Hier im Beispiel verwenden wir einen trivialen Error Handler, um alle Fehler abzufangen. Tritt ein Fehler auf, so wird dieser 1:1 weitergeleitet. 2. Wir senden die Nachricht parallel an drei verschiedene JMS Queues und führen die individuellen Antworten in eine einzige aggregierte Antwort zusammen (Multicast Pattern). 3. (4), (5), (6) sind die Endpunkte, wo wir die Information einsammeln. Wie in obigem Diagramm unserer Lösungsarchitektur gezeigt, sind die Warenwirtschaftssysteme über verschiedene, regionale Instanzen von ServiceMix mit dem zentralen ESB verbunden. Deshalb routen die ActiveMQ Broker in unserer föderierten SOA die Nachrichten intelligent durch das Broker-Netzwerk zum Consumer. Das ist kein Versuchs-und-Irrtum-Routing, sondern ein sorgfältig durchdachter Routing-Plan, der in Betracht zieht, wo sich die Konsumenten im Netzwerk tatsächlich befinden. Innerhalb unseres Architekturmodells sind es die Back­end-Module, die letztlich mit den Backend-Systemen interagieren. Wir nutzen hier drei Stück: ein Modul www.JAXenter.de ServiceMix Web Abb. 4: Bestellprozess pro Warenwirtschaftssystem, wobei jedes System mit einer anderen Technologie kommuniziert, weil die Warenwirtschaftssysteme unterschiedlich sind. Das Back­ end-Modul übersetzt also vom CDM in die Sprache des Backend-Systems und führt den Aufruf durch. Das deutsche Warenwirtschaftssystem kommuniziert via SOAP 1.2 und HTTPS. Wir verwenden deshalb die Camel-CXF-Komponente (Listing 3). Der Backend-Service für das Warenwirtschaftssystem in Singapur ist eine Datenbank. Wir greifen über eine JDBC-Verbindung zu und nutzen hierfür ein Prepared Statement, dessen Parameter über Camel-Header gesetzt werden. Den passenden Header bestücken wir per XPath (Listing 4). Zu guter Letzt holen wir die Informationen aus dem Backend-Service für das Warenwirtschaftssystem in Atlanta, das ein proprietäres TCP-Kommunikationsprotokoll nutzt. Deshalb verwenden wir hier die CamelNetty-Komponente (Listing 5). Jedes dieser Backend-Systeme normalisiert die Antwort des Warenwirtschaftssystems mit einer XSLT-Transformation zurück in unser kanonisches Datenmodell. Mit der sich daraus ergebenden Nachricht kümmert sich Camel dann um eine automatische Antwort an den Aufrufenden. Beispiel 2: Aufgabe einer Bestellung und Koordination der Systeme um einen Geschäftsprozess Wenn ein Kunde eine Bestellung aufgibt, wird der folgende Geschäftsprozess ausgeführt: •Für jeden Artikel prüfen wir die Verfügbarkeit, da sich diese geändert haben könnte. Wir verwenden die obige Lösung wieder und ernten somit die Früchte unserer sauberen Architektur. •Wir rufen den E-Commerce-Payment-Gateway auf, um die Zahlung zu bearbeiten. www.JAXenter.de •War dies erfolgreich, wird der Auftrag versendet. •Als Nächstes wird das zentrale CRM über die Auftrags-ID, die Versanddetails und den Inhalt des Auftrags informiert. Der Geschäftsprozess ist in Abbildung 4 beschrieben. Aus Platzgründen zeigen wir hier nur ein Codebeispiel für das Businessmodul, das den Geschäftsprozess koordiniert. Freilich würde die Gesamtlösung auch die Frontend-Services und die Backend-Services umfassen. Listing 4 from("jms:organization.processes.stock.apac.singapore.availability") .setHeader("productid", xpath("/cdm:Request/cdm:Product/cdm:Id") .namespace("cdm", "http://orga.com/schemas/cdm")) .to("sql:SELECT available from STOCK where PID = :#productid") .to("xslt:stock-availability-apac-singapore-response.xsl"); Listing 5 from("jms:organization.processes.stock.us.atlanta.availability") .to("xslt:stock-availability-us-atlanta-request.xsl") .to("netty:tcp://inv-stock-atl.orga.com:4567?textline=true") .to("xslt:stock-availability-us-atlanta-response.xsl"); javamagazin 7 | 2014 95 Web ServiceMix Der Businessservice ist eine schlanke Orchestrierung, die mit Camel-Routing-Logik implementiert ist. Er kommuniziert mit den Frontend- und Backend-Modulen einzig über JMS Endpoints und nutzt dabei immer das CDM. Da dieses auch Bedingungen an die Datenqualität erhält, muss sich das Businessmodul nicht mehr mit Validierungen oder Transformationen plagen, sondern kann sich auf seine eigentliche Aufgabe konzentrieren (Listing 6). Wir nutzen das Splitter Pattern, um die Bestellung in ihre einzelnen Positionen zu zerlegen, die wir individuell und parallel weiterverarbeiten. Die Ergebnisse werden von der konfigurierten Aggregationsstrategie zusammengeführt und dann weiterverarbeitet. Wir nutzen das Choice Pattern, um nun eine Entscheidung zu fällen. Falls wir nicht ausreichend Lagervorräte für einen Artikel haben, verursachen wir einen qualifizierten Geschäftsfehler und brechen den Prozess ab; andernfalls fahren wir fort. Wir benutzen einen Camel Direct Endpoint für eine bessere Codeorganisation, um die Route in kleinere Teile aufzubrechen. Wir rufen das Bezahlsystem auf; falls die Zahlung fehlschlägt, weisen wir eine weitere Business Exception an und brechen den Prozess ab (6). Wenn alles gut geht, lösen wir den Versandvorgang aus, indem wir eine JMS Message an den entsprechenden Geschäftsprozess senden. Wir zeichnen die Bestellung Listing 6 Fazit Systemintegrationen werden ständig wichtiger und häufiger. ServiceMix unterstützt viele Protokolle und Formate out of the box und ist zudem sehr robust und schlank. Damit ist diese Technologie ein geeigneter Kandidat, diesen Herausforderungen zu begegnen. ServiceMix steht zudem unter der Apache-Lizenz und ist somit geschäftsfreundlich. Bei Bedarf ist ein EnterpriseSupport erhältlich. Eher schwach ist die verfügbare ServiceMix-Dokumentation. Es gibt zwar einige Tutorials, aber diese decken nur einen kleinen Teil des Möglichen ab. Die Community ist jedoch sehr aktiv und Anfragen an das Forum werden zügig beantwortet. Die anderen ApacheTechnologien sind besser dokumentiert. Wir durften ServiceMix bereits in verschiedenen Projekten einsetzen. Oft kommt die Lösung im Kontext eines bestimmten Systems zum Einsatz, zumeist CMS oder PIM, um die konkreten Integrationsanforderungen dieses Systems zu lösen. In einigen Fällen erfüllt Ser­vice­ Mix als einzige Integrationsschicht im Unternehmen seine Pflicht. In beiden Fällen aber zuverlässig und mit geringem Ressourcenbedarf. Daniel Takai ist Technologiemanager bei der Unic AG in Bern. Er ist dort für die Entwicklungsprozesse, Technologieentwicklung und verteilte Softwarearchitekturen verantwortlich. from("jms:organization.processes.order.create") .split(xpath("/order/item")).parallelProcessing() im CRM-System auf. Doch machen wir dies asynchron, da wir den Kunden nicht länger warten lassen wollen. Das ist der Grund, warum diese Aktion mit dem WireTap Pattern ausgeführt wird. // (1) Raúl Kripalani arbeitet als Integrationsarchitekt für die Unic AG in Bern. Er ist spezialisiert auf Open-Source-Integration und Messag­ ing, SOA, Large-scale Java Enterprise Systems und Big Data. Er hat über fünfzig Kunden und Projekte weltweit beraten und ist PMCMitglied sowie Committer bei Apache Camel und anderen OpenSource-Communitys. .aggregationStrategy(new MergeItemAvailabilitiesStrategy()) .to("xslt:order-create-item-check-availability.xsl") .to("jms:organization.processes.stock.availability") .end() .choice() // (2) Matthias Rothe arbeitet bei der Unic GmbH in München als Senior Application Engineer und Technical Project Lead auf umfangreichen Integrationsprojekten für einen namhaften deutschen Fahr­zeug­hersteller. Daneben schreibt und veröffentlicht er OpenSource-Software, schreibt Artikel und hält Vorträge zu Technik- und Projektmanagementthemen. .when(xpath("/order/item[@available = 0]")) .throwException(new OutOfStockException()) // (3) .otherwise() .to("direct:payment.process") // (4) .to("jms:organization.processes.shipping.start") // (5) .wireTap("jms:organization.processes.crm.recordOrder") // (6) Links & Literatur [1] http://servicemix.apache.org/ .end(); 96 javamagazin 7 | 2014 [2] http://activemq.apache.org/ [3] https://camel.apache.org/ [4] http://www.eaipatterns.com/ [5] http://cxf.apache.org/ [6] https://karaf.apache.org/ www.JAXenter.de 3 JAVA n! e r e i n n o b a t z Jet gazin.de www.javama Jetzt 3 Top-Vorteile sichern! 1 lle Printausgaben frei A Haus erhalten Intellibook-ID kostenlos ­anfordern (www.intellibook.de) 2 Abo-Nr. (aus Rechnung oder Auftrags­bestätigung) eingeben 3 Zugriff auf das ­komplette ­PDF-Archiv mit der Intellibook-ID www.javamagazin.de