サンプルデータ

サンプルデータにより、操作とソースで生成する出力の例を提供できます。これらの例は、コネクションレスの例からの接続または出力形式を介して、ライブシステムから取得された情報を表示します。

サンプルデータは、Mule 4.4.0 以降でサポートされています。ただし、Mule バージョンに関係なく、すべての Anypoint Connector でこの機能を使用できます。

サンプルデータを使用して、次の作業を行うことができます。

  • SDK API を実装する

  • 操作パラメーターを使用して例を提供する

  • 設定と接続を使用して例を提供する

SDK API

SDK API を使用して、サンプルデータを提供したり、エラーを通知したり、コンポーネントを拡張したります。

SampleDataResolver

この API を実装して、実際の本番シナリオでコンポーネントが出力するデータを表すサンプルデータを使用し、操作とメッセージソースを拡張します。

実装には次の作業が必要です。

  • デフォルトのコンストラクターを提供する。

  • Result<T,A> オブジェクトを返すペイロード属性とメッセージ属性の両方のサンプルを提供する。

    汎用データ型は、拡張コンポーネントの戻り値のデータ型と常に一致します。動的なデータ型を返すコンポーネントの場合、各実装は正しい動的なデータ型のインスタンスを返します。操作が属性を返さない場合は、Result<T, Void> を使用します。

  • サンプルデータの取得によって、対象システムに重大な副次的影響が発生しないことを保証する。

  • 大きなオブジェクトやデータストリームを返すためには使用しない。データは、小さなワーカーインスタンスのメモリ内に収まる必要があります。

実装は、パラメーター、設定、および接続にアクセスし、​@Parameter​、​@Config​、および ​@Connection​ パラメーターを介してサンプルデータを生成できます。

コネクタの場合、ハードコードされた値を返す代わりに、接続先のシステムから実際のデータを返す実装が最も価値があります。

次の例は、SampleDataResolver API を示しています。

/**
* [...]
*
* @param <T> the generic type of the output value
* @param <A> the generic type of the message attributes
* @since 1.4
*/
@MinMuleVersion("4.4")
public interface SampleDataProvider<T, A> {

 /**
  * An ID that identifies each implementation of this interface. It must be unique among implementations in the same
  * extension. Subsequent invocations must always return the same fixed value.
  *
  * @return the resolver's id
  */
 String getId();

 /**
  * Obtains and returns the sample information.
  *
  * @return a {@link Result} object
  * @throws SampleDataException if the sample cannot be obtained
  */
 Result<T, A> getSample() throws SampleDataException;
}

ストリーミングは次の場合はサポートされていません。

  • InputStream 値を返す操作またはソース。

    リゾルバーは、ByteArrayInputStream 値や、getSample() メソッドを返す前にデータストリーム全体をすでに取得している他のオフライン実装など、接続を必要としない実装を常に返します。これは、基盤となる接続が閉じられた後でも InputStream 値は完全にコンシューマブルであるためです。一時バッファファイルも使用しないでください。

  • ストリーミングとみなされるため PagingProvider<C, T> 値を返す操作。以前の箇条書きで説明されている制限が適用されます。このような場合、代わりに同じ項目型の List<T> 値が返されます。

SampleDataException

このクラスはサンプルデータの取得中にエラーを通知するため、ランタイムはそれに応じてエラーを処理できます。必要に応じて、このクラスで説明される定義済みの失敗コードメッセージを使用します。

次の例は、SampleDataException クラスを示しています。

/**
* {@link Exception} to indicate that an error occurred fetching sample data through a {@link SampleDataProvider}.
*
* @since 1.4.0
*/
public class SampleDataException extends MuleException {

 /**
  * Signals an unexpected exception
  */
 public final static String UNKNOWN = "UNKNOWN";

 /**
  * Indicates that the {@link SampleDataProvider} didn't return any information
  */
 public final static String NO_DATA_AVAILABLE = "NO_DATA_AVAILABLE";

 /**
  * Indicates that a connection couldn't be established
  */
 public final static String CONNECTION_FAILURE = "CONNECTION_FAILURE";

 /**
  * Indicates that Sample Data resolution was attempted on a {@link Location} that doesn't exist
  */
 public final static String INVALID_LOCATION = "INVALID_LOCATION";

 /**
  * Indicates that the Sample Data resolution was attempted but the underlying {@link SampleDataProvider} has required parameters
  * that weren't supplied
  */
 public final static String MISSING_REQUIRED_PARAMETERS = "MISSING_REQUIRED_PARAMETERS";

 /**
  * Indicates that Sample Data resolution was attempted on a component that doesn't support that capability
  */
 public final static String NOT_SUPPORTED = "NOT_SUPPORTED";

