3 min read

Second Milestone Release of Smooks 2

Smooks logo

We’re delighted to announce the second milestone release of Smooks 2. The second milestone is geared towards simplifying Smook’s API along with a few goodies. Here’s a rundown of the new notable features:

SAX NG

Earlier versions of Smooks could have visitors applying operations on either DOM nodes or SAX events. To ensure interoperability, one would implement a visitor supporting both DOM node and SAX event processing which meant implementing two different application APIs:

The above broadly translated into two different execution paths, with all the baggage it entailed. Smooks 2.0.0-M2 unifies the DOM and SAX visitor APIs without sacrificing convenience or performance. The new SAX NG filter drops the API distinction between DOM and SAX. Instead, it streams SAX events as partial DOM elements to SAX NG visitors:

Traditional DOM trees are still supported with the help of the max.node.depth global config parameter. The max.node.depth knob instructs the SAX NG filter to build DOM trees for the targeted elements such that the tree’s maximum depth is equal to the max.node.depth value.

It’s all transparent from a visitor’s perspective. A visitor only sees an element but with the caveat that an element may have child nodes when max.node.depth is greater than 1.

The latest cartridge releases have been migrated to SAX NG. We recommend future visitor implementations extend the org.smooks.delivery.sax.ng.SaxNgVisitor interface given that it supersedes the org.smooks.delivery.dom.DOMVisitor and org.smooks.delivery.sax.SAXVisitor interfaces.

JSR Annotations

Smooks-specific annotations were dropped in favour of JSR annotations. Smooks 1 resources would have their dependencies injected like so:

Smooks 2.0.0-M2 does away with all these adhoc annotations and provides a single @Inject for this purpose:

Additionally, the @Initialize and @Uninitialize lifecycle annotations were replaced with the standard @PostConstruct and @PreDestroy annotations, respectively.

EDIFACT Java Bindings

By popular demand, we’re generating and distributing the Java bindings for the EDIFACT schemas starting from the M2 release of the EDIFACT cartridge. The bindings are available from Maven Central at the coordinates: org.smooks.cartridges.edi:[message version/release]-edifact-binding:2.0.0-M2. For instance, the D03B EDIFACT binding dependency can be declared in your POM with:

Visit the java-to-edifact project in the examples catalogue to see how Smooks turns an interchange Java bean instance into EDIFACT.

Selector Namespace Prefixes

In Smooks 1, you would bind selector namespace prefixes as follows:

This is no longer required. As of 2.0.0-M2, you can now bind a selector namespace prefix just like any other XML namespace prefix:

Furthermore, the new smooks-2.0.xsd removes the default-selector-namespace and selector-namespace XML attributes in favour of declaring namespaces within the standard xmlns attribute from the smooks-resource-list element. smooks-2.0.xsd also removes the default-selector attribute from the smooks-resource-list element: some may not like this change but we think a config is easier to comprehend when selectors are explicit.

Visitor Memento

Visitor mementos are a convenient way to store, track, and retrieve a visitor’s state from the execution context. In the past, given that visitors are not thread-safe, the general approach to holding onto state between visits was to stash the state inside the execution context and retrieve it later on. This led to boilerplate code because oftentimes the state to be retrieved depended on the fragment being processed and the visitor instance. Visitor mementos were introduced in order to eliminate this boilerplate code.

A great example showcasing mementos is accumulating character data in a visitor while SAX events are streamed:

getMementoCareTaker() is a new addition to the ExecutionContext interface. A MementoCareTaker manages mementos on behalf of visitors. In line 19, the MementoCareTaker stashes each chunk of read character data. It then goes on to restore the collected character data in the visitor’s visitAfter(Element, ExecutionContext) method as shown in lines 29-30. Observe that the element and visitor objects serve as keys for saving as well as restoring the memento’s state. Consult the Javadocs to take a deep dive into mementos.

comments powered by Disqus