11.12. Huge Message Processing
Huge Message Processing
In the example, a huge order message needs to be sent while routing the individual order item details to file. The split messages contain data from the order header and root elements:
<?xml version="1.0"?> <smooks-resource-list xmlns="http://www.milyn.org/xsd/smooks-1.1.xsd" xmlns:core="http://www.milyn.org/xsd/smooks/smooks-core-1.3.xsd" xmlns:jb="http://www.milyn.org/xsd/smooks/javabean-1.4.xsd" xmlns:file="http://www.milyn.org/xsd/smooks/file-routing-1.1.xsd" xmlns:ftl="http://www.milyn.org/xsd/smooks/freemarker-1.1.xsd"> <!-- Filter the message using the SAX Filter (i.e. not DOM, so no intermediate DOM, so we can process huge messages... --> <core:filterSettings type="SAX" /> <!-- Extract and decode data from the message. Used in the freemarker template (below). Note that we could also use a NodeModel here... --> (1) <jb:bean beanId="order" class="java.util.Hashtable" createOnElement="order"> <jb:value property="orderId" decoder="Integer" data="order/@id"/> <jb:value property="customerNumber" decoder="Long" data="header/customer/@number"/> <jb:value property="customerName" data="header/customer"/> <jb:wiring property="orderItem" beanIdRef="orderItem"/> </jb:bean> (2) <jb:bean beanId="orderItem" class="java.util.Hashtable" createOnElement="order-item"> <jb:value property="itemId" decoder="Integer" data="order-item/@id"/> <jb:value property="productId" decoder="Long" data="order-item/product"/> <jb:value property="quantity" decoder="Integer" data="order-item/quantity"/> <jb:value property="price" decoder="Double" data="order-item/price"/> </jb:bean> <!-- Create/open a file output stream. This is writen to by the freemarker template (below).. --> (3) <file:outputStream openOnElement="order-item" resourceName="orderItemSplitStream"> <file:fileNamePattern>order-${order.orderId}-${order.orderItem.itemId}.xml</file:fileNamePattern> <file:destinationDirectoryPattern>target/orders</file:destinationDirectoryPattern> <file:listFileNamePattern>order-${order.orderId}.lst</file:listFileNamePattern> <file:highWaterMark mark="10"/> </file:outputStream> <!-- Every time we hit the end of an <order-item> element, apply this freemarker template, outputting the result to the "orderItemSplitStream" OutputStream, which is the file output stream configured above. --> (4) <ftl:freemarker applyOnElement="order-item"> <ftl:template>target/classes/orderitem-split.ftl</ftl:template> <ftl:use> <!-- Output the templating result to the "orderItemSplitStream" file output stream... --> <ftl:outputTo outputStreamResource="orderItemSplitStream"/> </ftl:use> </ftl:freemarker> </smooks-resource-list>
Smooks Resource configurations shown in number one and two above define the Java Bindings for extracting the order header information (config #1) and the order-item information (config #2). When processing a huge message, make sure you only have the current order item in memory at any one time. The Smooks Javabean Cartridge manages all this for you, creating and recreating the orderItem beans as the order-item fragments are being processed.
The
file:outputStream
configuration in configuration number three manages the generation of the files on the file system. As you can see from the configuration, the file names can be dynamically constructed from data in the bean context. You can also see that it can throttle the creation of the files via the highWaterMark
configuration parameter. This helps you manage file creation so as not to overwhelm the target file system.
Smooks Resource configuration number four defines the FreeMarker templating resource used to write the split messages to the OutputStream created by the
file:outputStream
(config #3). See how configuration 4 references the file:outputStream
resource. The Freemarker template is as follows:
<orderitem id="${.vars["order-item"].@id}" order="${order.@id}"> <customer> <name>${order.header.customer}</name> <number>${order.header.customer.@number}</number> </customer> <details> <productId>${.vars["order-item"].product}</productId> <quantity>${.vars["order-item"].quantity}</quantity> <price>${.vars["order-item"].price}</price> </details> </orderitem>