 /**
  * Indicates that Sample Data resolution was attempted on an unregistered Extension
  */
 public final static String INVALID_TARGET_EXTENSION = "INVALID_TARGET_EXTENSION";

 private final String failureCode;

 public SampleDataException(String message, String failureCode) {
   super(createStaticMessage(message));
   this.failureCode = failureCode;
 }

 public SampleDataException(String message, String failureCode, Throwable cause) {
   super(createStaticMessage(message), cause);
   this.failureCode = failureCode;
 }

 public SampleDataException(I18nMessage message, String failureCode) {
   super(message);
   this.failureCode = failureCode;
 }

 public SampleDataException(I18nMessage message, String failureCode, Throwable cause) {
   super(message, cause);
   this.failureCode = failureCode;
 }

 /**
  * @return The failure code of the error that produced the error
  */
 public String getFailureCode() {
   return failureCode;
 }
}

@SampleData

このアノテーションは、リゾルバーを拡張コンポーネントに関連付けます。ソースではデータ型レベル、操作ではメソッドレベルで適用されます。

次の例は、​@SampleData​ アノテーションを示しています。

/**
* Associates a {@link Source} class or operation method with a {@link SampleDataProvider}.
*
* @since 1.4.0
* @see SampleDataProvider
*/
@Target({TYPE, METHOD})
@Retention(RUNTIME)
@Documented
public @interface SampleData {

 /**
  * @return the associated {@link SampleDataProvider}
  */
 Class<? extends SampleDataProvider> value();

 /**
  * @return bindings between parameters in the {@link SampleData#value()} to extraction expressions.
  */
 Binding[] bindings() default {};

}

サンプルデータの例

操作、または設定と接続を使用してサンプルデータを取得します。

直接操作を使用したサンプルデータの取得

この例を使用して、接続を使用せずに操作を使用して静的サンプルデータを提供します。

JSON 形式で情報を取得する操作を含む新しい GitHub Connector があるとします。ただし、限られた数またはコストのかかる API コールの 1 つをコンシュームするサンプルデータを提供している間は API コールをコンシュームしたくないため、操作を直接実装します。

次の例は、​@SampleData​ アノテーションを介してプロバイダーが接続された操作の定義を示しています。

@SampleData(JsonSampleDataProvider.class)
public Result<InputStream, Void> getUserInfo(String username, @Connection GitHubConnection connection) {
 // operation code...
}

次の例は、以前に示された実装を使用してパラメーターを挿入するサンプルデータプロバイダー実装を示しています。 @Parameter​ アノテーションの名前とデータ型は、操作のパラメーター (​username​) と同じです。

public class JsonSampleDataProvider implements SampleDataProvider<InputStream, Void> {

   private static JsonObject sampleJson = new JsonObject();

   public JsonSampleDataProvider() {
       sampleJson.add("company", "Mulesoft");
       sampleJson.add("email", "maxmule2007@mulesoft.com");
       sampleJson.add("repositories", new JsonArray("mule-api", "data-weave-2"));
   }

   @Parameter
   private String username;

   @Override
   public Result<InputStream, ObjectAttributes> getSample() throws SampleDataException {

       sampleJson.addFirst("username", username);
       String body = sampleJson.getBody();

       return Result.<InputStream, ObjectAttributes>builder()
               .output(new ByteArrayInputStream(body.getBytes()))
               .mediaType(MediaType.APPLICATION_JSON)
               .length(body.length())
               .build();
   }

   @Override
   public String getId() {
       return "jsonResolver";
   }
}

username​ パラメーターの値が ​John Doe​ だとします。プロバイダーは次の JSON を返します。

{
	"username": "John Doe",
	"company": "Mulesoft",
	"email": "maxmule2007@mulesoft.com",
	"repositories": ["mule-api", "data-weave-2"]
}

設定値と接続を使用したサンプルデータの取得

この例を使用して、パラメーターと設定値に従い、同時に接続も必要とする動的なサンプルデータを提供します。

次の条件を満たす操作とソースの両方を含む新しい GitHub Connector があるとします。

  • 取得するエンティティのデータ型を制御する ​objectType​ パラメーター (​pullRequest​、​issue​、​commit​ などの値を使用可能) がある。

  • 結果を絞り込む省略可能な ​status​ パラメーターがある

  • GitHub API の接続を使用する

  • Result<InputStream, ObjectAttributes> オブジェクトを返す

次の例は、操作定義を示しています。

@SampleData(ObjectSampleDataProvider.class)
public Result<InputStream, ObjectAttributes> getObject(String objectType, @Optional String status, String anotherParameter, @Connection GitHubConnection connection, @Config GitHubConfig config) {
 // operation code...
}

次の例は、ソース定義を示しています。

@SampleData(ObjectSampleDataProvider.class)
public class OnNewThingTrigger extends Source<InputStream, ObjectAttributes> {

