プライマリ・コンテンツに移動
Oracle® REST Data Servicesインストレーション、構成および開発ガイド
リリース3.0.11
E62039-09
目次へ移動
目次
索引へ移動
索引

前
次

3 Oracle REST Data Servicesアプリケーションの開発

この項では、Oracle REST Data Servicesを使用するアプリケーションを開発する方法を説明します。これにはガイダンスと例を含みます。

注意:

すぐに開始する場合は、ここで「RESTfulサービスのスタート・ガイド」のチュートリアルを試すことができます。ただし、後でこの章に戻り、主要な概念と技術を理解してください。

注意:

チュートリアルおよび例を試してみる前に、Oracle Application Express 4.2以上およびOracle REST Data Services 3.0以上の両方がインストールされ、構成されていることを確認してください。

JSONデータの永続にOracle REST APIを使用する場合は、まずOracle REST APIをインストールする必要があります。詳細は、『Oracle REST Data Services SODA for REST開発者ガイド』のOracle REST APIのインストールに関する項を参照してください。

読者はOracle Application Expressに精通していることを前提としています。Oracle Application Expressを初めて使用する場合は、Oracle Application Expressのドキュメントを参照してください。

トピック:

また、補足的な拡張例として、アプリケーションの構築にOracle Application Expressを使用する「開発チュートリアル: イメージ・ギャラリの作成​​」を確認することもできます。

3.1 関連するソフトウェアの紹介

この項では、Oracle REST Data Servicesを使用するアプリケーションを開発するための、いくつかの重要な関連ソフトウェアについて説明します。

トピック:

3.1.1 Oracle Application Expressについて

Oracle Application Expressは、Oracleデータベースのための宣言型のラピッドWebアプリケーション開発ツールです。これは、完全にサポートされている、Oracleデータベースのすべてのエディションで利用可能なコスト不要のオプションです。Webブラウザのみを使用して、高速でセキュアなプロフェッショナル・アプリケーションを開発し、デプロイできます。

3.1.2 RESTful Webサービスについて

Representational State Transfer (REST)は、World Wide Webのような分散ハイパーメディア・システムのためのソフトウェア・アーキテクチャのスタイルです。APIは、RESTの原則に適合する場合にRESTfulと称されます。RESTの詳しい説明はこのマニュアルの対象外ですが、RESTful APIの特性を次に示します。

  • データは一連のリソースとしてモデル化されます。リソースはURIで識別されます。

  • リソースの操作には、小さく統一的な操作セットが使用されます(たとえば、PUT、POST、GET、DELETE)。

  • リソースは、複数の形式で表示できます(たとえば、ブログはHTML形式およびRSS形式で表示できます)。

  • サービスはステートレスですが、クライアントが関連リソースへのアクセスを望む可能性があるため、戻される表現の中で(通常はハイパーテキスト・リンクを提供することで)関連リソースを示します。

Oracle Application Expressのリリース4.2では、Oracle REST Data Servicesの機能を活用し、RESTful Webサービスを定義およびテストするための使いやすいグラフィカル・ユーザー・インタフェースが開発者に提供されています。

3.2 RESTfulサービスのスタート・ガイド

この項では、RESTfulサービスを紹介し、RESTfulサービスを使用するアプリケーションを開発するためのガイドラインと例を提供します。

トピック:

3.2.1 RESTfulサービスの用語

この項では、このドキュメント全体で使用されている共通の用語をいくつか紹介します。

  • RESTfulサービス: RESTfulアーキテクチャ・スタイルの原則に準拠したHTTP Webサービス。

  • リソース・モジュール: 関連するリソース・テンプレートをグループ化するために使用される構成単位。

  • リソース・テンプレート: 一部のURI (Universal Resource Identifiers)のセットにサービス要求を行える個別のRESTfulサービス。URIのセットは、リソース・テンプレートのURIパターンで定義されます

  • URIパターン: リソース・テンプレートのパターン。ルート・パターンの使用をお薦めしますが、ルート・パターンまたはURIテンプレートのいずれにもできます。

  • ルート・パターン: URIのパス部分をコンポーネント・パーツに分解することに重点をおくパターン。たとえば、/:object/:id?のパターンは/emp/101と一致し(101idempリソースにあるアイテムのリクエストと一致)、/emp/とも一致します(:idパラメータには?修飾子の注釈が付き、これはidパラメータがオプションであることを示すため、empリソースのリクエストとも一致します)。

    ルート・パターンの詳細な説明は、<sqldeveloper-install>\ordsおよびOracle REST Data Servicesを手動でインストールした場所(存在する場合)の下にあるdocs\javadoc\plugin-api\route-patterns.htmlを参照してください。

  • URIテンプレート: 所定のリソース・テンプレートが処理可能な特定のURIパターンを定義する簡易文法。たとえば、employees/{id}というパターンは、パスがemployees/で始まる任意のURI (employees/2560など)に一致します。

  • リソース・ハンドラ: 特定のリソース・テンプレートで特定のHTTPメソッドのサービスを行うために必要なロジックを提供します。たとえは、前のリソース・テンプレートでGET HTTPメソッドを行うためのロジックは次のようになります。

    select empno, ename, dept from emp where empno = :id
    
  • HTTP操作: HTTP (HyperText Transport Protocol)により、GET(リソース内容の取得)、POST(新規リソースの格納)、PUT(既存のリソースの更新)およびDELETE(リソースの削除)という、リソースで実行可能な標準メソッドが定義されます。

3.2.2 リクエスト・パスの構文要件について

Oracle REST Data Servicesは、パス・ベースの攻撃を防ぐために、各リクエストURLのパス要素の構文に対していくつかの検証チェックを実行します。

