9.3. Fuse Online エクステンションの開発

Fuse Online がインテグレーションの作成に必要な機能を提供しない場合、開発者が必要な動作を提供するエクステンションを作成することができます。Syndesis エクステンションリポジトリー https://github.com/syndesisio/syndesis-extensions にエクステンションの例が含まれています。

ビジネスインテグレーターは、エクステンションを作成する開発者と要件を共有します。開発者は、エクステンションが含まれる .jar ファイルを提供します。ビジネスインテグレーターは Fuse Online に .jar ファイルをアップロードして、カスタムコネクター、カスタムステップ、またはライブラリーリソースを Fuse Online で使用できるようにします。

Red Hat Developer Studio への Fuse Tooling プラグインは、ステップのエクステンションまたはコネクターのエクステンションの開発に役立つウィザードを提供します。Developer Studio またはその他の IDE で、ステップエクステンションまたはコネクターエクステンションを開発するかどうかは、個人的に選択できます。Developer Studio プラグインの使用に関する詳細は、Fuse Online インテグレーション用エクステンションの開発 を参照してください。

選択した IDE でエクステンションを開発するための手順の概要、要件の説明、および追加の例については以下を参照してください。

9.3.1. エクステンション開発の一般的な手順

エクステンションの開発を開始する前に、実行する必要のあるタスクについて理解しておく必要があります。

前提条件

  • Maven を理解している必要があります。
  • コネクターを提供するエクステンションを開発したり、コネクション間のデータを操作するインテグレーションステップを提供するエクステンションを開発する場合は、Camel を理解している必要があります。
  • プログラミングの経験が必要です。
注意

インテグレーション Pod は、フラットなクラスパスを持つ Java プロセスで実行されます。バージョンの競合を避けるため、エクステンションが使用する依存関係が、以下のすべてのソースからインポートされた BOM (Bill of Materials) に対応することを確認してください。

  • org.springframework.boot:spring-boot-dependencies:$SPRING_BOOT_VERSION
  • org.apache.camel:camel-spring-boot-dependencies:$CAMEL_VERSION
  • io.syndesis.integration:integration-bom:$syndesis_VERSION

インポートされた BOM の一部ではない追加の依存関係がある場合、以下を行う必要があります。

  • lib ディレクトリーにあるエクステンション JAR ファイルでパッケージ化する必要があります。
  • エクステンションの JSON 記述子ファイルの dependencies プロパティーから省略します。

手順

  1. 拡張された機能の動作の理解します。機能要件を理解するために、ビジネスの関係者と話し合います。
  2. ステップエクステンション、コネクターエクステンション、またはライブラリーエクステンションを開発する必要があるかどうかを判断します。
  3. エクステンションを開発する Maven プロジェクトを設定します。
  4. ステップエクステンションを開発する場合は以下を行います。

    1. Camel ルートとして実装するか、または Syndesis Step API を使用して実装するかを決定します。Syndesis API に関する情報は http://javadoc.io/doc/io.syndesis.extension/extension-api を参照してください。
    2. Camel ルートとしてエクステンションを実装する場合は、XML フラグメント、RouteBuilder クラス、または Bean を実装するかどうかを決定します。
    3. Maven プロジェクトで、schemaVersion、エクステンション nameextensionId などの必要なメタデータを指定します。
  5. 機能を実装するクラスを作成します。
  6. 依存関係をプロジェクトの pom.xml ファイルに追加します。
  7. コネクターおよびライブラリーエクステンションと、XML に実装するステップエクステンションに、エクステンションを定義する JSON ファイルを作成します。

    Java に実装するステップエクステンションでは、Maven プロジェクトで対応するデータ構造の値を指定するときに Maven は JSON エクステンション定義ファイルを生成できます。

  8. Maven を実行してエクステンションを構築し、エクステンションの JAR ファイルを作成します。
  9. JAR ファイルを Fuse Online 開発環境にアップロードして、エクステンションをテストします。
  10. エクステンションをパッケージ化する JAR ファイルを Fuse Online 本番環境にアップロードするビジネス関係者に、そのファイルを提供します。JAR ファイルを提供するときに、Fuse Online の Web インターフェイスに表示される情報以外の設定について、ビジネス関係者に説明します。

9.3.2. エクステンションの種類の説明

エクステンションは以下のいずれかを定義します。

  • コネクション間のインテグレーションデータを操作する 1 つ以上のカスタムステップ。各カスタムステップは 1 つのアクションを実行します。これは、ステップエクステンションです。
  • インテグレーションランタイムが使用するライブラリーリソース。たとえば、ライブラリーエクステンションは、Oracle などのプロプライエタリー SQL データベースに接続するための JDBC ドライバーを提供できます。
  • 統合する特定のアプリケーションまたはサービスへのコネクションを作成するための単一のカスタムコネクター。これは、コネクターエクステンションです。

    注記

    Fuse Online は OpenAPI ドキュメントを使用して REST API クライアントのコネクターを作成できます。REST API クライアントコネクターの開発 を参照してください。

ビジネスインテグレーターは、エクステンションを作成する開発者と要件を共有します。開発者は、エクステンションが含まれる .jar ファイルを提供します。ビジネスインテグレーターは Fuse Online で .jar ファイルをアップロードし、カスタムコネクター、カスタムステップ、または Fuse Online 内で使用できるライブラリーリソースを作成します。

Fuse Online にアップロードするエクステンション .jar ファイルには、常に 1 つのエクステンションが含まれます。

コネクション間のデータを操作するステップを提供するエクステンションのアップロード例および使用例については、 AMQ から REST API へのサンプルインテグレーションのチュートリアル を参照してください。

9.3.3. エクステンションコンテンツおよび構造の概要

エクステンションとは、.jar ファイルにパッケージ化されるクラス、依存関係、およびリソースのコレクションです。

Fuse Online は Spring Boot を使用してエクステンションをロードします。そのため、Spring Boot の実行可能な JAR 形式に従い、エクステンションをパッケージ化する必要があります。たとえば、ZipEntry.STORED() を使用して、ネストされた JAR ファイルを保存するようにします。

エクステンションをパッケージ化する .jar ファイルの構造は次のとおりです。

extension.jar
|
+- META-INF
|  |
|  +- syndesis
|     |
|     +- syndesis-extension-definition.json 1
|
+- mycompany
|  |
|  +-project
|    |
|    +-YourClasses.class 2
|
+- lib 3
  |
  +-dependency1.jar
  |
  +-dependency2.jar
1
エクステンションを定義するデータ構造を指定する JSON スキーマファイル。これは、エクステンション定義の JSON ファイルです。
2
エクステンションが提供する動作を実装する Java クラス。
3
カスタム機能をビルドおよび実行するために必要な追加の依存関係。

9.3.4. エクステンション定義の JSON ファイルの要件

各エクステンションには、名前、説明、サポートされるアクション、依存関係などのデータ構造の値を指定してエクステンションを定義する .json ファイルが必要です。以下の表は、Maven がエクステンション定義 JSON ファイルを生成するかどうかと、必要になるデータ構造をエクステンションタイプ別に示しています。

エクステンションタイプMaven によるエクステンション定義の生成必要なデータ構造

Java のステップエクステンション

可能

schemaVersion
name
description
version
extensionId
extensionType
actions
dependencies *

XML のステップエクステンション

不可能

schemaVersion
name
description
version
extensionId
extensionType
actions
dependencies *

コネクターエクステンション

いいえ

schemaVersion
name
description
version
extensionId
extensionType
properties
actions
dependencies *
componentScheme
connectorCustomizers
connectorFactory

ライブラリーエクステンション

不可能

schemaVersion
name
description
version
extensionId
extensionType
dependencies *

* dependencies の指定は必ずしも必要ではありませんが、ほとんどの場合で指定する必要がある依存関係があります。

通常、エクステンション定義ファイルのレイアウトは次のようになります。

