DataWeave スクリプトが失敗した場合のトラブルシューティング

失敗したスクリプトをトラブルシューティングする場合、特に本番環境では入力の変化が予測できないため、エラーを再現するためにスクリプトの実行時と同じ入力を供給することは困難です。そのため、ロガーをデバッグまたは使用してスクリプトへの入力をキャプチャすることが重要です。多くの場合、失敗は別の上流コンポーネントからの入力が有効でないために発生します。ここでは、一般的な DataWeave エラーとその解決方法を示します。

入力コンテキストとスクリプトのフォルダーへのダンプ

Mule 4.2.1 では、スクリプトが失敗した原因となったデータに沿ってスクリプトを追跡できるように、入力コンテキストや失敗したスクリプトをフォルダーにダンプするための実験的な機能が DataWeave に導入されています。 間違ったスクリプトが失敗するのは上流コンポーネントが無効なデータを生成した場合が多いため、このツールは受信した入力データが有効であることを確認するために特に役立ちます。

この機能を使用する手順は、次のとおりです。

  1. ダンプ機能を有効にするには、次のシステムプロパティを設定します。

    -M-Dcom.mulesoft.dw.dump_files=true

  2. [省略可能] ダンプファイルを生成するパスを指定します。

    -M-Dcom.mulesoft.dw.dump_folder=<path_to_folder>

    デフォルトディレクトリは ​java.io.tmpdir​ プロパティに設定されています。

DataWeave の例外

ここでは、ダンプファイルに見られる一般的な DataWeave 例外と、これらのエラーをトラブルシューティングするための詳細を説明します。

間違った引数

間違った引数で関数を呼び出すと、​org.mule.weave.v2.exception.UnsupportedTypeCoercionException​ 例外がスローされます。 この例外の原因としては以下が考えられます。

関数が Null 引数を受け付けない

この例外が発生する最も一般的な原因は、いずれかの引数が ​Null​ で、関数が ​Null​ を引数として受け付けないことです。この問題が発生すると、次のようなエラーメッセージが返されます。

You called the function '++' with these arguments:
  1: Null (null)
  2: String (" A text")

But it expects one of these combinations:
  (Array, Array)
  (Date, Time)
  (Date, LocalTime)
  (Date, TimeZone)
  (LocalDateTime, TimeZone)
  (LocalTime, Date)
  (LocalTime, TimeZone)
  (Object, Object)
  (String, String)
  (Time, Date)
  (TimeZone, LocalDateTime)
  (TimeZone, Date)
  (TimeZone, LocalTime)

1| payload.message ++ " A text"
   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Trace:
  at ++ (line: 1, column: 1)
  at main (line: 1, column: 17)

この問題を解決する方法の 1 つは、​default​ 演算子を使用することです。たとえば、​payload.message default "" ++ " A text"​ を使用すると、メッセージが Null である場合には空のテキストが追加されます。

MIME タイプ設定されていない

MIME タイプが設定されていない場合は、次のようなエラーメッセージが返されます。

You called the function 'Value Selector' with these arguments:

  1: String ("{ \"message\": 123}")
  2: Name ("message")

But it expects one of these combinations:
  (Array, Name)
  (Array, String)
  (Date, Name)
  (DateTime, Name)
  (LocalDateTime, Name)
  (LocalTime, Name)
  (Object, Name)
  (Object, String)
  (Period, Name)
  (Time, Name)

1| payload.message
   ^^^^^^^^^^^^^^^
Trace:
  at main (line: 1, column: 1)

ペイロードで MIME タイプが設定されていない場合、MIME タイプはデフォルトで ​application/java​ に設定され、コンテンツは JSON オブジェクトではなく ​String​ として処理されます。

リーダープロパティが Mule アプリケーションで機能しない

Mule アプリケーションでは、DataWeave スクリプトへの ​input​ ディレクティブは機能しません。 Mule Runtime とは異なり、 DataWeave Playground+​ などのスタンドアロンの DataWeave Runtime は、同じ DataWeave スクリプトの ​input​ ディレクティブで設定された有効な MIME タイプを処理できます。 リーダープロパティを Mule アプリケーションのスクリプトに入力するには、データソースの ​outputMimeType​ 属性を設定して同じ結果を生成します。 詳細は、​「リーダーとライターのプロパティの使用」​を参照してください。

