コンテンツパラメーター

次の操作 (疑似コード) を考えてみます。

<file:write path="hello.txt" overwrite="true" content="#[payload]" />

操作を構成するパラメーターは、多くの場合異なる役割を果たします。

動作パラメーター

これらのパラメーターは、操作の動作方法を決定する設定を管理します。上記の例では、​overwrite​ パラメーターは、ファイルがすでに存在する場合に実行するアクションを設定します。​path​ パラメーターは、コンテンツの書き込み先を示します。両方のパラメーターは操作を構成しますが、これは Write 操作であるため、 書き込まれるデータの主な概念を表すものではありません。

一部の操作は、次のように動作パラメーターによって排他的に形成されます。

<file:copy from="somePath" to="anotherPath" />

この操作はコンテンツを取得しないため、両方のパラメーターが動作パラメーターです。コンテンツはコピーされるファイル内にあります。

コンテンツパラメーター

上記の動作パラメーターの説明を考慮すると、コンテンツパラメーターの定義は明確です。上記の ​file:write​ の例では、コンテンツは ​@Content​ パラメーターです。

コンテンツパラメーターには、次の特性があります。

  • 式を受け入れる必要がある。​SUPPORTS_EXPRESSIONS​ と ​EXPRESSION_REQUIRED​ の両方がサポートされていますが、​@Expression(NOT_SUPPORTED)​ が使用されている場合はコンパイルに失敗します。

  • 各コンテンツパラメーターは、コンテンツを生成するために独自の DataWeave スクリプトを埋め込むことができる。

  • コンテンツパラメーターは、埋め込まれた DataWeave スクリプトを有効にするため、常にテキスト要素として DSL に変換される。

今回はコンテンツパラメーターを使用して、もう一度 ​file:write​ 操作を考えてみます。この操作をフローで使用し、メッセージペイロードは XML として保存する JSON であるとします。

<file:write path="myFile.xml">
	<file:content>
		<![CDATA[#[
        %dw 2.0
        output application/xml
        ---
        rootElement: payload
        ]
        ]]>
	</file:content>
</file:write>

モジュールのコードでは、​content​ パラメーターは ​@Content​ アノテーションでマークされます。

public void write(String path, @Content InputStream content) {
    // write code
}

プライマリコンテンツパラメーター

場合によっては、次のように操作に多数のコンテンツパラメーターがあります。

<http:request path="/my/api">
	<http:request-builder>
		<http:body>
			#[body..]
		</http:body>
		<http:uri-params>
			#[uri-params …]
		</http:uri-params>
		<http:headers>
			#[you get the picture..]
		</http:headers>
	</http:request-builder>
</http:request>

ご覧のとおり、必要なだけのコンテンツパラメーターを設定できます。つまり、​@Content​ アノテーションを複数のメソッド引数で使用できます。 ただし、その場合でも ​body​ パラメーターは他のパラメーターよりも重要です。ヘッダーも HTTP 要求で送信されるコンテンツの一部ですが、それらのヘッダーは送信される本文を補完するものです。そのため、操作に複数のコンテンツパラメーターがある場合、​@Content(primary = true)​ を使用してその 1 つをプライマリコンテンツとしてマークする必要があります。

プライマリコンテンツパラメーターは、通常のコンテンツパラメーターと同じ特性のすべてに加えて、次の特性があります。

  • 自動的に省略可能になる。

  • デフォルトで自動的に ​#[payload]​ に設定される。

これら 2 つの機能は、ランタイムによって自動的にパラメーターに追加されます。

コンテンツパラメーターが 1 つのみだった ​file:write​ の例に戻りましょう。これはプライマリですか? ​YES​。操作のコンテンツパラメーターが 1 つのみの場合、SDK は自動的にそれをプライマリと見なします。つまり、​file:write​ 操作のコンテンツパラメーターは自動的に省略可能になり、デフォルトで ​#[payload]​ に設定されます。これは、モジュール間の一貫性を強化するために役立ちます。

プライマリコンテンツのデフォルトの変更

プライマリコンテンツをデフォルトでペイロード以外の何かに設定する必要がある極端な状況があります。これは、操作のコンテンツパラメーターが 1 つのみで、そのパラメーターが常に必要とは限らない場合に発生しがちです。たとえば、Database Connector を考えてみます。選択クエリの入力パラメーターはプライマリコンテンツですが、すべてのクエリに入力パラメーターが必要なわけではありません。そのため、実際のデフォルトは空のマップにする必要があります。

これを行うには、​@Content​ アノテーションと ​@Optional​ アノテーションを組み合わせます。たとえば、次の例はデフォルトを空のマップに設定しています。

public List<Map> select(@Text String sql,
                        @Optional(defaultValue="#[{}]") @Content Map<String, Object> inputParameters) {
	// select
}

コンテンツパラメーターを省略可能として、デフォルトなしで設定することもできます。

public List<Map> select(@Text String sql,
                        @Optional @Content Map<String, Object> inputParameters) {
	// select
}

最後に、次のように ​@Content​ アノテーションを ​@NullSafe​ と組み合わせることができます。

public List<Map> select(@Text String sql,
                        @Optional @NullSafe @Content Map<String, Object> inputParameters) {
	// select
}
最初と 3 番目の例は同等です。ただし、モジュールのユーザーの操作性が向上するため、​@NullSafe​ オプションをお勧めします。​#[{}]​ を明示的なデフォルトとして設定すると、経験の浅い Mule ユーザーは混乱する可能性があります。

パラメーターグループへのコンテンツパラメーターの埋め込み

上記の ​http:request​ 操作のコンテンツパラメーターは、​request-builder​ という要素に含まれています。使いやすさの理由から、コネクタの作成者はすべての要求関連の属性をそれを囲むオブジェクトでグループ化することを選択しました。これは、SDK によって 次の方法でサポートされています。

public void request(String path, @ParameterGroup(showInDsl=true) HttpRequestBuilder requestBuilder) {
    // request
}

ご覧のとおり、ここにはコンテンツパラメーターはありません。ただし、​HttpRequestBuilder​ クラス内を見ると、​@Content​ アノテーションがあります。

public class HttpRequestBuilder {

    @Parameter
    @Content(primary = true)
    private InputStream body;

    @Parameter
    @Content
    @NullSafe
    private Map<String, String> uriParams;

    @Parameter
    @Content
    @NullSafe
    private Map<String, String> uriParams;
}
サンプル要求操作の ​HttpRequestBuilder​ 引数から ​@ParameterGroup​ アノテーションを削除すると、コンパイルエラーになります。​@Content​ は複合型には使用できません。