第7章 テンプレート
7.1. Smooks テンプレート リンクのコピーリンクがクリップボードにコピーされました!
リンクのコピーリンクがクリップボードにコピーされました!
Smooks で利用できるテンプレートは、FreeMarker (http://freemarker.org) と XSL (http://www.w3.org/Style/XSL/) の 2 種類です。
これらのテクノロジーは、Smooks フィルタリングプロセスのコンテキスト内で使用できます。つまり、次のとおりです。
- フラグメント ごとにソースメッセージに適用できます。これは、メッセージ全体に適用されるフラグメントベースの変換プロセスとは対照的です。フラグメントごとに適用すると、SOAP メッセージにヘッダーを追加する場合など、非常に特定のポイントでメッセージにデータを挿入する必要がある場合に役立ちます。この場合、プロセスは、残りの部分を中断せずに、関心のあるフラグメントを対象とすることができます。
- Javabean Cartridge などの他の Smooks テクノロジーを利用できます。これは、Bean コンテキストへのメッセージデータのデコードおよびバインドに使用できます。次に、FreeMarker テンプレート内から、そのデコードされたデータを参照できます。(Smooks はデータを FreeMarker で使用できるようにします。)
- 巨大なメッセージストリーム (数ギガバイトのサイズ) を処理するために使用できます。同時に、単純な処理モデルと小さなメモリーフットプリントを維持します。
- 分割メッセージフラグメント を生成するために使用できます。これらは、Enterprise Service Bus 上の物理的または論理的なエンドポイントにルーティングできます。
7.2. FreeMarker テンプレート リンクのコピーリンクがクリップボードにコピーされました!
リンクのコピーリンクがクリップボードにコピーされました!
FreeMarker は非常に強力な テンプレートエンジン です。Smooks は、テキストベースのコンテンツを生成する手段として FreeMarker を使用できます。その後、このコンテンツをメッセージストリームに挿入できます (このプロセスは フラグメントベースの変換 と呼ばれます)。このプロセスを使用して、メッセージフラグメントを分割して、その後、別のプロセスにルーティングすることもできます。
設定 namespace http://www.milyn.org/xsd/smooks/freemarker-1.1.xsd を使用して、Smooks の FreeMarker テンプレートを設定します。次に、XSD を使い始めるために、統合開発環境で設定します。
7.3. FreeMarker テンプレートの例 リンクのコピーリンクがクリップボードにコピーされました!
リンクのコピーリンクがクリップボードにコピーされました!
- インラインテンプレートの例:
<smooks-resource-list xmlns="http://www.milyn.org/xsd/smooks-1.1.xsd" xmlns:ftl="http://www.milyn.org/xsd/smooks/freemarker-1.1.xsd"> <ftl:freemarker applyOnElement="order"> <ftl:template><!--<orderId>${order.id}</orderId>--></ftl:template> </ftl:freemarker> </smooks-resource-list> - FreeMarker 外部テンプレートの例:
<smooks-resource-list xmlns="http://www.milyn.org/xsd/smooks-1.1.xsd" xmlns:ftl="http://www.milyn.org/xsd/smooks/freemarker-1.1.xsd"> <ftl:freemarker applyOnElement="order"> <ftl:template>/templates/shop/ordergen.ftl</ftl:template> </ftl:freemarker> </smooks-resource-list> - Smooks が結果の出力にさまざまな操作を実行できるように、<ftl:freemarker> 設定に <use> 要素 を追加します。以下の例を参照してください。
<ftl:freemarker applyOnElement="order"> <ftl:template>/templates/shop/ordergen.ftl</ftl:template> <ftl:use> <ftl:inline directive="insertbefore" /> </ftl:use> </ftl:freemarker>
7.4. Smooks でのインライン リンクのコピーリンクがクリップボードにコピーされました!
リンクのコピーリンクがクリップボードにコピーされました!
インライン は、その名前が示すように、テンプレート結果を
Smooks.filterSource の結果にインラインできます。多くのディレクティブがサポートされています。
- addto: これにより、テンプレート結果が対象の要素に追加されます。
- replace (デフォルト): テンプレート結果を使用して、対象の要素を置換します。これは、<use> 要素が設定されていない場合の <ftl:freemarker> 設定のデフォルトの動作です。
- insertbefore: これにより、テンプレート結果が対象の要素の前に追加されます。
- insertafter: これにより、テンプレート結果が対象の要素の後に追加されます。
7.5. ftl:bindTo 要素 リンクのコピーリンクがクリップボードにコピーされました!
リンクのコピーリンクがクリップボードにコピーされました!
ftl:bindTo 要素を使用すると、テンプレート結果を Smooks Bean コンテキストにバインドできます。結果は、ルーティングに使用されるコンポーネントなど、他の Smooks コンポーネントからアクセスできます。特に、巨大なメッセージを小さなものに分割する場合に役立ちます。分割フラグメントは、別のプロセスにルーティングできます。
7.6. ftl:bindTo の例 リンクのコピーリンクがクリップボードにコピーされました!
リンクのコピーリンクがクリップボードにコピーされました!
<smooks-resource-list xmlns="http://www.milyn.org/xsd/smooks-1.1.xsd"
xmlns:jms="http://www.milyn.org/xsd/smooks/jms-routing-1.2.xsd"
xmlns:ftl="http://www.milyn.org/xsd/smooks/freemarker-1.1.xsd">
<jms:router routeOnElement="order-item" beanId="orderItem_xml" destination="queue.orderItems" />
<ftl:freemarker applyOnElement="order-item">
<ftl:template>/orderitem-split.ftl</ftl:template>
<ftl:use>
<!-- Bind the templating result into the bean context, from where
it can be accessed by the JMSRouter (configured above). -->
<ftl:bindTo id="orderItem_xml"/>
</ftl:use>
</ftl:freemarker>
</smooks-resource-list>
7.7. ftl:outputTo 要素 リンクのコピーリンクがクリップボードにコピーされました!
リンクのコピーリンクがクリップボードにコピーされました!
ftl:outputTo を使用して、出力結果を直接
OutputStreamResource クラスに書き込むことができます。これは、巨大なメッセージを小さなメッセージに分割するためのもう 1 つの役立つ機能です。
7.8. ftl:outputTo の例 リンクのコピーリンクがクリップボードにコピーされました!
リンクのコピーリンクがクリップボードにコピーされました!
テンプレートの結果を
OutputStreamSource に書き込む例:
<smooks-resource-list xmlns="http://www.milyn.org/xsd/smooks-1.1.xsd"
xmlns:jb="http://www.milyn.org/xsd/smooks/javabean-1.3.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">
<!-- Create/open a file output stream. This is written to by the freemarker template (below).. -->
<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="3"/>
</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.
-->
<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>
注記
包括的なチュートリアルは、http://www.smooks.org/mediawiki/index.php?title=Smooks_v1.3_Examples にあります。
7.9. 変換の設定 リンクのコピーリンクがクリップボードにコピーされました!
リンクのコピーリンクがクリップボードにコピーされました!
- セレクターの値を決定する際、HTML レポートツールにアクセスします。これは、Smooks から見た (セレクターが適用される) 入力メッセージモデルを視覚化するために役立ちます。
- ソースデータを使用して、レポートを生成しますが、変換設定は空です。レポートでは、設定を追加する必要があるモデルを確認できます。設定を 1 つずつ追加し、レポートを再実行して、設定が適用されていることを確認します。
- 設定を 1 つずつ追加し、レポートを再実行して、設定が適用されていることを確認します。
- その結果、次のような設定が生成されます (
$TODO$トークンに注意してください)。<?xml version="1.0"?> <smooks-resource-list xmlns="http://www.milyn.org/xsd/smooks-1.1.xsd" xmlns:jb="http://www.milyn.org/xsd/smooks/javabean-1.4.xsd"> <jb:bean beanId="order" class="org.milyn.javabean.Order" createOnElement="$TODO$"> <jb:wiring property="header" beanIdRef="header" /> <jb:wiring property="orderItems" beanIdRef="orderItems" /> <jb:wiring property="orderItemsArray" beanIdRef="orderItemsArray" /> </jb:bean> <jb:bean beanId="header" class="org.milyn.javabean.Header" createOnElement="$TODO$"> <jb:value property="date" decoder="$TODO$" data="$TODO$" /> <jb:value property="customerNumber" decoder="Long" data="$TODO$" /> <jb:value property="customerName" decoder="String" data="$TODO$" /> <jb:value property="privatePerson" decoder="Boolean" data="$TODO$" /> <jb:wiring property="order" beanIdRef="order" /> </jb:bean> <jb:bean beanId="orderItems" class="java.util.ArrayList" createOnElement="$TODO$"> <jb:wiring beanIdRef="orderItems_entry" /> </jb:bean> <jb:bean beanId="orderItems_entry" class="org.milyn.javabean.OrderItem" createOnElement="$TODO$"> <jb:value property="productId" decoder="Long" data="$TODO$" /> <jb:value property="quantity" decoder="Integer" data="$TODO$" /> <jb:value property="price" decoder="Double" data="$TODO$" /> <jb:wiring property="order" beanIdRef="order" /> </jb:bean> <jb:bean beanId="orderItemsArray" class="org.milyn.javabean.OrderItem[]" createOnElement="$TODO$"> <jb:wiring beanIdRef="orderItemsArray_entry" /> </jb:bean> <jb:bean beanId="orderItemsArray_entry" class="org.milyn.javabean.OrderItem" createOnElement="$TODO$"> <jb:value property="productId" decoder="Long" data="$TODO$" /> <jb:value property="quantity" decoder="Integer" data="$TODO$" /> <jb:value property="price" decoder="Double" data="$TODO$" /> <jb:wiring property="order" beanIdRef="order" /> </jb:bean> </smooks-resource-list>注記Smooks.filterSource メソッドを呼び出した後の JavaResult インスタンスの正確な内容に関する保証はありません。このメソッドを呼び出した後、JavaResult インスタンスには、任意のビジター実装によって追加できる Bean コンテキストの最終的な内容が含まれます。
7.10. FreeMarker と Java Bean カートリッジ リンクのコピーリンクがクリップボードにコピーされました!
リンクのコピーリンクがクリップボードにコピーされました!
FreeMarker
NodeModel は、強力で使いやすいですが、パフォーマンスの点でトレードオフがあります。W3C DOM の構成は低コストではありません。また、必要なデータがすでに抽出され、Java オブジェクトモデルに投入されている場合があります。たとえば、データを一連のオブジェクトとして Java Message Service エンドポイントにルーティングする必要がある場合などです。
NodeModel の使用が実用的でない場合は、Java Bean カートリッジを使用して、適切な Java オブジェクトまたは仮想モデルを設定します。このモデルは、FreeMarker テンプレートプロセスで使用できます。
7.11. NodeModel の例 リンクのコピーリンクがクリップボードにコピーされました!
リンクのコピーリンクがクリップボードにコピーされました!
次の例は、NodeModel 要素を設定する方法を示しています。
<?xml version="1.0"?>
<smooks-resource-list xmlns="http://www.milyn.org/xsd/smooks-1.1.xsd"
xmlns:jb="http://www.milyn.org/xsd/smooks/javabean-1.3.xsd"
xmlns:ftl="http://www.milyn.org/xsd/smooks/freemarker-1.1.xsd">
<!-- Extract and decode data from the message. Used in the freemarker template (below). -->
<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>
<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>
<ftl:freemarker applyOnElement="order-item">
<ftl:template><!--<orderitem id="${order.orderItem.itemId}" order="${order.orderId}">
<customer>
<name>${order.customerName}</name>
<number>${order.customerNumber?c}</number>
</customer>
<details>
<productId>${order.orderItem.productId}</productId>
<quantity>${order.orderItem.quantity}</quantity>
<price>${order.orderItem.price}</price>
</details>
</orderitem>-->
</ftl:template>
</ftl:freemarker>
</smooks-resource-list>
注記
7.12. プログラムによる設定 リンクのコピーリンクがクリップボードにコピーされました!
リンクのコピーリンクがクリップボードにコピーされました!
FreeMarker テンプレート設定は、Smooks インスタンスにプログラムで追加できます。これを行うには、次のように、
FreeMarkerTemplateProcessor インスタンスを追加および設定します。この例では、Java バインドと FreeMarker テンプレートの設定を Smooks に追加します。
Smooks smooks = new Smooks();
smooks.addVisitor(new Bean(OrderItem.class, "orderItem", "order-item").bindTo("productId", "order-item/product/@id"));
smooks.addVisitor(new FreeMarkerTemplateProcessor(new TemplatingConfiguration("/templates/order-tem.ftl")), "order-item");
// Then use Smooks as normal... filter a Source to a Result etc...
7.13. XSL テンプレート リンクのコピーリンクがクリップボードにコピーされました!
リンクのコピーリンクがクリップボードにコピーされました!
- Smooks で XSL テンプレートを使用するには、統合開発環境で http://www.milyn.org/xsd/smooks/xsl-1.1.xsd XSD を設定してください。重要JBoss SOA では、ルートフラグメントに適用される 1 つの XSLT のみが Smooks 設定に含まれている場合、フラグメントフィルターはバイパスされます。XSLT は直接適用されます。これは、パフォーマンス上の理由で行われ、
enableFilterBypassというパラメーターを追加し、falseに設定すると、無効にすることができます。<param name="enableFilterBypass">false</param>
7.14. XSL の例 リンクのコピーリンクがクリップボードにコピーされました!
リンクのコピーリンクがクリップボードにコピーされました!
次の例は、XSL テンプレートを設定する方法を示しています。
<?xml version="1.0"?>
<smooks-resource-list xmlns="http://www.milyn.org/xsd/smooks-1.1.xsd" xmlns:xsl="http://www.milyn.org/xsd/smooks/xsl-1.1.xsd">
<xsl:xsl applyOnElement="#document">
<xsl:template><!--<xxxxxx/>--></xsl:template>
</xsl:xsl>
</smooks-resource-list>
FreeMarker と同様、他のタイプの外部テンプレートは、<xsl:template> 要素内の URI 参照を使用して、設定できます。
7.15. XSL サポートの注意点 リンクのコピーリンクがクリップボードにコピーされました!
リンクのコピーリンクがクリップボードにコピーされました!
次の場合を除き、Smooks を使用して、XSL テンプレートを実行する理由はありません。
- メッセージ全体の変換ではなく、フラグメント変換を実行する必要があります。
- 分割、保持など、メッセージに追加の操作を行うには、他の Smooks 機能を使用する必要があります。
- XSL テンプレートは、DOM フィルターのみによってサポートされます。SAX フィルターではサポートされていません。これにより、(適用される XSL によっては) XSL の SAX ベースのアプリケーションと比較して、パフォーマンスが低下する可能性があります。
- Smooks は、メッセージフラグメントごとに XSL テンプレートを適用します。これは XSL のフラグメント化に非常に役立ちますが、スタンドアロンコンテキスト用に記述されたテンプレートが、変更なく、Smooks で自動的に機能するとは想定しないでください。このため、Smooks は、テンプレートを (ルート DOM 要素ではなく) DOM ドキュメントノードに適用するという点で、ドキュメントルートノードを対象とする XSL を異なる方法で処理します。
- ほとんどの XSL には、ルート要素に一致するテンプレートが含まれています。Smooks はフラグメントごとに XSL を適用するため、これはもはや有効ではありません。代わりに、コンテキストノード (つまり、対象のフラグメント) に一致するテンプレートがスタイルシートに含まれていることを確認してください。
7.16. 潜在的な問題: XSLT は、外部では機能するが、Smooks 内では機能しない リンクのコピーリンクがクリップボードにコピーされました!
リンクのコピーリンクがクリップボードにコピーされました!
これは、場合によって発生する可能性があり、通常、その原因は次のシナリオのいずれかです。
- ドキュメントルートノードへの絶対パス参照を使用するテンプレートがスタイルシートに含まれている場合は、Smooks フラグメントベースの処理モデルで問題が発生します。これは、Smooks が誤った要素を対象としているためです。この問題を解決するには、Smooks が対象としているコンテキストノードに一致するテンプレートが XSLT に含まれていることを確認してください。
- SAX と DOM の処理の比較: 「いいね」と「いいね」が比較されているわけではありません。現状では、Smooks は XSL を処理するための DOM ベースの処理モデルのみをサポートしています。正確な比較を行うには、Smooks 外で XSL テンプレートを実行する際、DOMSource (namespace を認識するもの) を使用します。(特定の XSL プロセッサーが、SAX または DOM を使用して、XSL テンプレートを適用しようとしても、常に同じ出力を生成するとはかぎりません。)