CData Embedded コネクタを使った動的な接続 UI の設計



CData Embedded は、多様なデータソースに対応するコネクタを提供しており、それぞれが独自の認証メカニズムと設定オプションを備えています。各コネクタには、接続を確立するためにユーザーが設定する固有のプロパティセットがあります。CData の Embedded パートナーは、これらのプロパティをユーザーに分かりやすく提示する、柔軟に構成できるユーザーインターフェースを必要とするケースが多くあります。この要件をサポートするために、ドライバーは2つのシステムテーブル(sys_connection_propssys_connection_hierarchy)を通じて、利用可能なプロパティに関する情報を返します。

この記事では、これら2つのアプローチを活用して、組み込みアプリケーションにユーザーフレンドリーな接続インターフェースを作成する方法を説明します。

なお、この記事の例では SalesforceMicrosoft SharePoint データソースを使用してプロパティを説明していますが、ここで紹介するコンセプトはすべての CData Embedded コネクタに適用できます。

目次


sys_connection_props

sys_connection_props システムテーブルは、利用可能なすべての接続プロパティの情報をフラットなリストとして返します。このテーブルは各プロパティの包括的なメタデータを提供するため、接続オプションの全体像を把握したい場合に便利です。

このテーブルをクエリする際は、config 接続文字列のフォーマット jdbc:cdata:[driverName]:config: を使用します。[driverName] にはデータソース名を指定します。この接続文字列を使用すると、データソースへの有効な接続を確立せずにテーブルをクエリできます。

カラム

以下は、sys_connection_props テーブルが公開するカラムの定義です。

  • Name: 接続プロパティの名前。
  • ShortDescription: プロパティの簡単な説明。
  • Type: 接続プロパティのデータ型。
  • Default: 明示的に設定されていない場合のデフォルト値。
  • Values: 指定可能な値のカンマ区切りリスト。リスト外の値を指定するとバリデーションエラーがスローされます。
  • Value: ユーザーが設定した値、または事前設定されたデフォルト値。
  • Required: 接続に必須かどうか。
  • Category: 接続プロパティのカテゴリ。
  • IsSessionProperty: セッションプロパティかどうか。現在の接続に関する情報の保存に使用されます。
  • Sensitivity: プロパティの機密レベル。ログや認証フォームでプロパティが難読化されるかどうかを示します。
  • PropertyName: 接続プロパティ名のキャメルケース省略形。
  • Ordinal: パラメータのインデックス。
  • CatOrdinal: パラメータカテゴリのインデックス。
  • Hierarchy: このプロパティと一緒に設定が必要な、関連する依存プロパティを表示します。
  • Visible: 接続 UI にプロパティが表示されるかどうか。
  • ETC: プロパティに関するその他の各種情報。

接続文字列で設定済み、またはデフォルト値を持つすべての接続プロパティを取得するには、以下のクエリを実行します。

SELECT * FROM sys_connection_props WHERE Value <> ''

出力サンプル

{
"SELECT * FROM sys_connection_props WHERE Name = 'Auth Scheme'": [
	{
		"Name" : "Auth Scheme",
		"ShortDescription" : "Specifies the authentication method to use when connecting to Salesforce.",
		"Type" : "String",
		"Values" : "Basic,OAuth,OAuthClient,OAuthPassword,OAuthJWT,OAuthPKCE,OneLogin,PingFederate,OKTA,ADFS,AzureAD",
		"Default" : "OAuth",
		"Category" : "Authentication",
		"Required" : false,
		"Value" : "Basic",
		"IsSessionProperty" : "",
		"Sensitivity" : "",
		"PropertyName" : "AuthScheme",
		"Ordinal" : 1,
		"CatOrdinal" : 1,
		"Hierarchy" : "",
		"Visible" : true,
		"ETC" : "",
		"alias" : "AuthScheme",
		"usercredential" : false
	}
]}

sys_connection_hierarchy

Hierarchy メカニズムは、API の標準インターフェースを使ってコネクタからフラットな接続プロパティリストを読み取る方法に対する、より実用的な代替手段を提供します。接続プロパティ情報を階層的な JSON ドキュメントとして表現することで、これを実現しています。

公開される属性

