Java Mag - Magazin

Werbung
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
Herunterladen