第2章 基本

本章では、Smooks の基本的な仕組みについて説明します。
smooks-core構造化データイベントストリームプロセッサーです。 そのコンポーネントは、カスタムのビジター論理をデータソースによって作成されたイベントストリームへ「フック」するよう設計されています。
Smooks の仕組みを理解するには、ビジター論理の概念を理解する必要があります。ビジターは簡単な Java ソースコードで、 ターゲットのメッセージ断片上で特定のタスクを実行するためのものです (例えば、 XSLT スタイルシートの適用を目的とします)。ビジター論理をサポートするには、org.milyn.delivery.sax.SAXElementVisitor インターフェースと org.milyn.delivery.dom.DOMElementVisitor インターフェースのどちらかまたは両方を介して、SAX または DOM フィルターのいずれかを実装します。
一般的に、この機能はトランスフォーメーションソリューションを作成するために使用されます。トランスフォーメーションソリューションを作成するには、ソース メッセージによって作成されたイベントストリームを使用してビジター論理を実装し、結果 を他の形式で作成します。しかし、他の用途で使用することも可能です。以下はその例になります。
  • Java バインディング: ソースメッセージから Java オブジェクトモデル に投入する機能です。
  • メッセージの分割とルーティング: ソースメッセージ上で複雑な分割やルーティングの操作を行う機能です。 複数の形式のデータを複数の宛先に同時にルーティングできる機能も含まれます。
  • 巨大サイズのメッセージ処理: コードを大量に記述する必要なく、 宣言的に巨大なメッセージを 消費 (変換または分割とルーティング) する機能です。

2.1. 基本的な処理モデル

前述の通り、Smooks の基本的な目的はデータソースを取得し、ビジター論理が適用されるイベントストリームを取得したデータソースから生成することです (結果を EDI などの他の形式で作成するために実行します)。
多くのデータソースや結果形式がサポートされるため、複数のトランスフォーメーションタイプを使用できます。一般的な例は次の通りです。
  • XML から XML
  • XNL から Java
  • Java から XML
  • Java から Java
  • EDI から XML
  • EDI から Java
  • Java から EDI
  • CSV から XML
Smooks は ドキュメントオブジェクトモデル (DOM) と Simple API for XML (SAX) イベントモデルの両方をサポートします。 ソースと結果をマッピングするためにこれらのイベントモデルを使用します。本書では、SAX イベントモデル を最も詳しく説明します。
名前の通り、 SAX イベントモデルは XML ソースから生成できる階層的な SAX イベントをベースにしています。 これには、startElementendElement などが含まれます。
このイベントモデルの利点は、 EDICSV、 Java ファイルなど、構造化され階層的な別のデータソースへ比較的簡単に適用できることです。
通常、 visitBeforevisitAfter が付けられたイベントが最も重要になります。 下図はこれらの階層的本質を表しています。
Hierarchical nature of the visitBefore and visitAfter events

図2.1 visitBefore および visitAfter イベントの階層的本質

2.2. 簡単な例

ソースメッセージから作成された SAX イベントストリームを使用できるようにするには、最初に SAXVisitor インターフェースを 1 つ以上実装する必要があります。選択するインターフェースは、特定のケースで消費されるイベントによって異なります。

注記

この例では ExecutionContext 名を使用します。 これは BoundAttributeStore クラスを拡張する公開インターフェースです。
この例は、 全体のイベントストリームの特定要素で visitBefore イベントと visitAfter イベントへ論理を示す方法を表しています。 このケースでは、 ビジター論理が <xxx> 要素のイベントに示されています。
Implementing Visitor Logic

図2.2 ビジター論理の実装

ビジター実装は、イベントごとに 1 つのメソッド実装で構成されるため、 大変シンプルです。 この実装を <xxx> 要素の visitBefore イベントと visitAfter イベントへ示すには、 次のように Smooks の設定を作成します。
このチュートリアルは、 Smooks を使用して (FreeMarker を併用) 巨大なメッセージ で XML から XML への変換を行う方法を表しています (このチュートリアルは文字ベースの変換の基本として使用することもできます)。

