Samstag, 11. Februar 2012


Artikel

Januar 2009 | Artikel

Open-Source-Framework Smooks: Transformers Fortsetzung, Teil 3

Teil 1   Teil 2   Teil 3   

Splitting und Routing
Neben der Transformierung von Daten kann Smooks auch für das Splitting und Routen von Daten eingesetzt werden. Sowohl der Splitter als auch der Router sind bekannte Vertreter der Enterprise Integration Patterns. Was fängt Smooks damit an? Um große Datenmengen in einer akzeptablen Performance verarbeiten zu können, macht es Sinn, die gesamte Datenmenge in kleine unabhängige Datenpakete aufzuteilen und diese an eine oder mehrere Destinationen zu schicken. In der Praxis gibt es genügend Beispiele für den Fall, dass die einzelnen Datenpakete an unterschiedliche Destinationen geroutet werden müssen, etwa bei der Trennung von Kopf- und Detaildaten. Aktuell unterstützt Smooks das Routing von Daten an Dateien, Datenbanken und JMS. Transformierung, Splitting oder Routing sind typische Schlagworte, die man mit einem ESB in Verbindung bringt. Das ist der ideale Ausgangspunkt, um die Integration von Smooks und Mule zu betrachten.

Smooks und Mule - ein gutes Paar?
Anfangs wurde erwähnt, dass die Transformierung von Daten eine der Kernaufgaben eines ESB ist. Oft kümmert sich ein Konnektor selbst um die Transformierung der Daten. Der JMS-Konnektor von Mule bietet für JMS einfache Transformatoren wie JMSToObject, JMSToString. Was soll man aber machen, wenn ein EDIFACT oder eine CSV als Inputstream verarbeitet werden muss? Es gibt durchaus Anwendungsfälle, bei denen ein ESB-Service nur die reine Transformierung übernehmen soll (zum Beispiel EDI2Java, XML2Java , CSV2Java oder auch Java2Java).

Warum nicht Smooks und Mule vereinen und von den Stärken profitieren, die Smooks bietet? Das Projekt Smooks for Mule auf MuleForge erlaubt es, Smooks in Mule Anwendungen zu integrieren. Es ist eines der wenigen Module, das bereits die Version 2 von Mule unterstützt.

Smooks kann zum einen als Transformer in Mule eingebunden werden, d.h. die Transformierung der Daten wird über Smooks erledigt, wie wir es zuvor bereits demonstriert haben. Zum Beispiel können wir die CSV-Datei über einen File-Connector einlesen und die Daten anschließend über unseren CSV-Transformer laufen lassen. Die Transformer-Konfiguration geschieht in Smooks (Listing 1). Danach können wir den Transformer in Mule definieren (siehe Listing 6), welcher über das Konfigurationsfile entsprechend eingestellt wurde. Zusätzlich definieren wir noch den resultType, in unserem Fall ein String. Es könnte aber auch ein Java-Objekt sein wie bei unserem EDIFACT-Beispiel. In diesem Fall müssten wir zusätzlich noch das Attribut javaResultBeanId = "order" angeben, damit wir die richtige Objektinstanz aus dem BeanContext von Smooks bekommen.

Der Transformer kann anschließend wie gehabt in Mule bei Inbound/Outbound Endpoints verwendet werden.

Listing 6: Transformierung mit Smooks in Mule
  1. <smooks:transformer name="MyCSVTransformer"
  2. configFile="/transforms/csv-smooks-config.xml"
  3. resultType="STRING"/>
  4. <service name="TransformService">
  5. <inbound>
  6. <file:inbound-endpoint
  7. path="./data/in"
  8. pollingFrequency="1000"
  9. transformer-refs=”MyCSVTransformer”
  10. <file:filename-wildcard-filter pattern="*.csv"/>
  11. </file:inbound-endpoint>
  12. </inbound>


Neben dem Transformer bietet das Smooks for Mule-Modul noch einen Router an, welcher mit der Routerlogik von Smooks konfiguriert werden kann. Für diesen Zweck wird ein Outbound Router (= MuleDispatcher) zur Verfügung gestellt, welcher mithilfe einer Smooks-Konfiguration eingestellt werden kann.

In Listing 7 ist die Smooks-Konfiguration für ein einfaches Beispiel dargestellt, bei dem ein XML-Dokument mit Artikelpositionen verarbeitet wird und alle Artikel-IDs in eine HashMap gespeichert werden. Die HashMap wird in Smooks als Bean zur Verfügung gestellt. Der Mule Dispatcher kann nun die HashMap an den definierten Endpoint (stockSystem) schicken. Für das Erstellen von Java-Objekten in Smooks ist die Java Cartridge zuständig. Schließlich kann mit folgender Mule-Anweisung der Router im Outbound-Bereich definiert werden:

  1. <smooks:router configFile="routing/smooks-config.xml">


An welchen Endpoint die Nachricht weitergeleitet wird, bestimmt der Mule Dispatcher von Smooks, welcher in Listing 7 definiert wurde.

