OData(Open Data Protocol)は、2007年にMicrosoft社が開始したオープンなプロトコルです。ODataは様々なWebアプリケーションで利用することができます。
このブログでは、SAP環境でODataをどのように利用できるかを、SAP Fioriと合わせて紹介します。さらに、ODataの基本的なクエリとリクエストについてもご紹介します。
SAP Fiori ODataとは何なのか?
ODataは問い合わせ可能で相互運用可能なREST APIを、シンプルかつ標準的な方法で作成・使用することができるオープンなプロトコルです。
このプロトコルでは、HTTPとJSONを適用することで、様々なクライアントに対しリソースをわかりやすい形式で公開することができます。
公開対象のリソースデータはサーバーでホストされており、クライアントはこのサービスを呼び出してリソースを取得・操作することができます。
これを実現するために必要なことは、サーバーが公開しているODataサービスと呼ばれるエンドポイント公開し、クライアント側はそれを呼び出すだけで済みます。
このプロトコルはHTTPベースでRESTfulなので、RESTfulなサービスと同じ制約に準拠する必要があります(https://restfulapi.net/rest-architectural-constraints/)。
しかし、一方で、HTTPスタックを持つあらゆるプログラミング言語でODataを利用することができます。
サーバー側では、JSONまたはATOMでリソースの公開エンドポイントを生成し、フロントエンドとはHTTPで通信します。
つまり、バックエンドとフロントエンドの言語は、HTTPで相互に通信できれば異なる言語を使用していても全く問題ありません。
特にクライアントサイドの言語にはJSONやATOMをオブジェクトに変換するライブラリを多種多様に持っているケースが多いため、開発者は簡単にODataによって公開されているデータを使用することができます。
クライアントからサーバーまでの概念図
ODataを使うメリットとは?
RESTベースのサービスが普及するにつれ、多くの企業がRESTfulなスタイルでデータを公開することが多くなりました。
しかしこれにより、異なるデータソースがそれぞれ微妙に異なる方法でデータを公開するケースが多くなり、開発者にとっては対応が面倒になるという問題が発生しました。
ODataは、データ使用のためのセマンティクスを含むメタデータを、公開されたサービスとともに提供することで、この問題を解決します。ODataは、XML、ATOM、JSONなどの一般的で扱いやすいフォーマットを使用しているため、クライアントはODataサービスを解析し、複数のデータソースからの情報を組み合わせることもできます。
ODataを使用するもう一つの利点は、前述していますが、プログラミング言語の柔軟性を可能にすることです。
SAPではどのように活用されているのか
スマートフォンやタブレットなどの様々なデバイスの登場により、従来のPoint-to-Point型のソリューションは、開発作業の重複やコストの増加、デザインと拡張性の低さなど、多くの面で時代遅れとなっています。
この問題に対するSAPのソリューションが「SAP NetWeaver Gateway」です。
SAP NetWeaver Gatewayは、ODataサービスを使用して、デバイス、プラットフォーム、環境全体をSAP Enterprise Dataに接続することができます。SAP NetWeaver Gatewayは、ODataサービスを使用してデバイスやプラットフォーム、環境全体をSAP Enterprise Dataに接続することができ、フロントエンドエンジニアがSAPの知識を持っていない場合でも、SAP Business Dataに接続することができます。
先程の図で説明をすると、NetWeaverがAPIの役割を担い、バックエンドサーバーに接続してデータを読み取り、フロントエンドが通信できるODataサービスに変換します。
SAP NetWeaver は既存の SAP Backend インフラストラクチャの上にあり、SAP NetWeaver Gateway サービスを有効にするために Backend システムにインストールする必要のある一連のアドオンコンポーネントがあります。
SAP NetWeaver Gateway Service Builder ツールは、OData サービスを作成して発行するための SAP GUI ベースのモデラーです。
これは、トランザクション SEGW で実行できます。
また、SAPはFioriによるモダンなソリューションを提供しました。
Fioriはブラウザベースで、シンプルさと効率性を重視したモダンでクリーンなデザインを提供します。
また、ユーザーはモバイルデバイスを使って、いつでもどこでもSAP Business Dataにアクセスすることができます。
Fiori は SAP UI5 と呼ばれる Javascript ベースのフレームワークを使用しており、Web 開発者は ABAP の知識がなくてもすぐに使用方法を習得することができます。
これにより、バックエンドからのODataサービスが提供されていれば、個々の画面やアプリケーションを簡単に構築することができるようになります。
ODataを生成できるバックエンドフレームワークは数多くありますが、それらについては別のブログ記事をご参照ください。
ODataの使い方
ODataの例として、実際に使われるRequestを見てみましょう。
この例で使用するサービスはl,旅行管理システムをシミュレートしたサンプルサービスで、以下のRequestに対するResponseを確認することで、誰が旅行に参加するかを確認できます。
これらの例はodata.org(https://www.odata.org/)からの引用です。
HTTP request:
GET https://services.odata.org/v4/TripPinServiceRW/People HTTP/1.1
OData-Version: 4.0
OData-MaxVersion: 4.0
可読性を上げるために、リクエストのURLを以下のように短縮して表現します。
GET serviceRoot/People
※ この例のサービスを試してみたい場合は、serviceRootを上記の完全なURLに置き換えてください。
Responseの内容は以下のようになります:
{
“@odata.context”: “serviceRoot/$metadata#People”,
“@odata.nextLink”: “serviceRoot/People?%24skiptoken=8”,
“value”: [
{
“@odata.id”: “serviceRoot/People(‘russellwhyte’)”,
“@odata.etag”: “W/”08D1694BD49A0F11″”,
“@odata.editLink”: “serviceRoot/People(‘russellwhyte’)”,
“UserName”: “russellwhyte”,
“FirstName”: “Russell”,
“LastName”: “Whyte”,
“Emails”: [
“Russell@example.com”,
“Russell@contoso.com”
],
“AddressInfo”: [
{
“Address”: “187 Suffolk Ln.”,
“City”: {
“CountryRegion”: “United States”,
“Name”: “Boise”,
“Region”: “ID”
}
}
],
“Gender”: “Male”,
“Concurrency”: 635404796846280400
},
……
,
{
“@odata.id”: “serviceRoot/People(‘keithpinckney’)”,
“@odata.etag”: “W/”08D1694BD49A0F11″”,
“@odata.editLink”: “serviceRoot/People(‘keithpinckney’)”,
“UserName”: “keithpinckney”,
“FirstName”: “Keith”,
“LastName”: “Pinckney”,
“Emails”: [
“Keith@example.com”,
“Keith@contoso.com”
],
“AddressInfo”: [],
“Gender”: “Male”,
“Concurrency”: 635404796846280400
}
]
}
クエリのURLから推測できるように、Responseには旅行者のリストと、その個人情報が含まれています。
しかし、旅行者のリストが長くなった場合には、毎回データセット全体を取得する必要はありません。
次の項で説明しますが、ODataには簡単で効率的なクエリオプションが用意されています。
データセットの1つのエントリを参照したい場合は、ID (主キー) で照会できます。
このモックサービスの例では、主キーはユーザー名なので、クエリは次のようになります。
GET serviceRoot/People(‘russellwhyte’)
Response の内容:
{
“@odata.context”: “serviceRoot/$metadata#People/$entity”,
“@odata.id”: “serviceRoot/People(‘russellwhyte’)”,
“@odata.etag”: “W/”08D1694BF26D2BC9″”,
“@odata.editLink”: “serviceRoot/People(‘russellwhyte’)”,
“UserName”: “russellwhyte”,
“FirstName”: “Russell”,
“LastName”: “Whyte”,
“Emails”: [
“Russell@example.com”,
“Russell@contoso.com”
],
“AddressInfo”: [
{
“Address”: “187 Suffolk Ln.”,
“City”: {
“CountryRegion”: “United States”,
“Name”: “Boise”,
“Region”: “ID”
}
}
],
“Gender”: “Male”,
“Concurrency”: 635404797346655200
}
ご覧のとおり、指定されたユーザーのみが返されました。
この構文は、ネストされたオブジェクトにアクセスするためのJavascriptの記法によく似ています:
GET serviceRoot/People(‘russellwhyte’)/LastName
→ returns {
“@odata.context”: “serviceRoot/$metadata#People(‘russellwhyte’)/LastName”,
“value”: “Whyte”
}
GET serviceRoot/People(‘russellwhyte’)/LastName/$value
→ さらに値のみを指定すると、次のように返されます。:
“Whyte”
ODataではフィルタリングも可能です。最も簡単な例は次のようなクエリで、名前が「Scott」の人物を全件フィルタリングすることを意味します。
GET serviceRoot/People?$filter=FirstName eq ‘Scott’
ODataのフィルタリングでは、複雑な取得条件を実現をするための、論理演算子や算術演算子も使用できます。
詳細な概要は以下を参照してください。
OData Version 4.0. Part 2: URL Conventions Plus Errata 03 (oasis-open.org)
OData を扱う際に頻繁に使用する、非常に重要なクエリ・オプションに $expand があります。
RDBのテーブルデータを参照する場合、1つまたは複数のエントリから関連するデータセットにアクセスする必要がある場合があります。
例えば、特定の人の友人のリストを取得する必要がある場合、次のようなクエリを使用できます。
GET serviceRoot/People(‘keithpinckney’)?$expand=Friends
上記の通り、ユーザー名「keithpinckney」のエンティティを1つ取得し、データベース内の「keithpinckney」に関連付けられている彼の友人全員のリストに展開しています。
レスポンスは次のようになります。:
{
“@odata.context”: “serviceRoot/$metadata#People/$entity”,
“@odata.id”: “serviceRoot/People(‘keithpinckney’)”,
“@odata.etag”: “W/”08D1694E2BB4317A””,
“@odata.editLink”: “serviceRoot/People(‘keithpinckney’)”,
“UserName”: “keithpinckney”,
“FirstName”: “Keith”,
“LastName”: “Pinckney”,
“Emails”: [
“Keith@example.com”,
“Keith@contoso.com”
],
“AddressInfo”: [],
“Gender”: “Male”,
“Concurrency”: 635404806897545600,
“Friends”: [
{
“@odata.id”: “serviceRoot/People(‘clydeguess’)”,
“@odata.etag”: “W/”08D1694E2BB4317A””,
“@odata.editLink”: “serviceRoot/People(‘clydeguess’)”,
“UserName”: “clydeguess”,
“FirstName”: “Clyde”,
“LastName”: “Guess”,
“Emails”: [
“Clyde@example.com”
],
“AddressInfo”: [],
“Gender”: “Male”,
“Concurrency”: 635404806897545600
},
{
“@odata.id”: “serviceRoot/People(‘marshallgaray’)”,
“@odata.etag”: “W/”08D1694E2BB4317A””,
“@odata.editLink”: “serviceRoot/People(‘marshallgaray’)”,
“UserName”: “marshallgaray”,
“FirstName”: “Marshall”,
“LastName”: “Garay”,
“Emails”: [
“Marshall@example.com”,
“Marshall@contoso.com”
],
“AddressInfo”: [],
“Gender”: “Male”,
“Concurrency”: 635404806897545600
}
]
}
この他にも、必要な特定のデータを参照、あるいはソートするための演算子やオプションが多くあります。この記事ですべてを紹介するのは1つのブログ記事としては無理があるので、代わりにエントリの作成方法を見てみましょう。
OData Entityの作成・更新・削除方法
Entityを作成するには、クライアントはODataサービスが提供するURLにPOST Requestを送信する必要があります。
また、POSTのBodyには有効なEntityの内容が含まれている必要があります。
これまでに紹介した人物の例にならって、データベースに新しいデータを作成します。
作成を行うためのRequestは以下のようになります。:
POST serviceRoot/People
OData-Version: 4.0
Content-Type: application/json;odata.metadata=minimal
Accept: application/json
{
“@odata.type” : “Microsoft.OData.SampleService.Models.TripPin.Person”,
“UserName”: “teresa”,
“FirstName” : “Teresa”,
“LastName” : “Gilbert”,
“Gender” : “Female”,
“Emails” : [“teresa@example.com”, “teresa@contoso.com”],
“AddressInfo” : [
{
“Address” : “1 Suffolk Ln.”,
“City” :
{
“CountryRegion” : “United States”,
“Name” : “Boise”,
“Region” : “ID”
}
}]
}
処理に成功した場合は、以下のようなResponseが返却されます。:
HTTP/1.1 201 Created
Content-Length: 468
Content-Type: application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8
Location: serviceRoot/People(‘teresa’)
OData-Version: 4.0
{
“@odata.context”:”serviceRoot/$metadata#People/$entity”,
“@odata.id”:”serviceRoot/People(‘teresa’)”,
“@odata.editLink”:”serviceRoot/People(‘teresa’)”,
“UserName”:”teresa”,
“FirstName”:”Teresa”,
“LastName”:”Gilbert”,
“Emails”:[“teresa@example.com”,”teresa@contoso.com”],
“AddressInfo”:[{“Address”:”1 Suffolk Ln.”,”City”:{“CountryRegion”:”United States”,”Name”:”Boise”,”Region”:”ID”}}],
“Gender”:”Female”
}
更新の場合は、POSTではなくPATCHを使用します:
PATCH serviceRoot/People(‘russellwhyte’)
OData-Version: 4.0
Content-Type: application/json;odata.metadata=minimal
Accept: application/json
{
“@odata.type” : “Microsoft.OData.SampleService.Models.TripPin.Person”,
“Emails” : [“Russell@example.com”, “Russell@contoso.com”, “newRussell@contoso.com”]
}
削除の場合は、参照時と同じようなRequestを書くことで実行できます。使用するメソッドはDELETEです。:
DELETE serviceRoot/People(‘vincentcalabrese’)
まとめ SAP Fiori ODataとは
ここまでで、SAP FioriのODataとはどのようなものなのか、ODataが如何に便利なものなのかを実例を通してご紹介させていただきました。この記事が皆様の開発作業の一助になれば幸いです。
ご覧頂きありがとうございました。その他のブログもご参照いただけますようお願いいたします。SAPアドオン
パソナテックではSAP Fioriの概要、技術要素を解説している「SAP FioriとBTPが理解できる基本ガイドブック」をご用意しました。本資料は、SAP FioriとBTPの理解を深めたい方に必見の資料です。ぜひダウンロードいただき、ご覧ください。