以下は、Hierarchy JSON で公開される属性の定義です。

  • name: スペースを含む、人間が読みやすい形式のプロパティ名。
  • propertyName: 接続文字列で使用される単一語の名前。
  • display: プロパティを3つのセグメントに分類します: RequiredBasicUnrequiredBasicNone
  • type: プロパティのデータ型を示します。StringNumberBoolean のいずれかです。
  • default: プロパティのデフォルト値を定義します。すべてのプロパティ型で使用されます。
  • enum: String プロパティにのみ(オプションで)存在し、プロパティの有効な値のセットを定義します。
  • sensitivity: プロパティが SENSITIVE(ログ等ではマスクされるが UI ではマスクされない)か PASSWORD(UI とログの両方でマスクされる)かを定義します。

Hierarchy JSON ドキュメントは、接続ユーザーインターフェースのセマンティックモデルも提示します。このドキュメントは、Basic(基本)と Advanced(詳細)の2つのビューに分割されるモデルを作成することから始まります。

display 属性

特に注目すべきは display 属性で、UI 開発において不可欠な要素です。この属性はプロパティを3つのセグメントに分類します: RequiredBasicUnrequiredBasicNone

RequiredBasic プロパティは、接続の確立に不可欠です。一方、UnrequiredBasic プロパティは接続に必須ではありませんが、ユースケースでこれらのプロパティが必要な場合にユーザーが認識できるよう表示することが推奨されます。None と設定されたプロパティは、詳細オプションとして扱われます。

CData のインターフェース設計では、必須と非必須の基本プロパティの両方が初期設定画面に表示され、その他のプロパティは Advanced タブに配置されます。

Basic ビュー

Hierarchy JSON ドキュメントの Basic セクションは、接続のセットアップに最も関連性の高い接続プロパティを含むビューを提示します。接続ウィンドウの Basic セクション/ビューでは、データソースへの接続に必要な最も重要なプロパティのみを使って、すばやく接続をセットアップできます。

Basic ビューはまた、他のプロパティで選択された値に基づいて動的にユーザーインターフェースを制御する、動的な階層ルールのセットも定義します。これにより、親プロパティが特定の値に設定されている場合にのみ、特定のプロパティが有効であることを示すことができます。

たとえば、子プロパティ APIToken は、親プロパティ AuthSchemeAPIToken に設定されている場合にのみ表示されるようにできます。これにより、ユーザーにとってより直感的な動的 UI を定義する手段が得られ、選択した設定に基づいて適切なプロパティの設定をガイドできます。

Advanced ビュー

Advanced セクションは、利用可能なすべての接続プロパティを含む従来型の設定エクスペリエンスを提供します。Advanced ビューでは、プロパティがカテゴリごとにグループ化されます。CData はカテゴリの順序と、各カテゴリ内のプロパティの順序を定義しています。この順序は、JSON ドキュメント内の定義順序に基づいて暗黙的に決定されます。

階層ルール

その名前が示すとおり、このテーブルはプロパティ間の依存関係の階層構造へのアクセスも提供します。階層ルールは、親プロパティと子プロパティの関係を定義するもので、Basic ビューの重要な要素です。この関係は、親プロパティが特定の値に設定されている場合にのみ子プロパティが関連性を持つという形で定義されます。

具体的には、hierarchyRules 属性が、別のプロパティの特定の値に基づいて必要となるプロパティを定義します。たとえば、AuthScheme プロパティが Basic に設定されている場合、ユーザー名/パスワードのプロパティが必須となり、目立つように表示されるべきです。同様に、AuthSchemePrivateKey に設定されている場合は、対応する秘密鍵の詳細が必要になります。

hierarchyRules では、親プロパティが特定の値に設定されると、対応する配列に設定可能な子プロパティの有効なリストが含まれます。親プロパティが別の値に設定された場合は、代わりに別のセットの子プロパティが含まれます。

この構造化されたアプローチにより、接続の確立に必要な重要な属性を理解できるだけでなく、異なるプロパティ間の階層的な関係についての洞察も得られるため、ドライバーの効果的な設定が促進されます。

重要な注意事項

階層ルールについて、いくつか知っておくべき重要なポイントがあります。