{
  "schemaVersion": "v1",
  "name": "",
  "description": "",
  "version": "",
  "extensionId": "",
  "extensionType": "",
  "properties": {
  },
  "actions": [
  ],
  "dependencies": [
  ],
}
  • schemaVersion は、エクステンション定義スキーマのバージョンを定義します。Syndesis は内部的に schemaVersion を使用して、エクステンション定義を内部モデルにマップする方法を決定します。これにより、古いバージョンの Syndesis に対して開発されたエクステンションを、より新しいバージョンの Syndesis にデプロイすることが可能になります。
  • name は、エクステンションの名前です。Fuse Online にエクステンションをアップロードするときに、この名前が表示されます。
  • description は、指定する便利な情報です。Fuse Online はこの値を操作しません。
  • version は、エクステンションへの更新を区別するのに便利です。Fuse Online はこの値を操作しません。
  • extensionId は、エクステンションの一意の ID を定義します。これは、少なくとも Syndesis 環境全体で一意である必要があります。
  • extensionType は、エクステンションが提供するものを Syndesis に示します。Syndesis バージョン 1.3 時点で、以下のエクステンションタイプがサポートされます。

    • Steps
    • コネクター
    • Libraries
  • コネクターエクステンションのトップレベルで properties が必要です。このオブジェクトは、Fuse Online ユーザーがコネクターを選択してコネクションを作成する時に Fuse Online で何を表示するかを制御します。この properties オブジェクトには、コネクションを作成するための各フォームコントロールのプロパティーセットが含まれます。以下は例になります。

    "myControlName": {
      "deprecated": true|false,
      "description": "",
      "displayName": "",
      "group": "",
      "kind": "",
      "label": "",
      "required": true|false,
      "secret": true|false,
      "javaType": "",
      "type": "",
      "defaultValue": "",
      "enum": {
      }
    }

    コネクターエクステンションでは、ネストされた properties オブジェクトはコネクションアクションを設定するための HTML フォームコントロールを定義します。ステップエクステンションでは、actions オブジェクトに properties オブジェクトが含まれます。properties オブジェクトは、ステップを設定するための各フォームコントロールのプロパティーセットを定義します。ユーザーインターフェイスプロパティーの説明 も参照してください。

  • actions はコネクターが実行できるオペレーションや、コネクション間のステップが実行できるオペレーションを定義します。コネクターおよびステップエクステンションのみが指定するアクションを使用します。アクションの指定形式は以下のようになります。

    {
        "id": "",
        "name": "",
        "description": "",
        "actionType": "step|connector",
        "descriptor": {
        }
    }
    • id は、アクションの一意の ID です。これは、少なくとも Syndesis 環境内で一意である必要があります。
    • name は、Fuse Online に表示されるアクション名です。インテグレーターは、この値をコネクションアクションの名前またはコネクション間のインテグレーションデータを操作するステップの名前として解釈します。
    • description は、Fuse Online に表示されるアクションの説明です。インテグレーターがアクションの動作を理解するよう、このフィールドを使用します。
    • actionType は、アクションがコネクションまたはコネクション間のステップによって実行されるかどうかを示します。
    • descriptor は、kindentrypointinputDataTypeoutputDatatype などのネストされた属性を指定します。
  • dependencies は、このエクステンションが必要とする Fuse Online が提供するリソースを定義します。

    以下のように依存関係を定義します。

    {
      "type": "MAVEN",
      "id"   : "org.apache.camel:camel-telegram:jar:2.21.0"
    }
    • type は依存関係のタイプを示します。MAVEN を指定します。(他のタイプは今後サポートされる予定です)
    • id は、Maven 依存関係 (Maven GAV) の ID です。

9.3.5. ユーザーインターフェイスプロパティーの説明

コネクターエクステンションおよびステップエクステンションで、エクステンション定義 JSON ファイルまたは Java クラスファイルにユーザーインターフェイスプロパティーを指定します。これらのプロパティーの設定は、Fuse Online ユーザーがコネクションの作成、コネクションアクションの設定、またはエクステンションによって提供されるステップの設定を行うときに Fuse Online が表示する HTML フォームコントロールを定義します。

Fuse Online コンソールのエクステンションのユーザーインターフェイスに表示する各フォームコントロールのプロパティーを指定する必要があります。各フォームコントロールで、一部またはすべてのプロパティーを任意の順序で指定します。

ユーザーインターフェイスプロパティーの指定例

IRC コネクターの一部である JSON ファイルでは、トップレベルの properties オブジェクトは、Fuse Online ユーザーがコネクションを作成するための IRC コネクターを選択した後に HTML フォームコントロールを定義します。3 つのフォームコントロールには、hostnamepassword、および port の 3 つのセットのプロパティー定義があります。

"properties": {
   "hostname": {
     "description": "IRC Server hostname",
     "displayName": "Hostname",
     "labelHint": "Hostname of the IRC server to connect to",
     "order": "1",
     "required": true,
     "secret": false,
     "type": "string"
   },
   "password": {
     "description": "IRC Server password",
     "displayName": "Password",
     "labelHint": "Required if IRC server requires it to join",
     "order": "3",
     "required": false,
     "secret": true,
     "type": "string"
   },
   "port": {
     "description": "IRC Server port",
     "displayName": "Port",
     "labelHint": "Port of the IRC server to connect to",
     "order": "2",
     "required": true,
     "secret": false,
     "tags": [],
     "type": "int"
   }
 },

これらのプロパティー指定を基にして、Fuse Online ユーザーが IRC コネクターを選択すると、Fuse Online に以下のダイアログが表示されます。ユーザーが 2 つの必須フィールドに値を入力し、Next をクリックすると、Fuse Online は Fuse Online ユーザーが入力する値で IRC コネクションを作成します。

Hostname

エクステンション定義 JSON ファイルの properties オブジェクト

コネクターエクステンションでは以下が行われます。

  • トップレベルの properties オブジェクトが必要です。このオブジェクトは、Fuse Online ユーザーがコネクターを選択してコネクションを作成する時に Fuse Online で何を表示するかを制御します。この properties オブジェクトには、コネクションを作成するための各フォームコントロールのプロパティーセットが含まれます。
  • action オブジェクトでは、アクションごとに properties オブジェクトがあります。これらの properties オブジェクトごとに、そのアクションを設定するための各フォームコントロールのプロパティーセットがあります。

ステップエクステンションでは、actions オブジェクトに properties オブジェクトが含まれます。properties オブジェクトは、ステップを設定するための各フォームコントロールのプロパティーセットを定義します。JSON 階層は、以下のようになります。