Listing 7: Routing Konfiguration in Smooks
  1. <resource-config selector="article">
  2. <resource>org.milyn.smooks.mule.MuleDispatcher</resource>
  3. <param name="endpointName">stockSystem</param>
  4. <param name="beanId">a</param>
  5. </resource-config>
  6. <resource-config selector="article">
  7. <resource>org.milyn.javabean.BeanPopulator</resource>
  8. <param name="beanClass">java.util.HashMap</param>
  9. <param name="beanId">a</param>
  10. <param name="bindings">
  11. <binding property="id" selector="a @id" />
  12. <binding property="value" selector="a"/>
  13. </param>
  14. </resource-config>


Fazit
Smooks ist eine interessante Technologie im Bereich der Datenintegration und hat auch eine akzeptable Performance bei großen Datenmengen. Es muss nicht immer ein XML-Dokument sein, wenn Daten ausgetauscht werden sollen. Ein Framework wie Smooks kann auch für einen ESB wie JBoss ESB oder Mule sinnvoll als Transformations-Engine eingesetzt werden. In der Smooks- Distribution befinden sich zahlreiche Beispiele, welche den Einstieg in diese Technologie erleichtern. Man kann sagen, dass Optimus Prime und seine Transformer-Kollegen gute Arbeit leisten.



Markus Demolsky ist Software-Engineer und Berater bei der Soreco Group. Seine Schwerpunkte liegen bei Softwarearchitektur, Workflow-Management-Systemen und Open-Source-Technologien im Java-EE-Umfeld. Er ist Committer bei MuleForge und arbeitet aktuell mit Dr. Alexander Schatten an einem Buch zum Thema "Software Engineering - Best Practices".

  1. Smooks
  2. Mulesource
  3. Muleforge
  4. Smooks for Mule

Teil 1   Teil 2   Teil 3   

Kommentare

Gravatar Tom Fennelly 29.01.2009
um 10:52 Uhr
Hi Markus. Excuse me for not being able to respond in German, but thank you for writing an article on Smooks.

If I could, I'd like to point out a small, but very important, inaccuracy. It's in the following statement:

"Hier ist aber zu erwähnen, dass Smooks jedes Format intern in ein XML-Dokument transformiert und auf dieser Basis dann fortfährt. Wenn also EDIFACT auf Java- Objekte abgebildet werden soll, dann wird auch EDIFACT zuerst in ein XML-Dokument transformiert und dieses dann in Java-Objekte überführt."

This is not 100% accurate and may lead people to believe that Smooks can only work by holding the complete message in memory. This was the case with earlier versions of Smooks (earlier versions only supported DOM internally), but is not the case since v1.0.

Smooks v1.0 added a SAX based filter (we will probably be adding StAX in the future). From a pure usability perspective, this typically makes no difference (just a simple config parameter) to the end user/developer because all Smooks components support working under both the DOM and SAX filters e.g. Java Binding, Templating, Scripting etc work exactly the same under both filters. What it does mean is however that Smooks can process a message (of many different types) as a stream of events (i.e. not a big internal document), allowing you to use Smooks to process huge gigabyte sized message - transforming, splitting, routing etc.

Once again, thanks for taking the time to write a very interesting article on Smooks :)
#zitieren
Gravatar Markus Demolsky 29.01.2009
um 11:49 Uhr
Hi Tom,

I am appreciate to get positive response about the article and thank your for the clarification. If Smooks holds the hole object graph in memory the processing of gigabyte sized messages will not be working with that performance as Smooks does it yet.

Thank you again for your response
#zitieren
Gravatar Maurice Zeijen 29.01.2009
um 12:04 Uhr
Hallo Markus,

Vielleicht verstehst du Tom verkehrt. Er meint das den Objektbaum NICHT ganz im Speicher gehalten wird. Wenn SAX in Smooks benutzt wird, in Kombination mit der Javabean Cartridge dann wird nur ein klein teil der Objektbaum im speicher gehalten. Beispielweise wenn du ein Dokument hast mit ein Liste von Bestellungen und du möchtest jeder Bestellung separat nach einen Endpoint routen dann wird nur die Objektbaum von ein Bestellung im Speicher gehalten. Wenn Smooks anfangt mit der nächst Bestellung dann wird der vorherige Bestellung ersetzt.

Mit freundliche grüße,
Maurice Zeijen
#zitieren
Gravatar Markus Demolsky 29.01.2009
um 12:44 Uhr
Hi,

dass war mir nach Toms Erklärung klar, dass nur ein Teil im Speicher gehalten wird und nicht der ganze. Aber dank deinen Beispiel ist jetzt alles 100%ig klar.

Danke & Schönen Tag
Markus
#zitieren
Gravatar Steff 12.04.2009
um 20:09 Uhr
Hallo,
was mich interessieren würde:
Was macht Smooks "besser" als Apache Cocoon? Beide verwenden doch eine ähnliche interne Logik? Oder anders gesagt, warum sollte man anstatt Cocoon, welches doch schon ziemlich ausgereift ist, das "Risiko" eingehen und Smooks verwenden?

Danke für die Antwort.

Gruß
Steff
#zitieren