スタックのオーバーフロー

関数の再帰が深すぎると、次のようなエラーがスローされます。

Stack Overflow. Max stack is 256

最大スタックサイズは、プロパティ ​com.mulesoft.dw.stacksize​ を使用して設定できます。

デバイスにスペースがない

大きなペイロードを処理するために、DataWeave ではペイロードが設定可能な制限を超えない限り、メモリ内で処理されるデータを生成します。 ペイロードが制限を超えた場合、データはディスク上の一時ディレクトリに出力、入力、およびバッファファイルとして保存されます。詳細は、​「DataWeave のメモリ管理」​を参照してくださいます。

そのファイルを参照するストリームが終了すると、ファイルはリリースされます。終了するのは通常、フローの実行が完了するときであるため、一時フォルダーにある多くのバッファファイルは、長時間や同時の実行の間、使用中のままになることがあります。

例外 ​No space left on device​ を回避するには、アプリケーションを実行するためのリソースを増やしてみるか、アプリケーションのリソース消費を減らせるかどうかを判断します。

フローが完了しているのに、バグでファイルがリリースされないこともあります。 最新の Mule リリースでこの問題が修正されていない場合は、問題を MuleSoft サポートチームに報告してください。

終了したストリーム

終了したストリーム通常、DataWeave への入力データはストリームです。Mule はストリームを処理し、ストリーム上の「カーソル」を生成して自動終了および反復可能機能を追加します。 ときにはストリームが早く終了して DataWeave スクリプトに到達せず、その理由を把握することが困難な場合があります。 こうした状況では、スクリプトは ​Cannot open a new cursor on a closed stream​ のようなエラーで失敗します。

最新の Mule 更新でこのエラーが発生した場合は、MuleSoft サポートチームに報告してください。この問題は回避できませんが、​com.mulesoft.dw.track.cursor.close​ システムプロパティを使用してストリームを早く終了したコンポーネントを判別することができます。 このプロパティを設定すると、エラーにストリームが終了した時点からのスタックトレースが表示され、終了をトリガーしたコンポーネントが指摘されます。

出力が未定義の場合の不一致

変換とは異なり、DataWeave 式では出力形式を定義する必要がありません。これは、DataWeave は使用される式と変数に基づいて出力を推定できるためです。場合によっては、推定プロセスによって推定された型と期待される型の間に不一致が生じることがあります。この問題を解決するには、出力を明示する必要があります。この状況が発生する一般的な例として次のものがあります。

XML からのデータの抽出

文字列を抽出する場合 (XML ペイロードから式 ​payload.order.product.model​ を使用して抽出するなど)、DataWeave はペイロード形式に基づいて XML を推定します。このような場合、次のようなエラーが発生します。

"Trying to output non-whitespace characters outside main element tree (in prolog or epilog), while writing Xml at ." evaluating expression: "payload.order.product.model".

このようなエラーが発生する場合は、出力形式を明示する必要があります。たとえば、​output text/plain --- payload.order.product.model​ のようにします。

マルチパートエントリの処理

特定の構造を持つマルチパートデータでは、一般的な推定エラーが発生します。マルチパートペイロードと式 ​dw::core::Objects::keySet(payload.parts)​ について考えてみます。明示的な出力形式がなければ、DataWeave はペイロード種別に基づいて、マルチパートコンテンツを出力すると推定します。この場合、次のようなエラーがスローされます。

"Expecting type is {
  preamble?: String,
  parts: {
    _*: {
      headers: Object,
      content: Any
    }
  }
} but got Array, while writing MultiPart.
Trace:
  at main (Unknown)" evaluating expression: "dw::core::Objects::keySet(payload.parts)".

この問題を解決するには、出力形式を定義する必要があります。たとえば、​output application/json --- dw::core::Objects::keySet(payload.parts)​ のようにします。

テキストデータの操作

テキストデータを使用して、より複雑なオブジェクトを作成できます。ただし、入力テキストデータに対して出力形式を定義しないと、DataWeave は出力にプレーンテキストライターを使用すると推定します。たとえば、式 ​payload splitBy ' '​ は次のようなエラーで失敗します。

"Text plain writer is unable to write Array.
Reason:
Cannot coerce Array (org.mule.weave.v2.model.values.ArrayValue$ArraySeqArrayValue@1331b353) to String
Trace:
  at main (Unknown), while writing TextPlain.
