Flex Gateway新着情報
Governance新着情報
Monitoring API ManagerJava Module バージョン 1.1 以降、Java 呼び出しに指定された引数が Java メソッドが想定する型と完全に一致しない場合でも、このモジュールはその引数を変換します。Java Module は、パラメーターをメソッドが想定するものに変換する方法を推定します。
Java Module は、指定されたパラメーターごとに、その型がそのパラメーターのメソッドが想定する型と一致するかどうかをチェックします。メソッドが想定する型でない場合は、Java Module が想定される型に変換します。
以下に、引数の 1 つが変換されるシンプルな例を示します。
Math クラスから min 静的メソッドがコールされますが、クラスは 2 つの int パラメーターを受け取ることを想定します。このコールの実行時には Number と String が使用されます。
<flow name="calculateMinimum">
  <java:invoke-static class="java.lang.Math" method="min(int,int)" >
    <java:args>#[{
        'arg0': 5,
        'arg1' : "3"
      }]
    </java:args>
  </java:invoke-static>
</flow>
この場合、arg1 は String として渡されるところですが、Java メソッドをコールする前に Integer に変換されます。
Mule 3 では、カスタム POJO を処理する場合に、ユーザーがデータをどの型に変換するかを DataWeave 式で明示的に宣言していました。Mule 4 では、引数の想定される型を Java Module が自動的に認識し、データを想定される型に変換しようとします。(POJO は Plain Old Java Object の略称です)。
以下の例では、Java Module で Map パラメーターがカスタム POJO に変換されています。
POJO の Car クラスを定義します。
public class Car {
  private String doors;
  private String wheels;
  private String engine;
  public String getDoors() {
    return doors;
  }
  public String getWheels() {
    return wheels;
  }
  public String getEngine() {
    return engine;
  }
}
POJO のインスタンスを受信するクラスの describeCar 静的メソッドを宣言します。
public class CarUtils {
  public static String describeCar(Car car) {
    return "This car has: " + car.getEngine() + ", " + car.getWheels() + ", " + car.getDoors();
  }
}
Mule フローで静的メソッドを呼び出します。
<flow name="describeCarFlow">
    <java:invoke-static class="CarUtils" method="describeCar(Car)" >
        <java:args>
            #[{
            'car': {
                'doors' : "Four doors",
                'engine' : "120 Horsepower engine",
                'wheels' : "17 Inch chromed rims"
            }
            }]
        </java:args>
    </java:invoke-static>
</flow>
Mule 操作は car Map を受け取り、そのキーと値は Car クラスインスタンスにマップされます。Java メソッドを呼び出す前に、この Map がインスタンスに変換されます。こうした改善がなければ呼び出しに失敗し、Java メソッドに渡された引数がその署名と一致していなかった旨が表示されるでしょう。
Java Module は、Collection の各要素と Map の各エントリが、メソッドの署名で宣言された Java ジェネリクスを使用しているかどうかをチェックします。使用していない要素がある場合、Java Module は Collection または Map 全体を作成して、変換済みの要素を再入力します。
| 
 変換が必要な場合は、Collection または Map の別のインスタンスで Java メソッドがコールされます (Mule フローで渡されるものと同じではありません)。この点が特に重要となるのは、コールされたメソッドで Collection または Map の要素を追加または削除し、呼び出しが必要になった後でこの Collection または Map を参照できることが想定される場合です。  | 
操作に指定された List が変換され、変換された項目を含む新しい List が Java メソッドに渡されます。
IntegerUtils Java クラスは、sumNumbers 静的メソッドを宣言します。
public class IntegerUtils {
  public static Integer sumNumbers(List<Integer> numbers) {
    return numbers.stream().mapToInt(i -> i.intValue()).sum();
  }
}
この Mule フローは、Java クラスを呼び出します。
<flow name="sumListOfNumbers">
  <java:invoke-static class="IntegerUtils" method="sumNumbers(List)">
    <java:args>
      #[{
        'numbers' : [1, "5", 4, "8", 3]
      }]
    </java:args>
  </java:invoke-static>
</flow>
フローの numbers リストに 2 つの String オブジェクト ("5" と "8") があり、モジュールはそれらを Integer に変換します。
操作の Map が変換され、変換されたキーと値を含む新しい Map が Java メソッドに渡されます。
この Java クラスは、sumMapValues 静的メソッドを宣言します。
public class MapUtils {
  public static Integer sumMapValues(Map<String, Integer> map) {
    return map.keySet().stream().mapToInt(i -> i.intValue()).sum();
  }
}
この Mule フローは、MapUtils Java クラスを呼び出します。
<flow name="sumValuesOnMap">
  <java:invoke-static class="MapUtils" method="sumMapValues(Map)">
    <java:args>
      #[{
        'map' :{
          'books': "22",
          'pencils': 33,
          'pens': 12
        }
      }]
    </java:args>
  </java:invoke-static>
</flow>
この Map には、Java メソッドで強制されるジェネリクスに従っていない値があります。このため、変換されたキーと値を指定した新しいインスタンスを使用してメソッドがコールされます。
ユーザーによりアップロードされた画像ファイルを処理する Mule アプリケーションについて考えてみます。このファイルを効率的に処理するために、画像データをバイト配列として Java メソッドに渡してさらに処理します。この例は、Anypoint Studio の Java Module でバイト配列を Java メソッドに渡すように設定し、画像データが正しく効率的に処理されるようにする方法を示しています。
Anypoint Studio で新しい Mule プロジェクトを作成し、HTTP Listener をフローに追加します。
これは、受信ファイルアップロード要求のエントリポイントになります。
[Set Payload] 操作を [HTTP Listener] の後にドラッグします。
[Set Payload] 操作を選択し、[Value (値)] で次の DataWeave ペイロードを設定します。
%dw 2.0
output application/octet-stream
---
payload
[Java Module Invoke] 操作を [Set Payload] の後にドラッグします。
[Invoke] 操作を選択し、Java メソッドをコールするように設定します。
メソッドの署名がバイト配列をパラメーターとして受け入れることを確認します。
Invoke 操作の設定で、Method プロパティを、呼び出す Java メソッドの名前 (processImage など) に設定します。
受信ファイルデータを Java メソッドのバイト配列パラメーターにマップします。
DataWeave を使用して、ファイルデータをバイト配列に変換することができます。
処理された画像データを処理するためのロジック (データベースへの保存や別のサービスへの送信など) を追加して、引き続き Mule フローを構築します。
[Configuration XML (設定 XML)] ウィンドウでは、設定は次のように記述されます。
<flow name="imageProcessingFlow">
    <http:listener doc:name="HTTP Listener" config-ref="HTTP_Listener_config" path="/upload"/>
    <set-payload value="#[%dw 2.0
output application/octet-stream
---
payload]"/>
            <java:invoke-static
                class="org.mule.extensions.internal.model.ByteArrayProcessor"
                method="processByteArray(byte[])"
                target="processedResult">
                <java:args><![CDATA[#[{bytes: payload}]]]></java:args>
            </java:invoke-static>
    <!-- Add additional steps to handle the processed image data -->
</flow>