form4 GmbH & Co.KG - Innovative Softwareentwicklung

Marshalling mit smooks – Erweiterung der javabeans-Cartridge
SuchenSitemap

Marshalling mit smooks – Erweiterung der javabeans-Cartridge

Oliver Meimberg, 27.02.2007

Für mein aktuellen JBoss-ESB-Projekt habe ich mir in den Kopf gesetzt eine eingehende XML-Datei in Entity-Beans zu transformieren. JBoss-ESB bietet das von Hause aus über die Integration des Smooks-Frameworks.

Kurz zur Erklärung: Smooks ist ein Framework zur generischen Verarbeitung von XML-Dateien, bzw. XML-Fragmenten. Die Verarbeitung ist einfach: In einer Mapping-datei wird für jeden XML-Pfad ein Handler definiert, der über das Visitor-Pattern irgendetwas ausführt. So kann für ein Element (oder einen Teilbaum) z.B. ein XSLT ausgeführt werden oder auch völlig individueller Java-Codeausgeführt werden.

Hier ein Beispiel aus der Mapping-Datei (smooks-res.xml):

useragent="from-type:text/xml:fullfillorder and
from:dvdstore:orderdispatchservice"
path="org.milyn.javabean.ProcessingPhaseBeanPopulator" >
ORDER
org.jboss.soa.esb.dvdstore.Order
true

useragent="from-type:text/xml:fullfillorder and
from:dvdstore:orderdispatchservice"
path="org.milyn.javabean.ProcessingPhaseBeanPopulator" >
order
orderId

In diesem Beispiel wird für jedes Element ORDER der ProcessingPhaseBeanPopulator besucht. Der ProcessingPhaseBeanPopulator wird vom smooks-Framework über eine sog. Cartridge mitgeliefert. Er hat die Aufgabe, aus dem element ORDER ein POJO, also eine Java-Klasse zu generieren. Attribute können zu Java-Properties gemappt werden und für Unterelemente können ebenfalls Visitors definiert werden, die beispielsweise wiederum Properties setzen. Sowie sogut. Das Problem ist bloss, dass bei echten Business-Daten die Datenstrukturen nicht so trivial sind, wie in dem vom ESB mitgelieferten Sample quickstarts/transformXML2POJO. Habe ich ein ORDER-Element mit 30 oder mehr Unterelementen, die die Properties der ORDER definieren, wird mein smooks-mappingfile recht umfangreich und vor allem sehr wartungsfeindlich.

Schön wäre eine Smooks-Cartridge, die die Unterlemente eines XML-Elements automatisch auf die Properties (genaugesagt auf die Setter) meines POJO Mappt. So kann mit minimaler Konfiguration eine ganze Reihe von umfangreichen XML-Strukturen auf POJOs transformiert werden, ohne tonnenweise quasi-redundanten Konfigurationscode zu erzeugen.

Hierzu habe ich die von smooks mitgelieferte javabeans-cartridge etwas modifiziert, so dass folgende Konfiguration möglich ist:

useragent="from-type:text/xml:fullfillorder and
from:dvdstore:orderdispatchservice"
path="org.milyn.javabean.MyProcessingPhaseBeanPopulator" >
order
org.jboss.soa.esb.dvdstore.Order
true

Damit das funktioniert, habe ich in der Klasse ProcessingPhaseBeanPopulator etwas Code ergänzt.

Zunächst das Einlesen der Konfiguration, die nun den Parameter attributesFromChildren unterstützen soll:

public void setConfiguration(SmooksResourceConfiguration config) {
// ... existing code
// START Added by om, form4
attributesFromChildren =
config.getBoolParameter("attributesFromChildren", false);
// END Added by om, form4
}

Und das Processing im eigentlichen Visitor:

public void visit(Element element, ContainerRequest request) {
Object bean = getBean(request);
// START Added by om, form4
if (attributesFromChildren) {
NodeList children = element.getElementsByTagName("*");
for (int i = 0; i < bean.getClass().getMethods().length; i++) {
Method method = bean.getClass().getMethods()[i];
if (method.getName().startsWith("set")) {
String attr = method.getName().replaceAll("^set", "").toLowerCase();
for (int j = 0; j < children.getLength(); j++) {
Element child = (Element) children.item(j);
if (attr.equalsIgnoreCase(child.getNodeName())) {
try {
String val = DomUtils.getAllText(child, false);
method.invoke(bean, new Object[] { val });
} catch (Exception e) {
logger.error(e); // etwas ignorant...
}
break;
}
}
}
}
}
// END Added by om, form4
// ... go on with original code ...
}