Trace:
  at main (Unknown)" evaluating expression: "payload splitBy ' '".

出力を明示することで問題が解決します。たとえば、​output application/java --- payload splitBy ' '​ のようにします。

エンコードの問題

エンコードの問題は、ファイルの読み取りと書き込みに使用されたエンコードが不一致の場合や、テキストを書き込むためのエンコードでサポートされない文字がある場合に発生することがあります。一般的な例として次のようなものがあります。

リーダーのエンコードが不正確

Mule で ​MIME Type​ 設定 (​Set Payload​、​File Read​、​HTTP Listener​ など) を提供するコンポーネントやコネクタ操作を使用するときには、設定したエンコードがペイロードの書き込みに使用されるエンコードに対応していることを確認します。DataWeave では、​MIME Type​ 設定に指定されたエンコードを読み取ります。

MIME タイプを設定しない場合、DataWeave では Mule で ​mule.encoding​ システムプロパティに指定されたデフォルトのエンコードを使用します。

ライターで使用されるエンコードでサポートされない文字がある

書き込もうとしている文字がライターのエンコードでサポートされていることを確認します。

たとえば、テキスト ​"~―-$¢£㈱①“​ をエンコード ​`sjis​ で書き込むと ​”???$????"`​ と出力されます。これは、入力文字の多くが (UTF-8 などとは異なり) そのエンコードでサポートされていないからです。

%dw 2.0
output application/json encoding="sjis"
---
"~―-$¢£㈱①"

マルチパート/フォームデータリーダーではデフォルトで UTF-8 文字がサポートされていない

マルチパートファイル名に UTF-8 文字を使用すると、名前の非 ASCII 文字が破損します。

マルチパートの UTF-8 のサポートを有効にするには、次のシステムプロパティを設定します。​-M-Dmail.mime.allowutf8=true

たとえば、​allowutf8​ プロパティを ​true​ に設定せずに filename=​不明.txt​ でマルチパートペイロードを転記すると、​filename​ 項目に次の判読できないテキストが生成されます。

{
  "Content-Disposition": {
    name: "file",
    filename: "ä\ufffd\ufffd明.txt",
    subtype: "form-data"
  },
  "Content-Type": "text/plain"
}

DataWeave の警告

以下は、ダンプファイルに見られる一般的な DataWeave 警告とその警告に対処するための詳細です。

入力の最後に達した

この警告は、DataWeave が Unicode 非文字 ​U+FFFF​ を入力の最後を示す特殊文字として扱うために発生します。

この警告を回避するには、未加工ペイロードの特殊文字を置き換えてから通常どおりに進めます。

read(payload.^raw replace "\uFFFF" with "NonChar")

低パフォーマンスの問題

application/dw 形式

output application/dw​ 形式を使用すると、変換のパフォーマンスに影響することがあります。この形式の目的は、DataWeave 変換の結果を容易にデバッグできるようにすることです。 他の形式よりも変換が大幅に遅くなるため、本番アプリケーションではこの形式の使用を避けてください。

multipart/form-data コンテンツの解析

multipart/form-data​ 入力では、特に ​application/xlsx​ などの高メモリ形式では、大きなパートのコンテンツにアクセスするとパフォーマンスが低下する可能性があります。これは、インタープリターがさらに照会して分析するためにパートのコンテンツを解析しようとするためです。

パートのバイナリコンテンツの解析を回避するには ​^raw​ セレクターを使用できます。

次の例では、各パートの特定の操作で ​^raw​ セレクターを使用します。

入力

--myboundary
Content-Disposition: form-data; name="file1"; filename="a.json"
Content-Type: application/json

{
"title": "Java 8 in Action",
"author": "Mario Fusco",
"year": 2014
}
--myboundary
Content-Disposition: form-data; name="file2"; filename="a.xml"
Content-Type: application/xml

<doc>
    <title> Available for download! </title>
    <content> Really large content </content>
</doc>
--myboundary--

ソース

%dw 2.0
input payload multipart boundary='myboundary'
output application/json
---
payload.parts mapObject ((value, key, index) ->
{
    (key): {
	fileName: payload.parts[index].headers.'Content-Disposition'.filename,
    rawContent: payload.parts[index].content.^raw
    }
})