"actions": [
   {
      ...

      "propertyDefinitionSteps": [
         {
            ...

            "properties":
               {
                  "control-ONE": {
                     "type": "string",
                     "displayName": "Topic Name",
                     "order": "2",
                     ...,
                     }

                  "control-TWO": {
                     "type": "boolean",
                     "displayName": "Urgent",
                     "order": "3",
                     ...
                     }

                  "control-THREE": {
                     "type": "textarea",
                     "displayName": "Comment",
                     "order": "1",
                     ...,
                     }
 } } ]

Java ファイルのユーザーインターフェイスプロパティー

Java ファイルでユーザーインターフェイスのフォームコントロールを定義するには、コネクション、アクション、またはステップのユーザー設定を定義する各クラスファイルに io.syndesis.extension.api.annotations.ConfigurationProperty をインポートします。Fuse Online コンソールが表示する各フォームコントロールに対して、@ConfigurationProperty アノテーションと後続のプロパティーリストを指定します。指定できるプロパティーに関する詳細は、このセクションの最後にあるユーザーインターフェイスプロパティーの参照テーブルを参照してください。

以下のコードは、単一のフォームコントロールのプロパティー定義を表しています。このコードは、RouteBuilder で Camel ルートを開発する例になります。

public class LogAction extends RouteBuilder {
    @ConfigurationProperty(
        name = "prefix",
        description = "The Log body prefix message",
        displayName = "Log Prefix",
        type = "string")

以下のコードは、2 つのコントロールのプロパティー定義を表しています。このコードは、Syndesis Step API をした例です。

@Action(id = "split", name = "Split", description = "Split your exchange")
public class SplitAction implements Step {

    @ConfigurationProperty(
        name = "language",
        displayName = "Language",
        description = "The language used for the expression")
    private String language;

    @ConfigurationProperty(
        name = "expression",
        displayName = "Expression",
        description = "The expression used to split the exchange
     private String language;

コントロールフォーム入力ファイルの説明

各 HTML フォームコントロールのプロパティーセットでは、type プロパティーが Fuse Online が表示するフォームコントロールの入力タイプを定義します。HTML フォームの入力タイプに関する詳細は、https://www.w3schools.com/html/html_form_input_types.asp を参照してください。

以下の表に、Fuse Online フォームコントロールの可能な入力タイプを示します。制御のプロパティーのセットで、不明な type の値を指定すると、Fuse Online は 1 行のテキストを許可する入力フィールドを表示します。デフォルトは "type": "text" です。

type プロパティーの値HTMLFuse Online が表示するもの

boolean

<input type="checkbox">

ユーザーが選択可能または不可能なチェックボックス。

duration

Fuse Online ユーザーが時間の単位を選択できるようにするカスタム制御。ミリ秒、秒、分、時、または日を選択できます。また、ユーザーは番号を入力し、Fuse Online はミリ秒数を返します。例:
"properties": {
   "period": {
      "type": "duration"
      "defaultValue": 60000,
      "description": "Period",
      "displayName": "Period",
      "labelHint": "Delay between integration executions.",
      "required": true,
      "secret": false,
   }
}

hidden

<input type="hidden">

このフィールドは Fuse Online コンソールに表示されません。他のプロパティーを使用して、テキストデータなどのこのフィールドに関連するデータを指定できます。Fuse Online ユーザーはこのデータを表示または変更できませんが、ユーザーが Fuse Online ページの View Source を選択すると、ソース表示に非表示のフィールドが表示されます。そのため、セキュリティーの目的で非表示フィールドを使用しないでください。

intintegerlongnumber

<input type="number">

数字を許可する入力フィールドです。

password

<input type="password">

ユーザーが入力する文字を通常はアスタリスクでマスクする入力フィールド。

select

<select> 要素の例:
<select name="targets">
  <option value="queue">Queue</option>
  <option value="topic">Topic</option>
</select>

フォームコントロールの enum プロパティーで指定するラベルと値のペアのエントリーが含まれるドロップダウンメニュー。

textstring、または未知の値

<input type="text">`

1 行のテキストを許可する入力フィールド。

textarea

<input type="textarea"

textarea 要素が使用されます。

コントロールフォームのユーザーインターフェイスプロパティーの説明

コネクターまたはステップエクステンションでは、Fuse Online コンソールに表示される各 HTML フォームコントロールに対して、以下の表に説明があるプロパティーを 1 つ以上指定できます。HTML フォームの入力タイプに関する詳細は、https://www.w3schools.com/html/html_form_input_types.asp を参照してください。

プロパティー名タイプ説明

type

string

Fuse Online が表示するフォームコントロールの種類を制御します。詳細は、前述の表を参照してください。

cols

number

textarea フィールドに設定された場合、textarea 制御で最初に表示される列数を制御します。

controlHint または controlTooltip

string

設定された場合、値はフォームコントロール要素の HTML title 属性にマッピングされます。title 属性を持つ他の要素と同様に、コントロールにカーソルを合わせるとツールチップが表示されます。ツールチップの内容は、controlHint または controlTooltip プロパティーの値から取得されます。

dataList

array

type プロパティーの値が text の場合、Fuse Online は dataList プロパティーの値を使用してタイプアヘッドサポートを追加します。文字列の配列を指定します。

defaultValue

type プロパティーの値によって異なります。

Fuse Online は、最初にこの値をフォームフィールドに表示します。defaultValue プロパティーの設定のタイプは、type プロパティーの値と一致する必要があります。たとえば、type プロパティーが number に設定された場合、defaultValue 設定は number になります。ユーザーがこの初期フィールド値を変更しないと、Fuse Online は defaultValue を使用します。

description

string

設定されている場合、Fuse Online はこの値をフォームコントロールの下に表示します。通常、これはコントロールに関する短い便利なメッセージです。

displayName

string

Fuse Online はこの値を表示します。

enum

array

設定した場合、Fuse Online は type プロパティーの設定をオーバーライドし、select コントロールを実装します。配列を label および value 属性のセットとして指定します。label 属性は、選択項目のラベルとしてユーザーインターフェイスに表示されます。value 属性は、対応する選択項目の値になります。

labelHint または labelTooltip

string

設定されている場合、表示名の横に ? アイコンが表示されます。Fuse Online ユーザーが ? アイコンをクリックすると、labelHint プロパティーの値が表示されます。

max

number

number フィールドが設定されている場合、許容される最大値を定義します。

min

number

number フィールドが設定されている場合、許容される最小値を定義します。

multiple

Boolean

select フィールドまたは enum プロパティーセットを持つフィールドに true が設定されている場合、Fuse Online は選択ドロップダウンの代わりに複数選択コントロールを表示します。

order

number

Fuse Online コンソールでの制御の順序を決定します。Fuse Online は昇順を適用します。つまり、"order": "1" のコントロールが最初に表示されます。order プロパティーを指定しないと、Fuse Online は JSON ファイルが定義する順序でコントロールを表示します。

placeholder

string

設定された場合、ユーザーに想定される入力を分かりやすく示すため、この値を薄いフォントで入力フィールドに表示します。

required

Boolean

required 属性がコントロールに設定されるかどうかを制御します。true の場合、Fuse Online ユーザーはこのコントロールの値を入力する必要があります。

raws

number

type プロパティーの値が textarea の場合、rows プロパティーは textarea コントロールに最初に表示される行数を制御します。

secret

Boolean

指定された場合、Fuse Online はコントロールの type プロパティーの設定を password に変更します。

9.3.6. エクステンションをサポートする Maven プラグインの説明

extension-maven-plugin は、エクステンションを有効な Spring Boot モジュールとしてパッケージ化し、エクステンションの開発をサポートします。Java に実装するステップエクステンションでは、このプラグインでエクステンション定義 JSON ファイルを生成できます。

Maven プロジェクトの pom.xml ファイルに、以下のプラグイン宣言を追加します。

<plugin>
    <groupId>io.syndesis.extension</groupId>
    <artifactId>extension-maven-plugin</artifactId>
    <version>${syndesis.version}</version>
    <executions>
        <execution>
        <goals>
            <goal>generate-metadata</goal>
            <goal>repackage-extension</goal>
        </goals>
        </execution>
    </executions>
</plugin>

extension-maven-plugin は以下のゴールを定義します。

  • generate-metadata は、生成された JAR ファイルに含まれる JSON エクステンション定義ファイルを以下のように生成します。

    1. Maven は META-INF/syndesis/syndesis-extension-definition.json ファイルにあるデータ構造の指定から開始します (このファイルがある場合)。

      XML でコーディングする場合、エクステンション定義 JSON ファイルを独自に定義する必要があり、そのファイルに必要なデータ構造をすべて指定する必要があります。

      コネクターまたはライブラリーエクステンションを開発する場合、エクステンション定義 JSON ファイルを独自に定義する必要があり、そのファイルに必要なデータ構造をすべて指定する必要があります。

      Java でステップエクステンションを開発する場合、以下を行うことが可能です。

      • エクステンション定義 JSON ファイルをユーザー自身が作成します。
      • Java コードで、必要なデータ構造すべてを定義するアノテーションを指定します。ユーザーはエクステンション定義 JSON ファイルを作成しません。
      • エクステンション定義 JSON ファイルを作成し、一部のデータ構造を指定します。
    2. Java で開発するステップエクステンションの場合、Maven はコードアノテーションから、不足している指定を取得します。
    3. Maven は、scope が provided で、extension-bom を介して管理される依存関係を指定する、依存関係リストを追加します。
  • repackage-extension はエクステンションをパッケージ化します。

    • extension-bom を介して管理されない依存関係および関連する推移的依存関係は、生成された JAR の lib フォルダーにあります。
    • ライブラリーエクステンションの場合、scope が system の依存関係は、生成された JAR の lib フォルダーにあります。

たとえば、Maven プロジェクトに以下の pom.xml ファイルがあるとします。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

  <modelVersion>4.0.0</modelVersion>
  <groupId>com.company</groupId>
  <artifactId>my-extension</artifactId>
  <version>1.0.0</version>
  <name>MyExtension</name>
  <description>A Sample Extension</description>
  <packaging>jar</packaging>

  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>io.syndesis.extension</groupId>
        <artifactId>extension-bom</artifactId>
        <version>1.3.10</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
    </dependencies>
  </dependencyManagement>

  <dependencies>
    <dependency>
      <groupId>io.syndesis.extension</groupId>
      <artifactId>extension-api</artifactId>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>com.github.lalyos</groupId>
      <artifactId>jfiglet</artifactId>
      <version>0.0.8</version>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.7.0</version>
        <configuration>
          <source>1.8</source>
          <target>1.8</target>
        </configuration>
      </plugin>
      <plugin>
        <groupId>io.syndesis.extension</groupId>
        <artifactId>extension-maven-plugin</artifactId>
        <version>1.3.10</version>
        <executions>
          <execution>
            <goals>
              <goal>generate-metadata</goal>
              <goal>repackage-extension</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
</project>

この pom.xml ファイルを基にすると、生成されたエクステンション定義 JSON ファイルは以下のようになります。

{
  "name": "MyExtension",
  "description": "A Sample Extension",
  "extensionId": "com.company:my-extension",
  "version": "1.0.0",
  "dependencies": [ {
    "type": "MAVEN",
    "id": "io.syndesis.extension:extension-api:jar:1.3.10"
  } ],
  "extensionType": "Libraries",
  "schemaVersion": "v1"
}

生成されたアーカイブの構造と内容は次のようになります。

my-extension-1.0.0.jar
|
+- lib
|  |
|  + jfiglet-0.0.8.jar
|
+- META-INF
  |
  +- MANIFEST.MF
     |
     +- syndesis
        |
        +- syndesis-extension-definition.json

9.3.7. エクステンションでデータシェイプを指定する方法

データシェイプは、データマッパーによって使用されるデータタイプメタデータを保持します。データマッパーはこのメタデータを、データマッパーユーザーインターフェイスでソースおよびターゲットデータフィールドを表示するために使用する内部ドキュメントに変換します。コネクターまたはカスタムステップのエクステンション定義 JSON ファイルでは、各アクションの指定が入力データシェイプ (inputDataShape) および出力データシェイプ (outputDataShape) を定義します。

エクステンションを開発する場合、データマッパーがソースおよびターゲットフィールドを正しく処理および表示できるようにするデータシェイププロパティーを指定することが重要になります。以下のデータシェイププロパティーは、データマッパーの動作に影響します。

  • kind
  • type
  • specification
  • name
  • description

kind プロパティー

データシェイプ kind プロパティーは DataShapeKinds 列挙によって表されます。kind プロパティーで使用可能な値は次のとおりです。

  • any は、データタイプが構造化されていないことを示します。たとえば、バイト配列やフリーフォーマットテキストであることがあります。データマッパーは、kind プロパティーが any に設定されている場合にデータシェイプを無視します。つまり、データはデータマッパーに表示されないため、このデータとフィールドの間にマッピングを作成することはできません。

    しかし、kind プロパティーが any に設定された場合、カスタムコネクターから作成したコネクションを設定するときに、Fuse Online は入力および出力データタイプを指定するよう要求します。これは、コネクションをインテグレーションに追加するときに発生します。データシェイプのスキーマの種類、指定するスキーマの種類に対応するドキュメント、およびデータタイプの名前を指定できます。

  • none はデータタイプがないことを示します。入力データシェイプでは、コネクションまたはステップがデータを読み取らないことを示します。出力データシェイプでは、コネクションまたはステップがデータを変更しないことを示します。たとえば、入力メッセージボディーが出力メッセージボディーに転送される場合は、kind プロパティーを none に設定すると、データが通過することを意味します。データマッパーは、kindnone に設定された場合にデータシェイプを無視します。つまり、データはデータマッパーに表示されないため、このデータとフィールドの間にマッピングを作成することはできません。
  • java は、データタイプが Java クラスによって表されることを示します。type プロパティーの完全修飾クラス名を指定して、"kind": "java" 宣言に従います。以下は例になります。

    "outputDataShape": {
         "kind": "java",
         "type": "org.apache.camel.component.telegram.model.IncomingMessage"
    },
  • json-schema はデータタイプが JSON スキーマによって表されることを示します。kindjson-schema に設定された場合、JSON スキーマをデータシェイプの specification プロパティーの値として指定します。以下は例になります。

    "inputDataShape": {
      "description": "Person data",
      "kind": "json-schema",
      "name": "Person",
      "specification": "{\"$schema\":\"http://json-schema.org/draft-04/schema#\",\"title\":\"Person\",\"type\":\"object\",\"properties\":{\"firstName\":{...}}}"
    }

    SAP Concur コネクターのコードには、JSON スキーマによって指定されるデータシェイプの例 が含まれています。

  • json-instance は、データタイプが JSON インスタンスで表されることを示しています。kindjson-instance に設定された場合、JSON インスタンスをデータシェイプの specification プロパティーの値として指定します。以下は例になります。

    "inputDataShape": {
      "description": "Person data",
      "kind": "json-instance",
      "name": "Person",
      "specification": "{\"firstName\":\"John\",...}"
    }
  • xml-schema は、データタイプが XML スキーマで表されることを示しています。kindxml-schema に設定された場合、XML スキーマをデータシェイプの specification プロパティーの値として指定します。以下は例になります。

    "inputDataShape": {
      "description": "Person data",
      "kind": "xml-schema",
      "name": "Person",
      "specification": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?><xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">...</xs:schema>"
    }
  • xml-instance は、データタイプが XML インスタンスによって表されることを示しています。kindxml-instance に設定された場合、XML インスタンスをデータシェイプの specification プロパティーの値として指定します。以下に例を示します。

    "inputDataShape": {
      "description": "Person data",
      "kind": "xml-instance",
      "name": "Person",
      "specification": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?><Person><firstName>Jane</firstName></Person>"
    }
  • csv-instance は、データ型が CSV インスタンスによって表されることを示します。

    CSV データのデータマッパーのサポートは、テクノロジープレビュー機能であることに注意してください。

    kindcsv-instance に設定されている場合は、CSV インスタンスをデータシェイプの specification プロパティーの値として指定します。以下に例を示します。

    "inputDataShape": {
      "description": "Person data",
      "kind": "csv-instance",
      "name": "Person",
      "specification":  "John,Doe,120 Jefferson Street,Riverside, NJ, 08075"
    }

    kindcsv-instance に設定されている場合は、次の boolean (true/false) パラメーターを指定できます。

    ラベル名前。説明

    ヘッダー名の重複を許可

    allowDuplicateHeaderNames

    CSV データのヘッダー行で名前の重複を許可します。

    欠落している列名を許可

    allowMissingColumnNames

    CSV データのヘッダー行を解析するときに、欠落している列名を許可します。

    コメントマーカー

    commentMarker

    CSV データのコメント行の開始を示す文字を指定します。

    デリミタ

    delimiter

    CSV データの値を区切る文字 (通常は ";"、","、または "\t") を指定します。

    Escape

    escape

    CSV データのエスケープ文字を指定します。

    ヘッダーとしての最初のレコード

    firstRecordAsHeader

    CSV データの最初のレコードをヘッダー行として使用します。

    空行を無視

    ignoreEmptyLines

    CSV データの空行を無視します。

    ヘッダーの大文字小文字を無視

    ignoreHeaderCase

    CSV データのヘッダー行の大文字と小文字を無視します。

    周囲のスペースを無視

    ignoreSurroundingSpaces

    CSV データを囲む空白文字は無視されます。

    Null 文字列

    nullString

    CSV データで null との間で変換するときに使用する文字列を指定します。

    ヘッダーレコードをスキップ

    skipHeaderRecord

    CSV データのヘッダーレコードをスキップします。

type プロパティー

kind プロパティーの値が java の場合、"kind": "java" 宣言の後に完全修飾 Java クラス名を指定する type 宣言が続きます。以下は例になります。

"outputDataShape": {
     "kind": "java",
     "type": "org.apache.camel.component.telegram.model.IncomingMessage"
},

kind プロパティーが java 以外に設定された場合、type プロパティーの設定は無視されます。

specification プロパティー

kind プロパティーの設定は、以下の表のように、specification プロパティーの設定を決定します。

kind プロパティーの設定specification プロパティーの設定

java

Java インスペクションの結果。

Java で作成する各エクステンションに、extension-maven-plugin を使用して、最低でも Java インスペクションの結果を取得します。プラグインは、Java インスペクションの結果を specification プロパティーの設定として JSON エクステンション定義ファイルに挿入します。これは、Fuse Online のデータマッピングに必要な Java インスペクションの結果を取得する唯一の方法です。

Java で記述されたステップエクステンションの場合、extension-maven-plugin は JSON エクステンション定義ファイルを生成し、必要なコンテンツを追加します。コネクターエクステンションでは、extension-maven-plugin は Java インスペクションの結果を JSON エクステンション定義ファイルに挿入しますが、プラグインが挿入しない必要なコンテンツを手作業で追加する必要があります。

json-schema

実際の JSON スキーマのドキュメント。設定をドキュメントへの参照とすることはできず、参照の手段として JSON スキーマが他の JSON スキーマドキュメントを示すことはできません。

json-instance

サンプルデータが含まれる実際の JSON ドキュメント。データマッパーは、サンプルデータからデータタイプを取得します。この設定をドキュメントへの参照とすることはできません。

xml-schema

実際の XML スキーマドキュメント。設定をドキュメントへの参照とすることはできず、参照の手段として XML スキーマが他の XML スキーマドキュメントを示すことはできません。

xml-instance

実際の XML インスタンスドキュメントです。この設定をドキュメントへの参照とすることはできません。

csv-instance

実際の CSV インスタンスドキュメント。この設定をドキュメントへの参照とすることはできません。

any

specification プロパティーは必要ありません。設定は無視されます。

none

specification プロパティーは必要ありません。設定は無視されます。

name プロパティー

データシェイプの name プロパティーは、データタイプの人間が判読できる名前を指定します。データマッパーは、この名前をデータフィールドのラベルとしてユーザーインターフェイスに表示します。以下のイメージの Person は、name プロパティーの値が表示される場所の例になります。

Name example

この名前は、Fuse Online フロービジュアライゼーションのデータタイプインジケーターにも表示されます。

description プロパティー

データシェイプの description プロパティーは、データマッパーユーザーインターフェイスのデータタイプ名にカーソルを合わせたときにツールチップとして表示されるテキストを指定します。

9.3.8. ステップエクステンションの開発例

ステップエクステンションは、1 つまたは複数のカスタムステップを実装します。各カスタムステップは、コネクション間のインテグレーションデータを処理するために 1 つのアクションを実装します。以下の例は、ステップエクステンション開発の代替を示します。

Syndesis は、syndesis-extension-plugin とともに使用できる、カスタム Java アノテーションを提供します。ステップエクステンションまたはコネクターエクステンションを Java で実装する場合、Maven がアクション定義をエクステンション定義 JSON ファイルに追加できるようにするアノテーションを指定できます。アノテーションの処理を有効にするには、以下の依存関係を Maven プロジェクトに追加します。

<dependency>
  <groupId>io.syndesis.extension</groupId>
  <artifactId>extension-annotation-processor</artifactId>
  <optional>true</optional>
</dependency>

Spring Boot はインテグレーションランタイムであるため、Bean を Camel コンテキストにインジェクトするには、Spring Boot の標準の方法に従う必要があります。たとえば、自動設定クラスを作成 し、Bean を作成します。ただし、デフォルトの動作では、エクステンションコードはパッケージスキャンの対象ではありません。したがって、ステップエクステンションの META-INF/spring.factories ファイルを作成し、内容を追加する必要があります。

9.3.8.1. XML フラグメントでの Camel ルートの開発例

カスタムステップを開発するには、 direct などの入力がある Camel ルートである XML フラグメントとして、アクションを実装できます。Syndesis ランタイムは、このルートを他の Camel ルートを呼び出す同じ方法で呼び出します。

たとえば、任意の接頭辞を持つメッセージのボディーをログに記録するステップを作成する場合に以下の XML はこれを行う Camel ルートを定義します。

<?xml version="1.0" encoding="UTF-8"?>
<routes xmlns="http://camel.apache.org/schema/spring"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
      http://camel.apache.org/schema/spring
      http://camel.apache.org/schema/spring/camel-spring.xsd">

  <route id="log-body-with-prefix">
    <from uri="direct:log"/>
    <choice>
      <when>
        <simple>${header.prefix} != ''</simple>
        <log message="${header.prefix} ${body}"/>
      </when>
      <otherwise>
        <log message="Output ${body}"/>
      </otherwise>
    </choice>
  </route>

</routes>

XML でエクステンションを開発する場合は、エクステンション定義 JSON ファイルを独自に作成する必要があります。この XML フラグメントに対し、src/main/resources/META-INF/syndesis/syndesis-extension-definition.json ファイルは以下のようにアクションを定義できます。

{
  "actionType": "step",
  "id": "log-body-with-prefix",
  "name": "Log body with prefix",
  "description": "A simple body log with a prefix",
  "descriptor": {
    "kind": "ENDPOINT", 1
    "entrypoint": "direct:log", 2
    "resource": "classpath:log-body-action.xml", 3
    "inputDataShape": {
      "kind": "none"
    },
    "outputDataShape": {
      "kind": "none"
    },
  "propertyDefinitionSteps": [ {
    "description": "extension-properties",
    "name": "extension-properties",
    "properties": { 4
      "prefix": {
        "componentProperty": false,
        "deprecated": false,
        "description": "The Log body prefix message",
        "displayName": "Log Prefix",
        "javaType": "String",
        "kind": "parameter",
        "required": false,
        "secret": false,
        "type": "string"
      }
    }
  } ]
  }
}
1
アクションのタイプは ENDPOINT に設定されます。ランタイムは、Camel エンドポイントを呼び出して、このカスタムステップによって提供されるアクションを実行します。
2
呼び出す Camel エンドポイントは direct:log です。これはルートの from 指定です。
3
これは、XML フラグメントの場所になります。
4
これらは、このカスタムステップでアクションが定義したプロパティーで、このステップをインテグレーションに追加するインテグレーターに公開します。Fuse Online では、インテグレーターがユーザーインターフェイスで指定する値は、プロパティーと同じ名前を持つメッセージヘッダーにマップされます。この例では、インテグレーターは Log Prefix 表示名を持つ 1 つの入力フィールドを確認できます。詳細は ユーザーインターフェイスプロパティーの説明 を参照してください。
警告

Syndesis は、完全な Camel XML 設定をサポートしません。Syndesis は <routes> タグのみをサポートします。

9.3.8.2. RouteBuilder を使った Camel ルートの開発例

カスタムステップを実装するには、RouteBuilder クラスを利用してアクションを Camel ルートとして開発します。このようなルートには、direct などの入力があります。Syndesis は、他の Camel ルートの呼び出しと同じ方法でこのルートを呼び出します。

任意の接頭辞でメッセージのボディーをログに記録するステップを作成する例を実装するには、以下のように記述します。

import org.apache.camel.builder.RouteBuilder;

import io.syndesis.extension.api.annotations.Action;
import io.syndesis.extension.api.annotations.ConfigurationProperty;

@Action( 1
    id = "log-body-with-prefix",
    name = "Log body with prefix",
    description = "A simple body log with a prefix",
    entrypoint = "direct:log")
public class LogAction extends RouteBuilder {
    @ConfigurationProperty( 2
        name = "prefix",
        description = "The Log body prefix message",
        displayName = "Log Prefix",
        type = "string")
    private String prefix;

    @Override
    public void configure() throws Exception {
        from("direct::start") 3
            .choice()
                .when(simple("${header.prefix} != ''"))
                    .log("${header.prefix} ${body}")
                .otherwise()
                    .log("Output ${body}")
            .endChoice();
    }
}
1
@Action アノテーションは、アクション定義を示します。
2
@ConfigurationProperty アノテーションは、ユーザーインターフェイスのフォームコントロールの定義を示します。詳細は ユーザーインターフェイスプロパティーの説明 を参照してください。
3
これはアクションの実装です。

この Java コードは Syndesis アノテーションを使用するため、extension-maven-plugin はアクション定義を自動的に生成できます。エクステンション定義 JSON ファイルのアクション定義は以下のようになります。

{
  "id": "log-body-with-prefix",
  "name": "Log body with prefix",
  "description": "A simple body log with a prefix",
  "descriptor": {
    "kind": "ENDPOINT", 1
    "entrypoint": "direct:log", 2
    "resource": "class:io.syndesis.extension.log.LogAction", 3
    "inputDataShape": {
      "kind": "none"
    },
    "outputDataShape": {
      "kind": "none"
    },
    "propertyDefinitionSteps": [ {
      "description": "extension-properties",
      "name": "extension-properties",
      "properties": { 4
        "prefix": {
          "componentProperty": false,
          "deprecated": false,
          "description": "The Log body prefix message",
          "displayName": "Log Prefix",
          "javaType": "java.lang.String",
          "kind": "parameter",
          "required": false,
          "secret": false,
          "type": "string",
          "raw": false
        }
      }
    } ]
  },
  "actionType": "step"
}
1
アクションのタイプは ENDPOINT です。ランタイムは Camel エンドポイントを呼び出して、このステップが実装するアクションを実行します。
2
これが呼び出す Camel エンドポイントです。これはルートの from 指定です。
3
これは、RoutesBuilder を実装するクラスです。
4
これらは、このカスタムステップでアクションが定義したプロパティーで、このステップをインテグレーションに追加するインテグレーターに公開します。Fuse Online では、インテグレーターがユーザーインターフェイスで指定する値は、プロパティーと同じ名前を持つメッセージヘッダーにマップされます。この例では、インテグレーターは Log Prefix 表示名を持つ 1 つの入力フィールドを確認できます。詳細は ユーザーインターフェイスプロパティーの説明 を参照してください。

9.3.8.3. RouteBuilder および Spring Boot を使った Camel ルートの開発例

カスタムステップを実装するには、RouteBuilder クラスと Spring Boot を利用してアクションを Camel ルートとして開発します。この例では、Spring Boot は RouteBuilder オブジェクトを Camel コンテキストに登録するファシリティーです。Syndesis は、他の Camel ルートの呼び出しと同じ方法でこのルートを呼び出します。

任意の接頭辞でメッセージのボディーをログに記録するステップを作成する例を実装するには、以下のように記述します。

import io.syndesis.extension.api.annotations.Action;
import io.syndesis.extension.api.annotations.ConfigurationProperty;
import org.apache.camel.builder.RouteBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ActionsConfiguration {

    @Action( 1
        id = "log-body-with-prefix",
        name = "Log body with prefix",
        description = "A simple body log with a prefix",
        entrypoint = "direct:log")
    @ConfigurationProperty( 2
        name = "prefix",
        description = "The Log body prefix message",
        displayName = "Log Prefix",
        type = "string")
    @Bean 3
    public RouteBuilder logBodyWithprefix() {
        return new RouteBuilder() {
            @Override
            public void configure() throws Exception {
                from("direct::start") 4
                    .choice()
                        .when(simple("${header.prefix} != ''"))
                            .log("${header.prefix} ${body}")
                        .otherwise()
                            .log("Output ${body}")
                    .endChoice();
             }
        };
    }
}
1
@Action アノテーションは、アクション定義を示します。
2
@ConfigurationProperty アノテーションは、ユーザーインターフェイスのフォームコントロールの定義を示します。詳細は ユーザーインターフェイスプロパティーの説明 を参照してください。
3
RouteBuilder オブジェクトを Bean として登録します。
4
これはアクションの実装です。

この Java コードは Syndesis アノテーションを使用するため、extension-maven-plugin はアクション定義を自動的に生成できます。エクステンション定義 JSON ファイルのアクション定義は以下のようになります。

{
  "id": "log-body-with-prefix",
  "name": "Log body with prefix",
  "description": "A simple body log with a prefix",
  "descriptor": {
    "kind": "ENDPOINT", 1
    "entrypoint": "direct:log", 2
    "inputDataShape": {
      "kind": "none"
    },
    "outputDataShape": {
      "kind": "none"
    },
    "propertyDefinitionSteps": [ {
      "description": "extension-properties",
      "name": "extension-properties",
      "properties": { 3
        "prefix": {
          "componentProperty": false,
          "deprecated": false,
          "description": "The Log body prefix message",
          "displayName": "Log Prefix",
          "javaType": "java.lang.String",
          "kind": "parameter",
          "required": false,
          "secret": false,
          "type": "string",
          "raw": false
        }
      }
    } ]
  },
  "actionType": "step"
}
1
アクションのタイプは ENDPOINT です。ランタイムは Camel エンドポイントを呼び出して、このステップが実装するアクションを実行します。
2
これが呼び出す Camel エンドポイントです。これはルートの from 指定です。
3
これらは、このカスタムステップでアクションが定義したプロパティーで、このステップをインテグレーションに追加するインテグレーターに公開します。Fuse Online では、インテグレーターがユーザーインターフェイスで指定する値は、プロパティーと同じ名前を持つメッセージヘッダーにマップされます。この例では、インテグレーターは Log Prefix 表示名を持つ 1 つの入力フィールドを確認できます。詳細は ユーザーインターフェイスプロパティーの説明 を参照してください。
重要

Spring Boot が設定クラスを検出できるようにするには、以下のように META-INF/spring.factories という名前のファイルにこれらのクラスを記載する必要があります。

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.company.ActionsConfiguration

Spring Boot では、設定クラスに最終的に登録するすべての Bean を Camel コンテキストで利用できます。詳細は、独自の自動設定を作成 するための Spring Boot ドキュメントを参照してください。

9.3.8.4. Camel Bean の使用例

アクションを Camel Bean プロセッサーとして開発すると、カスタムステップを実装できます。任意の接頭辞でメッセージのボディーをログに記録するステップを作成する例を実装するには、以下のように記述します。

import org.apache.camel.Body;
import org.apache.camel.Handler;
import org.apache.camel.Header;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.syndesis.extension.api.annotations.Action;
import io.syndesis.extension.api.annotations.ConfigurationProperty;

@Action(
    id = "log-body-with-prefix",
    name = "Log body with prefix",
    description = "A simple body log with a prefix")
public class LogAction  {
    private static final Logger LOGGER = LoggerFactory.getLogger(LogAction.class);

    @ConfigurationProperty(
        name = "prefix",
        description = "The Log body prefix message",
        displayName = "Log Prefix",
        type = "string")
    private String prefix;

    @Handler 1
    public void process(@Header("prefix") String prefix, @Body Object body) {
        if (prefix == null) {
            LOGGER.info("Output {}", body);
        } else {
            LOGGER.info("{} {}", prefix, body);
        }
    }
}
1
これは、アクションを実装する関数です。

この Java コードは Syndesis アノテーションを使用するため、extension-maven-plugin はアクション定義を自動的に生成できます。エクステンション定義 JSON ファイルのアクション定義は以下のようになります。

{
  "id": "log-body-with-prefix",
  "name": "Log body with prefix",
  "description": "A simple body log with a prefix",
  "descriptor": {
    "kind": "BEAN", 1
    "entrypoint": "io.syndesis.extension.log.LogAction::process", 2
    "inputDataShape": {
      "kind": "none"
    },
    "outputDataShape": {
      "kind": "none"
    },
    "propertyDefinitionSteps": [ {
      "description": "extension-properties",
      "name": "extension-properties",
      "properties": {
        "prefix": { 3
          "componentProperty": false,
          "deprecated": false,
          "description": "The Log body prefix message",
          "displayName": "Log Prefix",
          "javaType": "java.lang.String",
          "kind": "parameter",
          "required": false,
          "secret": false,
          "type": "string",
          "raw": false
        }
      }
    } ]
  },
  "actionType": "step"
}
1
アクションのタイプは BEAN です。ランタイムは、Camel Bean プロセッサーを呼び出して、このカスタムステップのアクションを実行します。
2
この Camel Bean を呼び出します。
3
これらは、このカスタムステップでアクションが定義したプロパティーで、このステップをインテグレーションに追加するインテグレーターに公開します。Fuse Online では、インテグレーターがユーザーインターフェイスで指定する値は、プロパティーと同じ名前を持つメッセージヘッダーにマップされます。この例では、インテグレーターは Log Prefix 表示名を持つ 1 つの入力フィールドを確認できます。詳細は ユーザーインターフェイスプロパティーの説明 を参照してください。

Bean を使用する場合、交換ヘッダーからユーザープロパティーを取得する代わりに、ユーザープロパティーを Bean にインジェクトすると便利である可能性があります。これには、インジェクトするプロパティーに getter および setter メソッドを実装します。アクション実装は以下のようになります。

import org.apache.camel.Body;
import org.apache.camel.Handler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.syndesis.extension.api.annotations.Action;
import io.syndesis.extension.api.annotations.ConfigurationProperty;

@Action(
    id = "log-body-with-prefix",
    name = "Log body with prefix",
    description = "A simple body log with a prefix")
public class LogAction  {
    private static final Logger LOGGER = LoggerFactory.getLogger(LogAction.class);

    @ConfigurationProperty(
        name = "prefix",
        description = "The Log body prefix message",
        displayName = "Log Prefix",
        type = "string")
    private String prefix;

    public void setPrefix(String prefix) { 1
        this.prefix = prefix;
    }

    public String getPrefix() { 2
        return prefix;
    }

    @Handler
    public void process(@Body Object body) {
        if (this.prefix == null) {
            LOGGER.info("Output {}", body);
        } else {
            LOGGER.info("{} {}", this.prefix, body);
        }
    }
}
1
これは、プロパティーの setter メソッドです。
2
これは、プロパティーの getter メソッドです。

9.3.8.5. Syndesis Step API の使用例

Syndesis Step API を使用することで、カスタムステップを実装できます。これにより、ランタイムルートの作成と対話することが可能になります。ProcessorDefinition クラスによって提供されるすべてのメソッドを使用でき、さらに複雑なルートを作成できます。Syndesis API に関する情報は http://javadoc.io/doc/io.syndesis.extension/extension-api を参照してください。

以下は、スプリットアクションを実装するために Syndesis Step API を使用するステップエクステンションの例になります。

import java.util.Map;
import java.util.Optional;

import io.syndesis.extension.api.Step;
import io.syndesis.extension.api.annotations.Action;
import io.syndesis.extension.api.annotations.ConfigurationProperty;
import org.apache.camel.CamelContext;
import org.apache.camel.model.ProcessorDefinition;
import org.apache.camel.util.ObjectHelper;
import org.apache.camel.Expression;
import org.apache.camel.builder.Builder;
import org.apache.camel.processor.aggregate.AggregationStrategy;
import org.apache.camel.processor.aggregate.UseOriginalAggregationStrategy;
import org.apache.camel.spi.Language;

@Action(id = "split", name = "Split", description = "Split your exchange")
public class SplitAction implements Step {

    @ConfigurationProperty(
        name = "language",
        displayName = "Language",
        description = "The language used for the expression")
    private String language;

    @ConfigurationProperty(
        name = "expression",
        displayName = "Expression",
        description = "The expression used to split the exchange")
    private String expression;

    public String getLanguage() {
        return language;
    }

    public void setLanguage(String language) {
        this.language = language;
    }

    public String getExpression() {
        return expression;
    }

    public void setExpression(String expression) {
        this.expression = expression;
    }

    @Override
    public Optional<ProcessorDefinition> configure(
            CamelContext context,
            ProcessorDefinition route,
            Map<String, Object> parameters) { 1

        String languageName = language;
        String expressionDefinition = expression;

        if (ObjectHelper.isEmpty(languageName) && ObjectHelper.isEmpty(expressionDefinition)) {
            route = route.split(Builder.body());
        } else if (ObjectHelper.isNotEmpty(expressionDefinition)) {

            if (ObjectHelper.isEmpty(languageName)) {
                languageName = "simple";
            }

            final Language splitLanguage = context.resolveLanguage(languageName);
            final Expression splitExpression = splitLanguage.createExpression(expressionDefinition);
            final AggregationStrategy aggreationStrategy = new UseOriginalAggregationStrategy(null, false);

            route = route.split(splitExpression).aggregationStrategy(aggreationStrategy);
        }

        return Optional.of(route);
    }
}
1
これは、カスタムステップが実行するアクションの実装です。

この Java コードは Syndesis アノテーションを使用するため、extension-maven-plugin はアクション定義を自動的に生成できます。エクステンション定義 JSON ファイルのアクション定義は以下のようになります。

{
  "id": "split",
  "name": "Split",
  "description": "Split your exchange",
  "descriptor": {
    "kind": "STEP", 1
    "entrypoint": "io.syndesis.extension.split.SplitAction", 2
    "inputDataShape": {
      "kind": "none"
    },
    "outputDataShape": {
      "kind": "none"
    },
    "propertyDefinitionSteps": [ {
      "description": "extension-properties",
      "name": "extension-properties",
      "properties": {
        "language": {
          "componentProperty": false,
          "deprecated": false,
          "description": "The language used for the expression",
          "displayName": "Language",
          "javaType": "java.lang.String",
          "kind": "parameter",
          "required": false,
          "secret": false,
          "type": "string",
          "raw": false
        },
        "expression": {
          "componentProperty": false,
          "deprecated": false,
          "description": "The expression used to split the exchange",
          "displayName": "Expression",
          "javaType": "java.lang.String",
          "kind": "parameter",
          "required": false,
          "secret": false,
          "type": "string",
          "raw": false
        }
      }
    } ]
  },
  "tags": [],
  "actionType": "step"
}
1
アクションのタイプは STEP です。
2
これは、Step インターフェイスを実装するクラスです。

その他のリソース

ユーザーインターフェイスプロパティーの詳細は ユーザーインターフェイスプロパティーの説明 を参照してください。

9.3.9. コネクターエクステンションの開発例

Fuse Online が、インテグレーションで接続するアプリケーションやサービスのコネクターを提供しない場合、経験のある開発者は Fuse Online に新しいコネクターを提供するエクステンションを作成できます。このドキュメントは、初心者向けのコネクターエクステンションの開発に関する情報を提供します。コネクターの開発に関する詳細は、Syndesis コミュニティーの Web サイトにある Developing Syndesis connectors を参照してください。

重要

コネクターエクステンションでは、Java コードからエクステンション定義 JSON ファイルを自動的に生成できません。

コネクターは基本的に Camel コンポーネントのプロキシーになります。コネクターは基盤のコンポーネントを設定し、エクステンション定義で定義されるオプションや、Fuse Online Web インターフェイスが収集するユーザー提供のオプションに応じてエンドポイントを作成します。

コネクターエクステンションの定義は、以下の追加のデータ構造を使用して、ステップエクステンションに必要なエクステンション定義を拡張します。

  • componentScheme

    コネクターが使用する Camel コンポーネントを定義します。コネクターまたはアクションに componentScheme を設定できます。componentScheme をコネクターとアクションの両方に設定した場合、アクションの設定が優先されます。

  • connectorCustomizers

    ComponentProxyCustomizer クラスを実装するクラスの一覧を指定します。各クラスはコネクターの動作をカスタマイズします。たとえば、クラスはプロパティーが基礎となるコンポーネントやエンドポイントに適用される前にプロパティーを操作したり、クラスは事前または事後のエンドポイントロジックを追加する場合があります。各クラスに対して、com.mycomponent.MyCustomizer のように実装の完全クラス名を指定します。connectorCustomizers はアクションおよびコネクターに設定できます。Fuse Online は設定に応じて、カスタマイザーを最初にコネクターに適用した後、アクションに適用します。

  • connectorFactory

    基盤のコンポーネント/エンドポイントの作成や設定を行う、ComponentProxyFactory クラスを実装するクラスを定義します。実装の完全クラス名を指定します。コネクターまたはアクションの connectorFactory を設定できます。アクションには優先順位があります。

カスタマイザーの例

以下のカスタマイザーの例は、個別のオプションから DataSource を設定します。

public class DataSourceCustomizer implements ComponentProxyCustomizer, CamelContextAware {
    private final static Logger LOGGER = LoggerFactory.getLogger(DataSourceCustomizer.class);

    private CamelContext camelContext;

    @Override
    public void setCamelContext(CamelContext camelContext) { 1
        this.camelContext = camelContext;
    }

    @Override
    public CamelContext getCamelContext() { 2
        return this.camelContext;
    }

    @Override
    public void customize(ComponentProxyComponent component, Map<String, Object> options) {
        if (!options.containsKey("dataSource")) {
            if (options.containsKey("user") && options.containsKey("password") && options.containsKey("url")) {
                try {
                    BasicDataSource ds = new BasicDataSource();

                    consumeOption(camelContext, options, "user", String.class, ds::setUsername); 3
                    consumeOption(camelContext, options, "password", String.class, ds::setPassword); 4
                    consumeOption(camelContext, options, "url", String.class, ds::setUrl); 5

                    options.put("dataSource", ds);
                } catch (@SuppressWarnings("PMD.AvoidCatchingGenericException") Exception e) {
                    throw new IllegalArgumentException(e);
                }
            } else {
                LOGGER.debug("Not enough information provided to set-up the DataSource");
            }
        }
    }
}
1 2
 Syndesis は CamelContextAware を実装することで Camel コンテキストをインジェクトし、カスタマイズメソッドを呼び出します。
3 4 5
 オプションを処理し、オプションマップから削除します。

プロパティーのインジェクト例

カスタマイザーが Java Bean の慣例に従う場合、以下のようにプロパティーもインジェクトできます (前述の例を編集)。

public class DataSourceCustomizer implements ComponentProxyCustomizer, CamelContextAware {
    private final static Logger LOGGER = LoggerFactory.getLogger(DataSourceCustomizer.class);

    private CamelContext camelContext;
    private String userName;
    private String password;
    private String url;

    @Override
    public void setCamelContext(CamelContext camelContext) { 1
        this.camelContext = camelContext;
    }

    @Override
    public CamelContext getCamelContext() { 2
        return this.camelContext;
    }

    public void setUserName(String userName) { 3
      this.userName = userName;
    }

    public String getUserName() { 4
      return this.userName;
    }

    public void setPassword(String password) { 5
      this.password = password;
    }

    public String getPassword() { 6
      return this.password;
    }

    public void setUrl(String url) { 7
      this.url = url;
    }

    public String getUrl() { 8
      return this.url;
    }

    @Override
    public void customize(ComponentProxyComponent component, Map<String, Object> options) {
        if (!options.containsKey("dataSource")) {
            if (userName != null && password != null && url != null) {
                try {
                    BasicDataSource ds = new BasicDataSource();
                    ds.setUserName(userName);
                    ds.setPassword(password);
                    ds.setUrl(url);

                    options.put("dataSource", ds);
                } catch (@SuppressWarnings("PMD.AvoidCatchingGenericException") Exception e) {
                    throw new IllegalArgumentException(e);
                }
            } else {
                LOGGER.debug("Not enough information provided to set-up the DataSource");
            }
        }
    }
}
1 2 3
 Syndesis は CamelContextAware を実装することで Camel コンテキストをインジェクトし、カスタマイズメソッドを呼び出します。このサンプルコードは、setCamelContext() および getCamelContext() メソッドを上書きし、ユーザー名を設定します。
4 5 6 7 8
 サンプルコードはインジェクトされたオプションを処理し、オプションマップから自動的に削除します。

カスタマイザーを使用した before/after 論理の設定

以下の例のように、カスタマイザーを使用して before/after 論理を設定できます。

public class AWSS3DeleteObjectCustomizer implements ComponentProxyCustomizer {
  	private String filenameKey;

    public void setFilenameKey(String filenameKey) {
      this.filenameKey = filenameKey;
    }

    public String getFilenameKey() {
        return this.filenameKey;
    }

    @Override
    public void customize(ComponentProxyComponent component, Map<String, Object> options) {
      	component.setBeforeProducer(this::beforeProducer);
    }

    public void beforeProducer(final Exchange exchange) throws IOException {
      	exchange.getIn().setHeader(S3Constants.S3_OPERATION, S3Operations.deleteObject);

    	  if (filenameKey != null) {
    		    exchange.getIn().setHeader(S3Constants.KEY, filenameKey);
    	  }
    }
}

ComponentProxyComponent の動作のカスタマイズ

ComponentProxyFactory クラスは、基礎となるコンポーネント/エイドポイントの作成や設定を行います。ComponentProxyFactory が作成する ComponentProxyComponent オブジェクトの動作をカスタマイズするには、以下のメソッドのいずれかをオーバーライドします。

  • createDelegateComponent()

    Syndesis は、プロキシーの開始時にこのメソッドを呼び出し、最終的に componentScheme オプションによって定義されたスキームでコンポーネントの専用インスタンスを作成します。

    このメソッドのデフォルトの動作は、いずれかのコネクター/アクションオプションがコンポーネントレベルで適用されるかどうかを判断します。同じオプションをエンドポイントに適用できない場合のみ、メソッドによってカスタムコンポーネントインスタンスが作成され、適用可能なオプションに応じて設定されます。

  • configureDelegateComponent()

    Syndesis は、委譲されたコンポーネントインスタンスの追加の動作を設定するためにカスタムコンポーネントインスタンスが作成された場合に限り、このメソッドを呼び出します。

  • createDelegateEndpoint()

    Syndesis は、プロキシーがエンドポイントを作成するときにこのメソッドを呼び出し、デフォルトで Camel カタログファシリティーを使用してエンドポイントを作成します。

  • configureDelegateEndpoint()

    委譲されたエンドポイントの作成後に、Syndesis がこのメソッドを呼び出し、委譲されたエンドポイントインスタンスの追加動作を設定します。以下に例を示します。

    public class IrcComponentProxyFactory implements ComponentProxyFactory {
    
        @Override
        public ComponentProxyComponent newInstance(String componentId, String componentScheme) {
            return new ComponentProxyComponent(componentId, componentScheme) {
                @Override
                protected void configureDelegateEndpoint(ComponentDefinition definition, Endpoint endpoint, Map<String, Object> options) throws Exception {
                    if (!(endpoint instanceof IrcEndpoint)) {
                        throw new IllegalStateException("Endpoint should be of type IrcEndpoint");
                    }
    
                    final IrcEndpoint ircEndpoint = (IrcEndpoint)endpoint;
                    final String channels = (String)options.remove("channels");
    
                    if (ObjectHelper.isNotEmpty(channels)) {
                        ircEndpoint.getConfiguration().setChannel(
                            Arrays.asList(channels.split(","))
                        );
                    }
                }
            };
        }
    }

9.3.10. ライブラリーエクステンションの開発方法

ライブラリーエクステンションは、インテグレーションがランタイムに必要なリソースを提供します。ライブラリーエクステンションは、ステップやコネクターを Fuse Online に提供しません。

インテグレーションを保存するときに、必要の応じて、インテグレーションと含まれるようにするインポートされたライブラリーエクステンションを 1 つまたは複数選択できます。

ライブラリーエクステンションは、いかなるアクションも定義しません。以下は、ライブラリーエクステンションの定義例になります。

{
  "schemaVersion" : "v1",
  "name" : "Example Library Extension",
  "description" : "Syndesis Extension for adding a runtime library",
  "extensionId" : "io.syndesis.extensions:syndesis-library",
  "version" : "1.0.0",
  "tags" : [ "my-libraries-extension" ],
  "extensionType" : "Libraries"
}

ライブラリーエクステンションの例は https://github.com/syndesisio/syndesis-extensions でも参照できます。

ライブラリーエクステンションの構造は、アクションがないこと以外は、ステップまたはコネクターエクステンションの構造と同じです。

ライブラリーエクステンションを作成する Maven プロジェクトで、Maven リポジトリーから使用できない依存関係を追加するには、以下のように system 依存関係を指定します。

<dependency>
    <groupId>com.company</groupId>
    <artifactId>my-library-extension</artifactId>
    <version>1.0</version>
    <scope>system</scope>
    <systemPath>${project.basedir}/lib/my-library-extension.jar</systemPath>
</dependency>

9.3.11. JDBC ドライバーライブラリーエクステンションの作成

Apache Derby、MySQL、および PostgreSQL 以外の SQL データベースに接続するには、接続するデータベースの JDBC ドライバーをラップするライブラリーエクステンションを作成します。Fuse Online にこのエクステンションをアップロードした後、Fuse Online が提供する Database コネクターはドライバーにアクセスしてプロプライエタリーデータベースへのコネクションを検証および作成することができます。特定のデータベースに新しいコネクターを作成しません。

Syndesis オープンソースコミュニティーは、JDBC ドライバーをラップするエクステンションを作成するためのプロジェクトを提供します。

エクステンションで 1 つのドライバーのみをパッケージ化します。これにより、特定のデータベースを管理する一環として、エクステンションの管理が容易になります。ただし、複数のドライバーをラップするライブラリーエクステンションを作成することは可能です。

前提条件

Syndesis プロジェクトを使用するには、GitHub アカウントが必要です。

手順

  1. 以下のいずれかを行って、接続するデータベースの JDBC ドライバーへアクセスできるようにします。

    1. ドライバーが Maven リポジトリーにあることを確認します。
    2. ドライバーをダウンロードします。
  2. ブラウザーのタブで https://github.com/syndesisio/syndesis-extensions にアクセスします。
  3. syndesis-extensions リポジトリーを GitHub アカウントにフォークします。
  4. フォークからローカルのクローンを作成します。
  5. syndesis-extensions のクローンで以下を行います。

    1. このドライバーが Maven リポジトリーにない場合、syndesis-library-jdbc-driver/lib フォルダーにコピーします。
    2. syndesis-library-jdbc-driver/pom.xml ファイルを編集します。

      1. Name 要素の値を更新し、このエクステンションに選択する名前にします。
      2. Description 要素の値を更新し、このエクステンションに関する便利な情報を提供します。
      3. ドライバーを syndesis-library-jdbc-driver/lib にコピーした場合、pom.xmlsystemPath がそのドライバーファイルを示すようにしてください。必要に応じて、groupIdartifactId、および version を変更し、ドライバーに応じた適切な値を反映するようにします。
      4. このドライバーが Maven リポジトリーにある場合は、その Maven 依存関係への参照が pom.xml ファイルにあることを確認します。
      5. pom.xml ファイルの残りの内容を確認し、必要に応じて関連するメタデータを変更します。
    3. ./mvnw -pl :syndesis-library-jdbc-driver clean package を実行し、エクステンションをビルドします。

生成された .jar ファイルは syndesis-library-jdbc-driver/target フォルダーにあります。この .jar ファイルを Fuse Online でエクステンションとしてインポートします。

ライブラリーエクステンションのインポート後、Fuse Online にインテグレーションを保存するときに、必要に応じて、インポートされたライブラリーエクステンションを選択し、インテグレーションに関連付けることができます。