1つの子プロパティが、同じ階層内の複数の場所に出現することがあります。たとえば、OAuthClientId プロパティは、AuthSchemeOAuth に設定されている場合と、OAuthClient に設定されている場合の両方で有効になることがあります。この場合、そのプロパティの2つの定義は互いに異なる可能性があります。具体的には以下のとおりです。

  1. 階層の構成に応じて、プロパティのデフォルト値が異なる場合があります。たとえば SharePoint では、AuthScheme プロパティのデフォルト値は SharePointEdition = SharePoint Online の場合は AzureAD ですが、SharePointEdition = SharePoint OnPremise の場合は NTLM になります。
  2. 有効な列挙値のセットも、階層内の子プロパティの位置によって異なる場合があります。たとえば SharePoint では、AuthScheme プロパティは SharePointEdition = SharePoint Online の場合は13個の有効な列挙値を持ちますが、SharePointEdition = SharePoint OnPremise の場合は5個のみです。

CData の JDBC ドライバーで Hierarchy を活用するサンプルプロジェクトは GitHub で公開されています。

Hierarchy 定義の取得

Hierarchy 定義は、クエリを実行することでドライバーから実行時に取得できます。必要なステップは以下の2つです。

  1. 設定専用の接続を開きます。CData JDBC ドライバーでは、接続プロパティを指定せずに次の JDBC URI プレフィックスを使用してこの接続を開くことができます: jdbc:cdata:[driverName]:config:[driverName] にはデータソース名を指定)。他のエディションでは、DriverConfigOnly プロパティを True に設定して設定専用の接続を開くことができます。
  2. 以下のクエリを実行します(Context の値は非 JDBC エディションでは異なります):
    SELECT Definition FROM sys_connection_hierarchy WHERE Context = '_jdbc'

返される結果セットには、対応する Hierarchy JSON ドキュメントを含む単一の String カラムが格納されています。

出力サンプル