各パスは、次のルールに準拠する必要があります。

  • 空や空白文字のみでない

  • 次のいずれの文字も含まない: ?、#、;、%

  • null文字(\u0000)を含まない

  • 次の範囲の文字を含まない: \u0001-\u0031

  • ホワイトスペースまたはピリオド(.)で終わらない

  • 二重のフォワード・スラッシュ(//)または二重のバックスラッシュ(\\)を含まない

  • 連続する2つ以上のピリオドを含まない(..、...など)

  • 全長が{@value #MAX_PATH_LENGTH}文字以下である

  • ファイル拡張子を含んで、または含まないで、次のいずれの名前にも一致しない(大文字と小文字は区別されない): CON、PRN、AUX、CLOCK$、NUL、COM0、COM1、COM2、COM3、COM4、COM5、COM6、COM7、COM8、COM9、LPT0、LPT1、LPT2、LPT3、LPT4、LPT5、LPT6、LPT7、LPT8、LPT9

オブジェクトを自動REST有効化する場合、これらの要件を満たさないオブジェクト名は避けてください。たとえば、#EMPSという名前の表は作成しないでください。不適格な名前を持つオブジェクトを自動REST有効化するには、要件を満たす別名を使用する必要があります。

これらの要件は、URLデコードされた形式のURLに適用され、パーセント・エンコーディングによる回避の試みを阻止します。

3.2.3 インストールに含まれるドキュメント「スタート・ガイド」

Oracle REST Data Servicesをインストールすると、参考になるサブフォルダやファイルの入った例のフォルダが作成されます。インストール・フォルダの階層には、次のものがあります。

ords
  conf
  docs
  examples
    soda
    getting-started
    getting-started-nosql
  ...

階層の内容:

  • examples\soda: 『Oracle REST Data Services SODA for REST開発者ガイド』の中のいくつかの例で使用されるサンプルのJSONドキュメントが含まれています。

  • examples\getting-started: index.htmlをダブルクリックすると、Oracle REST Data Servicesを使用したRESTfulサービスの開発を開始する方法についての簡潔なドキュメントが表示されます。このマニュアルでは、まず初めにSQL Developerの使用を中心に説明します。(SQL Developerは、Oracle REST Data Servicesを管理するための主ツールです。たとえば、スキーマおよび表のRESTサポートを自動的に有効にする機能は、SQL Developerでのみ使用可能です。)

  • examples\getting-started-nosql: index.htmlをダブルクリックすると、Oracle REST Data Servicesを使用したNoSQLストア・アクセスを開始する方法についての簡潔なドキュメントが表示されます。

3.2.4 cURLおよびRESTfulサービスのテストについて

他の項で、Webブラウザを使用したRESTfulサービスのテストについて説明しています。しかし、RESTfulサービスをテストするもう1つの便利な方法に、cURLという名前のコマンドライン・ツールを使用する方法があります。

この強力なツールはほとんどのプラットフォームで利用可能で、RESTfulサービスとの間で送受信されるデータを確認および制御できます。

curl -i https://server:port/ords/workspace/hr/employees/7369

この例では、次のようなレスポンスが生成されます。

HTTP/1.1 200 OK
Server: Oracle-REST-Data-Services/2.0.6.78.05.25
ETag: "..." 
Content-Type: application/json
Transfer-Encoding: chunked
Date: Thu, 28 Mar 2014 16:49:34 GMT  

{
 "empno":7369,
 "ename":"SMITH",
 "job":"CLERK",
 "mgr":7902,
 "hiredate":"1980-12-17T08:00:00Z",
 "sal":800,
 "deptno":20
}

-iオプションは、cURLに対し、サーバーから戻されたHTTPヘッダーを表示するように指示します。

関連項目:

cURL

この項の例では、「サンプルのRESTfulサービスの調査(チュートリアル)」で説明したサービスでcURLを使用します。

3.2.5 RESTアクセスのためのスキーマ・オブジェクトの自動的な有効化(AutoREST)

Oracle REST Data Servicesがデータベース接続に関連付けられたシステムにインストールされている場合、AutoREST機能を使用して、そのデータベース接続と関連付けられたスキーマ内の指定された表およびビューへのOracle REST Data Servicesアクセスを簡単に有効または無効にすることができます。表、ビューまたはPL/SQLファンクション、プロシージャまたはパッケージへのRESTアクセスを有効化すると、RESTfulサービスを介したアクセスが可能になります。

AutoRESTは、データベース表をRESTリソースとして公開する素早く簡単な方法です。労力を削減するために、柔軟性とカスタマイズの容易性を若干犠牲にします。AutoRestによってデータを素早く公開できますが、(例えた言い方をすると)ガイド・レールのセットに乗せてしまいます。たとえば、出力形式や入力形式をカスタマイズできず、追加の検証も実行できません。

一方、手動で作成したリソース・モジュールでは、RESTリソースをサポートするためにSQLおよびPL/SQLを指定する必要があります。リソース・モジュールを使用することは労力を要しますが、柔軟性を向上します。たとえば、どのフィールドを含めるかのカスタマイズ、複数の表の結合、およびPL/SQLを使用した受信データの検証を実現できます。

そのため、アプリケーション開発者は、AutoRESTの「ガイド・レール」を使用するか、まさに必要なことを実行するためにリソース・モジュールを作成するかを選択する必要があります。AutoRESTを選択した場合、スキーマ内で表(または表のセット)を有効にするだけです。

スキーマを有効化することは、スキーマ内のすべての表とビューを有効化することとは異なることに注意してください。Oracle REST Data Servicesにスキーマが存在することを認識させ、HTTPに公開するリソースがゼロまたはそれ以上ある可能性があることを意味するのみです。それらのリソースは、AutoRESTリソースでも、リソース・モジュール・リソースでもかまいません。

Oracle SQL Developerの便利なウィザードを使用して、Oracle REST Data Servicesの問合せによる個々のデータベース・スキーマ・オブジェクト(表、ビュー、およびPL/SQL)へのアクセスを自動的に有効にできます。(これらの機能は、Oracle REST Data Services対応のスキーマでのみ有効で、Oracle Application Expressワークスペースでは有効でないことに注意してください。)

1つ以上の指定した表またはビューに対するOracle REST Data Servicesアクセスを有効にするには、SQL Developerで次を実行する必要があります。

  1. RESTアクセス用にスキーマ(接続に関連付けられているスキーマ)を有効にします。

    スキーマ・レベル: 接続に関連付けられているスキーマの(次の手順で指定する)選択したオブジェクトへのOracle REST Data Servicesアクセスを有効にするには、「接続」ナビゲータでその名前を右クリックし、「RESTサービス」「RESTサービスの有効化」の順に選択します。

    (接続に関連付けられているスキーマのオブジェクトへのOracle REST Data Servicesアクセスのサポートを削除するには、「接続」ナビゲータでその名前を右クリックし、「RESTサービス」「RESTサービスの削除」の順に選択します。)

  2. 希望するオブジェクトのRESTアクセスを個別に有効化します。

    表またはビュー・レベル: 指定した表またはビューへのOracle REST Data Servicesアクセスを有効化するには、「接続」ナビゲータでその名前を右クリックし、「RESTサービスの有効化」の順に選択します。

使用方法の詳細は、SQL Developerのウィザードまたはダイアログ・ボックスの「ヘルプ」ボタンをクリックします。

3.2.5.1 例: RESTfulサービスを使用してオブジェクトにアクセスする

この項では、Oracle REST Data Services問合せの使用例およびREST対応した後の表やビューに対するその他の操作の例を示します。

SQL Developerを使用して、表オブジェクトおよびビュー・オブジェクトを自動的にRESTfulサービスとして公開できます。この項では、これらのRESTfulサービスにアクセスする例を説明します。

ヒント:

こうした例は、これらのリソースにアクセスするのに使用するURLパターンを示しますが、クライアントはこれらのURLの構造の知識をハード・コーディングしないでください。かわりに、クライアントはリソースのハイパーリンクに従ってリソース間を移動してください。URLパターンの構造は、将来のリリースで進化したり、変更されたりする可能性があります。

この項では、RESTfulサービスを使用してオブジェクトにアクセスする例を説明します。

3.2.5.1.1 スキーマ・メタデータのGet

この例では、指定したスキーマの別名で、使用可能なリソースの一覧を取得します。表またはビューを自動的に有効化することで作成されるRESTfulサービスと、リソース・モジュールによって作成されるRESTfulサービスを示します。

この例では、指定したスキーマの別名で、使用可能なリソースの一覧を取得します。

パターン: GET http://<HOST>:<PORT>/ords/<SchemaAlias>/metadata-catalog/

: GET http://localhost:8080/ords/ordstest/metadata-catalog/

結果:

{
  "items": [
 {
   "name": "EMP",
   "links": [
  {
    "rel": "describes",
    "href": "http://localhost:8080/ords/ordstest/emp/"
  },
  {
    "rel": "canonical",
    "href": "http://localhost:8080/ords/ordstest/metadata-catalog/emp/",
    "mediaType": "application/json"
  }
   ]
 },
 {
   "name": "oracle.examples.hello",
   "links": [
  {
    "rel": "describes",
    "href": "http://localhost:8080/ords/ordstest/examples/hello/"
  },
  {
    "rel": "canonical",
    "href": "http://localhost:8080/ords/ordstest/metadata-catalog/examples/hello/",
    "mediaType": "application/json"
  }
   ]
 }
  ],
  "hasMore": false,
  "limit": 25,
  "offset": 0,
  "count": 2,
  "links": [
 {
   "rel": "self",
   "href": "http://localhost:8080/ords/ordstest/metadata-catalog/"
 },
 {
   "rel": "first",
   "href": "http://localhost:8080/ords/ordstest/metadata-catalog/"
 }
  ]
}

リソースの一覧には、次が含まれます。

  • REST対応の表またはビューを示すリソース。

  • リソース・モジュールによって定義されているリソース。具体的なパス(つまり、パラメータを含まない)のリソースのみが表示されることに注意してください。たとえば、/module/some/path/のパスのリソースは表示されますが、/module/some/:parameter/のパスのリソースは表示されません。

有効な各リソースには、次の2つのハイパーリンクがあります。

  • 関係にdescribesのあるリンクは実際のリソースを指します。

  • 関係にcanonicalのあるリンクはリソースを説明します。

3.2.5.1.2 オブジェクト・メタデータのGet

この例では、個別オブジェクトのメタデータ(オブジェクトを説明するメタデータ)を取得しています。メタデータの場所はcanonicalリンクの関係で指定されています。

パターン: GET http://<HOST>:<PORT>/ords/<SchemaAlias>/metadata-catalog/<ObjectAlias>/

: GET http://localhost:8080/ords/ordstest/metadata-catalog/emp/

結果:

{
    "name": "EMP",
    "primarykey": [
        "empno"
    ],
    "members": [
        {
            "name": "empno",
            "type": "NUMBER"
        },
        {
            "name": "ename",
            "type": "VARCHAR2"
        },
        {
            "name": "job",
            "type": "VARCHAR2"
        },
        {
            "name": "mgr",
            "type": "NUMBER"
        },
        {
            "name": "hiredate",
            "type": "DATE"
        },
        {
            "name": "sal",
            "type": "NUMBER"
        },
        {
            "name": "comm",
            "type": "NUMBER"
        },
        {
            "name": "deptno",
            "type": "NUMBER"
        }
    ],
    "links": [
        {
            "rel": "collection",
            "href": "http://localhost:8080/ords/ordstest/metadata-catalog/",
            "mediaType": "application/json"
        },
        {
            "rel": "canonical",
            "href": "http://localhost:8080/ords/ordstest/metadata-catalog/emp/"
        },
        {
            "rel": "describes",
            "href": "http://localhost:8080/ords/ordstest/emp/"
        }
    ]
}
3.2.5.1.3 オブジェクト・データのGet

この例では、オブジェクトのデータを取得します。オブジェクトの各行は、JSON配列に埋め込まれているJSONオブジェクトに対応します

パターン: GET http://<HOST>:<PORT>/ords/<SchemaAlias>/<ObjectAlias>/

: GET http://localhost:8080/ords/ordstest/emp/

結果:

{
 "items": [
  {
   "empno": 7499,
   "ename": "ALLEN",
   "job": "SALESMAN",
   "mgr": 7698,
   "hiredate": "1981-02-20T00:00:00Z",
   "sal": 1600,
   "comm": 300,
   "deptno": 30,
   "links": [
    {
     "rel": "self",
     "href": "http://localhost:8080/ords/ordstest/emp/7499"
    }
   ]
  },
  ...
  {
   "empno": 7934,
   "ename": "MILLER",
   "job": "CLERK",
   "mgr": 7782,
   "hiredate": "1982-01-23T00:00:00Z",
   "sal": 1300,
   "comm": null,
   "deptno": 10,
   "links": [
    {
     "rel": "self",
     "href": "http://localhost:8080/ords/ordstest/emp/7934"
    }
   ]
  }
 ],
 "hasMore": false,
 "limit": 25,
 "offset": 0,
 "count": 13,
 "links": [
  {
   "rel": "self",
   "href": "http://localhost:8080/ords/ordstest/emp/"
  },
  {
   "rel": "edit",
   "href": "http://localhost:8080/ords/ordstest/emp/"
  },
  {
   "rel": "describedby",
   "href": "http://localhost:8080/ords/ordstest/metadata-catalog/emp/"
  },
  {
   "rel": "first",
   "href": "http://localhost:8080/ords/ordstest/emp/"
  }
 ]
}
3.2.5.1.4 ページ区切りを使用した表データのGet

この例では、結果データのページ区切りを制御するパラメータのoffsetおよびlimitを指定します。

パターン: GET http://<HOST>:<PORT>/ords/<SchemaAlias>/<ObjectAlias>/?offset=<Offset>&limit=<Limit>

: GET http://localhost:8080/ords/ordstest/emp/?offset=10&limit=5

結果:

{
 "items": [
  {
   "empno": 7900,
   "ename": "JAMES",
   "job": "CLERK",
   "mgr": 7698,
   "hiredate": "1981-12-03T00:00:00Z",
   "sal": 950,
   "comm": null,
   "deptno": 30,
   "links": [
    {
     "rel": "self",
     "href": "http://localhost:8080/ords/ordstest/emp/7900"
    }
   ]
  },
  ...
  {
   "empno": 7934,
   "ename": "MILLER",
   "job": "CLERK",
   "mgr": 7782,
   "hiredate": "1982-01-23T00:00:00Z",
   "sal": 1300,
   "comm": null,
   "deptno": 10,
   "links": [
    {
     "rel": "self",
     "href": "http://localhost:8080/ords/ordstest/emp/7934"
    }
   ]
  }
 ],
 "hasMore": false,
 "limit": 5,
 "offset": 10,
 "count": 3,
 "links": [
  {
   "rel": "self",
   "href": "http://localhost:8080/ords/ordstest/emp/"
  },
  {
   "rel": "edit",
   "href": "http://localhost:8080/ords/ordstest/emp/"
  },
  {
   "rel": "describedby",
   "href": "http://localhost:8080/ords/ordstest/metadata-catalog/emp/"
  },
  {
   "rel": "first",
   "href": "http://localhost:8080/ords/ordstest/emp/?limit=5"
  },
  {
   "rel": "prev",
   "href": "http://localhost:8080/ords/ordstest/emp/?offset=5&limit=5"
  }
 ]
}
3.2.5.1.5 問合せを使用した表データのGet

この例では、戻されるオブジェクトを制限するフィルタ句を指定します。

パターン: GET http://<HOST>:<PORT>/ords/<SchemaAlias>/<ObjectAlias>/?q=<FilterClause>

: GET http://localhost:8080/ords/ordstest/emp/?q={"deptno":{"$lte":20}}

結果:

{
 "items": [
  {
   "empno": 7566,
   "ename": "JONES",
   "job": "MANAGER",
   "mgr": 7839,
   "hiredate": "1981-04-01T23:00:00Z",
   "sal": 2975,
   "comm": null,
   "deptno": 20,
   "links": [
    {
     "rel": "self",
     "href": "http://localhost:8080/ords/ordstest/emp/7566"
    }
   ]
  },
  ...
  {
   "empno": 7934,
   "ename": "MILLER",
   "job": "CLERK",
   "mgr": 7782,
   "hiredate": "1982-01-23T00:00:00Z",
   "sal": 1300,
   "comm": null,
   "deptno": 10,
   "links": [
    {
     "rel": "self",
     "href": "http://localhost:8080/ords/ordstest/emp/7934"
    }
   ]
  }
 ],
 "hasMore": false,
 "limit": 25,
 "offset": 0,
 "count": 7,
 "links": [
  {
   "rel": "self",
   "href": "http://localhost:8080/ords/ordstest/emp/?q=%7B%22deptno%22:%7B%22%24lte%22:20%7D%7D"
  },
  {
   "rel": "edit",
   "href": "http://localhost:8080/ords/ordstest/emp/?q=%7B%22deptno%22:%7B%22%24lte%22:20%7D%7D"
  },
  {
   "rel": "describedby",
   "href": "http://localhost:8080/ords/ordstest/metadata-catalog/emp/"
  },
  {
   "rel": "first",
   "href": "http://localhost:8080/ords/ordstest/emp/?q=%7B%22deptno%22:%7B%22%24lte%22:20%7D%7D"
  }
 ]
}
3.2.5.1.6 主キーを使用した表の行のGet

この例では、オブジェクトを識別するキーの値を指定することでオブジェクトを取得します。

パターン: GET http://<HOST>:<PORT>/ords/<SchemaAlias>/<ObjectAlias>/<KeyValues>

ここで、<KeyValues>​はカンマで区切ったキー値のリストです(キー順)。

: GET http://localhost:8080/ords/ordstest/emp/7839

結果:

{
 "empno": 7839,
 "ename": "KING",
 "job": "PRESIDENT",
 "mgr": null,
 "hiredate": "1981-11-17T00:00:00Z",
 "sal": 5000,
 "comm": null,
 "deptno": 10,
 "links": [
  {
   "rel": "self",
   "href": "http://localhost:8080/ords/ordstest/emp/7839"
  },
  {
   "rel": "edit",
   "href": "http://localhost:8080/ords/ordstest/emp/7839"
  },
  {
   "rel": "describedby",
   "href": "http://localhost:8080/ords/ordstest/metadata-catalog/emp/item"
  },
  {
   "rel": "collection",
   "href": "http://localhost:8080/ords/ordstest/emp/"
  }
 ]
}
3.2.5.1.7 表の行の挿入

この例では、オブジェクトにデータを挿入します。リクエストに付加するボディのデータは、挿入するデータを格納したJSONオブジェクトです。

オブジェクトに主キーがある場合、オブジェクトには主キー・フィールドに移入する挿入トリガーが必要です。表に主キーがない場合には、行のROWIDがアイテムの識別子として使用されます。

オブジェクトに主キー値を割り当てるトリガーがない場合、次の項「表の行の更新/挿入」で説明されているPUT操作をかわりに使用してください。

パターン: POST http://<HOST>:<PORT>/ords/<SchemaAlias>/<ObjectAlias>/

:

curl -i -H "Content-Type: application/json" -X POST -d "{ \"empno\" :7, \"ename\": \"JBOND\", \"job\":\"SPY\", \"deptno\" :11 }" "http://localhost:8080/ords/ordstest/emp/
Content-Type: application/json
 
{ "empno" :7, "ename": "JBOND", "job":"SPY", "deptno" :11 }

結果:

{
 "empno": 7,
 "ename": "JBOND",
 "job": "SPY",
 "mgr": null,
 "hiredate": null,
 "sal": null,
 "comm": null,
 "deptno": 11,
 "links": [
  {
   "rel": "self",
   "href": "http://localhost:8080/ords/ordstest/emp/7"
  },
  {
   "rel": "edit",
   "href": "http://localhost:8080/ords/ordstest/emp/7"
  },
  {
   "rel": "describedby",
   "href": "http://localhost:8080/ords/ordstest/metadata-catalog/emp/item"
  },
  {
   "rel": "collection",
   "href": "http://localhost:8080/ords/ordstest/emp/"
  }
 ]
}
3.2.5.1.8 表の行の更新/挿入

この例では、オブジェクト内のデータを挿入または更新します(「アップサート」とも呼ばます)。リクエストに付加するボディのデータは、挿入または更新するデータを格納したJSONオブジェクトです。

パターン: PUT http://<HOST>:<PORT>/ords/<SchemaAlias>/<ObjectAlias>/<KeyValues>

:

curl -i -H "Content-Type: application/json" -X PUT -d "{ \"empno\" :7, \"ename\": \"JBOND\", \"job\":\"SPY\", \"deptno\" :11 }" "http://localhost:8080/ords/ordstest/emp/7
Content-Type: application/json
 
{ "empno" :7, "ename": "JBOND", "job":"SPY", "deptno" :11 }

結果:

{
 "empno": 7,
 "ename": "JBOND",
 "job": "SPY",
 "mgr": null,
 "hiredate": null,
 "sal": null,
 "comm": null,
 "deptno": 11,
 "links": [
  {
   "rel": "self",
   "href": "http://localhost:8080/ords/ordstest/emp/7"
  },
  {
   "rel": "edit",
   "href": "http://localhost:8080/ords/ordstest/emp/7"
  },
  {
   "rel": "describedby",
   "href": "http://localhost:8080/ords/ordstest/metadata-catalog/emp/item"
  },
  {
   "rel": "collection",
   "href": "http://localhost:8080/ords/ordstest/emp/"
  }
 ]
}
3.2.5.1.9 フィルタを使用したDelete

この例では、フィルタ句で指定されたオブジェクトのデータを削除します。

パターン: DELETE http://<HOST>:<PORT>/ords/<SchemaAlias>/<ObjectAlias>/?q=<FilterClause>

: curl -i -X DELETE http://localhost:8080/ords/ordstest/emp/?q={"deptno":11}"

結果:

{ 
    "itemsDeleted": 1 
}
3.2.5.1.10 バッチ・ロードによるPost

この例では、バッチ・ロード機能を使用してオブジェクトのデータを挿入します。リクエストに付加するボディのデータはCSVファイルです。バッチ操作の動作はオプションの問合せパラメータを使用して制御できます。このパラメータは表3-1で説明しています。

パターン: POST http://<HOST>:<PORT>/ords/<SchemaAlias>/<ObjectAlias>/batchload?<Parameters>

パラメータ:

表3-1 バッチ・ロードのパラメータ

パラメータ 説明

batchesPerCommit

コミットの頻度を設定します。バッチがデータベースに送信された後、オプションのコミット・ポイントを設定できます。デフォルトは10個のバッチごとです。0はロードの終了までコミットを延期することを示します。型: Integer。

batchRows

データベースに送信する各バッチ内の行数を設定します。デフォルトは、バッチ当たり50行です。型: Integer。

dateFormat

日付データ型の書式マスクを設定します。入力データを日付型の列に変換するときに、この形式が使用されます。型: String。

delimiter

ファイル内のフィールドのフィールド区切り文字を設定します。デフォルトはカンマ(,)です。

enclosures

embeddedRightDouble

errors

エラー数の制限に使用されるユーザー・オプションを設定します。エラーの数がerrorsMax(サービスのオプション)またはerrors(ユーザーのオプション)に指定された値を超えた場合、ロードが終了します。

エラーを許容しない場合は、0を指定します。すべてのエラーを許容する(errorsMaxの値まで)場合は、UNLIMITED(-1)を指定します。

errorsMax

ユーザーによって許容されるエラーの数を制限するために使用されるサービスのオプションです。これは、サービス・プロバイダ用のオプションとして用意されており、ユーザーのオプションとしては公開しません。エラーの数がerrorsMax(サービスのオプション)またはerrors(ユーザーのオプション)に指定された値を超えた場合、ロードが終了します。

エラーを許容しない場合は、0を指定します。すべてのエラーを許容する場合は、UNLIMITED(-1)を指定します。

lineEnd

行の終わり(ターミネータ)を設定します。ファイルに、標準的な行の終了文字(\r、\r\nまたは\n)が含まれている場合は、lineEndを指定する必要はありません。

lineMax

データ・ストリーム中の行(row)当たりの行(line)数を識別するための最大の行(line)の長さを設定します。lineMaxの値により、誤ったlineEnd文字が使用された場合に、ストリーム全体を単一の行として読むことを防止できます。デフォルトは無制限。

locale

ロケールを設定します。

responseEncoding

レスポンス・ストリームのエンコーディングを設定します。

responseFormat

レスポンス・ストリームの形式を設定します。この形式は、メッセージや不良データを書式化する方法を決定します。有効な値: RAWSQL

timestampFormat

タイム・スタンプ・データ型の書式マスクを設定します。入力データをタイム・スタンプ型の列に変換するときに、この形式が使用されます。

timestampTZFormat

タイム・スタンプのタイムゾーン・データ型の書式マスクを設定します。入力データをタイム・スタンプのタイムゾーン型の列に変換するときに、この形式が使用されます。

truncate

ロードする前に表のデータ行を削除するか、または削除する方法、あるいはその両方を示します。False(デフォルト)の場合、ロード前に表のデータを削除しません。Trueの場合、SQL文のDELETEで表のデータが削除されます。Truncateの場合、SQL文のTRUNCATEで表のデータが削除されます。

:

POST http://localhost:8080/ords/ordstest/emp/batchload?batchRows=25
Content-Type: text/csv
 
empno,ename,job,mgr,hiredate,sal,comm,deptno
0,M,SPY MAST,,2005-05-01 11:00:01,4000,,11
7,J.BOND,SPY,0,2005-05-01 11:00:01,2000,,11
9,R.Cooper,SOFTWARE,0,2005-05-01 11:00:01,10000,,11
26,Max,DENTIST,0,2005-05-01 11:00:01,5000,,11

結果:

#INFO Number of rows processed: 4
#INFO Number of rows in error: 0
#INFO Elapsed time: 00:00:03.939 - (3,939 ms) 0 - SUCCESS: Load processed without errors

3.2.5.2 問合せでのフィルタリング

この項では、REST対応の表やビューに対する問合せでのフィルタリングの例を示し、説明します。

フィルタリングは、全コレクションで見つかった項目のサブセットが含まれている複数ページのリソース全体に対し、リクエストごとの動的フィルタ定義を使用してコレクション・リソースを制限する処理です。フィルタリングは、大規模なコレクションの効率的な走査を可能にします。

問合せでフィルタリングするには、q=FilterObjectパラメータを含め、FilterObjectはリソースに適用するカスタムな選択やソートを表すJSONオブジェクトです。たとえば、次のようなリソースを仮定します。

https://example.com/ords/scott/emp/

次の問合せには、ENAME列を「JOHN」に制限するフィルタが含まれています。

https://example.com/ords/scott/emp/?q={"ENAME":"JOHN"}
3.2.5.2.1 FilterObjectの文法

FilterObjectは、次の構文に準拠したJSONオブジェクトである必要があります。

FilterObject { orderby , asof, wmembers }

orderbyasofおよびwmembers属性はオプションで、その定義は次のとおりです。

orderby
  "$orderby": {orderByMembers}
 
orderByMembers
    orderByProperty
    orderByProperty , orderByMembers
 
orderByProperty
    columnName : sortingValue
 
sortingValue
  "ASC"
  "DESC"
  "-1"
  "1"
   -1
   1
   
asof
  "$asof": date
  "$asof": "datechars"
  "$asof": scn
  "$asof": +int
 
wmembers
    wpair
    wpair , wmembers
 
wpair
    columnProperty
    complexOperatorProperty
 
columnProperty
    columnName : string
    columnName : number
    columnName : date
    columnName : simpleOperatorObject
columnName : complexOperatorObject
    columnName : [complexValues]
 
columnName
  "\p{Alpha}[[\p{Alpha}]]([[\p{Alnum}]#$_])*$"
 
complexOperatorProperty
    complexKey : [complexValues]
    complexKey : simpleOperatorObject 
 
complexKey
  "$and"
  "$or"
 
complexValues
    complexValue , complexValues
 
complexValue
    simpleOperatorObject
    complexOperatorObject
    columnObject
 
columnObject
    {columnProperty}
 
simpleOperatorObject
    {simpleOperatorProperty}
 
complexOperatorObject
    {complexOperatorProperty}
 
simpleOperatorProperty
   "$eq" : string | number | date
   "$ne" : string | number | date
   "$lt" :  number | date
   "$lte" : number | date
   "$gt" : number | date
   "$gte" : number | date
   "$instr" : string 
   "$ninstr" : string
   "$like" : string
   "$null" : null
   "$notnull" : null
   "$between" : betweenValue
 
betweenValue
    [null , betweenNotNull]
    [betweenNotNull , null]
    [betweenRegular , betweenRegular]
 
betweenNotNull
    number
    date
    
betweenRegular
    string
    number
    date

データ型の定義には次のものがあります。

string 
       JSONString
number
       JSONNumber
date
       {"$date":"datechars"}
scn
       {"$scn": +int}

説明:

datechars is an RFC3339 date format in UTC (Z)
        
 
JSONString
          ""
          " chars "
chars
         char
         char chars
char
         any-Unicode-character except-"-or-\-or-control-character
          \"
          \\
           \/
          \b
          \f
          \n
          \r
          \t
          \u four-hex-digits
 
 
JSONNumber
    int
    int frac
    int exp
    int frac exp
int
    digit
    digit1-9 digits 
    - digit
    - digit1-9 digits
frac
    . digits
exp
    e digits
digits
    digit
    digit digits
e
    e
    e+
    e-
    E
    E+
    E-

FilterObjectはRFC3986の第2.1項に従って符号化する必要があります。

3.2.5.2.2 例: FilterObjectの記述

FilterObjectの記述における演算子の例を次に示します。

ORDER BY property ($orderby)

Order by with literals
 
{
 "$orderby": {"SALARY":  "ASC","ENAME":"DESC"}
}
 
Order by with numbers
 
{
 "$orderby": {"SALARY":  -1,"ENAME":  1}
}
 

ASOF property ($asof)
 
With SCN (Implicit)
 
{
  "$asof": 1273919
}
 
With SCN (Explicit)
 
{
  "$asof": {"$scn": "1273919"}
}
 
With Date (Implicit)
 
{
  "$asof": "2014-06-30T00:00:00Z"
}
 
With Date (Explicit)
 
{
  "$asof": {"$date": "2014-06-30T00:00:00Z"}
}
 
 
EQUALS operator ($eq)
 
(Implicit and explicit equality supported._
 
Implicit (Support String and Dates too)
 
{
 "SALARY": 1000
}
 
Explicit
 
{
 "SALARY": {"$eq": 1000}
}
 
Strings
 
{
 "ENAME": {"$eq":"SMITH"}
}
 
Dates
 
{
  "HIREDATE": {"$date": "1981-11-17T08:00:00Z"}
}
 
 
NOT EQUALS operator ($ne)
 
Number
 
{
 "SALARY": {"$ne": 1000}
}
 
String
 
{
 "ENAME": {"$ne":"SMITH"}
}
 
Dates
 
{
  "HIREDATE": {"$ne": {"$date":"1981-11-17T08:00:00Z"}}
}
 
 
LESS THAN operator ($lt)
(Supports dates and numbers only)
 
Numbers
 
{
  "SALARY": {"$lt": 10000}
}
 
Dates
 
{
  "SALARY": {"$lt": {"$date":"1999-12-17T08:00:00Z"}}
}
 
LESS THAN OR EQUALS operator ($lte)
(Supports dates and numbers only)
 
Numbers
 
{
  "SALARY": {"$lte": 10000}
}
 
Dates
 
{
  "HIREDATE": {"$lte": {"$date":"1999-12-17T08:00:00Z"}}
}
 
GREATER THAN operator ($gt)
(Supports dates and numbers only)
 
Numbers
 
{
  "SALARY": {"$gt": 10000}
}
 
Dates
 
{
  "SALARY": {"$gt": {"$date":"1999-12-17T08:00:00Z"}}
}
 
 
GREATER THAN OR EQUALS operator ($gte)
(Supports dates and numbers only)
 
Numbers
 
{
  "SALARY": {"$gte": 10000}
}
 
Dates
 
{
  "HIREDATE": {"$gte": {"$date":"1999-12-17T08:00:00Z"}}
}
 

In string operator ($instr)
(Supports strings only)
 
{
  "ENAME": {"$instr":"MC"}
}
 
 
Not in string operator ($ninstr)
(Supports strings only)
 
{
  "ENAME": {"$ninstr":"MC"}
}
 
 
#### LIKE operator ($like)
(Supports strings. Eescape character not supported to try to match expressions with _ or % characters.)
 
{
  "ENAME": {"$like":"AX%"}
}
 
 
#### BETWEEN operator ($between)
(Supports string, dates, and numbers)
 
Numbers
 
{
  "SALARY": {"$between": [1000,2000]}
}
 
Dates
 
{
  "SALARY": {"$between": [{"$date":"1989-12-17T08:00:00Z"},{"$date":"1999-12-17T08:00:00Z"}]}
}
 
Strings
 
{
  "ENAME": {"$between": ["A","C"]}
}
 
Null Ranges ($lte equivalent) 
(Supported by numbers and dates only)

{
  "SALARY": {"$between": [null,2000]}
}
 
Null Ranges ($gte equivalent)
(Supported by numbers and dates only)

{
  "SALARY": {"$between": [1000,null]}
}
 
 
#### NULL operator ($null)
 
{
  "ENAME": {"$null": null}
}
 
#### NOT NULL operator ($notnull)
 
{
  "ENAME": {"$notnull": null}
}
 
 
#### AND operator ($and)
(Supports all operators, including $and and $or)
 
Column context delegation
(Operators inside $and will use the closest context defined in the JSON tree.)

{
  "SALARY": {"$and": [{"$gt": 1000},{"$lt":4000}]}
}
 
Column context override
(Example: salary greater than 1000 and name like S%) 

{
  "SALARY": {"$and": [{"$gt": 1000},{"ENAME": {"$like":"S%"}} ] }
}
 
Implicit and in columns
 
```
{
  "SALARY": [{"$gt": 1000},{"$lt":4000}] 
}
```
 
High order AND
(All first columns and or high order operators -- $and and $ors -- defined at the first level of the JSON will be joined and an implicit AND)
(Example: Salary greater than 1000 and name starts with S or T)
 
{
  "SALARY": {"$gt": 1000}, 
  "ENAME": {"$or": [{"$like":"S%"}, {"$like":"T%"}]} 
}
 
Invalid expression (operators $lt and $gt lack column context)
 
{
   "$and": [{"$lt": 5000},{"$gt": 1000}]
}
 
Valid alternatives for the previous invalid expression
 
{
   "$and": [{"SALARY": {"$lt": 5000}}, {"SALARY": {"$gt": 1000}}]
}
 
{
   "SALARY": [{"$lt": 5000},{"$gt": 1000}]
}
 
{
   "SALARY": {"$and": [{"$lt": 5000},{"$gt": 1000}]}
}


OR operator ($or)
(Supports all operators including $and and $or)
 
Column context delegation
(Operators inside $or will use the closest context defined in the JSON tree)

{
  "ENAME": {"$or": [{"$eq":"SMITH"},{"$eq":"KING"}]}
}
 
Column context override
(Example: name starts with S or salary greater than 1000)

{
  "SALARY": {"$or": [{"$gt": 1000},{"ENAME": {"$like":"S%"}} ] }
}

3.2.5.3 自動PL/SQL

この項では、HTTP(S)を介してPL/SQLをリモート・プロシージャ・コール(RPC)のために利用可能にする方法について説明します。

自動PL/SQL機能は、ステートレスなWebサービス環境でエンコーディングとデータ転送の整合性を提供するために標準を使用します。この機能を使用すると、ORDSを介してパッケージ・レベルでOracle DatabaseのストアドPL/SQLファンクションおよびプロシージャを有効化できます。ビューや表を有効化する方法と同様です。

PL/SQLサブプログラムの自動有効化

ORDSは、カタログ・オブジェクト識別子に基づいて、次のPL/SQLオブジェクトの自動有効化をサポートします。
  • PL/SQLプロシージャ

  • PL/SQLファンクション

  • PL/SQLパッケージ

PL/SQLパッケージ内のファンクションおよびプロシージャはPL/SQLパッケージ・オブジェクトの範囲内で名前を付けられているオブジェクトなので、個々に有効化することはできません。このため、粒度レベルがパッケージ・レベルでオブジェクトを有効化します。この粒度レベルは、そのパブリック・ファンクションおよびプロシージャをすべて公開可能にします。

ファンクションおよびプロシージャのサブセットのみを有効化する場合、別の委任パッケージを作成し、ファンクションおよびプロシージャのそのサブセットだけを公開できるようにする必要があります。

注意:

オーバーロードしたパッケージ・ファンクションとプロシージャはサポートされていません。
3.2.5.3.1 PL/SQLオブジェクトの自動有効化がサポートされているメソッドとコンテンツ・タイプ

この項では、この機能によってサポートされるメソッドおよびコンテンツ・タイプについて説明します。

PL/SQLオブジェクトの自動有効化機能は、POSTをHTTPメソッドとしてサポートします。POSTメソッドでは、入力パラメータはペイロード内でエンコードされ、出力パラメータはレスポンスからデコードされます。

注意:

この機能はRPCスタイルのインタラクションを行うため、CRUDからHTTPメソッドへの標準データ・マッピングには適用できません。

サポートされるコンテンツ・タイプは、application/jsonです。

3.2.5.3.2 PL/SQLオブジェクトの自動有効化

この項では、ORDSを介してPL/SQLオブジェクトを自動的に有効化する方法を説明します。

次のいずれかの方法でPL/SQLオブジェクトを有効化できます。
3.2.5.3.2.1 ORDS PL/SQL APIを使用した自動有効化

ORDS PL/SQL APIを使用してPL/SQLオブジェクトを有効化できます。

PL/SQLパッケージを有効化するには、次のサンプル・コード・スニペットに示すように、ORDS PL/SQL APIを使用します。

BEGIN
  ords.enable_object(
    p_enabled => TRUE,
    p_schema => 'MY_SCHEMA',
    p_object => 'MY_PKG',
    p_object_type => 'PACKAGE',
    p_object_alias => 'my_pkg',
    p_auto_rest_auth => FALSE);
   commit;
END;
/

例3-1 PL/SQLファンクションの有効化

PL/SQLファンクションを有効化するには、次のサンプル・コード・スニペットに示すように、ORDS PL/SQL APIを使用します。

BEGIN
  ords.enable_object(
    p_enabled => TRUE,
    p_schema => 'MY_SCHEMA',
    p_object => 'MY_FUNC',
    p_object_type => 'FUNCTION',
    p_object_alias => 'my_func',
    p_auto_rest_auth => FALSE);

    commit;
END;
/

例3-2 PL/SQLプロシージャの有効化

PL/SQLプロシージャを有効化するには、次のサンプル・コード・スニペットに示すように、ORDS PL/SQL APIを使用します。

BEGIN
  ords.enable_object(
    p_enabled => TRUE,
    p_schema => 'MY_SCHEMA',
    p_object => 'MY_PROC',
    p_object_type => 'PROCEDURE',
    p_object_alias => 'my_proc',
    p_auto_rest_auth => FALSE);

    commit;
END;
/
3.2.5.3.2.2 SQL Developerを使用したPL/SQLオブジェクトの自動有効化

この項では、SQL Developer 4.2以降を使用してPL/SQLオブジェクトを有効化する方法を説明します。

SQL Developerを使用してPL/SQLオブジェクト(たとえば、パッケージ)を有効化するには、次の手順を実行します。

注意:

これでパッケージ、ファンクションおよびプロシージャを有効化できるようになりました。ただし、有効化の粒度は、パッケージ全体レベル、スタンドアロン・ファンクション・レベル、またはスタンドアロン・プロシージャ・レベルのいずれかです。
  1. SQL Developerで、次の図に示すようにパッケージを右クリックします。

    図3-1 「RESTサービスの有効化」オプションの選択

    図3-1の説明が続きます
    「図3-1 「RESTサービスの有効化」オプションの選択」の説明
  2. 「RESTfulサービスを有効にする」を選択して、次のウィザード・ページを表示します。

    図3-2 PL/SQLパッケージ・オブジェクトの自動有効化

    図3-2の説明が続きます
    「図3-2 PL/SQLパッケージ・オブジェクトの自動有効化」の説明
    • オブジェクトの有効化: このオプションを有効にします(つまり、パッケージのRESTアクセスを有効にします)。

    • オブジェクト別名: オブジェクト別名としてregistry_pkgを受け入れます。

    • 承認が必要: 簡潔性を保つため、このオプションは無効にしておきます。

    • ウィザードのRESTfulサマリー・ページで「終了」をクリックします。

3.2.5.3.3 PL/SQLエンドポイントの生成

HTTPエンドポイントは、有効なデータベース・オブジェクトに対してリクエストに応じて動的に生成されます。ORDSは、問合せを使用してエンドポイントを生成するために、接続したデータベース・カタログを使用します。

HTTPエンドポイントを生成するため、すべてのデータベース・オブジェクトに対して次のルールが適用されます。

  • 名前はすべて小文字に変換されます

  • エンドポイントがすでに割り当てられていなければ、生成されます

ストアド・プロシージャおよびストアド・ファンクションのエンドポイント

ファンクションまたはプロシージャ名は、同じネームスペースの表やビューと同じ方法でURL内に生成されます。

例3-3 ストアド・プロシージャのためのエンドポイントの生成

CREATE OR REPLACE PROCEDURE MY_SCHEMA.MY_PROC IS
BEGIN
  NULL;
END;
次のエンドポイントが生成されます。
http://localhost:8080/ords/my_schema/my_proc/

例3-4 パッケージ・プロシージャおよびファンクションのエンドポイント

パッケージ、ファンクションおよびプロシージャ・エンドポイントは、パッケージ名を親として生成されます。オーバーロードしていないか、小文字名がまだ使用されていないファンクションとプロシージャのエンドポイントが生成されます。

次のコード・スニペットで定義されているようにMY_PKGパッケージがある場合:

CREATE OR REPLACE  PACKAGE MY_SCHEMA.MY_PKG AS
  PROCEDURE MY_PROC;
  FUNCTION MY_FUNC RETURN VARCHAR2;
  PROCEDURE MY_PROC2;
  PROCEDURE "my_proc2";
  PROCEDURE MY_PROC3(P1 IN VARCHAR);
  PROCEDURE MY_PROC3(P2 IN NUMBER);
END MY_PKG;
次のエンドポイントが生成されます。
http://localhost:8080/ords/my_schema/my_pkg/MY_PROC
http://localhost:8080/ords/my_schema/my_pkg/MY_FUNC

注意:

プロシージャmy_proc2のエンドポイントは、名前を小文字に変換すると一意にならないため生成されません。プロシージャmy_proc3のエンドポイントは、オーバーロードしているため生成されません。
3.2.5.3.4 リソース入力ペイロード

入力ペイロードは、REST標準に従った値を持つJSONドキュメントです。

ペイロードは、次のコード・スニペットに示すように、INまたはIN OUTの各パラメータに対する名前/値ペアを含んでいる必要があります。

{
  "p1": "abc",
  "p2": 123,
  "p3": null
}

注意:

INまたはIN OUTパラメータがない場合、次のコード・スニペットに示すように、空のJSONボディが必要です。
{

}
ORDSは、データベース・カタログ・メタデータを使用してJSONペイロードをOracleデータベース・タイプにアンマーシャリングし、そこではJDBCを介してデータベースに渡される準備ができています。
3.2.5.3.5 リソース・ペイロード・レスポンス

PL/SQLオブジェクトが正常に実行されると、JSONボディが戻されます。

戻されるJSONボディは、すべてのOUTおよびIN OUT出力パラメータ値を含んでいます。ORDSは、次のコード・スニペットで示すように、データベース・カタログ・メタデータを使用して結果の実行をJSON内にマーシャリングします。

{
  "p3" : "abc123",
  "p4" : 1
}
OUTまたはIN OUTパラメータがない場合、次のコード・スニペットに示すように、空のJSONボディが戻されます。
{

}
3.2.5.3.6 ファンクションの戻り値

ファンクションの戻り値には関連した名前がありません。

ファンクションの戻り値に関連した名前がないため、次のコード・スニペットに示すように名前"~ret"が使用されます。
{
  "~ret" : "abc123"
}

3.2.6 SQLおよびPL/SQLを使用したRESTful Servicesの手動作成

この項では、SQLおよびPL/SQLを使用して手動でRESTful Servicesを作成する方法を説明し、JSONドキュメントを使用してRESTリクエストのボディにあるストアド・プロシージャにパラメータを渡す方法を表示します。

3.2.6.1 Oracle REST Data Servicesのパラメータ引き渡しメカニズムについて

この項では、Oracle REST Data Servicesがサポートしている、REST HTTPを使用して開発者作成のハンドラにパラメータを引き渡す主要なメカニズムについて説明します。

パラメータ引き渡しタスク実行前に完了しておく必要がある前提条件セットアップ・タスク

この前提条件セットアップ情報は、「RESTfulサービスのスタート・ガイド」の項の手順1および2を完了していることを前提にしています。そこでは、ordstestスキーマおよびempデータベース・テーブルをREST対応にし(手順1)、SQL問合せからRESTfulサービスを作成、テストしました(手順2)。これら2つの手順を、パラメータ引き渡しタスクを実行する前に完了する必要があります(次以降のサブセクションを参照)。

3.2.6.1.1 JSONを使用したパラメータの引き渡し

この項では、RESTリクエスト(たとえばPOSTまたはPUTメソッド)のボディでJSONドキュメントを使用してストアド・プロシージャにパラメータを渡す方法を示します(各パラメータは名前/値ペア)。この操作はレコード上で更新を実行し、その結果、レコードに対する変更がOUTパラメータとして戻されます。

次の手順を実行します。

  1. 注意:

    次のストアド・プロシージャは、emp表内の既存のレコード上で次の一部または全部を変更することによって更新を実行して従業員を昇格します: ジョブ、給与、委任、部門番号および管理者。ストアド・プロシージャは、OUTパラメータとして給与の変更を戻します。

    create or replace procedure promote ( l_empno IN number,  l_job IN varchar2,
               l_mgr IN number, l_sal IN number,  l_comm IN number,  l_deptno IN number,
               l_salarychange OUT number)
            is
                oldsalary   number;
            begin
                select nvl(e.sal, 0)into oldsalary FROM emp e
                        where e.empno = l_empno;
                update emp e set
                    e.job = nvl(l_job, e.job),
                    e.mgr = nvl(l_mgr, e.mgr),
                    e.sal = nvl(l_sal, e.sal),
                    e.comm = nvl(l_comm, e.comm),
                    e.deptno = nvl(l_deptno, e.deptno)
                            where e.empno = l_empno;
                l_salarychange := nvl(l_sal, oldsalary) - oldsalary;
            end;
    特権ordstestユーザーとしてordstestスキーマに接続し、promoteストアド・プロシージャを作成します。
  2. 次の手順を実行してempリソース上にPUTリクエストのハンドラをセットアップし、JSONドキュメントのPUTメソッドのボディのパラメータをpromoteストアド・プロシージャに引き渡します。
    1. Oracle SQL Developerを使用して、REST Developmentセクションで、empテンプレート上で右クリックし、PUTメソッドに対応する「ハンドラの追加」を選択します。
    2. リソース・ハンドラを作成するダイアログで、緑色のプラス記号をクリックしてMIMEタイプapplication/jsonを追加し、「適用」をクリックしてPUTメソッドのボディにあるJSONドキュメントを送信します。
    3. SQLワークシートを使用して、次の無名PL/SQLブロックを追加します: begin promote (:l_empno, :l_job, :l_mgr, :l_sal, :l_comm, :l_deptno, :l_salarychange); end;(次の図を参照)。

      図3-3 無名PL/SQLブロックをPUTメソッドのハンドラとして追加する

      図3-3の説明が続きます
      「図3-3 無名PL/SQLブロックをPUTメソッドのハンドラとして追加する」の説明
    4. 「パラメータ」タブをクリックして、「バインド・パラメータ」l_salarychangeに、「アクセス方法」OUTパラメータに、「ソース・タイプ」RESPONSEに、および「データ型」INTEGERに設定します(次の図を参照)。これは昇格手順の出力で、JSON名前/値形式を取る、給与の変更に等しい整数値です。

      図3-4 PUTメソッドに引き渡すバインド・パラメータl_salarychangeの設定

      図3-4の説明が続きます
      「図3-4 PUTメソッドに引き渡すバインド・パラメータl_salarychangeの設定」の説明
    5. 「詳細」タブをクリックしてコールするURLを取得します(次の図の「例」のセクションを参照)。このURLをクリップボードにコピーします。

      図3-5 「詳細」タブからコールするURLを取得する

      図3-5の説明が続きます
      「図3-5 「詳細」タブからコールするURLを取得する」の説明
    6. testモジュールを右クリックしてモジュールをアップロードします。この手順を忘れないでください。
  3. RESTfulサービスをテストするには、コマンド・プロンプトで次のcURLコマンドを実行します:curl -i -H "Content-Type: application/json" -X PUT -d "{ \"l_empno\" : 7499, \"l_sal\" : 9999, \"l_job\" : \"Director\", \"l_comm\" : 300}

    注意:

    利用できる任意のRESTクライアントを使用してRESTfulサービスをテストすることもできます。
    cURLコマンドは、次のレスポンスを戻します。
    HTTP/1.1 200 OK 
    Content-Type: application/json Transfer-Encoding: chunked 
    {"salarychange":8399}
  4. SQL Developer SQLワークシートで、emp表でSELECT文: SELECT * from empを実行してPUTメソッドが実行されたのを確認し、続いて「DATA」タブを選択してEMP表のレコードを表示します。

    図3-6 SQL問合せからの結果を表示してPUTメソッドの実行を確認する

    図3-6の説明が続きます
    「図3-6 SQL問合せからの結果を表示してPUTメソッドの実行を確認する」の説明

注意:

  • すべてのパラメータはオプションです。 JSONドキュメントでパラメータの名前/値ペアを省略すると、パラメータはNULLに設定されます。

  • 名前/値ペアは、JSONドキュメント内に、任意の順序で並べることができます。 JSONを使用すると、JSONドキュメントでこの点に多くの柔軟性を得られます。

  • 1レベルのJSONのみサポートされます。JSONオブジェクトまたは配列をネストすることはできません。

3.2.6.1.2 ルート・パターンを使用したパラメータの引き渡し
この項では、URIでルート・パターンを使用してRESTリクエストにパラメータを指定する方法を説明します(ボディを持たないGETメソッドなど)。

まず、多くのバインド変数を持つemp表で、問合せに対してGETメソッド・ハンドラを作成します。この手順では、ルート・パターンを使用して、必要なパラメータ値を指定します。

ルート・パターンを使用していくつかの必要なパラメータ値を持つGETメソッドを送信するには、次の手順を実行します。

  1. SQL Developerで、テスト・モジュールを右クリックし、「テンプレートの追加」を選択してempをコールする新しいテンプレートを作成します。ただし、この場合、テンプレート定義に、メソッドのボディでなくURIに含まれる、パラメータまたはバインド変数のルート・パターンが含まれます。必要なパラメータを定義するには、jobおよびdeptnoパラメータの前に/:を指定することによってルート・パターンを使用します。たとえば、URIパターンの場合、emp/:job/:deptnoと入力します(次の図参照)。

    図3-7 いくつかのパラメータまたはバインド変数のルート・パターンを含むテンプレート定義の作成

    図3-7の説明が続きます
    「図3-7 いくつかのパラメータまたはバインド変数のルート・パターンを含むテンプレート定義の作成」の説明
  2. 「次」をクリックして「RESTデータ・サービス — 手順2/3」に移動し、「次」をクリックして「RESTデータ・サービス — 手順3/3」に移動し,次に「終了」をクリックしてテンプレートを完成します。
  3. emp/:job/:deptnoテンプレートを右クリックし、GETメソッドに対して「ハンドラの追加」を選択します。
  4. GETメソッド上で右クリックしてハンドラを開きます。
  5. SQLワークシートに次の問合せを追加します: select * from emp e where e.job = :job and e.deptno = :deptno and e.mgr = NVL (:mgr, e.mgr) and e.sal = NVL (:sal, e.sal); (次の図も参照)。

    図3-8 SQL問合せのハンドラへの追加

    図3-8の説明が続きます
    「図3-8 SQL問合せのハンドラへの追加」の説明
  6. 「詳細」タブをクリックして、コールするURLを取得します。このURLをクリップボードにコピーします。
  7. testモジュールを右クリックしてモジュールをアップロードします。 この手順を忘れないでください。
  8. RESTエンドポイントをテストします。Webブラウザで、次の図に示すように、URL http://localhost:8080/ords/ordstest/test/emp/SALESMAN/30を入力します。

    図3-9 ルート・パターンを使用してGETメソッドといくつかの必須パラメータ値を送信した結果をブラウザを使用して表示する

    図3-9の説明が続きます
    「図3-9 ルート・パターンを使用してGETメソッドといくつかの必須パラメータ値を送信した結果をブラウザを使用して表示する」の説明

問合せは、Ward、MartinおよびTurnerという名のセールスマンに対応する3件のレコードを戻します。

関連項目:

ルート・パターンの詳細は、ORDSディストリビューションに含まれるドキュメントdocs/javadoc/plugin-api/route-patterns.htmlと、ドキュメント「Oracle REST Data Servicesのルート・パターン」を参照してください。

3.2.6.1.3 オプションのパラメータのための問合せ文字列の使用

この項では、URIでルート・パターンを使用してRESTリクエストにパラメータを指定する方法を説明します(ボディを持たないGETメソッドなど)。任意の問合せにおいて、その他のオプションのバインド変数に対して問合せ文字列を使用できます。

問合せ文字列を使用する構文は次のとおりです: ?parm1=value1&parm2=value2 … &parmN=valueN

たとえば、問合せhttp://localhost:8080/ords/ordstest/test/emp/SALESMAN/30をさらにフィルタする場合、問合せ文字列を使用していくつかのパラメータ名/値ペアとともにGETメソッドを送信するには、mgr(管理者)が7698sal(給与)が1500である従業員を、問合せ文字列?mgr=7698&sal=1500をURLに付加することで選択します: http://localhost:8080/ords/ordstest/test/emp/SALESMAN/30?mgr=7698&sal=1500

エンドポイントをテストするには、WebブラウザにURL「http://localhost:8080/ords/ordstest/test/emp/SALESMAN/30?mgr=7698&sal=1500」を入力します(次の図を参照)。

図3-10 問合せ文字列を使用してGETメソッドとともにいくつかのパラメータ名/値ペアを送信した結果をブラウザを使用して表示する

図3-10の説明が続きます
「図3-10 問合せ文字列を使用してGETメソッドとともにいくつかのパラメータ名/値ペアを送信した結果をブラウザを使用して表示する」の説明

この問合せは、名前がTurner、部門が30、給与が1500、管理者が7698であるセールスマンに対応する1件のレコードを戻します。

次の点に注意してください:
  • パラメータ値をURLエンコードするのは有効です。必ずしも必要ではないこともありますが、行っても安全です。これにより、インターネットにより何かが改変されること、たとえば、特殊文字が障害を引き起こす可能性がある他の文字に変換されることを防げます。RESTクライアントにこの機能があることもありますし、フレーズurlエンコーダでインターネットを検索することでその機能があるツールを見つけることもできます。

  • URIでパラメータ・リストの末尾に決してバックスラッシュを入れないでください。そうしないと、404 Not Foundエラーが表示される場合があります。

関連項目:

JSONを使用してパラメータ値を渡す経験をさらに充実させるには、ORDSチュートリアル(OBE)の演習4およびデータベース・アプリケーション開発仮想イメージを参照します。

3.2.6.2 SQL/JSONデータベース・ファンクションのORDSとの使用

この項では、Oracle Database 12c リリース2 (12.2)で利用できるSQL/JSONデータベース・ファンクションを使用して、ネストされたJSONオブジェクトと階層関係表を互いにマップするために説明します。

3.2.6.2.1 ネストされたJSONオブジェクトの関係表への挿入

この項では、ネスト配列を持つJSONオブジェクトを複数の階層的な関係表に挿入する方法を説明します。

この機能を実装するために使用される2つの主要なテクノロジは次のとおりです。

  • ORDSが提供してPOSTおよび他のRESTコールのボディにあるJSONおよび他のコンテンツをPL/SQL RESTハンドラに配信する:bodyバインド変数

  • Oracle Database 12cリリース2 (12.2)で提供されるJSON_TABLEおよびその他のSQL/JSON演算子

関係表にデータを挿入するためのこれらのテクノロジを使用する利点のいくつかを次に示します。

  • 機能を実装するための要件が最小限です。たとえば、JSONパーサー・ソフトウェアのインストールは不要です

  • JSONからの関係マッピングが単純な場合、書くのも読むのも簡単な、単純な宣言型コードを使用できます

  • より複雑なマッピングを処理する機能は強力で洗練されています。次のものが含まれます。

    • NULLSおよびブール値をマッピングするためのメカニズム

    • JSONを処理するための洗練されたメカニズム。JSONは時間とともに進化します。このため、マッピング・コードは、JSONドキュメントの古いバージョンも新しいバージョンも処理できる必要があります。

      たとえば、単純なスカラー値が進化して、複数のスカラーまたはネストされたスカラー値やオブジェクトの配列を含むJSONオブジェクトになる場合があります。スカラー値を戻すSQL/JSON演算子は、単純なスカラーがこれらのより精巧な構造内に埋め込まれた場合でも、引き続き機能できます。特別なメカニズム(Ordinality列と呼ばれます)を使用して、値が導出されたところから構造を決定することができます。

関連項目:

JSON_TABLEおよび他のSQL/JSON演算子、およびOrdinality列メカニズムに関する詳細は、次のページ:
3.2.6.2.1.1 :bodyバインド変数の使用法

この項では、:bodyバインド変数を使用するために役に立つヒントをいくつか提供します。

:bodyバインド変数を使用する際に役に立ついくつかのヒントを次に示します。
  • :bodyバインド変数は、一度のみ、アクセスまたは参照解除できます。以降のアクセスは、NULL値を戻します。このため、2つのJSON_Table操作で使用するには、その前にローカルのL_PO変数に:bodyにバインド変数を割り当てる必要があります。

  • :bodyバインド変数はBLOBデータ型であり、BLOB変数にのみ割り当てることができます。

    注意:

    L_POはBLOB変数なので、JSON_TABLEファンクションの式の後にFORMAT JSON句を使用する必要があります。詳細は項を参照。

    :bodyバインド変数は、画像データなど、他のタイプのデータとともに使用できます。

関連項目:

3.2.6.2.1.2 ネストされたLineItemsがあるJSON発注書の例

この項では、ネストされたLineItemsがあるJSON発注書を取得し、PurchaseOrder表の行およびLineItem表の行に挿入する例を示します。

例3-5 ネストされたLineItemsがあるネストされたJSON発注書

{"PONumber"        : 1608,
  "Requestor"      : "Alexis Bull",
  "CostCenter"     : "A50",
  "Address"        : {"street"  : "200 Sporting Green",
                       "city"    : "South San Francisco",
                       "state"   : "CA",
                       "zipCode" : 99236,
                       "country" : "United States of America"},
  "LineItems"      : [ {"ItemNumber" : 1,
                         "Part"       : {"Description" : "One Magic Christmas",
                                         "UnitPrice"   : 19.95,
                                         "UPCCode"     : 1313109289},
                         "Quantity"   : 9.0},
                       {"ItemNumber" : 2,
                        "Part"       : {"Description" : "Lethal Weapon",
                                        "UnitPrice"   : 19.95,
                                        "UPCCode"     : 8539162892},
                        "Quantity"   : 5.0}]}'
3.2.6.2.1.3 PurchaseOrderおよびLineItems表の表定義

この項では、PurchaseOrderおよびLineItem表に定義を提供します。

PurchaseOrderおよびLineItems表の定義は次のとおりです。

CREATE TABLE PurchaseOrder (
     PONo NUMBER (5),
     Requestor VARCHAR2 (50),
     CostCenter VARCHAR2 (5),
     AddressStreet VARCHAR2 (50),
     AddressCity VARCHAR2 (50), 
     AddressState VARCHAR2 (2),
     AddressZip VARCHAR2 (10),
     AddressCountry VARCHAR2 (50),
     PRIMARY KEY (PONo));

CREATE TABLE LineItem (
     PONo NUMBER (5),
     ItemNumber NUMBER (10),
     PartDescription VARCHAR2 (50), 
     PartUnitPrice NUMBER (10),
     PartUPCCODE NUMBER (10), 
     Quantity NUMBER (10),
     PRIMARY KEY (PONo,ItemNumber));
3.2.6.2.1.4 POSTリクエストのPL/SQLハンドラ・コード

この項では、POSTリクエストに対応するサンプルのPL/SQLハンドラ・コードを示します。ハンドラ・コードは、PurchaseOrder表の行およびLineItem表の行に発注書を挿入するために使用されます。

例3-6 POSTリクエストに対して使用されたPL/SQLハンドラ・コード

Declare
  L_PO     BLOB;
 
Begin
  L_PO := :body;
 
INSERT INTO PurchaseOrder
      SELECT * FROM json_table(L_PO  FORMAT JSON, '$'
         COLUMNS (
           PONo            Number    PATH '$.PONumber',
           Requestor       VARCHAR2  PATH '$.Requestor',
           CostCenter      VARCHAR2  PATH '$.CostCenter',
           AddressStreet   VARCHAR2  PATH '$.Address.street',
           AddressCity     VARCHAR2  PATH '$.Address.city',
           AddressState    VARCHAR2  PATH '$.Address.state',
           AddressZip      VARCHAR2  PATH '$.Address.zipCode',
           AddressCountry  VARCHAR2  PATH '$.Address.country'));
 
INSERT INTO LineItem 
SELECT * FROM json_table(L_PO  FORMAT JSON, '$'
         COLUMNS (
           PONo  Number PATH '$.PONumber',
           NESTED             PATH '$.LineItems[*]'
             COLUMNS (
               ItemNumber        Number   PATH '$.ItemNumber',
               PartDescription   VARCHAR2   PATH '$.Part.Description',
               PartUnitPrice     Number   PATH '$.Part.UnitPrice',
               PartUPCCode       Number   PATH '$.Part.UPCCode',
               Quantity          Number   PATH '$.Quantity')));
commit;
end;
3.2.6.2.1.5 REST APIサービスの作成によるハンドラの起動

この項では、REST APIサービスを作成してハンドラを起動する方法を説明します。Oracle REST Data Servicesを使用します。

REST APIサービスをセットアップするために、RESTコールの対象となるリソースを識別するためにURIが定義されます。URIは、Oracle REST Data Servicesが特定のハンドラにREST HTTPコールをルーティングするためにも使用されます。 このURIの一般的な書式は次のとおりです。

<server>:<port>/ords/<schema>/<module>/<template>/<parameters>

ここで、<server>:<port>は、Oracle REST Data Serviceがインストールされた場所です。テスト目的で、URIのmoduleおよびtemplateの代わりに、それぞれdemoおよびtestを使用することができます。モジュールは、REST APIの対象となるリソースを定義する関連のテンプレートをまとめてグループ化するために使用されます。

REST APIサービスを作成するには、次のいずれかの方法を使用します。

  • ORDS PL/SQL APIを使用して、POST挿入のためにRESTサービスとハンドラを定義します。次に、PurchaseOrderおよびLineItem表を含むデータベース・サーバー上のjsontableスキーマに接続します。

    注意:

    JSON_TABLEおよび他のSQL/JSON演算子は、エスケープする必要があるため、一重引用符を使用します。たとえば、すべての一重引用符(’)を二重引用符(“)に置き換える必要があります。
  • SQL Developerで、ORDSの「REST開発」ペインを使用してRESTサービスを定義します。

3.2.6.2.1.6 ORDS PL/SQL APIを使用したREST Serviceおよびハンドラの定義

この項では、Oracle REST Data Services (ORDS) PL/SQL APIを使用して、POST挿入のためにREST Serviceとハンドラを定義する方法を示します。

代替として、SQL DeveloperでORDSの「REST開発」ペインを使用してモジュール、テンプレートおよびハンドラを作成できます。

BEGIN
  ORDS.ENABLE_SCHEMA(
      p_enabled             => TRUE,
      p_schema              => 'ORDSTEST',
      p_url_mapping_type    => 'BASE_PATH',
      p_url_mapping_pattern => 'ordstest',
      p_auto_rest_auth      => FALSE);    

  ORDS.DEFINE_MODULE(
      p_module_name    => 'demo',
      p_base_path      => '/demo/',
      p_items_per_page =>  25,
      p_status         => 'PUBLISHED',
      p_comments       => NULL);      
  ORDS.DEFINE_TEMPLATE(
      p_module_name    => 'demo',
      p_pattern        => 'test',
      p_priority       => 0,
      p_etag_type      => 'HASH',
      p_etag_query     => NULL,
      p_comments       => NULL);
  ORDS.DEFINE_HANDLER(
      p_module_name    => 'demo',
      p_pattern        => 'test',
      p_method         => 'POST',
      p_source_type    => 'plsql/block',
      p_items_per_page =>  0,
      p_mimes_allowed  => '',
      p_comments       => NULL,
      p_source         => ' 
declare
    L_PO BLOB := :body;
begin

INSERT INTO PurchaseOrder
      SELECT * FROM json_table(L_PO  FORMAT JSON, ''$''
         COLUMNS (
           PONo                  Number           PATH ''$.PONumber'',
           Requestor            VARCHAR2  PATH ''$.Requestor'',
           CostCenter          VARCHAR2   PATH ''$.CostCenter'',
           AddressStreet      VARCHAR2  PATH ''$.Address.street'',
           AddressCity         VARCHAR2  PATH ''$.Address.city'',
           AddressState        VARCHAR2  PATH ''$.Address.state'',
           AddressZip           VARCHAR2  PATH ''$.Address.zipCode'',
           AddressCountry    VARCHAR2  PATH ''$.Address.country''));

INSERT INTO LineItem
SELECT * FROM json_table(L_PO  FORMAT JSON, ''$''
         COLUMNS (
           PONo  Number PATH ''$.PONumber'',
           NESTED                      PATH ''$.LineItems[*]''
             COLUMNS (
               ItemNumber       Number      PATH ''$.ItemNumber'',
               PartDescription  VARCHAR2    PATH ''$.Part.Description'',
               PartUnitPrice      Number     PATH ''$.Part.UnitPrice'',
               PartUPCCode     Number     PATH ''$.Part.UPCCode'',
               Quantity              Number    PATH ''$.Quantity'')));

commit;
end;'
      );


  COMMIT; 
END;
3.2.6.2.2 階層リレーショナル・データからのネストされたJSONオブジェクトの生成

この項では、Oracle REST Data Servicesを使用して、階層(親/子)関係内の関係表を問い合わせ、ネストされたJSON形式でデータを戻す方法を説明します。

この機能を実装するために使用される2つの主要なテクノロジは次のとおりです。

  • Oracle Database 12c リリース2 (12.2)で利用できる新しいSQL/JSONファンクション。json_objectsを使用して関係表からJSONオブジェクトを生成したり、json_arrayaggを使用してネストされた(子)関係表からネストされたJSON配列を生成したりできます。

  • RESTサービス・ハンドラが次の種類のデータを戻すSQL問合せを実行できるようにするために使用されるORDSメディア・ソース・タイプ:

    • データのHTTP Content-Type (この場合はapplication/json)

    • json_objectによって戻されるJSONデータ

この手法を使用する利点のいくつかを次に示します。

  • 機能を実装するための要件が最小限です。たとえば、JSONパーサー・ソフトウェアのインストールは不要です

  • 書きやすく読みやすいシンプルな宣言型コーディングにより、JSONオブジェクトから関係表へのマッピングがシンプルになる。

  • より複雑なマッピングを処理する機能は強力で洗練されています。これには、NULLSおよびブール値をマッピングするためのメカニズムが含まれます。

    たとえば、Oracle DatabaseのNULLは、JSON要素の欠如、またはJSONのNULL値に変換できます。Oracle Database はブール型を格納しませんが、SQL/JSONファンクションでは、データベース内の文字列または数値の値をブーリアンのTRUEまたはFALSEの値にマッピングできます。

3.2.6.2.2.1 階層関係表からのネストされたJSONオブジェクトの生成例

この項では、ネストされたJSON発注書の形式でPurchaseOrderおよびLineItem関係表に挿入したデータを問い合わせるか、GETする方法を説明します。

例3-7 関係表上でOracle REST Data Servicesの問合せを使用してネストされたJSONオブジェクトを生成するGETハンドラ・コード

SELECT 'application/json', json_object('PONumber' VALUE po.PONo,
       'Requestor' VALUE po.Requestor,
       'CostCenter' VALUE po.CostCenter,
       'Address' VALUE
           json_object('street' VALUE po.AddressStreet,
                 'city' VALUE po.AddressCity,
                 'state' VALUE po.AddressState,
                 'zipCode' VALUE po.AddressZip,
                 'country' VALUE po.AddressCountry),
        'LineItems' VALUE (select json_arrayagg(
            json_object('ItemNumber' VALUE li.ItemNumber,
                   'Part' VALUE 
                     json_object('Description' VALUE li.PartDescription,
                                 'UnitPrice' VALUE li.PartUnitPrice,
                                 'UPCCode' VALUE li.PartUPCCODE),
                   'Quantity' VALUE li.Quantity))
                   FROM LineItem li WHERE po.PONo = li.PONo))
             FROM PurchaseOrder po
               WHERE po.PONo = :id
3.2.6.2.2.2 テンプレートとGETハンドラを定義するためのORDS PL/SQL APIコール

この項では、作成したモジュールに新しいテンプレートを作成するためのORDS PL/SQL APIコールの例を提供します。

例3-8 demoモジュールに新しいtest/:id テンプレートおよびGETハンドラを作成するためのORDS PL/SQL APIコール

Begin
ords.define_template(
 p_module_name => 'demo',
 p_pattern => 'test/:id');
 
ords.define_handler(
 p_module_name => 'demo',
 p_pattern => 'test/:id',
 p_method  => 'GET',
 p_source_type => ords.source_type_media,
 p_source => '
 
   SELECT ''application/json'', json_object(''PONumber'' VALUE po.PONo,
          ''Requestor'' VALUE po.Requestor,
          ''CostCenter'' VALUE po.CostCenter,
          ''Address'' VALUE
              json_object(''street'' VALUE po.AddressStreet,
                          ''city'' VALUE po.AddressCity,
                          ''state'' VALUE po.AddressState,
                          ''zipCode'' VALUE po.AddressZip,
                          ''country'' VALUE po.AddressCountry),
          ''LineItems'' VALUE (select json_arrayagg(
              json_object(''ItemNumber'' VALUE li.ItemNumber,
                     ''Part'' VALUE
                       json_object(''Description'' VALUE li.PartDescription,
                                   ''UnitPrice'' VALUE li.PartUnitPrice,
                                   ''UPCCode'' VALUE li.PartUPCCODE),
                      ''Quantity'' VALUE li.Quantity))
                      FROM LineItem li WHERE po.PONo = li.PONo))
               FROM PurchaseOrder po
                 WHERE po.PONo = :id '
   );
 
Commit;
End;  
3.2.6.2.3 RESTfulサービスのテスト

この項では、Oracleデータベースにアクセスして結果をJSON形式で取得するためにPOSTおよびGET RESTful Servicesをテストする方法を示します。

この項には次のトピックが含まれます:

3.2.6.2.3.1 JSONオブジェクトのデータベースへの挿入

この項では、JSON発注書のデータベースへの挿入をテストする方法を表示します。

URIパターン: http://<HOST>:<PORT>/ords/<SchemaAlias>/<module>/<template>

例:

メソッド: POST

URIパターン: http://localhost:8080/ords/ordstest/demo/test/

RESTfulサービスをテストするには、PONumber 1608に対する次のデータを使用して、po1.jsonのようにファイルを作成します。
{"PONumber"        : 1608,
 "Requestor"       : "Alexis Bull",
 "CostCenter"      : "A50",
 "Address"         : {"street"  : "200 Sporting Green",
                                  "city"    : "South San Francisco",
                                  "state"   : "CA",
                                  "zipCode" : 99236,
                                  "country" : "United States of America"},
      "LineItems"  : [ {"ItemNumber" : 1,
                          "Part"     : {"Description" : "One Magic Christmas",
                                        "UnitPrice"   : 19.95,
                                        "UPCCode"     : 1313109289},
                                        "Quantity"   : 9.0},
                                        {"ItemNumber" : 2,
                                          "Part"       : {"Description" : "Lethal Weapon",
                                                          "UnitPrice"   : 19.95,
                                                          "UPCCode"     : 8539162892},
                                          "Quantity"   : 5.0}]}'
その後、コマンド・プロンプトで次のcURLコマンドを実行します。
curl -i -H "Content-Type: application/json" -X POST -d @po1.json "http://localhost:8080/ords/ordstest/demo/test/"
cURLコマンドは、次のレスポンスを戻します。
HTTP/1.1 200 OK 
Transfer-Encoding: chunked
3.2.6.2.3.2 データベースからのJSONオブジェクトの生成

この項では、データベースからJSONオブジェクトをフェッチするためのGETメソッドの結果を示します。

メソッド: GET

URIパターン: http://<HOST>:<PORT>/ords/<SchemaAlias>/<module>/<template>/<parameters>

例:

RESTfulサービスをテストするには、次の図に示すようにWebブラウザにURL http://localhost:8080 /ords/ordstest/demo/test/1608を入力します。

図3-11 ネストされたJSONオブジェクトの生成

図3-11の説明が続きます
「図3-11 ネストされたJSONオブジェクトの生成」の説明

3.2.7 ORDSを使用した日付の処理

ORDSを使用すると、開発者は、Oracle Database、Oracle Database 12c JSONドキュメント・ストアおよびOracle NoSQL DatabaseへのRESTインタフェースを可能な限り短時間で簡単に作成できます。Oracle Databaseで作業する場合、開発者は表に対してAutoREST機能を使用したり、より複雑な操作のためにSQLおよびPL/SQLルーチンを使用してカスタム・モジュールを作成したりできます。

文字列中の日付をエンコーディングするために、ORDSはRFC3339標準を使用します。通常、使用される日付形式はdd-mmm-yyyyです(例: 15-Jan-2017)。ORDSは、Oracle Databaseで値の挿入や更新などの操作を実行したときに、指定された形式のJSON文字列をOracle日付データ型に自動的に変換します。JSON文字列に再変換する場合、ORDSはOracle日付データ型を文字列形式に自動的に変換します。

注意:

JSONは日付データ型をサポートしませんが、Oracle Databaseは日付データ型をサポートします。

この項には次のトピックが含まれます:

関連項目:

時刻やタイムゾーンの処理方法などの詳細は次のページを参照してください: https://jsao.io/2016/10/working-with-dates-using-ords/

3.2.7.1 Oracle REST Data Servicesによる日時処理について

データがRESTリクエストから到着すると、Oracle REST Data Services (ORDS)がISO 8601文字列を解析し、Oracle DatabaseのTIMESTAMPデータ型に変換する場合があります。これは、AutoREST (POSTおよびPUT)でも、カスタム・モジュールのバインド変数でも発生します。TIMESTAMPがタイムゾーン関連のコンポーネントをサポートしないのを思い出してください。このため、DATETIME値が、変換処理時にORDSが使用するタイムゾーンに設定されます。

RESTリクエストへのレスポンスを作成する場合、ORDSはOracle DatabaseのDATETIME値をズールー語のISO 8601文字列に変換します。これは、AutoREST (GET)と、SQL問合せ(GET)にマッピングされるカスタム・モジュールで発生します。DATEおよびTIMESTAMPデータ型の場合、タイムゾーン関連のコンポーネントを持たないため、タイムゾーンはORDSが実行されているタイムゾーンとみなされ、ズールー語への変換はそこから行われます。

RESTに対してORDSで処理する場合(つまり、APEXでない)の一般的な推奨事項を次にいくつか示します。
  • ORDSがデータベースのデータに従って適切なタイムゾーンを使用していることを確認します(たとえば、日付をデータベースに入れたいタイムゾーン)。

  • NLS設定(time_zone)をストリーム中で変更しないでください。

ISO 8601文字列について説明していますが、ORDSは実際には文字列をサポートしている点に注意してください。RFC3339文字列はISO 8601文字列に準拠しているサブセットです。JSON.stringify(date)によって戻されるデフォルトの形式がサポートされます。

警告:

TIMESTAMP WITH TIME ZONEまたはTIMESTAMP WITH LOCAL TIME ZONEへの暗黙的なデータ変換に関する問題を防止するために、ORDSが使用するタイムゾーンは、セッション・タイムゾーンとの同期を維持することが重要です。デフォルトでORDSは自動的にこれを行いますが、開発者はALTER SESSION文でセッション・タイムゾーンを変更できます。

関連項目:

RFC3339

3.2.7.2 ORDSが使用するタイムゾーンの設定について

Oracle REST Data Services (ORDS)の起動時に、それにより内部で実行されるJVMは、ORDSが様々なタイムゾーン変換に使用するタイムゾーンを取得およびキャッシュします。デフォルトで、タイムゾーンはオペレーティング・システム(OS)から取得されるため、ORDSが使用するタイムゾーンを変更する簡単な方法は、OSのタイムゾーンを変更し、続いてORDSまたはそれが実行されているアプリケーション・サーバーを再起動することです。言うまでもなく、タイムゾーンを変更するための指示は、オペレーティング・システムにより異なります。

もしなんらかの理由でOSと同じタイムゾーンを使用したくない場合、Java環境変数Duser.timezoneを使用してデフォルトをオーバーライドすることができます。その変数が正確にはどのように設定されているかは、スタンドアロン・モードとJavaアプリケーション・サーバーのどちらで実行されているかにより異なります。次のトピックではいくつか例を示します。

スタンドアロン・モード

ORDSをスタンドアロン・モードで実行する場合、-jarオプションの前のコマンドライン・オプションとして指定することで、Java環境変数を設定できます。

例3-9 Duser.timezone Java環境変数のスタンドアロン・モードでの設定

次のコード例は、スタンドアロン・モードでコマンドラインからタイムゾーンを設定する方法を示しています。

$ java -Duser.timezone=America/New_York -jar ords.war standalone 

Javaアプリケーション・サーバー — Tomcat 8

Javaアプリケーション・サーバー、Tomcat 8では、おそらくバージョンに関係なく、環境変数CATALINA_OPTSを使用してタイムゾーンを設定できます。これに関して推奨される方法は、CATALINA_BASE/bin/catalina.shを直接変更しないことです。その代わりに、CATALINA_BASE/binsetenv.shという名前のスクリプトを作成することで環境変数を設定します。

例3-10 Duser.timezone Java環境変数のJavaアプリケーション・サーバーでの設定

次のコード例は、Javaアプリケーション・サーバー — Tomcat 8でタイムゾーンを設定するための、setenv.shスクリプトの内容を示しています。

CATALINA_TIMEZONE="-Duser.timezone=America/New_York"
CATALINA_OPTS="$CATALINA_OPTS $CATALINA_TIMEZONE

3.2.7.3 Application ExpressでのサンプルのRESTfulサービスの調査(チュートリアル)

最近のORDSリリース(3.0.X)をサポートするSQL Developerを使用してORDSアプリケーションを開発することを強くお薦めします。Application Expressは、RESTおよびORDSの基本概念を学ぶために役立つチュートリアルを提供します。ただし、チュートリアルは以前のORDSリリース(2.0.X)を使用しています。使用方法のチュートリアルで説明されている役に立つヒントのいくつかを次に示します。

Application Expressインスタンスがサンプルのアプリケーションおよびサンプルのデータベース・オブジェクトを自動的にワークスペースに追加するように構成されている場合、リソース・モジュールのリストにoracle.example.hrという名前のサンプルのリソース・モジュールが表示されます。リソース・モジュールがリストにない場合は、RESTfulサービス・ページの右側にあるサンプル・データのリセットタスクをクリックし、サンプルのリソース・モジュールを作成できます。

  1. oracle.example.hrをクリックし、モジュール内に定義されているリソース・テンプレートとリソース・ハンドラを表示します。モジュールがどのようにhr/という値のURI接頭辞を持つのかに注意してください。これは、このモジュールが処理するすべてのURIはhr/という文字列で始まることを意味します。
  2. employees/{id}という名前のリソース・テンプレートをクリックします。テンプレートがどのようにemployees/{id}という値のURIテンプレートを持つのかに注意してください。これは、hr/employees/で始まるすべてのURIがこのリソース・テンプレートで処理されることを意味します。

    リソース・テンプレートでサポートされているHTTPメソッドは、リソース・テンプレートの下に表示されます。この場合は、サポートされているメソッドはGETメソッドのみです。

  3. hr/employees/{id}のリソース・ハンドラの「GET」をクリックし、その構成を表示します。

    このハンドラの「ソース・タイプ」「1行問い合せる」です。これは、このリソースの問合せ結果セットの単一行へのマッピングが予想されることを意味します。このハンドラのソースは、次のとおりです。

    select * from emp 
             where empno = :id
    

    empno列が一意であると仮定すると、この問合せの結果は1行(または、:idの一致が見つからない場合は結果なし)になるはずです。試してみるには、「テスト」ボタンを押します。次のエラー・メッセージが表示されるはずです。

    400 - 不正なリクエストです - バインドされていないパラメータがリクエスト・パスに含まれています: id

    ブラウザに表示されるURIは次のようになります。

    https://server:port/ords/workspace/hr/employees/{id}
    

    説明:

    • serverは、Oracle Application ExpressがデプロイされているサーバーのDNS名

    • portは、サーバーがリスニング中のポート

    • workspaceは、ログインしているOracle Application Expressワークスペースの名前

    URIの最後の部分のhr/employees/{id}に注意してください。エラー・メッセージには有効なURIではないと表示され、問題は{id}という名前のパラメータを具体的な値に置き換えていなかったことです。修正するには、ブラウザの「戻る」ボタンを押し、「バインド変数の設定」をクリックします。

  4. :idという名前のバインド変数の値として7369を入力し、「テスト」を押します。

    新規のブラウザ・ウィンドウに、次のJSON(JavaScript Object Notation)が表示されます。

    {
     "empno":7369,
     "ename":"SMITH",
     "job":"CLERK",
     "mgr":7902,
     "hiredate":"1980-12-17T08:00:00Z",
     "sal":800,
     "deptno":20
    }
    

    ブラウザに表示されるこのリソースのURIにも注意してください。

    https://server:port/ords/workspace/hr/employees/7369
    

    URIテンプレートのパラメータ{id}がSQLのバインド変数:idにバインドされ(この場合は7369という具体的な値が指定され)、RESTfulサービスに実行される問合せは次のようになります。

    select * from emp
              where empno = 7369
    

    この問合せの結果は、前述のJSONとしてレンダリングされます。

    ヒント:

    JSONを読むのは困難な場合があります。読みやすくするには、JSONを自動整形(pretty print)するブラウザ拡張機能をインストールします。たとえば、Mozilla FirefoxおよびGoogle Chromeは、どちらも拡張機能があります。

    ここで、存在しないリソースのURIを入力したときに何が起こるかを見てみます。

  5. バインド変数の設定ページで、:idの値を7369から1111に変更し、「テスト」を押します。

    前述のように新規のウィンドウがポップアップ表示され、JSONリソースの表示ではなく、次のエラー・メッセージが表示されます。

    404 - Not Found
    

    これは、このハンドラの予想どおりの動作です。:idemp表に存在しない値がバインドされた場合、問合せの結果は生成されず、標準HTTPステータス・コード「404 - 見つかりません」が戻されます。

    従業員のIDを知っていれば個別の従業員に関する情報を提供するサービスは可能ですが、有効な従業員IDのセットはどのように検出するのでしょう。

  6. 「取消」を押して、リソース・モジュールの内容が表示されている前のページに戻ります。
  7. employees/という名前のテンプレートをクリックします。

    次の手順では、まず生成されるリソースを確認し、その後でロジックの理解に役立つ説明を見ていきます。

  8. employees/の下にある「GET」ハンドラをクリックし、「テスト」をクリックします。

    次のようなリソースが表示されます(まだブラウザにJSONビューア拡張機能をインストールしていないなら、出力を見やすくするため、この機会にインストールをお薦めします)。

    {         
     "next": 
      {"$ref": 
        "https://server:port/ords/workspace/hr/employees/?page=1"},
     "items": [ 
      {
       "uri": 
        {"$ref": 
          "https://server:port/ords/workspace/hr/employees/7369"},
       "empno": 7369,
       "ename": "SMITH"
      }, 
      {
       "uri": 
        {"$ref": 
          "https://server:port/ords/workspace/hr/employees/7499"},
       "empno": 7499,
       "ename": "ALLEN"
      },
      ...
      {
       "uri": 
        {"$ref": 
          "https://server:port/ords/workspace/hr/employees/7782"},
       "empno": 7782,
       "ename": "CLARK"
      }     
     ]
    }
    

    このJSONドキュメントには注目すべき点が多数あります。

    • ドキュメントの最初の要素にはnextという名前が付けられ、結果の次のページを指すURIがあります。(ページ分割された結果がどのようにサポートされるかは、この後の手順で説明します)

    • 第2の要素はitemsという名前で、多数の子要素が含まれています。各子要素は、問合せによって生成される結果セットの行に対応します。

    • 各子要素の最初の要素はuriという名前で、各従業員の詳細情報を提供するサービスを指すURIが含まれています。URIの後半部分がどのようにURIテンプレートのemployees/{id}と一致しているかに注意してください。つまり、クライアントがこれらのURIのいずれかにアクセスすると、そのリクエストは前述のemployees/{id}のRESTfulサービスによって処理されます。

    このサービスは、すべての有効な従業員のリソースをリストするリソースを生成することで、有効な従業員IDの特定という問題に対処しています。ここで理解すべき重要な点は、サービスがID値のみをリストし、クライアントがこのIDを取得して予備知識のemployees/{id}サービスと組み合せて従業員のURIを生成するのではなく、サービスが各従業員のURIをリストしている点です。

    この理由は、有効な従業員のリストは大きくなる可能性があるためで、サービスがリストを小さいページに分割した場合でも、クライアントに結果の次のページを検索する場所を通知できるように、URIが使用されています。

    このサービスの実装方法を確認するには、次の手順に進みます。

  9. ブラウザで「戻る」ボタンを押し、「GET」ハンドラの定義に戻ります。

    「ソース・タイプ」が「問合せ」であることに注意してください。これはデフォルトのソース・タイプで、リソースにゼロ以上の結果を含められることを示しています。「ページ区切りサイズ」は7で、これは結果の各ページに7つの項目があることを意味します。最終的に、ハンドラのソースは次のようになります。

    select empno "$uri", empno, ename from (
     select emp.*, 
            row_number() over (order by empno) rn 
            from emp
     ) tmp 
     where 
      rn between :row_offset and :row_count
     
    

    問合せの内容:

    • 1行目は、3つの列を戻したいことを示しています。最初の列は従業員IDのempnoですが、列名に$uriという別名が付けられており(後述)、2列目は再び従業員ID、3列目は従業員の名前であるenameです。

    • 最初の文字が$(ドル記号)の結果セットの列は特別な扱いを受けます。それはURIに変換する必要のある列とみなされ、ハイパーリンク列と呼ばれます。このように、先頭に$を付けた列名はリソース内にハイパーリンクを生成するための方法です。

      ハイパーリンク列が見つかると、列が取得されるリソースのURIが列の値の前に付加されて、新しいURIが生成されます。たとえば、このサービスのURIがhttps://server:port/ords/workspace/hr/employees/であることを思い出してください。このサービスの問合せによって生成される最初の列empnoの値が7369の場合、$uriの値はhttps://server:port/ords/workspace/hr/employees/7369となります。

    • JSONにはURIのデータ型がないため、クライアントに対し、特定の値がURIを表していることを明確にするための規則が必要です。Oracle REST Data ServicesはJSON Reference提言を使用しており、その提言では$refという名前のメンバーを含み、その値が文字列である任意のJSONオブジェクトはURIであると述べられています。こうして、$uri列およびその値https://server:port/ords/workspace/hr/employees/7369は、次のJSONオブジェクトに変換されます。

      {"uri": 
           {"$ref": 
            "https://server:port/ords/workspace/hr/employees/7369"
           }
          } 
      
    • 内部の問合せは、分析関数row_number()を使用して結果セット内の行数をカウントし、外側のWHERE句は、結果セットとして戻される行数を結果ページ内に収まるように制限します。Oracle REST Data Servicesには2つの暗黙のバインド・パラメータとして:row_offsetおよび:row_countが定義されており、そのパラメータには常に、指定されたページの結果として戻すべき、最初および最後の行のインデックスが含まれています。

      たとえば、現在のページが最初のページで、ページ区切りサイズが7の場合は、:row_offsetの値は1に、:row_countの値は7になります。

    ハイパーリンクおよび結果のページ分割の両方を行うための簡単​​な方法を確認するには、次の手順に進みます。

  10. employeesfeed/リソース・テンプレートの「GET」ハンドラをクリックします。

    このハンドラの「ソース・タイプ」が「フィード」で、「ページ区切りサイズ」が25であることに注意してください。

  11. ページ区切りサイズを7に変更し、「変更を適用」をクリックします。

    ハンドラのソースは、単に次のようになります。

    select empno, ename from emp 
                        order by deptno, ename
    

    このように、問合せは前の例よりもはるかにシンプルですが、「テスト」をクリックすると前述の例によって生成される結果と非常によく似た結果が表示されます。

    • 「フィード」ソース・タイプは「問合せ」ソース・タイプの拡張版で、$で始まる名前の別名の列が不要になり、自動的に結果セットの最初の列をハイパーリンクに変換するものとみなします。この例では、「フィード」ソース・タイプにより、empnoの列が自動的にハイパーリンクに変換されます。

    • この例は、0より大きい「ページ区切りサイズ」が定義されていて、問合せが明示的にバインド・パラメータの:row_offsetまたは:row_countの参照を解除していない場合、自動的に結果セットのページを区切るOracle REST Data Servicesの機能を示しています。この例はこれら2つの条件の両方を満たすため、Oracle REST Data Servicesにより、戻す行の数とオフセットをカウントして制約する句でラップして問合せが拡張されます。自動的に結果をページに区切るこの機能は、「問合せ」ソース・タイプにも適用されることに注意してください。

3.3 RESTfulサービスへのセキュアなアクセスの構成

この項では、RESTfulサービスへのセキュアなアクセスの構成方法について説明します。

RESTful APIは、それぞれのリソースが一意のURIを持つ複数のリソースから構成されています。リソースのセットは権限によって保護できます。権限はロールのセットを定義し、認証済のユーザーのうちの少なくとも1人は、権限によって保護されたリソースへのアクセス権を持っている必要があります。

特定の権限によって保護されるリソースを構成するには、権限のマッピングを作成する必要があります。権限のマッピングは、権限が保護するリソースを特定するパターンのセットを定義します。

トピック:

3.3.1 認証

ユーザーは、ファースト・パーティのCookieベースの認証またはサード・パーティのOAuth 2.0ベースの認証を使用して認証できます。

トピック:

3.3.1.1 ファースト・パーティのCookieベースの認証

ファースト・パーティは、RESTful APIの作成者です。ファースト・パーティのアプリケーションは、RESTful APIと同じWebオリジンにデプロイされたWebアプリケーションです。ファースト・パーティのアプリケーションは、Webアプリケーションが使用しているものと同じCookieセッションを使用し、RESTful APIに自身を認証し、権限を付与することが可能です。ファースト・パーティのアプリケーションにはRESTful APIへの完全なアクセス権があります。

3.3.1.2 サード・パーティのOAuth 2.0ベースの認証

サード・パーティは、RESTful APIの作成者以外のパーティです。サード・パーティのアプリケーションは、ファースト・パーティのアプリケーションと同じようには信頼できません。そのため、サード・パーティ製のアプリケーションに対し、選択的に制限付きのRESTful APIへのアクセス権を付与するための仲介手段が必要となります。

OAuth 2.0プロトコルは、RESTful APIへの条件付きおよび制限アクセスを提供するフローを定義します。簡単に言えば、サード・パーティのアプリケーションは、まずファースト・パーティに登録する必要があり、その後、ファースト・パーティ(またはファースト・パーティのRESTfulサービスのエンド・ユーザー)が、そのサード・パーティ・アプリケーションに対する期限の短いアクセス・トークンを発行することで、サード・パーティ・アプリケーションのRESTful APIへの制限付きアクセスを承認します。

3.3.1.2.1 Two-LeggedおよびThree-LeggedのOAuthフロー

OAuth内の一部のフローはTwo-Leggedで、その他のフローはThree-Leggedで定義されています。

Two-Legged OAuthのフローには、RESTful APIを呼び出すパーティ(サード・パーティ・アプリケーション)、およびRESTful APIを提供するパーティの2つのパーティが関与します。Two-Leggedのフローは、エンド・ユーザーがRESTful APIへのアクセスを承認する必要はなく、サーバーとサーバー間の相互作用に使用されます。OAuth 2.0では、このフローはクライアント資格証明フローと呼ばれます。これは、最も典型的には、企業間取引(business to business)のシナリオで使用されます。

Three-Legged OAuthのフローには、RESTful APIを呼び出すパーティ、RESTful APIを提供するパーティ、およびRESTful APIによりアクセスを行うデータを所有または管理しているエンド・ユーザー・パーティの3つのパーティが関与します。Three-Leggedのフローは、エンド・ユーザーがRESTful APIへのアクセスを承認する必要のある、クライアントとサーバーの相互作用に使用されます。OAuth 2.0では、認可コードのフローおよび暗黙のフローはThree-Leggedフローです。これらのフローは、通常、企業と消費者間の取引(business to consumer)シナリオで使用されます。

Three-Leggedフローによって保護されたリソースでは、OAuthのクライアントがRESTful APIに登録されている場合、アクセスを必要とする保護されたリソースを安全に示すことができ、クライアントのアクセスを許可するかどうかの最終的な承認の決定権をエンド・ユーザーが持ちます。しかし、Two-Leggedフローによって保護されたリソースでは、各クライアントにどのリソースへのアクセスを認可するかをRESTful APIの所有者が承認する必要があります。

3.3.2 リソースにアクセスするための権限について

リソースにアクセスするための権限は、次のデータで構成されます。

  • 名前: 権限の一意の識別子。この値は必須です。

  • ラベル: OAuthを使用してユーザーが権限へのアクセスを承認するように求められるとき、エンド・ユーザーに提示される権限の名前。権限がThree-LeggedのOAuthフローで使用される場合、この値は必須です。

  • 説明: 権限の目的の説明。これも、ユーザーが権限へのアクセスを承認するように求められるとき、エンド・ユーザーに提示されます。権限がThree-LeggedのOAuthフローで使用される場合、この値は必須です。

  • ロール: 権限に関連付けられているロール名のセット。認証されたパーティは、権限で保護されたリソースへのアクセスを許可されるために、指定されたロールの少なくとも1つを持っている必要があります。値は必須ですが、空のセットとすることはでき、それはユーザーの認証は必要だが、権限にアクセスするための特定のロールは必要ないことを示します。

Two-LeggedのOAuthフローでは、サード・パーティのアプリケーション(OAuthの用語ではクライアントと呼ばれる)は、必要なロールの少なくとも1つを持つ必要があります。

Three-LeggedのOAuthフローでは、サード・パーティのアプリケーションからのアクセス・リクエストを承認するエンド・ユーザーは、必要なロールの少なくとも1つを持つ必要があります。

3.3.3 リソースにアクセスするためのユーザーおよびロールについて

権限は一連のロールを列挙し、ユーザーはロールを持つことはできますが、これらのロールはどこに定義されるのでしょう。ロールを持っているユーザーについてはどうでしょう。彼らはどこに定義されているのでしょう。

権限は一連のロールを列挙し、ユーザーはロールを持つことができます。Oracle REST Data Servicesは、ユーザー管理のタスクをOracle REST Data Servicesがデプロイされているアプリケーション・サーバーに委任します。Oracle REST Data Servicesでは、アプリケーション・サーバーによって定義および管理されるユーザーを認証でき、認証されたユーザーが所属するロールおよびグループを識別できます。アプリケーション・サーバーのユーザー・リポジトリを構成することも、アプリケーション・サーバーにOracle REST Data Servicesをデプロイするパーティの責任です。

ユーザー・リポジトリを定義したり、既存のユーザー・リポジトリと統合したり、アプリケーション・サーバーはいろいろな方法で構成できるため、アプリケーション・サーバーのユーザー・リポジトリを構成する方法はこのドキュメントでは説明できません。詳細は、アプリケーション・サーバーのドキュメントを参照してください。

3.3.4 ファイルベースのユーザー・リポジトリについて

Oracle REST Data Servicesでは、簡易なファイルベースのユーザー・リポジトリ・メカニズムが提供されます。ただし、このユーザー・リポジトリはデモおよびテストのみを目的としており、本番使用はサポートされていません。

このリポジトリにユーザーを作成する方法の詳細は、次のように、ユーザー・コマンドのコマンドライン・ヘルプを参照してください。

java -jar ords.war help user

形式:

java -jar ords.war user <user> <roles>

引数:

  • <user>はユーザーのユーザーIDです。

  • <roles>はユーザーが持つロール(ゼロ以上)のリストです。

3.3.5 チュートリアル: リソースの保護およびアクセス

このチュートリアルでは、次のOAuth機能を使用し、リソースのセットを保護するための権限を作成し、保護されたリソースにアクセスする方法を示します。

  • クライアント資格証明

  • 認可コード

  • 暗黙のフロー

また、ファースト・パーティCookieベースの認証を使用してリソースにアクセスする方法を示します。

トピック:

3.3.5.1 OAuthフローと各フローの用途

この項では、様々なOAuthフロー機能の用途を説明します。

ファースト・パーティCookieベースの認証は、RESTful APIと同じオリジンでホストされるWebアプリケーションからRESTful APIにアクセスするときに使用します。

認可コード・フローは、RESTful APIにアクセスするサード・パーティのWebアプリケーションを許可する必要があり、そのサード・パーティ・アプリケーションが、安全にクライアントの資格証明を保持できる独自のWebサーバーを持っている場合に使用します。これは、ほとんどのWebアプリケーションの標準的な状況で、サード・パーティのアプリケーションは、アプリケーションの再認証をユーザーに促すことなく、リフレッシュ・トークンを使用してユーザー・セッションの存続期間を延長でき、最高のセキュリティと最高のユーザー・エクスペリエンスを提供できます。

暗黙のフローは、サード・パーティのアプリケーションがその資格証明を安全に保持できるWebサーバーを持たない場合に使用します。このフローは、サード・パーティの単一ページ・ベースのアプリケーションで役立ちます。暗黙のフローではリフレッシュ・トークンを発行できないので、ユーザーはアプリケーションを認証するように頻繁に促されます。

ネイティブ・モバイルやデスクトップのアプリケーションは、認可コードまたは暗黙のフローを使用する必要があります。それらは、Webブラウザの画面にサイン・インおよび認可のプロンプトを表示し、認可処理の最後にWebブラウザの画面からアクセス・トークンを取得する必要があります。

クライアント資格証明フローは、RESTful APIによって管理されるデータへのアクセスを承認するようにユーザーに要求せず、サード・パーティのアプリケーションにRESTful APIへの直接アクセスを提供する必要がある場合に使用します。このサード・パーティのアプリケーションは、資格証明の機密を保持できるサーバー・ベースのアプリケーションである必要があります。クライアント資格証明はいつでもネイティブの実行可能ファイル内で検出できるため、クライアント資格証明フローはネイティブ・アプリケーションでは使用しないでください。

3.3.5.2 このチュートリアルの前提

このチュートリアルでは、次のことが前提となっています。

  • Oracle REST Data Servicesは、次のURLにデプロイされています: https://example.com/ords/

  • ORDSTESTという名前のデータベース・スキーマがOracle REST Data Servicesで使用するために有効になっており、そのRESTful APIが次の場所で公開されています: https://example.com/ords/ordstest/

  • ORDSTESTスキーマには、次のように作成されたEMPという名前のデータベース表があります。

    create table emp (
      empno    number(4,0), 
      ename    varchar2(10 byte), 
      job      varchar2(9 byte), 
      mgr      number(4,0), 
      hiredate date, 
      sal      number(7,2), 
      comm     number(7,2), 
      deptno   number(2,0), 
      constraint pk_emp primary key (empno)
      );
    
  • 保護するリソースは次の場所にあります: https://example.com/ords/ordstest/examples/employees/

3.3.5.3 このチュートリアルの手順

リソースのセットを保護してアクセスするには、次の手順を実行します。

  1. スキーマを有効にします。ORDSTESTスキーマに接続し、次のPL/SQL文を実行します。

    begin
      ords.enable_schema;
      commit;
    end;
    
  2. リソースを作成します。ORDSTESTスキーマに接続し、次のPL/SQL文を実行します。

    begin
    ords.create_service(
          p_module_name => 'examples.employees' ,
          p_base_path  => '/examples/employees/',
          p_pattern =>  '.' ,
          p_items_per_page => 7,
          p_source  =>  'select * from emp order by empno desc');
    commit;
    end;
    

    このコードにより、この後の手順で権限で保護する/examples/employees/リソースが作成されます。

    次のようにcURLコマンドを実行して、リソースを確認できます。

    curl -i https://example.com/ords/ordstest/examples/employees/
    

    結果は次のようになるはずです(読みやすくするために編集しています)。

    Content-Type: application/json
    Transfer-Encoding: chunked
     
    {
     "items":
       [
        {"empno":7934,"ename":"MILLER","job":"CLERK","mgr":7782,"hiredate":"1982-01-23T00:00:00Z","sal":1300,"comm":null,"deptno":10},
        ...
       ],
     "hasMore":true,
     "limit":7,
     "offset":0,
     "count":7,
     "links":
       [
        {"rel":"self","href":"https://example.com/ords/ordstest/examples/employees/"},
        {"rel":"describedby","href":"https://example.com/ords/ordstest/metadata-catalog/examples/employees/"},
        {"rel":"first","href":"https://example.com/ords/ordstest/examples/employees/"},
        {"rel":"next","href":"https://example.com/ords/ordstest/examples/employees/?offset=7"}
       ]
    }
    
  3. 権限を作成します。ORDSTESTスキーマに接続し、次のPL/SQL文を実行します。

    begin
      ords.create_role('HR Administrator');     
     
      ords.create_privilege(
          p_name => 'example.employees',
          p_role_name => 'HR Administrator',
          p_label => 'Employee Data',
          p_description => 'Provide access to employee HR data');
      commit;
    end;
    

    このコードにより、ORDSTESTスキーマに属するロールと権限が作成されます。

    • ロール名は一意である必要があり、印刷可能な文字のみを含める必要があります。

    • 権限名は一意である必要があり、OAuth 2.0仕様の第3.3項のスコープ名で指定されている構文に準拠する必要があります。

    • Three-Leggedの認可コードおよび暗黙のフローでこの権限を使用する場合は、ラベルおよび権限の説明を用意する必要があります。このラベルおよび説明は、Three-Leggedフローの承認フェーズでエンド・ユーザーに提示されます。

    • 値は、その権限の名前と目的を識別するプレーン・テキストである必要があります。

    USER_ORDS_PRIVILEGESビューの問合せで、権限が正しく作成されたことを確認できます。

    select id,name from user_ords_privileges where name = 'example.employees';
    

    結果は次のようになるはずです。

    ID    NAME                                                                                                                                                                                                                                                           
    ----- -----------------
    10260 example.employees
    

    IDの値はデータベースによって異なりますが、NAMEの値はこのように表示されるはずです。

  4. 権限をリソースと関連付けます。ORDSTESTスキーマに接続し、次のPL/SQL文を実行します。

    begin
     ords.create_privilege_mapping(
          p_privilege_name => 'example.employees',
          p_pattern => '/examples/employees/*');     
      commit;
    end;

    このコードは、example.employees権限を/examples/employees/というリソース・パターンと関連付けます。

    USER_ORDS_PRIVILEGE_MAPPINGSビューの問合せで、権限が正しく作成されたことを確認できます。

    select privilege_id, name, pattern from user_ords_privilege_mappings;
    

    結果は次のようになるはずです。

    PRIVILEGE_ID NAME                 PATTERN          
    ------------ -------------------- ---------------------
    10260        example.employees    /examples/employees/*
    

    PRIVILEGE_IDの値はデータベースによって異なりますが、NAMEおよびPATTERNの値はこのように表示されるはずです。

    次のcURLコマンドを実行し、/examples/employees/リソースがexample.employees権限で保護されていることを確認できます。

    curl -i https://example.com/ords/ordstest/examples/employees/
    

    結果は次のようになるはずです(読みやすくするために再フォーマットしています)。

    HTTP/1.1 401 Unauthorized
    Content-Type: text/html
    Transfer-Encoding: chunked
     
    <!DOCTYPE html>
    <html>
    ...
    </html>
    

    保護されたリソースにファースト・パーティの認証を介してアクセスできることを、次の手順で確認できます。

    1. エンド・ユーザーを作成します。ファイルベースのユーザー・リポジトリを使用して、examples.employees権限にアクセスするために必要なHR管理者のロールを持つテスト・ユーザーを作成します。コマンド・プロンプトで次のコマンドを実行します。

      java -jar ords.war user "hr_admin" "HR Administrator"
      

      パスワードの入力を求められたら、入力し、確認します。

    2. エンド・ユーザーとしてサイン・インします。Webブラウザに次のURLを入力します。

      https://example.com/ords/ordstest/examples/employees/
      

      アクセスが拒否されたことを示すページで、サイン・インへのリンクをクリックします。

      HR_ADMINユーザーのために登録した資格証明を入力し、「サインイン」をクリックします。

      ページがhttps://example.com/ords/ordstest/examples/employees/にリダイレクトされること、およびJSONドキュメントが表示されることを確認します。

  5. OAuthクライアントを登録します。ORDSTESTスキーマに接続し、次のPL/SQL文を実行します。

    begin 
     oauth.create_client(
          p_name => 'Client Credentials Example',
          p_grant_type => 'client_credentials',
          p_privilege_names => 'example.employees',
          p_support_email => 'support@example.com');
     commit;
    end;
    

    このコードは、クライアント資格証明のOAuthフローを使用してexamples.employees権限にアクセスする、Client Credentials Exampleという名前のクライアントを登録します。

    次のSQL文を実行し、クライアントが登録されたこと、およびexamples.employees権限へのアクセスがリクエストされたことを確認できます。

    select client_id,client_secret from user_ords_clients where name = 'Client Credentials Example';
    

    結果は次のようになるはずです。

    CLIENT_ID                        CLIENT_SECRET                   
    -------------------------------- ------------------------
    o_CZBVkEMN23tTB-IddQsQ..         4BJXceufbmTki-vruYNLIg.. 
    

    CLIENT_IDおよびCLIENT_SECRETの値は、OAuthクライアントの機密の資格証明を表します。これらの値は、記録して安全に保管する必要があります。これは、クライアント・アプリケーションのユーザーIDおよびパスワードと考えることができます。

  6. OAuthクライアントに必要な権限を付与します。ORDSTESTスキーマに接続し、次のPL/SQL文を実行します。

    begin 
     oauth.grant_client_role(
         'Client Credentials Example',
         'HR Administrator');
     commit;
    end;
    

    このコードは、クライアント資格証明のOAuthフローを使用してexamples.employees権限にアクセスする、Client Credentials Exampleという名前のクライアントを登録します。

    次のSQL文を実行することで、クライアントにロールが付与されたことを確認できます。

    select * from user_ords_client_roles where client_name = 'Client Credentials Example';
    

    結果は次のようになるはずです。

     CLIENT_ID CLIENT_NAME                 ROLE_ID   ROLE_NAME           
    ---------- --------------------------- --------  ----------------------
         10286 Client Credentials Example    10222   HR Administrator   
    
  7. クライアントの資格証明を使用してのOAuthのアクセス・トークンを取得します。

    OAuthプロトコルでは、HTTPリクエストに、クライアント資格証明フローを使用して作成したアクセス・トークンを使用しなければならないと明記されています。[rfc6749-4.4.]。

    リクエストは、トークン・エンドポイントと呼ばれる、周知のURLとして作成する必要があります。Oracle REST Data Servicesのトークン・エンドポイントのパスは常にoauth/tokenで、アクセスされるスキーマのルート・パスからの相対です。この例のトークン・エンドポイントは次のとおりです。

    https://example.com/ords/ordstest/oauth/token
    

    次のcURLコマンドを実行します。

    curl -i --user clientId:clientSecret --data "grant_type=client_credentials" https://example.com/ords/ordstest/oauth/token
    

    このコマンドで、clientIdClient Credentials ExampleのUSER_ORDS_CLIENTS内のCLIENT_IDの値で置き換え、clientSecretClient Credentials ExampleのUSER_ORDS_CLIENTS内のCLIENT_SECRETの値で置き換えます。出力は次のようになります。

    HTTP/1.1 200 OK
    Content-Type: application/json
     
    {
     "access_token": "2YotnFZFEjr1zCsicMWpAA",
     "token_type":   "bearer",
     "expires_in":3600
    }
    

    この出力では、アクセス・トークンはbearerタイプで、その値はaccess_tokenフィールドで指定されています。この値はリクエストごとに異なります。expires_inの値は、アクセス・トークンの有効期限が切れるまでの秒数を示し、この例のトークンは1時間(3600秒)で期限切れになります。

  8. アクセス・トークンを使用して保護されたリソースにアクセスします。次のcURLコマンドを実行します。

    curl -i -H"Authorization: Bearer accessToken" https://example.com/ords/ordstest/examples/employees/
    

    このコマンドで、accessTokenが前の手順で示したaccess_tokenフォールドの値で置き換えられます。出力は次のようになります。

    Content-Type: application/json
    Transfer-Encoding: chunked
     
    {
     "items":
       [
        {"empno":7934,"ename":"MILLER","job":"CLERK","mgr":7782,"hiredate":"1982-01-23T00:00:00Z","sal":1300,"comm":null,"deptno":10},
        ...
       ],
     "hasMore":true,
     "limit":7,
     "offset":0,
     "count":7,
     "links":
       [
        {"rel":"self","href":"https://example.com/ords/ordstest/examples/employees/"},
        {"rel":"describedby","href":"https://example.com/ords/ordstest/metadata-catalog/examples/employees/"},
        {"rel":"first","href":"https://example.com/ords/ordstest/examples/employees/"},
        {"rel":"next","href":"https://example.com/ords/ordstest/examples/employees/?offset=7"}
       ]
    }
    
  9. 認可コード用のクライアントを登録します。ORDSTESTスキーマに接続し、次のPL/SQL文を実行します。

    begin
     oauth.create_client(
        p_name => 'Authorization Code Example',
        p_grant_type => 'authorization_code',
        p_owner => 'Example Inc.',
        p_description => 'Sample for demonstrating Authorization Code Flow',
        p_redirect_uri => 'http://example.org/auth/code/example/',
        p_support_email => 'support@example.org',
        p_support_uri => 'http://example.org/support',
        p_privilege_names => 'example.employees'
        );
     commit;
    end;
    

    このコードは、認可コードのOAuthフローを使用してexamples.employees権限にアクセスする、Authorization Code Exampleという名前のクライアントを登録します。実際のアプリケーションでは、認可コードをリダイレクトして戻すURIを用意する必要があり、有効なサポート電子メール・アドレスを指定する必要があります。この例では、架空のデータおよびサンプルのWebサービスexample.orgを使用しています。

    次のSQL文を実行し、クライアントが登録されたこと、およびexamples.employees権限へのアクセスがリクエストされたことを確認できます。

    select id, client_id, client_secret from user_ords_clients where name = 'Authorization Code Example';
    

    結果は次のようになるはずです。

            ID CLIENT_ID                        CLIENT_SECRET
    ---------- -------------------------------- --------------------------------
         10060 IGHso4BRgrBC3Jwg0Vx_YQ.. GefAsWv8FJdMSB30Eg6lKw.. 
    

    権限へのアクセス権を付与するには、エンド・ユーザーがアクセスを承認する必要があります。CLIENT_IDおよびCLIENT_SECRETの値は、OAuthクライアントの機密の資格証明を表します。これらの値は、記録して安全に保管する必要があります。これは、クライアント・アプリケーションのユーザーIDおよびパスワードと考えることができます。

  10. 認可コードを使用してOAuthアクセス・トークンを取得します。この手順には、いくつかのサブ手順があります。(前の手順でHR_ADMINエンド・ユーザーを作成しておく必要があります。)

    1. OAuth認可コードを取得します。

      エンド・ユーザーには、サイン・インおよびサード・パーティ・アプリケーションへのアクセスを承認するためのプロンプトを表示する(Webページを介して)必要があります。サード・パーティ・アプリケーションは、OAuthの認可エンドポイントにユーザーを誘導することによってこのプロセスを開始します。Oracle REST Data Servicesの認可エンドポイントのパスは常にoauth/authで、アクセスされるスキーマのルート・パスからの相対です。この例のトークン・エンドポイントは次のとおりです。

      https://example.com/ords/ordstest/oauth/auth
      

      OAuth 2.0プロトコルでは、認可リクエストのURIに、問合せ文字列に特定のパラメータを含める必要があると明記されています。

      response_typeパラメータには、codeの値が必要です。

      client_idパラメータには、アプリケーションのクライアント識別子の値が含まれている必要があります。これは前の手順で決定したclient_idの値です。

      stateパラメータには、一意の推測できない値が含まれている必要があります。この値には、2つの目的があります。それは、クライアント・アプリケーションが各認可リクエストを一意に識別する方法を提供すること(それにより、任意のアプリケーション固有の状態を値に関連付け、その値をアプリケーション自身のセッション識別子と考える)、およびクライアント・アプリケーションがクロス・サイト・リクエスト・フォージェリ(CSRF)攻撃から身を守る手段を提供することです。stateの値は、認可プロセスの最後にリダイレクトURIに戻されます。クライアントは、その値がアプリケーションによって開始された認可リクエストのものであることを確認する必要があります。クライアントが状態の値を検証できない場合は、認可リクエストが攻撃者によって開始されたものとみなし、リダイレクトを無視してください。

      認可リクエストを開始するには、Webブラウザで次のURLを入力します。

      https://example.com/ords/ordstest/oauth/auth?response_type=code&client_id=cliendId&state=uniqueRandomValue
      

      このURIは、clientIdを以前に注目したCLIENT_ID列の値と置き換え、uniqueRandromValueを一意の推測できない値に置き換えます。クライアント・アプリケーションは、この値を記憶し、認可フローの最後にリダイレクトの一部として戻されるstateパラメータと照合する必要があります。

      client_idが認識された場合、サイン・インのプロンプトが表示されます。エンド・ユーザーHR_ADMINの資格証明を入力して「サインイン」をクリックし、次のページで「承認」をクリックすると、クライアントが登録されたときに指定したリダイレクトURIへリダイレクトされます。リダイレクトURIは、URIの問合せ文字列部分に認可コードが含まれます。また、クライアントがフローの開始時に指定したものと同じstateパラメータの値が含まれます。リダイレクトURIは次のようになります。

      http://example.org/auth/code/example/?code=D5doeTSIDgbxWiWkPl9UpA..&state=uniqueRandomValue
      

      クライアント・アプリケーションは、stateパラメータの値を検証し、アクセス・トークンの取得に使用するcodeパラメータの値を記録する必要があります。

    2. OAuthのアクセス・トークンを取得します。

      サード・パーティ・アプリケーションは、認可コードを取得した後、それをアクセス・トークンと交換する必要があります。サード・パーティ・アプリケーションのサーバーは、トークン・エンドポイントにHTTPSリクエストを行う必要があります。次の例のようにcURLコマンドを使用して、このリクエストを行うサーバーを模倣できます。

      curl --user clientId:clientSecret --data "grant_type=authorization_code&code=authorizationCode" https://example.com/ords/ordstest/oauth/token
      

      このコマンドで、clientIdAuthorization Code ExampleのUSER_ORDS_CLIENTSにあるCLIENT_IDの値と置き換え、clientSecretAuthorization Code ExampleのUSER_ORDS_CLIENTSにあるCLIENT_SECRETの値と置き換え、authorizationCodeを前の手順で記録した認可コードの値(codeパラメータの値)と置き換えます。

      結果は次のようになるはずです。

      HTTP/1.1 200 OK
      Content-Type: application/json
       
      {
       "access_token": "psIGSSEXSBQyib0hozNEdw..",
       "token_type":   "bearer",
       "expires_in":3600,
       "refresh_token": "aRMg7AdWPuDvnieHucfV3g.."
      }
      

      この結果では、アクセス・トークンがaccess_tokenフィールドで指定され、リフレッシュ・トークンがrefresh_tokenフィールドで指定されています。このリフレッシュ・トークンの値は、ユーザーにサード・パーティ・アプリケーションの再認可を求めることなく、ユーザー・セッションを延長するために使用できます。

    3. アクセス・トークンを使用して保護されたリソースにアクセスします。

      サード・パーティ・アプリケーションでは、OAuthのアクセス・トークンを取得した後、そのアクセス・トークンを使用して保護された/examples/employees/リソースにアクセスできます。

      curl -i -H"Authorization: Bearer accessToken" https://example.com/ords/ordstest/examples/employees/
      

      このコマンドで、accessTokenが前の手順で示したaccess_tokenフォールドの値で置き換えられます。

      結果は次のようになるはずです。

      Content-Type: application/json
      Transfer-Encoding: chunked
       
      {
       "items":
         [
          {"empno":7934,"ename":"MILLER","job":"CLERK","mgr":7782,"hiredate":"1982-01-23T00:00:00Z","sal":1300,"comm":null,"deptno":10},
          ...
         ],
       "hasMore":true,
       "limit":7,
       "offset":0,
       "count":7,
       "links":
         [
          {"rel":"self","href":"https://example.com/ords/ordstest/examples/employees/"},
          {"rel":"describedby","href":"https://example.com/ords/ordstest/metadata-catalog/examples/employees/"},
          {"rel":"first","href":"https://example.com/ords/ordstest/examples/employees/"},
          {"rel":"next","href":"https://example.com/ords/ordstest/examples/employees/?offset=7"}
         ]
      }
      
    4. リフレッシュ・トークンを使用してセッションを延長します。

      サード・パーティ・アプリケーションは、いつでも、リフレッシュ・トークンの値を使用して新規の存続期間を持つ新規のアクセス・トークンを生成できます。これにより、サード・パーティ・アプリケーションは自由にユーザー・セッションを延長できます。このためには、サード・パーティ・アプリケーションのサーバーは、トークン・エンドポイントにHTTPSリクエストを行う必要があります。次の例のようにcURLコマンドを使用して、このリクエストを行うサーバーを模倣できます。

      curl --user clientId:clientSecret --data “grant_type=refresh_token&refresh_token=refreshToken" https://example.com/ords/ordstest/oauth/token

      このコマンドで、clientIdClient Credentials ClientのUSER_ORDS_CLIENTSにあるCLIENT_IDの値と置き換え、clientSecretClient Credentials ClientのUSER_ORDS_CLIENTSにあるCLIENT_SECRETの値と置き換え、refreshTokenを前の手順で取得したrefresh_tokenの値と置き換えます。

      結果は次のようになるはずです。

      HTTP/1.1 200 OK
      Content-Type: application/json
       
      {
       "access_token":  "psIGSSEXSBQyib0hozNEdw..",
       "token_type":    "bearer",
       "refresh_token": "aRMg7AdWPuDvnieHucfV3g..",
       "expires_in":    3600
      }
      

      この結果では、アクセス・トークンがaccess_tokenフィールドで指定され、新規リフレッシュ・トークンがrefresh_tokenフィールドで指定されています。このリフレッシュ・トークンの値は、ユーザーにサード・パーティ・アプリケーションの再認可を求めることなく、ユーザー・セッションを延長するために使用できます。(前のアクセス・トークンおよびリフレッシュ・トークンは無効となり、そのかわりに新規の値を使用する必要があることに注意してください。)

  11. 暗黙のフローのクライアントを登録します。ORDSTESTスキーマに接続し、次のPL/SQL文を実行します。

    begin
     oauth.create_client(
        p_name => 'Implicit Example',
        p_grant_type => 'implicit',
        p_owner => 'Example Inc.',
        p_description => 'Sample for demonstrating Implicit Flow',
        p_redirect_uri => 'http://example.org/implicit/example/',
        p_support_email => 'support@example.org',
        p_support_uri => 'http://example.org/support',
        p_privilege_names => 'example.employees'
        );
     commit;
    end;
    

    このコードは、暗黙のOAuthフローを使用してexamples.employees権限にアクセスする、Implicit Exampleという名前のクライアントを登録します。実際のアプリケーションでは、認可コードをリダイレクトして戻すURIを用意する必要があり、有効なサポート電子メール・アドレスを指定する必要があります。この例では、架空のデータおよびサンプルのWebサービスexample.orgを使用しています。

    次のSQL文を実行し、クライアントが登録されたこと、およびexamples.employees権限へのアクセスがリクエストされたことを確認できます。

    select id, client_id, client_secret from user_ords_clients where name = 'Implicit Example';
    

    結果は次のようになるはずです。

            ID CLIENT_ID CLIENT_SECRET
    ---------- -------------------------------- --------------------------------
         10062 7Qz--bNJpFpv8qsfNQpS1A.. 
    

    権限へのアクセス権を付与するには、エンド・ユーザーがアクセスを承認する必要があります。

  12. 暗黙のフローを使用してのOAuthのアクセス・トークンを取得します。(前の手順でHR_ADMINエンド・ユーザーを作成しておく必要があります。)

    エンド・ユーザーには、サイン・インおよびサード・パーティ・アプリケーションへのアクセスを承認するためのプロンプトを表示する(Webページを介して)必要があります。サード・パーティ・アプリケーションは、OAuthの認可エンドポイントにユーザーを誘導することによってこのプロセスを開始します。Oracle REST Data Servicesの認可エンドポイントのパスは常にoauth/authで、アクセスされるスキーマのルート・パスからの相対です。この例のトークン・エンドポイントは次のとおりです。

    https://example.com/ords/ordstest/oauth/auth
    

    OAuth 2.0プロトコルでは、認可リクエストのURIに、問合せ文字列に特定のパラメータを含める必要があると明記されています。

    response_typeパラメータには、tokenの値が必要です。

    client_idパラメータには、アプリケーションのクライアント識別子の値が含まれている必要があります。これは前の手順で決定したclient_idの値です。

    stateパラメータには、一意の推測できない値が含まれている必要があります。この値には、2つの目的があります。それは、クライアント・アプリケーションが各認可リクエストを一意に識別する方法を提供すること(それにより、任意のアプリケーション固有の状態を値に関連付け、その値をアプリケーション自身のセッション識別子と考える)、およびクライアント・アプリケーションがクロス・サイト・リクエスト・フォージェリ(CSRF)攻撃から身を守る手段を提供することです。stateの値は、認可プロセスの最後にリダイレクトURIに戻されます。クライアントは、その値がアプリケーションによって開始された認可リクエストのものであることを確認する必要があります。クライアントが状態の値を検証できない場合は、認可リクエストが攻撃者によって開始されたものとみなし、リダイレクトを無視してください。

    認可リクエストを開始するには、Webブラウザで次のURLを入力します。

    https://example.com/ords/ordstest/oauth/auth?response_type=token&client_id=cliendId&state=uniqueRandomValue
    

    このURIは、clientIdを以前に注目したCLIENT_ID列の値と置き換え、uniqueRandromValueを一意の推測できない値に置き換えます。クライアント・アプリケーションは、この値を記憶し、認可フローの最後にリダイレクトの一部として戻されるstateパラメータと照合する必要があります。

    client_idが認識された場合、サイン・インのプロンプトが表示されます。エンド・ユーザーHR_ADMINの資格証明を入力して「サインイン」をクリックし、次のページで「承認」をクリックすると、クライアントが登録されたときに指定したリダイレクトURIへリダイレクトされます。リダイレクトURIは、URIの問合せ文字列部分にアクセス・トークンが含まれます。また、クライアントがフローの開始時に指定したものと同じstateパラメータの値が含まれます。リダイレクトURIは次のようになります。

    http://example.org/auth/code/example/#access_token=D5doeTSIDgbxWiWkPl9UpA..&type=bearer&expires_in=3600&state=uniqueRandomValue
    

    クライアント・アプリケーションは、stateパラメータの値を検証し、そのアクセス・トークンの値をメモする必要があります。

  13. アクセス・トークンを使用して保護されたリソースにアクセスします。次のcURLコマンドを実行します。

    curl -i -H "Authorization: Bearer accessToken" https://example.com/ords/ordstest/examples/employees/
    

    このコマンドで、accessTokenが前の手順で示したaccess_tokenフォールドの値で置き換えられます。出力は次のようになります。

    Content-Type: application/json
    Transfer-Encoding: chunked
     
    {
     "items":
       [
        {"empno":7934,"ename":"MILLER","job":"CLERK","mgr":7782,"hiredate":"1982-01-23T00:00:00Z","sal":1300,"comm":null,"deptno":10},
        ...
       ],
     "hasMore":true,
     "limit":7,
     "offset":0,
     "count":7,
     "links":
       [
        {"rel":"self","href":"https://example.com/ords/ordstest/examples/employees/"},
        {"rel":"describedby","href":"https://example.com/ords/ordstest/metadata-catalog/examples/employees/"},
        {"rel":"first","href":"https://example.com/ords/ordstest/examples/employees/"},
        {"rel":"next","href":"https://example.com/ords/ordstest/examples/employees/?offset=7"}
       ]
    }

3.4 Oracle REST Data Servicesのユーザー・ロールについて

Oracle REST Data Servicesでは、少数のユーザー・ロールが事前定義されています。

  • RESTful Services - 保護されたRESTfulサービスに関連付けられたデフォルトのロールです。

  • OAuth2 Client Developer - OAuth 2.0のアプリケーションを登録するユーザーはこのロールが必要です。

  • SQL Developer - Oracle SQL Developerを使用してRESTfulサービスを開発するユーザーはこのロールが必要です。

  • SODA Developer - これは、SODA REST APIにアクセスする必要があるデフォルト・ロールです。このロールの詳細は、『Oracle REST Data Services SODA for REST開発者ガイド』を参照してください。

  • Listener Administrator - Oracle SQL Developerを介してOracle REST Data Servicesのインスタンスを管理するユーザーはこのロールが必要です。通常、java -jar ords.war userコマンドによって作成されたユーザーのみがこのロールを持ちます。

    Listener AdministratorロールによりOracle REST Data Servicesのインスタンスを構成でき、その結果、そのインスタンスで処理されるすべてのApplication Expressのワークスペースに影響を与えることが可能となるため、Application ExpressユーザーはListener Administratorロールを取得することを許可されません。

トピック:

3.4.1 Oracle Application ExpressのユーザーとOracle REST Data Servicesのロールについて

デフォルトでは、Oracle Application ExpressのユーザーはOracle REST Data Servicesの事前定義済ユーザー・ロールを持っていません。これは、デフォルトでは、Application Expressのユーザーは次のことができないことを意味します。

  • 保護されたRESTfulサービスの起動

  • OAuth 2.0アプリケーションの登録

  • Oracle SQL Developerを使用したRESTfulサービスの開発

これは、Application Expressの開発者および管理者を含め、すべてのApplication Expressユーザーに適用されます。そこで、Application Expressのユーザーを適切なユーザー・グループに追加して前述のアクションを実行できるようにするため、次の手順に従うことを覚えておくことが重要です。

トピック:

3.4.1.1 Application ExpressユーザーにOracle REST Data Servicesロールを付与する

Application Expressユーザーに前述のロールのいずれかを付与するには、ユーザーをロールに対応するApplication Expressのユーザー・グループに追加する必要があります。たとえば、RESTEASY_ADMINユーザーにRESTful Servicesロールを付与するには、次の手順を実行します。

  1. RESTEASY_ADMINRESTEASYワークスペースにログインします。
  2. 「管理」に移動し、「ユーザーとグループの管理」に移動します。
  3. RESTEASY_ADMINユーザーの左にある編集アイコンをクリックします。
  4. 「ユーザー・グループ」で、「RESTfulサービス」を選択します。
  5. 「変更の適用」をクリックします。

3.4.1.2 Application Expressユーザーに自動的にOracle REST Data Servicesロールを付与する

Application Expressユーザーを適切なユーザー・グループに追加するのは、手順を見落としがちで、管理するユーザーが多い場合は反復的なタスクとなります。

この問題に対処するため、defaults.xml構成ファイルを変更し、Application Expressユーザーに自動的に事前定義済のRESTfulサービス・ロールのセットを付与するようにOracle REST Data Servicesを構成できます。

このファイルには、Oracle REST Data Servicesがロールを構成するための3つのプロパティ設定が定義されています。

  • apex.security.user.roles - 開発者または管理者ではない通常のユーザーに付与するロールのカンマ区切りのリスト。

  • apex.security.developer.roles - Developerアカウントの権限を持つユーザーに付与するロールのカンマ区切りのリスト。Developerは、apex.security.user.roles設定で定義されているロールも継承します。

  • apex.security.administrator.roles - Administratorアカウントの権限を持つユーザーに付与するロールのカンマ区切りのリスト。Administratorは、apex.security.user.rolesおよびapex.security.developer.roles設定で定義されているロールも継承します。

たとえば、自動的に、すべてのユーザーにRESTful Services権限を付与し、すべての開発者および管理者にOAuth2 Client DeveloperおよびSQL Developerロールを付与するには、defaults.xml構成ファイルに次のように追加します。

<!-- Grant all Application Express Users the ability      
        to invoke protected RESTful Services -->
<entry key="apex.security.user.roles">RESTful Services</entry> 
<!-- Grant Application Express Developers and Administrators the ability
        to register OAuth 2.0 applications and use Oracle SQL Developer
        to define RESTful Services --> 
<entry key="apex.security.developer.roles">
   OAuth2 Client Developer, SQL Developer</entry>

defaults.xml構成ファイルを変更したら、Oracle REST Data Servicesを再起動する必要があります。

3.4.2 ロールによるRESTfulサービスのアクセス制御

組込みのRESTful Serviceロールは、保護されたRESTfulサービスにアクセスすることを許可されたユーザーの識別に役立つデフォルトです。

しかし、特定のRESTfulサービスにアクセスできるユーザーのセットを制限するため、きめ細かいロール定義が必要になることもあります。

トピック:

3.4.2.1 RESTfulサービスのロールの定義について

RESTfulサービスのロールは、Application Expressのユーザー・グループです。ギャラリRESTfulサービスへのアクセスを制御するためにユーザー・グループを作成するには、次の手順に従います。 (

  1. ワークスペース管理者としてRESTEASYワークスペースにログインします。

  2. 「管理」に移動し、「ユーザーとグループの管理」に移動します。

  3. 「グループ」タブをクリックします。

  4. 「ユーザー・グループの作成」をクリックします。

  5. 「名前」Gallery Usersと入力します。

  6. 「グループの作成」をクリックします。

3.4.2.2 ロールとRESTful権限の関連付け

ユーザー・グループを作成したら、それをRESTful権限と関連付けることができます。ギャラリ・ユーザーのロールをexample.gallery権限に関連付けるには、次の手順に従います。

  1. 「SQLワークショップ」に移動し、「RESTfulサービス」に移動します。
  2. タスクのセクションで、RESTfulサービスの権限をクリックします。
  3. 「ギャラリ・アクセス」をクリックします。
  4. 「割当済グループ」で、ギャラリ・ユーザーを選択します。
  5. 「変更の適用」をクリックします。

この変更で、ユーザーはギャラリRESTfulサービスにアクセスできるギャラリ・ユーザー・ロールを持ちます。

関連項目:

この手順では、例として「開発チュートリアル: イメージ・ギャラリの作成」のイメージ・ギャラリ・アプリケーションを使用します。

3.5 WebLogic ServerおよびGlassFishユーザー・リポジトリに対する認証

Oracle REST Data Servicesでは、WebLogic ServerおよびGlassFishによって提供されるAPIを使用し、資格証明(ユーザー名とパスワード)を検証し、ユーザーがメンバーであるグループおよびロールのセットを取得できます。

この項では、WebLogic ServerおよびGlassFishによって提供される組込みのユーザー・リポジトリでユーザーを作成し、そのユーザーに対して認証を行う機能を検証します。

このドキュメントではWebLogic ServerおよびGlassFishをLDAPリポジトリなどの多くの一般的なユーザー・リポジトリ・システムと統合する方法は説明しませんが、WebLogic ServerまたはGlassFishが正しく構成されていれば、Oracle REST Data Servicesでそのようなリポジトリに対して認証が可能です。アプリケーション・サーバーでどのようなユーザー・リポジトリがサポートされているか、およびそれらのリポジトリへのアクセスを構成する方法の詳細は、アプリケーション・サーバーのドキュメントを参照してください。

トピック:

3.5.1 WebLogic Serverに対する認証

WebLogic Serverに対してのユーザー認証には、大きな手順として次のものがあります。

  1. WebLogic Serverユーザーの作成

  2. WebLogic Serverユーザーの検証

3.5.1.1 WebLogic Serverユーザーの作成

サンプルのWebLogic Serverユーザーを作成するには、次の手順を実行します。

  1. WebLogic Serverがまだ実行されていなければ、起動します。

  2. WebLogic Server管理コンソール(通常は、http://server:7001/console)にアクセスし、資格証明を入力します。

  3. 左側のナビゲーション・ツリーで「セキュリティ・レルム」ノードをクリックします。

  4. セキュリティ・レルムがすでに存在する場合は、次の手順に進みます。セキュリティ・レルムが存在しない場合は、次のようにして1つ作成します。

    1. 「新規」をクリックします。

    2. 「名前」Test-Realmと入力し、「OK」をクリックします。

    3. 「Test-Realm」をクリックします。

    4. 「プロバイダ」タブをクリックします。

    5. 「新規」をクリックし、次の情報を入力します。

      名前: test-authenticator

      タイプ: DefaultAuthenticator

    6. 再起動が必要であると警告される場合は、WebLogic Serverを再起動します。

    7. 「Test-Realm」をクリックします。

  5. 「ユーザーとグループ」タブをクリックします。

  6. 「新規」をクリックし、次の情報を入力します。

    • 名前: 3rdparty_dev2

    • 「パスワード」: ユーザーの希望するパスワードを入力し、確認します。

  7. 「OK」をクリックします。

  8. 「グループ」タブをクリックします。

  9. 「新規」をクリックし、次の情報を入力します。

    • 名前: OAuth2 Client Developer(大文字/小文字を区別)

  10. 「OK」をクリックします。

  11. 「ユーザー」タブをクリックします。

  12. 「3rdparty_dev2」ユーザーをクリックします。

  13. 「グループ」タブをクリックします。

  14. 「選択済み」リストにOAuth2 Client Developerを追加します。

  15. 「保存」をクリックします。

3rdparty_dev2という名前のユーザーが作成され、OAuth2 Client Developerという名前のグループのメンバーになります。これは、このユーザーがOAuth2 Client Developerロールを取得することを意味し、それによりOAuth 2.0アプリケーションの登録が許可されます。

では、ユーザーを正常に認証できることを検証します。

3.5.1.2 WebLogic Serverユーザーの検証

作成したWebLogic Serverユーザーが正常に認証されることを検証するには、次の手順を実行します。

  1. ブラウザで、次の形式でURIにアクセスします。

    https://server:port/ords/resteasy/ui/oauth2/clients/

  2. 3rdparty_dev2ユーザーの資格証明を入力し、「サインイン」をクリックします。

アプリケーションが1つもリストされていない状態でOAuth 2.0クライアントの登録ページが表示されるはずです。このページが表示された場合は、WebLogic Serverのユーザー・リポジトリに対する認証が機能していることを検証できたことになります。

「ユーザーには、リソースにアクセスする権限がありません。」というメッセージとともにサインオンのプロンプトが再表示される場合は、誤りを犯しています(おそらく、グループ・リストの値のスペルミス)。

3.5.2 GlassFishに対する認証

GlassFishに対してのユーザー認証には、大きな手順として次のものがあります。

  1. GlassFishユーザーの作成

  2. GlassFishユーザーの検証

3.5.2.1 GlassFishユーザーの作成

サンプルのGlassFishユーザーを作成するには、次の手順を実行します。

  1. GlassFishがまだ実行されていなければ、起動します。
  2. GlassFishの管理コンソール(通常は、http://server:4848)にアクセスし、パスワードを設定している場合は資格証明を入力します。
  3. セキュリティ構成ページに移動します。
  4. 左のナビゲーション・ツリーで「構成」ノードを展開し、さらに次のノードを展開します: 「サーバー構成」「セキュリティ」「レルム」、および「ファイル」
  5. 「ユーザーの管理」をクリックします。
  6. 「新規」をクリックし、次の情報を入力します。
    • 名前: 3rdparty_dev2

    • グループ・リスト: OAuth2 Client Developer(大文字/小文字を区別)

    • 「パスワード」: ユーザーの希望するパスワードを入力し、確認します。

  7. 「OK」をクリックします。

3rdparty_dev2という名前のユーザーが作成され、OAuth2 Client Developerという名前のグループのメンバーになります。これは、このユーザーがOAuth2 Client Developerロールを取得することを意味し、それによりOAuth 2.0アプリケーションの登録が許可されます。

では、ユーザーを正常に認証できることを検証します。

3.5.2.2 GlassFishユーザーの検証

「GlassFishユーザーの作成」で作成したWebLogic Serverユーザーが正常に認証されることを検証するには、次の手順を実行します。

  1. ブラウザで、次の形式でURIにアクセスします。

    https://server:port/ords/resteasy/ui/oauth2/clients/

  2. 3rdparty_dev2ユーザーの資格証明を入力し、「サインイン」をクリックします。

アプリケーションが1つもリストされていない状態でOAuth 2.0クライアントの登録ページが表示されるはずです。このページが表示された場合は、WebLogic Serverのユーザー・リポジトリに対する認証が機能していることを検証できたことになります。

「ユーザーには、リソースにアクセスする権限がありません。」というメッセージとともにサインオンのプロンプトが再表示される場合は、誤りを犯しています(おそらく、グループ・リストの値のスペルミス)。

3.6 既存のグループ/ロール・モデルとの統合

他の項の例で、WebLogic ServerおよびGlassFishの組込みのユーザー・リポジトリの構成方法を説明しています。そのような状況では、ユーザー・グループの名前の付け方を完全に制御できます。ユーザーがロールとまったく同じ(大文字/小文字を区別)名前を持つグループのメンバーである場合、そのユーザーはそのロールを持っていると考えられます。

しかし、既存のユーザー・リポジトリと統合する場合は、RESTfulサービスの開発者がユーザー・リポジトリ内のユーザー・グループの命名や編成を制御できないことがあります。このような状況では、ユーザー・リポジトリに定義された既存の「物理」ユーザーグループをOracle REST Data ServicesまたはRESTfulサービス(あるいはその両方)で定義された「論理」ロールにマッピングするメカニズムが必要とされます。

このグループからロールへのマッピングは、Oracle REST Data Servicesではrole-mapping.xmlという名前の構成ファイルを構成することで実現されます。

トピック:

3.6.1 role-mapping.xmlについて

role-mapping.xmlは、各プロパティ・キーにユーザー・グループのセットに一致するパターンを定義し、そのプロパティ値で一致したユーザー・グループにマッピングされるロールを示すJava XMLプロパティ・ファイルです。これは、defaults.xml構成ファイルと同じフォルダに配置する必要があります。ファイルは手動で作成して編集する必要があります。

次の例を考えてみます。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
 <entry key="webdevs">RESTful Services</entry>
</properties>

このロール・マッピングは単純で、webdevsグループのメンバーであるすべてのユーザーにRESTful Servicesロールが付与され、それはwebdevsグループのすべてのメンバーがRESTful Servicesを起動できることを意味します。

1つのマッピングで、グループに複数のロールを適用できます。次に例を示します。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
 <entry key="webdevs">RESTful Services, SQL Developer</entry>
</properties>

この規則は、webdevsグループにRESTful ServicesおよびSQL Developerロールの両方を付与します。

トピック:

3.6.1.1 マッピング・ルールのパラメータ化

グループまたはロールの数が多い場合には、各グループから各ロールに明示的にマッピングするのは拡張性がよくありません。この問題に対処するため、ルールをパラメータ化できます。次の例を考えてみます。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> 
<properties>
 <entry key="{prefix}.webdevs">RESTful Services</entry>
</properties>

この例では、グループ名が.webdevsで終わる任意のグループにRESTful Servicesロールがマッピングされます。たとえば、HQ.webdevsという名前のグループは、EAST.webdevsという名前のグループと同じようにこのルールに一致します。

ルールのパラメータを指定する構文はURIテンプレートに使用するものと同じで、パラメータ名が中カッコ({})で区切られます。

3.6.1.2 パラメータの間接参照

グループのルールで定義された任意のパラメータは、ロールのルールでも間接参照できます。次の例を考えてみます。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> 
<properties>
 <entry key="cn={userid},ou={group},dc=MyDomain,dc=com">{group}</entry>
</properties>

この例では、LDAP識別名の組織単位コンポーネントをロールにマップします。つまり、組織単位の名前が同じ名前のロールに直接マッピングされるということです。{userid}パラメータを参照しますが、実際にはそれが使用されていないことに注意してください。{userid}は、ワイルドカードのフラグとして使用されています。

たとえば、識別名cn=jsmith,ou=Developers,dc=MyDomain,dc=comは、Developersという名前の論理ロールにマッピングされます。

3.6.1.3 間接マッピング

必要なロール・マッピングを実現するため、複数の中間的なルールの適用を必要とする場合もあります。次の例を考えてみます。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
 <entry key="cn={userid},ou={group},dc=example,dc=com">{group}</entry>
 <entry key="{prefix},ou={group},dc=acquired,dc=com">{group}</entry>
 <entry key="Developers">RESTful Services, SQL Developer</entry>
</properties>

この例では、LDAP識別名の組織単位コンポーネントをいくつかのロールにマップします。問題を複雑にしているのは、ユーザーは2つの異なる組織に属することがあり、その結果として識別名のパターンが異なるという事実です。

  • example.comのユーザーは、必ず、彼らのユーザーIDを識別する単一の共通名(CN)を持ち、それに組織単位(OU)とドメイン名(DC)が続きます。たとえば、cn=jsmith,ou=Developers,dc=example,dc=comです。

  • acquired.comのユーザーの共通名(CN)接頭辞は様々ですが、ここで重要なのは組織単位のフィールドです。たとえば、cn=ProductDev,cn=abell,ou=Engineering,dc=acquired,dc=comです。

  • どちらの組織もソフトウェア・エンジニアをou=Developersで識別します。

ここでは、両方の組織のエンジニアをRESTful ServicesおよびSQL Developerロールにマッピングする必要があります。

  • 最初のルールにより、組織example.comのエンジニアが中間のDevelopersロールにマッピングされます。

  • 2つ目のルールにより、組織acquired.comのエンジニアが中間のDevelopersロールにマッピングされます。

  • 最後のルールにより、中間のDevelopersロールからRESTful ServicesおよびSQL Developerロールにマッピングされます。

3.7 Oracle REST Data Services PL/SQL APIの使用

Oracle REST Data Servicesには、多くの操作でSQL Developerのグラフィカル・インタフェースのかわりに使用できるPL/SQL API (アプリケーション・プログラミング・インタフェース)があります。使用可能なサブプログラムは次のPL/SQLパッケージに含まれています。

Oracle REST Data Services PL/SQL APIを使用するには、まず次の手順を実行する必要があります。

  • RESTfulサービスを開発するために使用するデータベースに、Oracle REST Data Servicesをインストールします。

  • RESTアクセス用に1つ以上のデータベース・スキーマを有効化します。

トピック:

3.7.1 PL/SQL APIを使用したRESTfulサービスの作成

REST対応スキーマに接続してORDS.CREATE_SERVICEプロシージャを使用することで、RESTfulサービスを作成できます。

次の例では、簡単な「Hello-World」タイプのサービスを作成します。

begin
 ords.create_service(
      p_module_name => 'examples.routes' ,
      p_base_path   => '/examples/routes/',
      p_pattern     => 'greeting/:name',
      p_source => 'select ''Hello '' || :name || '' from '' || nvl(:whom,sys_context(''USERENV'',''CURRENT_USER'')) "greeting" from dual');
 commit;
end;
/

この例では、次の手順が実行されます。

  • examples.routesという名前のリソース・モジュールを作成します。

  • モジュールのベース・パス(URI接頭辞としても知られている)を/examples/routes/に設定します。

  • モジュールに、ルート・パターンがgreeting/:nameのリソース・テンプレートを作成します。

  • GETハンドラを作成し、そのソースを短い挨拶を作成するSQL問合せとして次の手順で設定します。

    • GETp_methodパラメータのデフォルト値で、そのパラメータが省略されているため、ここではそのデフォルト値が使用されます。

    • COLLECTION_FEEDp_methodパラメータのデフォルト値で、そのパラメータが省略されているため、ここではそのデフォルト値が使用されます

  • whomという名前のオプションのパラメータが指定されます。

関連トピック

3.7.2 RESTfulサービスのテスト

作成したRESTfulサービスをテストするために、まだ開始されていなければOracle REST Data Servicesを開始します。

java -jar ords.war

ブラウザでサービスのURIを入力します。次の例ではwhomパラメータが指定されていないため、デフォルトでは現行ユーザーからJoeに対して「Hello」の挨拶を表示します。

http://localhost:8080/ords/ordstest/examples/routes/greeting/Joe

この例の説明は、次のとおりです。

  • Oracle REST Data Servicesは、localhostで実行されていて、ポート8080でリスニングしています。

  • Oracle REST Data Servicesは、コンテキスト・パス/ordsでデプロイされています。

  • RESTfulサービスは、ordstestと呼ばれるデータベース・スキーマで作成されました。

  • URLにはオプションのwhomパラメータが含まれていないため、:whomバインド・パラメータはnull値にバインドされ、その結果、問合せは現行データベース・ユーザー(sys_context(''USERENV'',''CURRENT_USER''))の値をかわりに使用することになります。

ブラウザにJSON表示拡張機能がある場合、次のような結果が表示されます。

{
 "items": [
  {
   "greeting": "Hello Joe from ORDSTEST"
  }
 ],
 "hasMore": false,
 "limit": 25,
 "offset": 0,
 "count": 1,
 "links": [
  {
   "rel": "self",
   "href": "http://localhost:8080/ords/ordstest/examples/routes/greeting/"
  },
  {
   "rel": "describedby",
   "href": "http://localhost:8080/ords/ordstest/metadata-catalog/examples/routes/greeting/"
  },
  {
   "rel": "first",
   "href": "http://localhost:8080/ords/ordstest/examples/routes/greeting/Joe"
  }
 ]
}

次の例は、前述の例と類似していますが、オプションのパラメータwhomが指定されていて、挨拶がJaneからであることを示しています。

http://localhost:8080/ords/ordstest/examples/routes/greeting/Joe?whom=Jane

今回は、次のような結果になります。

{
 "items": [
  {
   "greeting": "Hello Joe from Jane"
  }
 ],
 "hasMore": false,
 "limit": 25,
 "offset": 0,
 "count": 1,
 "links": [
  {
   "rel": "self",
   "href": "http://localhost:8080/ords/ordstest/examples/routes/greeting/"
  },
  {
   "rel": "describedby",
   "href": "http://localhost:8080/ords/ordstest/metadata-catalog/examples/routes/greeting/"
  },
  {
   "rel": "first",
   "href": "http://localhost:8080/ords/ordstest/examples/routes/greeting/Joe"
  }
 ]
}

この結果では、:whomバインド・パラメータがJane値にバインドされているため、"from"の後にはORDSTESTではなくJaneが続くことに注意してください。