Content Handlers are the cornerstone of the Smooks component model. The following Content Handler types are currently in existance:
- Stream Readers: Smooks supports filtering of both XML and non-XML data because it allows you to configure a "Stream Reader" for each filter process. If no reader is configured, it defaults to XML. So, the Stream Reader resource is responsible for generating a stream of SAX events from a hierarchical data stream (e.g. XML, CSV, EDI etc.). This stream of SAX events can then be processed by XML Element Visitors (via Smooks). More on this later.
- Element Visitors: After Smooks hooks a Stream Parser to the data Stream, it starts receiving a stream of SAX events i.e. "startElement", "endElement" etc. These events are then used by Smooks to select an "ElementVisitor" implementation, which process the event in some way. This is the primary extension point in Smooks, as well as being the mechanism though which Smooks supports a fragment based processing model. See the list of Smooks Cartridges for examples of ElementVisitor implementations already available with Smooks. More on this later.
- Element Serializers: DOM based processing supports implementation of DOM Element "Serialization Units", allowing you to implement custom serialization at a fragment level.
Configuration
All Content Handler types share the same configuration model. This is based on the SmooksResourceConfiguration class (see Smooks Resources). Version 1.0 of Smooks also introduces an Annotation driven approach to Content Handler configuration.
SmooksResourceConfiguration
Content Handlers can receive their configuration by implementing the setConfiguration method:
public void setConfiguration(SmooksResourceConfiguration resourceConfig) throws SmooksConfigurationException;
Annotations
Version 1.0 of Smooks introduces support for annotation driven Content Handler configuration. This means that as well as supporting the old "setConfiguration(SmooksResourceConfiguration resourceConfig)" style Content Handler configuration, Smooks v1.0 also supports configuration injection via annotations. Two annotations are supported for this purpose:
@Config for injecting the SmooksResourceConfiguration directly onto the Content Handler e.g.
public class MyVisitor implements SAXElementVisitor {
@Config
private SmooksResourceConfiguration config;
... etc...
}
@ConfigParam for injecting specific <param> values from the SmooksResourceConfiguration directly onto the Content Handler e.g.
public class MyVisitor implements SAXElementVisitor {
/**
* Inject the "encoding" <param> from the SmooksResourceConfiguration. Do some automatic type conversion on the value (to Charset). Also default the value to "UTF-8".
*/
@ConfigParam(defaultVal = "UTF-8")
private Charset encoding;
/**
* Inject the "action" <param> from the SmooksResourceConfiguration. Do some defaulting and validation on the value.
*/
@ConfigParam(defaultVal = "replace", choice = {"replace", "addto", "insertbefore", "insertafter"})
private String action;
... etc...
}
Annotation based <param> injection has a number of advantages:
- Cleaner code.
- Automatic type conversion.
- Automatic validation.
- Automatic "choice" support.
Lifecycle
Content Handler lifecycle is supported through the method annotations @Initialize and @Uninitialize.
Content Handler methods annotated with @Initialize will be automatically called by Smooks after handler creation and configuration. Content Handler methods annotated with @Uninitialize will be automatically called on VM shutdown (via a shutdown hook), or after calling Smooks.close() (useful where multiple Smooks instances are running in the same VM, with container managed lifecycle).
Stream Readers
Smooks relies on a "Stream Reader" for generating a stream of SAX events from the Source message data stream. A Stream Reader is a class that implements the XMLReader interface (or the SmooksXMLReader interface).By default, Smooks uses the default XMLReader (XMLReaderFactory.createXMLReader()), but can be easily configured to read non-XML data Sources by configuring a specialized XMLReader:
<?xml version="1.0"?>
<smooks-resource-list xmlns="http://www.milyn.org/xsd/smooks-1.1.xsd">
<reader class="com.acme.ZZZZReader" />
<!--
Other Smooks resources, e.g. <jb:bindings> configs for
binding data from the ZZZZ data stream into Java Objects....
-->
</smooks-resource-list>
The reader can also be configured with a set of handlers, features and parameters. Here is a full example configuration.
<reader class="com.acme.ZZZZReader">
<handlers>
<handler class="com.X" />
<handler class="com.Y" />
</handlers>
<features>
<setOn feature="http://a" />
<setOn feature="http://b" />
<setOff feature="http://c" />
<setOff feature="http://d" />
</features>
<params>
<param name="param1">val1</param>
<param name="param2">val2</param>
</params>
</reader>
A number of non-XML Readers are available with Smooks out of the box:
Any of the above XMLReaders can be configured as outlined above, but some of them have a specialized configuration namespaces that simplify configuration.
Example - CSVReader Configuration
<?xml version="1.0"?>
<smooks-resource-list xmlns="http://www.milyn.org/xsd/smooks-1.1.xsd" xmlns:csv="http://www.milyn.org/xsd/smooks/csv-1.1.xsd">
<!--
Configure the CSV to parse the message into a stream of SAX events.
-->
<csv:reader fields="firstname,lastname,gender,age,country" separator="|" quote="'" skipLines="1" />
</smooks-resource-list>
Example - SmooksEDIReader Configuration
<?xml version="1.0"?>
<smooks-resource-list xmlns="http://www.milyn.org/xsd/smooks-1.1.xsd" xmlns:edi="http://www.milyn.org/xsd/smooks/edi-1.1.xsd">
<edi:reader mappingModel="/org/milyn/smooks/edi/edi-to-xml-mapping.xml" />
</smooks-resource-list>
Example - JSONReader Configurations
<?xml version="1.0"?>
<smooks-resource-list xmlns="http://www.milyn.org/xsd/smooks-1.1.xsd" xmlns:json="http://www.milyn.org/xsd/smooks/json-1.1.xsd">
<!--
Basic configuration...
-->
<json:reader/>
</smooks-resource-list>
<?xml version="1.0"?>
<smooks-resource-list xmlns="http://www.milyn.org/xsd/smooks-1.1.xsd" xmlns:json="http://www.milyn.org/xsd/smooks/json-1.1.xsd">
<!--
Key replacement...
-->
<json:reader>
<json:keyMap>
<json:key from="some key">someKey</json:key>
<json:key from="some&key" to="someAndKey" />
</json:keyMap>
</json:reader>
</smooks-resource-list>
<?xml version="1.0"?>
<smooks-resource-list xmlns="http://www.milyn.org/xsd/smooks-1.1.xsd" xmlns:json="http://www.milyn.org/xsd/smooks/json-1.1.xsd">
<!--
Other configurations...
-->
<json:reader keyWhitspaceReplacement="_" keyPrefixOnNumeric="n" illegalElementNameCharReplacement="." nullValueReplacement="##NULL##" />
</smooks-resource-list>
To set features on the default reader, simply omit the class name from the configuration:
<reader>
<features>
<setOn feature="http://a" />
<setOn feature="http://b" />
<setOff feature="http://c" />
<setOff feature="http://d" />
</features>
</reader>
DOM Element Vistors & Serializers
DOMElementVisitors and SerializationUnits are Content Handler specializations that are applied during the DOM Filtering process.
DOMElementVisitors implement a very simple 2 method interface:
public interface DOMElementVisitor extends ContentHandler {
public abstract void visitBefore(Element element, ExecutionContext executionContext) throws SmooksException;
public abstract void visitAfter(Element element, ExecutionContext executionContext) throws SmooksException;
}
See the DOM Filtering section for details on when the SmooksDOMFilter calls the visitiBefore and visitAfter methods.
Points to note:
|
SAX Element Vistors
SAXElementVisitors are Content Handler specializations that are applied during the SAX Filtering process.
SAXElementVisitors implement a very simple 4 method interface:
public interface SAXElementVisitor extends ContentHandler {
public abstract void visitBefore(SAXElement element, ExecutionContext executionContext) throws SmooksException, IOException;
public abstract void onChildText(SAXElement element, SAXText childText, ExecutionContext executionContext) throws SmooksException, IOException;
public abstract void onChildElement(SAXElement element, SAXElement childElement, ExecutionContext executionContext) throws SmooksException, IOException;
public abstract void visitAfter(SAXElement element, ExecutionContext executionContext) throws SmooksException, IOException;
}
See the SAX Filtering section for details on when the SmooksSAXFilter calls the visitor methods.
Smooks Cartridges
The basic functionality of Smooks Core can be extended through the creation of what we call a "Smooks Cartridge". A Cartridge is simply a Java archive (jar) containing reusable Content Handlers (Visitor Logic). A Smooks Cartridge should provide "ready to use" support for a specific type of XML analysis or transformation.Name |
DOM Support |
SAX Support |
Description |
|---|---|---|---|
|
|
Enables population of Java Object Model from data embedded in |
|
|
|
Enables fragment-level templating using different templating solutions |
|
|
|
Enables routing of message fragments (including populated object models) |
|
|
|
Enables fragment-level Transformation/Analysis using different |
|
|
|
Smooks Cartridge that converts an EDI message data stream |
|
|
|
Smooks Cartridge that converts a Comma Separated Value (CSV) |
|
JSON |
|
|
Smooks Cartridge that converts a JSON formatted |
|
|
Contains miscellaneous resources for performing common analysis/transformation tasks |
|
|
|
Plugs Smooks into the J2EE Servlet Container. This allows Smooks to be |
|
|
|
Makes Cascading Style Sheet (CSS) information easily available to web content |
|
Calc |
|
|
Smooks Cartridge that can do simple calculation tasks. |