{
  "basic": [
    {
      "name": "URL",
      "property": "URL",
      "display": "RequiredBasic",
      "type": "String",
      "default": ""
    },
    {
      "name": "SharePoint Edition",
      "property": "SharePointEdition",
      "display": "RequiredBasic",
      "type": "String",
      "default": "SharePoint OnPremise",
      "enum": [
        "SharePoint Online",
        "SharePoint OnPremise"
      ]
    },
    {
      "name": "Schema",
      "property": "Schema",
      "display": "RequiredBasic",
      "type": "String",
      "default": "SOAP",
      "enum": [
        "SOAP",
        "REST"
      ]
    }
  ],

  "authSchemes": {
    "SharePointOnline": {
      "AzureAD": [
        {
          "name": "Initiate OAuth",
          "property": "InitiateOAuth",
          "display": "RequiredBasic",
          "type": "String",
          "default": "OFF",
          "enum": ["OFF", "REFRESH", "GETANDREFRESH"]
        }
      ],

      "AzureServicePrincipalCert": [
        {
          "name": "Azure Tenant",
          "property": "AzureTenant",
          "display": "RequiredBasic",
          "type": "String",
          "default": ""
        },
        {
          "name": "Initiate OAuth",
          "property": "InitiateOAuth",
          "display": "RequiredBasic",
          "type": "String",
          "default": "OFF",
          "enum": ["OFF", "REFRESH", "GETANDREFRESH"]
        },
        {
          "name": "OAuth JWT Cert",
          "property": "OAuthJWTCert",
          "display": "RequiredBasic",
          "type": "String",
          "default": ""
        },
        {
          "name": "OAuth JWT Cert Type",
          "property": "OAuthJWTCertType",
          "display": "RequiredBasic",
          "type": "String",
          "default": "USER"
        },
        {
          "name": "OAuth JWT Issuer",
          "property": "OAuthJWTIssuer",
          "display": "RequiredBasic",
          "type": "String",
          "default": ""
        },
        {
          "name": "OAuth JWT Cert Password",
          "property": "OAuthJWTCertPassword",
          "display": "UnrequiredBasic",
          "type": "String",
          "default": ""
        }
      ],

      "AzurePassword": [
        {
          "name": "User",
          "property": "User",
          "display": "RequiredBasic",
          "type": "String",
          "default": ""
        },
        {
          "name": "Password",
          "property": "Password",
          "display": "RequiredBasic",
          "type": "String",
          "default": ""
        },
        {
          "name": "Azure Tenant",
          "property": "AzureTenant",
          "display": "RequiredBasic",
          "type": "String",
          "default": ""
        },
        {
          "name": "OAuth Client Id",
          "property": "OAuthClientId",
          "display": "RequiredBasic",
          "type": "String",
          "default": ""
        }
      ],

      "PingFederate": [
        {
          "name": "User",
          "property": "User",
          "display": "RequiredBasic",
          "type": "String",
          "default": ""
        },
        {
          "name": "Password",
          "property": "Password",
          "display": "RequiredBasic",
          "type": "String",
          "default": ""
        },
        {
          "name": "SSO Domain",
          "property": "SSODomain",
          "display": "UnrequiredBasic",
          "type": "String",
          "default": ""
        }
      ],

      "ADFS": [
        {
          "name": "User",
          "property": "User",
          "display": "RequiredBasic",
          "type": "String",
          "default": ""
        },
        {
          "name": "Password",
          "property": "Password",
          "display": "RequiredBasic",
          "type": "String",
          "default": ""
        },
        {
          "name": "SSO Domain",
          "property": "SSODomain",
          "display": "UnrequiredBasic",
          "type": "String",
          "default": ""
        }
      ],

      "OneLogin": [
        {
          "name": "User",
          "property": "User",
          "display": "RequiredBasic",
          "type": "String",
          "default": ""
        },
        {
          "name": "Password",
          "property": "Password",
          "display": "RequiredBasic",
          "type": "String",
          "default": ""
        },
        {
          "name": "SSO Domain",
          "property": "SSODomain",
          "display": "UnrequiredBasic",
          "type": "String",
          "default": ""
        }
      ],

      "Okta": [
        {
          "name": "User",
          "property": "User",
          "display": "RequiredBasic",
          "type": "String",
          "default": ""
        },
        {
          "name": "Password",
          "property": "Password",
          "display": "RequiredBasic",
          "type": "String",
          "default": ""
        },
        {
          "name": "SSO Domain",
          "property": "SSODomain",
          "display": "UnrequiredBasic",
          "type": "String",
          "default": ""
        }
      ],

      "SharePointOAuth": [
        {
          "name": "OAuth Client Id",
          "property": "OAuthClientId",
          "display": "RequiredBasic",
          "type": "String",
          "default": ""
        },
        {
          "name": "OAuth Client Secret",
          "property": "OAuthClientSecret",
          "display": "RequiredBasic",
          "type": "String",
          "default": ""
        }
      ],

      "NTLM": [
        {
          "name": "User",
          "property": "User",
          "display": "RequiredBasic",
          "type": "String",
          "default": ""
        },
        {
          "name": "Password",
          "property": "Password",
          "display": "RequiredBasic",
          "type": "String",
          "default": ""
        }
      ],

      "Basic": [
        {
          "name": "User",
          "property": "User",
          "display": "RequiredBasic",
          "type": "String",
          "default": ""
        },
        {
          "name": "Password",
          "property": "Password",
          "display": "RequiredBasic",
          "type": "String",
          "default": ""
        }
      ],

      "OAuth": [
        {
          "name": "Initiate OAuth",
          "property": "InitiateOAuth",
          "display": "RequiredBasic",
          "type": "String",
          "default": "OFF",
          "enum": ["OFF", "REFRESH", "GETANDREFRESH"]
        }
      ],

      "OAuthJWT": [
        {
          "name": "Azure Tenant",
          "property": "AzureTenant",
          "display": "RequiredBasic",
          "type": "String",
          "default": ""
        },
        {
          "name": "Initiate OAuth",
          "property": "InitiateOAuth",
          "display": "RequiredBasic",
          "type": "String",
          "default": "OFF",
          "enum": ["OFF", "REFRESH", "GETANDREFRESH"]
        },
        {
          "name": "OAuth JWT Cert",
          "property": "OAuthJWTCert",
          "display": "RequiredBasic",
          "type": "String",
          "default": ""
        },
        {
          "name": "OAuth JWT Cert Type",
          "property": "OAuthJWTCertType",
          "display": "RequiredBasic",
          "type": "String",
          "default": "USER"
        },
        {
          "name": "OAuth JWT Issuer",
          "property": "OAuthJWTIssuer",
          "display": "RequiredBasic",
          "type": "String",
          "default": ""
        },
        {
          "name": "OAuth JWT Cert Password",
          "property": "OAuthJWTCertPassword",
          "display": "UnrequiredBasic",
          "type": "String",
          "default": ""
        }
      ]
    },

    "SharePointOnPremise": {
      "NTLM": [
        {
          "name": "User",
          "property": "User",
          "display": "RequiredBasic",
          "type": "String",
          "default": ""
        },
        {
          "name": "Password",
          "property": "Password",
          "display": "RequiredBasic",
          "type": "String",
          "default": ""
        }
      ],

      "Negotiate": [
        {
          "name": "User",
          "property": "User",
          "display": "RequiredBasic",
          "type": "String",
          "default": ""
        },
        {
          "name": "Password",
          "property": "Password",
          "display": "RequiredBasic",
          "type": "String",
          "default": ""
        }
      ],

      "Basic": [
        {
          "name": "User",
          "property": "User",
          "display": "RequiredBasic",
          "type": "String",
          "default": ""
        },
        {
          "name": "Password",
          "property": "Password",
          "display": "RequiredBasic",
          "type": "String",
          "default": ""
        }
      ],

      "ADFS": [
        {
          "name": "User",
          "property": "User",
          "display": "RequiredBasic",
          "type": "String",
          "default": ""
        },
        {
          "name": "Password",
          "property": "Password",
          "display": "RequiredBasic",
          "type": "String",
          "default": ""
        },
        {
          "name": "SSO Domain",
          "property": "SSODomain",
          "display": "UnrequiredBasic",
          "type": "String",
          "default": ""
        }
      ]
    }
  }
}