 @Parameter
 private String objectType;

 @Parameter
 @Optional
 private String status;

 @Parameter
 private String extraParameter;

 @Config
 private GitHubConfig config;

 @Connection
 private ConnectionProvider<GitHubConnection> connection;

 // source code...
}

次の例は、両方のケースに対応する SampleDataProvider 実装を示しています。​objectType​ パラメーターと ​status​ パラメーター、および接続と設定を使用します。

public class ObjectSampleDataProvider implements SampleDataProvider<InputStream, ObjectAttributes> {

   @Parameter
   private String objectType;

   @Parameter
   @Optional
   private String status;

   @Connection
   private GitHubConnection connection;

   @Config
   private GitHubConfig config;

   @Override
   public Result<InputStream, ObjectAttributes> getSample() throws SampleDataException {
       String query = "objectType=" + objectType;
       if (status != null) {
           query += "; status=" + status;
       }
       query += ";organization=" + config.getOrganization();

       List<GitHubObject> jsonDocs = connection.query(query);

       if (jsonDocs.isEmpty()) {
           throw new SampleDataException("No data available", NO_DATA_AVAILABLE);
       }

       GitHubObject sample = jsonDocs.get(0);
       String body = sample.getBody();

       return Result.<InputStream, ObjectAttributes>builder()
               .output(new ByteArrayInputStream(body.getBytes()))
               .mediaType(MediaType.APPLICATION_JSON)
               .length(body.length())
               .attributes(sample.getMetadata())
               .attributesMediaType(MediaType.APPLICATION_JAVA)
               .build();
   }

   @Override
   public String getId() {
       return "objectResolver";
   }
}

両方のコンポーネントには、サンプルデータプロバイダーと同じデータ型の署名があります。これらはリゾルバーで必要な同じパラメーターを定義しますが、それぞれにリゾルバーでは不要な独自のパラメーターがあります。リゾルバーは、値プロバイダーと同じ方法でパラメーター、接続、および設定にアクセスします。

使用可能なデータがない場合、リゾルバーは定義済みの失敗コードで ​SampleDataException​ エラーをスローします。

OAuth トークンの更新

操作またはソースで OAuth 接続を使用している場合は、 操作またはソース​で実行する場合と同様に、getSample() メソッド内で ​AccessTokenExpiredException​ エラーをスローして、プロバイダーでトークンの更新をトリガーします。

次の例は、トークンの更新を示しています。

public class RefreshedOAuthSampleDataProvider implements SampleDataProvider<String, String> {

 public static final String SAMPLE_PAYLOAD_VALUE = "Sample payload!";
 public static final String SAMPLE_ATTRIBUTES_VALUE = "Sample Attributes!";

 @Connection
 private TestOAuthConnection testOAuthConnection;

 @Override
 public String getId() {
   return "OAuth sample data";
 }

 @Override
 public Result getSample() throws SampleDataException {
   if (!testOAuthConnection.getState().getAccessToken().contains("refresh")) {
     throw new AccessTokenExpiredException();
   }
   return builder()
       .output(SAMPLE_PAYLOAD_VALUE)
       .attributes(SAMPLE_ATTRIBUTES_VALUE)
       .build();
 }
}

別名および機能パラメーター

値プロバイダーを解決するのと同じ方法でパラメーターを解決できます。 パラメーターの一部として機能パラメーターを定義するのと同様に、別名を定義できます。

エラー条件

コンパイル中に、一連の検証によりサンプルデータプロバイダーが前述の制限の一部に準拠していることがチェックされます。

  • 出力と属性のデータ型のチェック

SDK は、出力と属性のデータ型が <T, A> 汎用タプルで宣言されたものと一致するコンポーネントにプロバイダーが適用されていることを検証します。そうでない場合、検証エラーがスローされます。

  • パラメーターの使用状況チェック

SDK は、サンプルデータプロバイダーでパラメーターが使用される場合、関連コンポーネントでもそれがパラメーターとして宣言されていることを検証し、両方の宣言でパラメーターのデータ型が同じであることもチェックします。そうでない場合、検証エラーがスローされます。

  • 接続と設定の使用状況チェック

SDK は、サンプルデータプロバイダーで接続または設定が使用されている場合、関連コンポーネントでもそれらが使用されていることを検証します。そうでない場合、検証エラーがスローされます。

  • インスタンス化チェック

SDK は、各プロバイダーがインスタンス化可能であることを検証します。これは必須の条件です。そうでない場合、検証エラーがスローされます。

  • void なし

サンプルデータプロバイダーを void 操作に配置することはできません。そうでない場合、検証エラーがスローされます。

  • ストリーミング

ストリーミングはサポートされませんが、これは強制されていません。 拡張開発者は、ベストプラクティスに従って契約を遵守する必要があります。