注記

FreeMarker はテンプレーティングエンジンです。 FreeMarker を使用して、NodeModel をテンプレート操作のドメインモデルとして作成し、使用することができます。 Smooks は断片ベースのテンプレートトランスフォーメーションを行う機能と、 モデルを巨大メッセージに適用する機能を追加します。
ソース形式は次の通りです。
<order id='332'>
    <header>
        <customer number="123">Joe</customer>
    </header>
    <order-items>
        <order-item id='1'>
            <product>1</product>
            <quantity>2</quantity>
            <price>8.80</price>
        </order-item>
 
        <!-- etc etc -->
 
    </order-items>
</order>
ターゲット形式は次のようになります。
<salesorder>
    <details>
        <orderid>332</orderid>
        <customer>
            <id>123</id>
            <name>Joe</name>
        </customer>
    <details>
    <itemList>
        <item>
            <id>1</id>
            <productId>1</productId>
            <quantity>2</quantity>
            <price>8.80</price>
        <item>        
 
        <!-- etc etc -->
 
    </itemList>
</salesorder>
使用する Smooks の設定は次の通りです。
<?xml version="1.0"?>
<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">
 
    <!--
    Filter the message using the SAX Filter (i.e. not DOM, so no
    intermediate DOM for the "complete" message - there are "mini" DOMs
    for the NodeModels below)....
    -->
    <params>
        <param name="stream.filter.type">SAX</param>
        <param name="default.serialization.on">false</param>
    </params>
 
    <!--
    Create 2 NodeModels.  One high level model for the "order"
    (header etc) and then one per "order-item".
 
    These models are used in the FreeMarker templating resources
    defined below.  You need to make sure you set the selector such
    that the total memory footprint is as low as possible.  In this
    example, the "order" model will contain everything accept the
    <order-item> data (the main bulk of data in the message).  The
    "order-item" model only contains the current <order-item> data
    (i.e. there's max 1 order-item in memory at any one time).
    -->
    <resource-config selector="order,order-item">
        <resource>org.milyn.delivery.DomModelCreator</resource>
    </resource-config>
 
    <!--
    Apply the first part of the template when we reach the start
    of the <order-items> element.  Apply the second part when we
    reach the end.
 
    Note the <?TEMPLATE-SPLIT-PI?> Processing Instruction in the
    template.  This tells Smooks where to split the template,
    resulting in the order-items being inserted at this point.
    -->
    <ftl:freemarker applyOnElement="order-items">
        <ftl:template><!--<salesorder>
    <details>
        <orderid>${order.@id}</orderid>
        <customer>
            <id>${order.header.customer.@number}</id>
            <name>${order.header.customer}</name>
        </customer>
    </details>
    <itemList>
        <?TEMPLATE-SPLIT-PI?>
    </itemList>
</salesorder>--></ftl:template>
    </ftl:freemarker>
 
    <!--
    Output the <order-items> elements.  This will appear in the
    output message where the <?TEMPLATE-SPLIT-PI?> token appears in the
    order-items template.
    -->
    <ftl:freemarker applyOnElement="order-item">
        <ftl:template><!--        <item>
            <id>${.vars["order-item"].@id}</id>
            <productId>${.vars["order-item"].product}</productId>
            <quantity>${.vars["order-item"].quantity}</quantity>
            <price>${.vars["order-item"].price}</price>
        </item>
        --></ftl:template>
    </ftl:freemarker>
 
</smooks-resource-list>
ここで次を実行する必要があります。
Smooks smooks = new Smooks("smooks-config.xml");
try {
    smooks.filterSource(new StreamSource(new FileInputStream("input-message.xml")), new StreamResult(System.out));
} finally {
    smooks.close();
}
結果として、 XML から XML へ変換が行われます。
この例では、「低レベル」の Smooks プログラミングモデルの仕組みが実証されます。 Smooks には機能的なモジュールの一部が同梱されているため、Smooks に対して大量の Java コードを書く必要はありません。これらのモジュールは、カートリッジと呼ばれる一般的なユースケースの多くに対応します。

2.3. Smooks のリソース

Smooks は大変一般的な処理モジュールを使用します。このモジュールは、すべてのビジター論理を イベントセレクタ へ適用される Smooks リソース (SmooksResourceConfiguration) として見なします。これは、Smooks Core やそのアーキテクチャーを維持する観点から見ると道理にかなっています。しかし、設定ではすべてが同じように見えるため、有用性の観点から見ると一般的すぎることがあります。 そのため、 Smooks v1.1 には 拡張可能設定モデル が導入されました。 このモデルにより、独自の専用 XSD 名前空間を使用するよう特定のリソースタイプ (Java Bean バインディングの設定や FreeMarker テンプレートの設定など) を指定することができます。

例2.1 Java バインディングリソース

<jb:bean beanId="lineOrder" class="example.trgmodel.LineOrder" 
    createOnElement="example.srcmodel.Order">
    <jb:wiring property="lineItems" beanIdRef="lineItems" />
    <jb:value property="customerId" data="header/customerNumber" />
    <jb:value property="customerName" data="header/customerName" />
</jb:bean>

例2.2 FreeMarker テンプレートリソース

<ftl:freemarker applyOnElement="order-item">
    <ftl:template><!-- <item>
        <id>${.vars["order-item"].@id}</id>
        <productId>${.vars["order-item"].product}</productId>
        <quantity>${.vars["order-item"].quantity}</quantity>
        <price>${.vars["order-item"].price}</price>
        </item>-->
    </ftl:template>
</ftl:freemarker>
これらの例での重要な点は次の通りです。
  • 設定は「強くタイプ化」され、 ドメインに固有します。 これにより、 読み取りが楽になります。
  • 設定は XSD ベースです。 これにより、 統合開発環境を使用している場合に自動補間サポートが提供されます。
  • リソースタイプの実際のハンドラを定義する必要はありません (Java バインディングの BeanPopulator クラスなど)。

2.3.1. セレクター

Smooks リソースセレクタ はツールの大変重要な一部分です。セレクタは、どのメッセージ断片にビジター論理を適用するか Smooks に指示します。また、非ビジター論理の簡単なルックアップ値としても機能します。
リソースがビジター実装である場合 (<jb:bean><ftl:freemarker> など)、Smooks はリソースセレクタを XPath セレクタのように扱います。
次の点に注意してください。
  1. XPath 式が適用される順番は通常の順番の逆になります。Smooks はメッセージの root 要素からではなく、ターゲットの fragment 要素から逆順に適用します。
  2. XPath の仕様は完全サポートされていません。リソースセレクタは次の XPath 構文をサポートします。
    • リテラル値および数値両方の text() および属性 (@x など) の値セレクタ。
      例: "a/b[text() = 'abc']""a/b[text() = 123]""a/b[@id = 'abc']""a/b[@id = 123]".
      • text() は式の最後のセレクタ手順でのみサポートされます。たとえば、 "a/b[text() = 'abc']" は許可されますが "a/b[text() = 'abc']/c" は許可されません。
      • text()SAXVisitAfter インターフェースのみを使用する SAXVisitor 実装でのみサポートされます。SAXVisitorSAXVisitBefore インターフェースまたは SAXVisitChildren インターフェースを実装すると、エラーが発生します。
    • And および Or 論理演算。例: "a/b[text() = 'abc' and @id = 123]""a/b[text() = 'abc' or @id = 123]"
    • 要素と属性両方の名前空間。例: "a:order/b:address[@b:city = 'NY']"
    • 名前空間の prefix-to-URI マッピングを定義しなければなりません。定義しないと、設定エラーが発生します。
    • 次の演算もサポートされます。
      • = (等号)
      • != (不等号)
      • < (小なり記号)
      • > (大なり記号)
    • 索引セレクター。"a/b[3]" など。

2.3.2. 名前空間の宣言

コア設定名前空間を介して名前空間のプレフィックスから URI へのマッピングを設定します。名前空間セレクターを解決する時にこれらの設定が使用できるようになります。
<?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">

    <core:namespaces>
        <core:namespace prefix="a" uri="http://a"/>
        <core:namespace prefix="b" uri="http://b"/>
        <core:namespace prefix="c" uri="http://c"/>
        <core:namespace prefix="d" uri="http://d"/>
    </core:namespaces>

    <resource-config selector="c:item[@c:code = '8655']/d:units[text() = 1]">
        <resource>com.acme.visitors.MyCustomVisitorImpl</resource>
    </resource-config>

</smooks-resource-list>

2.4. カートリッジ

ソリューションを迅速に実装できるようにするため、 Smooks にはすぐ使用できるプレビルドのビジター論理が含まれています。 ビジター論理はカートリッジと呼ばれるモジュールに組み合わされます。
カートリッジは再使用できるコンテンツハンドラーが含まれる Java アーカイブ (JAR) ファイルです。独自の新しいカートリッジを作成して smooks-core の基本機能を拡張することもできます。 Smooks の各カートリッジは、 トランスフォーメーションプロセスまたは XML 分析の特定形式のいずれかにすぐ対応できるサポートを提供します。
Smooks に含まれる全カートリッジの一覧は次の通りです。
  • Calc: "milyn-smooks-calc"
  • CSV: "milyn-smooks-csv"
  • 固定長リーダー: "milyn-smooks-fixed-length"
  • EDI: "milyn-smooks-edi"
  • Javabean: "milyn-smooks-javabean"
  • JSON: "milyn-smooks-json"
  • ルーティング: "milyn-smooks-routing"
  • テンプレート: "milyn-smooks-templating"
  • CSS: "milyn-smooks-css"
  • Servlet: "milyn-smooks-servlet"
  • 永続化: "milyn-smooks-persistence"
  • バリデーション: "milyn-smooks-validation"

2.5. フィルタリング処理の選択

本項では、 Smooks がフィルタリング処理を選択する方法について説明します。
  • すべてのビジターリソースが DOM ビジターインターフェース (DOMElementVisitor または SerializationUnit) のみを実装する場合、 自動的に DOM 処理モデルが選択されます。
  • すべてのビジターリソースが SAX ビジターインターフェース (SAXElementVisitor) のみを実装する場合、 自動的に SAX 処理モデルが選択されます。
  • ビジターリソースが DOM インターフェースと SAXインターフェースの両方を実装する場合、 Smooks のリソース設定ファイルに SAX が指定されない限り、 デフォルトでは DOM 処理モデルが選択されます。

    注記

    Smooks 1.3 では、<core:filterSettings type="SAX" /> を使用して行われます。

注記

このコンテキストでは、readers などの 非要素ビジタリソース はビジターリソースに含まれません。

例2.3 Smooks 1.3 でフィルタータイプを SAX に設定する

<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">

    <core:filterSettings type="SAX" />

</smooks-resource-list>

2.5.1. DOM モデルと SAX モデルの混合

ドキュメントオブジェクトモデルでは、 ノードのトラバーサルやその他機能が使用できるため、 コーディングのレベルでは SAX よりも使用が簡単です。 また、ドキュメントオブジェクトを使用すると、 DOM 構造のビルトインサポートを持つ FreeMarkerGroovy など既存のスクリプトエンジンやテンプレートエンジンを使用することもできます。
ただし、 DOM にはメモリーによって制約される難点もあります。 これにより、 巨大なメッセージの処理能力が大幅に制限されます。
Smooks の DomModelCreator ビジタークラスを使用して 2 つのモデルを混合することが可能です。このビジタークラスを SAX フィルターと共に使用すると、このビジターは visited 要素から DOM 断片を構築します。そのため、ストリーミング環境内で DOM ユーティリティを使用することができます。
複数のモデルがネストされている場合、 外部モデルに内部モデルのデータが含まれることはありません。 よって、 2 つのモデル内に同じ断片が共存することはありません。 次のサンプルメッセージにこの原理が示されています。
<order id="332">
    <header>
        <customer number="123">Joe</customer>
    </header>
    <order-items>
        <order-item id='1'>
            <product>1</product>
            <quantity>2</quantity>
            <price>8.80</price>
        </order-item>
        <order-item id='2'>
            <product>2</product>
            <quantity>2</quantity>
            <price>8.80</price>
        </order-item>
        <order-item id='3'>
            <product>3</product>
            <quantity>2</quantity>
            <price>8.80</price>
        </order-item>
    </order-items>
</order>
Smooks 内で DomModelCreator を設定して、 次のコード例のように order メッセージ断片と order-item メッセージ断片の両方にモデルを作成することができます。
<resource-config selector="order,order-item">
    <resource>org.milyn.delivery.DomModelCreator</resource>
</resource-config>
このケースでは、 order には order-item のモデルデータが含まれることはありません (order-item 要素は order 要素内にネストされるからです)。 order のインメモリモデルは次のようになります。
<order id='332'>
     <header>
         <customer number="123">Joe</customer>
     </header>
     <order-items />
</order>
新しいモデルは以前のモデルを上書きするため、メモリ内に複数の order-item モデルが存在することはありません。使用されるメモリの容量が最低限になるようソフトウェアはこのように設計されています。
これまでの説明をまとめると、 Smooks 処理モデルはイベント主導となります 。これは、 フィルタリングやストリーミング処理の異なる点に適用するビジター論理を「フック」することができるという意味です。 ビジター論理はメッセージ独自の内容を使用して適用されます。 そのため、DOMSAX の混合処理モデルを使用することもできます。
DOMSAX の混合処理モデルについての詳細は、次の Web サイトを参照してください。

2.6. Bean コンテキスト

Bean コンテキスト は、フィルタリング処理中に Smooks がアクセスできるオブジェクトのコンテナです。実行コンテキストごとに 1 つの Bean コンテキストが作成されます (Smooks.filterSource 操作より)。カートリッジによって作成される各 Bean は、この BeanId 下のコンテキストにファイルされます。
Smooks.filterSource プロセスの最後に Bean コンテキストの内容を返したい場合は、Smooks.filterSource メソッドへの呼び出しに org.milyn.delivery.java.JavaResult オブジェクトが含まれるようにします。次の例はこの方法を示しています。
//Get the data to filter
StreamSource source = new StreamSource(getClass().getResourceAsStream("data.xml"));

//Create a Smooks instance (cachable)
Smooks smooks = new Smooks("smooks-config.xml");

//Create the JavaResult, which will contain the filter result after filtering
JavaResult result = new JavaResult();

//Filter the data from the source, putting the result into the JavaResult
smooks.filterSource(source, result);

//Getting the Order bean which was created by the JavaBean cartridge
Order order = (Order)result.getBean("order");
ランタイム時に Bean コンテキスト Bean にアクセスする必要がある場合 (カスタムビジター実装より)、BeanContext オブジェクトを介して接続します。このオブジェクトは、 getBeanContext() メソッドを介して ExecutionContext より読み出すことができます。
BeanContext よりオブジェクトを追加または読み出しする時、最初に BeanIdStore より BeanId オブジェクトを読み出すようにしてください (BeanId オブジェクトは文字列キーよりも優れたパフォーマンスを実現できる特別なキーです。文字列キーもサポートされます)。
getBeanIdStore() メソッドを介して ApplicationContext より BeanIdStore を読み出さなければなりません。BeanId オブジェクトを作成するには、register("BeanId name") メソッドを呼び出します (BeanId がすでに登録されている場合は、getBeanId("BeanId name") メソッドを呼び出して読み出すことが可能です)。
BeanId オブジェクトは ApplicationContext がスコープ指定されたオブジェクトです。これらのオブジェクトをカスタムビジター実装の初期化メソッドに登録し、プロパティとしてビジターオブジェクトに置きます。その後、これらのオブジェクトは visitBefore および visitAfter メソッドで使用できます (BeanId オブジェクトおよび BeanIdStore はスレッドセーフです)。
Bean コンテキストの事前インストールされた Bean でランタイム時に使用可能なものは次の通りです。
  • PUUID: UniqueId Bean です。この Bean は、ExecutionContext のフィルタリング対して一意な識別子を提供します。
  • PTIME: Time Bean です。ExecutionContext のフィルタリングに対して、時間ベースのデータを提供します。
以下の例は、FreeMarker テンプレートで上記の各 Bean を使用する方法を示しています。
  • ExecutionContext の一意な ID (メッセージをフィルタリング): $PUUID.execContext
  • ランダムで一意な ID: $PUUID.random
  • メッセージのフィルタリングを開始する時間 (ミリ秒単位): $PTIME.startMillis
  • メッセージのフィルタリングを開始する時間 (ナノ秒単位): $PTIME.startNanos
  • メッセージのフィルタリングを開始する時間 (日付): $PTIME.startDate
  • 現在の時間 (ミリ秒単位): $PTIME.nowMillis
  • 現在の時間 (ナノ秒単位): $PTIME.nowNanos
  • 現在の時間 (日付): $PTIME.nowDate

2.6.1. 複数の出力や結果

本項では、 Smooks でフィルタリング処理より出力を生成する方法について説明します。
Smooks は次の方法で出力を表示できます。
  • 「結果内」のインスタンスより: Smooks.filterSource メソッドへ渡された 結果インスタンス内に返されます。
  • フィルタリング処理中: フィルタリング処理中に外部エンドポイント (ESB サービス、ファイル、JMS の宛先、データベースなど) へ生成され送信 された出力を介して行われます。メッセージ断片のイベントによって外部エンドポイントへの自動ルーティングが引き起こされます。

重要

Smooks はメッセージストリームの単一のフィルタリングパスより、 上記 2 つの方法の両方またはいずれかを用いて出力を生成することができます。 複数の出力を生成するためにメッセージストリームを複数回フィルター処理する必要はありません。

2.6.2. 「結果内」のインスタンス

API が公開する通り、複数の結果インスタンスを Smooks に提供できます。
public void filterSource(Source source, Result... results) throws SmooksException
Smooks は 標準的な JDK StreamResultDOMResult 結果タイプ、および次のような特殊なタイプと動作します。
  • JavaResult: この結果タイプを使用して Smooks Java Bean コンテキストの内容をキャプチャします。
  • ValidationResult: この結果タイプを使用して出力をキャプチャします。
  • Simple Result タイプ: テストを書き込む時に使用します。StringWriter をラッピングする StreamResult 拡張です。
これが Smooks のフィルタリング処理より出力をキャプチャする最も一般的な方法となります。

注記

Smooks は同じタイプである複数の結果インスタンスから結果データをキャプチャすることをサポートしていません。 例えば、 Smooks.filterSource メソッド呼び出しで複数の StreamResult インスタンスを指定できますが、 Smooks はこれらの StreamResult インスタンスを 1 つだけ (最初のインスタンス) 出力します。

2.6.3. StreamResults と DOMResults

これらの結果タイプは特別に処理されます。Smooks がメッセージソースを処理すると、 イベントのストリームを作成します。 StreamResult または DOMResultSmooks.filterSource 呼び出しへ提供されると、 デフォルトでは、イベントストリーム (ソースによって作成された) を提供された StreamResult または DOMResultXML としてシリアライズします (シリアライズする前にビジター論理をイベントストリームへ適用できます)。

注記

これが 1 つの入力で 1 つの xml を出力する、標準の文字ベーストランスフォーメーションを実行するために使用されるメカニズムとなります。

2.6.4. フィルタリング処理中

Smooks は Smooks.filterSource プロセス中に異なるタイプの出力を生成することもできます (メッセージイベントストリームをフィルタリング処理し、メッセージの最後に到達する前)。 他プロセスによる実行のため、エンドポイントの異なるタイプへメッセージ断片を分割およびルーティングするために使用される場合が、この例となります。
Smooks は次のような理由で、メッセージデータを単に一括処理せず、メッセージ全体をフィルタリングした後にすべての出力を生成します。
  • パフォーマンスへの影響
  • これにより、メッセージイベントストリームを活用し、断片のトランスフォーメーションやルーティング操作をトリガーできます。
たとえば、決定した基準を基に、異なる形式で異なる部署に分割およびルーティングする必要がある注文商品が数十万個注文メッセージに記載されているとしましょう。 このような大きさのメッセージを処理する唯一の方法がプロセスのストリーミングになります。

2.7. Smooks 実行処理の確認

Smooks がメッセージをフィルタリングすると、キャップチャ可能でプログラムによる分析も可能なイベントを パブリッシュ します。Smooks より実行レポートを入手する最も簡単な方法は、 ExecutionContext クラスを設定してレポートを生成する方法です (Smooks を設定して HtmlReportGenerator クラスより HTML レポートを生成することも可能です)。
次のコード例は、Smooks を設定して HTML レポートを生成する方法を示しています。
Smooks smooks = new Smooks("/smooks/smooks-transform-x.xml");
ExecutionContext execContext = smooks.createExecutionContext();

execContext.setEventListener(new HtmlReportGenerator("/tmp/smooks-report.html"));
smooks.filterSource(execContext, new StreamSource(inputStream), new StreamResult(outputStream));
HtmlReportGenerator は、開発作業に従事しているユーザーに便利なツールです。現在、 IDE ベースのデバッガーに最も近い Smooks のツールです (「正式」なデバッガーは今後のリリースに同梱される予定です)。

注記

レポートの例は、Web ページ http://www.milyn.org/docs/smooks-report/report.html を参照してください。

注記

代わりに、カスタムの ExecutionEventListener 実装を作成することも可能です。

2.8. フィルタリング処理の終了

メッセージの最後に到達する前にフィルタリング処理を終了する必要がある場合があります。途中でフィルタリング処理を終了するには、<core:terminate> 設定を Smooks 設定に追加します。この設定は SAX フィルタでのみ動作するため、DOM に追加しても意味がありません。
メッセージの顧客断片の最後にフィルタリングを終了する設定の例は次の通りです。
<?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">

    <!-- Visitors... -->
    <core:terminate onElement="customer" />

</smooks-resource-list>
デフォルトでは、ターゲットの断片の最後に終了します (visitAfter イベント)。最初に終了するには (visitBefore イベント)、次のコードを使用します。
<?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">

   <!-- Visitors... -->

   <core:terminate onElement="customer" terminateBefore="true" />

</smooks-resource-list>

2.9. グローバル設定

グローバル設定 とは、 1 回のみの設定で設定内のすべてのリソースがその設定を使用できるオプションのことです。
Smooks は、 default propertiesglobal parameters の 2 種類のグローバル設定をサポートします。
デフォルトプロパティ
デフォルトプロパティは <resource-config> 属性のデフォルト値を指定します。 対応する <resource-config> が属性の値を指定しない場合、 これらのプロパティが SmooksResourceConfiguration クラスへ自動的に適用されます。
グローバルパラメータ
<param> 要素は <resource-config> ごとに指定することができます。 これらのパラメータ値は、 SmooksResourceConfiguration よりランタイム時に取得できますが、 できない場合は @ConfigParam アノテーションより挿入されます。
グローバル設定パラメータは一ヶ所で定義されます。 各ランタイムコンポーネントは ExecutionContext を使用してこれらのパラメータにアクセスできます。

2.9.1. グローバル設定パラメータ

グローバルパラメータは root 要素に指定されず、 リソースへ自動的に適用されない点がデフォルトのプロパティと異なります。
グローバルパラメータは <params> 要素に指定されます。
<params>
    <param name="xyz.param1">param1-val</param>
</params>
グローバル設パラメータは ExecutionContext よりアクセス可能です。
public void visitAfter(
    final Element element, final ExecutionContext executionContext) 
    throws SmooksException 
    {
        String param1 = executionContext.getConfigParameter(
            "xyz.param1", "defaultValueABC");

        ....
}

2.9.2. デフォルトプロパティ

デフォルトプロパティとは、 Smooks 設定の root 要素に設定でき、 その後 smooks-conf.xml ファイルにあるすべてのリソース設定へ適用できるプロパティのことです。
たとえば、 すべてのリソース設定のセレクタ値が同じである場合、 すべてのリソース設定にセレクタを指定する代わりに default-selector=order を指定することができます。
<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" 
    default-selector="order">

    <resource-config>
        <resource>com.acme.VisitorA</resource>
        ...
    </resource-config>

    <resource-config>
        <resource>com.acme.VisitorB</resource>
        ...
    </resource-config>

<smooks-resource-list>
使用できるオプションは次の通りです。
default-selector
セレクタが定義されていない場合、 このセレクタが Smooks 設定ファイルにあるすべての resource-config 要素に適用されます。
default-selector-namespace
デフォルトのセレクタ名前空間です。他の名前空間が定義されていない場合に使用されます。
default-target-profile
ターゲットプロファイルが定義されていない場合、 Smooks 設定ファイルにあるすべてのリソースに適用されるデフォルトのターゲットプロファイルになります。
default-condition-ref
条件識別子によってグローバル条件を参照します。 この条件は、 グローバルに定義された条件を参照しない空の条件要素 (<condition/>) を定義するリソースに適用されます。

2.10. フィルター設定

フィルターオプションを設定するには、smooks-core 設定の名前空間を使用します。

例2.4 設定例

<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">
   <core:filterSettings type="SAX" defaultSerialization="true" 
      terminateOnException="true" readerPoolSize="3" closeSource="true" 
      closeResult="true" rewriteEntities="true" />

      .. Other visitor configs etc...

</smooks-resource-list>
type
SAX と DOM のどちらか (デフォルトは DOM) から使用される処理モデルのタイプを決定します。
defaultSerialization
デフォルトのシリアライズを有効にするかを決定します。 デフォルトは true です。 有効にすると、Smooks.filterSource メソッドに提供される結果オブジェクトにある StreamResult (または DOMResult) を探すよう Smooks に伝え、 デフォルトではその結果へのイベントをすべてシリアライズします。
この挙動はグローバル設定パラメータを介して無効にできます。また、結果ライターを所有する断片 (SAX フィルタリングを使用する場合) または DOM を変更する断片 (DOM フィルタリイングを使用する場合) へビジター実装をターゲットして断片ごとに上書きすることも可能です。
terminateOnException
例外によって処理が停止されるべきであるかどうかを決定します。デフォルトの設定は true になります。
closeSource
Smooks.filterSource メソッドに渡されたソースインスタンスストリームを閉じます。 デフォルトは true です。 この場合の例外は閉じられることがない System.in になります。
closeResult
Smooks.filterSource メソッドに渡された結果ストリームを閉じます。 デフォルトは true です。 この場合の例外は閉じられることがない System.outSystem.err になります。
rewriteEntities
これを使用して XML を読み書きする時に (デフォルトのシリアライゼーション) XML エンティティを再書き込みします。
readerPoolSize
リーダーのプールサイズを設定します。リーダー実装によっては作成が高価になることがあります。 特に小さいメッセージを大量に処理する場合、 リーダーインスタンスをプールすると (再使用) パフォーマンスを大幅に改善することができます。 この設定のデフォルト値は 0 (プールされず、各メッセージに対して新しいリーダーインスタンスが作成されます) になります。
アプリケーションのスレッディングモデルに従ってこれを設定します。