接続テスト

ユーザーからプロパティを収集するだけでなく、接続 UI を設計する際に考慮すべきポイントがいくつかあります。まず重要なのが、有効な接続のテストです。デフォルトでは、CData コネクタは接続オブジェクトの作成時に接続の検証を行いません。接続の有効性をテストするには、追加プロパティ ConnectOnOpenTrue に設定した接続オブジェクトを作成します。このプロパティが設定されると、コネクタは内部の TestConnection() メソッドを呼び出します。

このメソッドが失敗すると、失敗の原因の詳細を含む例外がスローされます。接続 UI に「接続テスト」要素を設けて、ユーザーが続行する前に資格情報が正しいかどうかを確認できるようにすることを推奨します。

ログの設定

ドライバーのログは、主に2つのプロパティで管理されます: Logfile(ログの書き込み先を制御)と Verbosity(ログに記録される詳細レベルを制御)です。これらのプロパティは、CData コネクタの接続レベルで設定します。

トラブルシューティングを支援するために、エンドユーザーがジョブごとに個別に Verbosity を設定できる方法を提供することを推奨します。ログはサポートプロセスにおいて不可欠であり、ログを生成する機能がなければ解決できない問題もあります。

ログの詳細については、ドライバーのドキュメントを参照してください。

OAuth 2.0 認可コードフロー

認可コードフローは、CData がサポートするデータソースで広く使用されている認証メカニズムです。このフローの特徴は、初回接続の確立時にエンドユーザーをソースシステムにリダイレクトしてログインさせる必要がある点です。CData コネクタは、このフローを実装するための標準化されたメカニズムを提供しています。CData Embedded コネクタでの OAuth フロー実装に関する包括的なガイドについては、CData コネクタを使った OAuth 認可コードグラントの統合の記事をご覧ください。詳細については、OAuth ホワイトペーパーもご参照ください。

CData Embedded を使い始める

CData Embedded は、強力なデータ接続機能をアプリケーションに組み込むために必要なツールを提供します。sys_connection_propssys_connection_hierarchy の両方を活用することで、さまざまな認証スキームやデータソースに適応する、ユーザーフレンドリーな接続インターフェースの構築を効率化できます。

CData によるコネクティビティの組み込みについて詳しくはこちらをご覧いただくか、コネクティビティの専門家との打ち合わせをご予約いただき、連携要件についてご相談ください。