2021年12月10日金曜日

Oracle RDF Graph ServerをAutonomous Databaseで使用する(5) - REST APIを呼び出す

 Oracle RDF Graph ServerはREST APIを提供しています。Autonomous Databaseから、このREST APIを呼び出してみます。

今までのところOracle RDF Graph Serverでは、認証にorg.eclipse.jetty.security.authentication.FormAuthenticatorを使っています。REST APIを保護するには使いにくい(フォームに対してユーザー名/パスワードを送信する必要がある)ため、HTTPのBasic認証を使うように変更します。

jetty.homeのwebapps以下にあるorardf.xmlを変更します。authenticatorとしてorg.eclipse.jetty.security.authentication.BasicAuthenticatorを使うように変更したorardf.xmlは以下になります。

Oracle RDF Graph Serverが提供するREST APIの仕様は、ダウンロードしたアーカイブoracle-graph-webapps-xx.x.x.ziprdf-doc/orardf_swagger.jsonとして含まれています。これ以外にドキュメントはありません。REST APIのテスト実行もできるように、Oracle RDF Graph ServerよりSwagger UIを使って参照できるようにします。

Oracle RDF Graph Serverを実装したコンピュート・インスタンス上で作業を行います。Swagger UIをインストールするためにgitコマンドを使用します。未インストールであれば、gitをインストールします。

sudo dnf -y install git

[opc@rdfgs ~]$ sudo dnf -y install git

Failed to set locale, defaulting to C.UTF-8

Last metadata expiration check: 0:47:04 ago on Fri Dec 10 03:31:38 2021.

Dependencies resolved.

==========================================================================================================

 Package                     Architecture      Version                     Repository                Size

==========================================================================================================

Installing:

 git                         x86_64            2.27.0-1.el8                ol8_appstream            164 k

Installing dependencies:

 git-core                    x86_64            2.27.0-1.el8                ol8_appstream            5.7 M

 git-core-doc                noarch            2.27.0-1.el8                ol8_appstream            2.5 M

 perl-Error                  noarch            1:0.17025-2.el8             ol8_appstream             46 k

 perl-Git                    noarch            2.27.0-1.el8                ol8_appstream             78 k

 perl-TermReadKey            x86_64            2.37-7.el8                  ol8_appstream             40 k


Transaction Summary

==========================================================================================================

Install  6 Packages


Total download size: 8.5 M

Installed size: 45 M


[中略]


Installed:

  git-2.27.0-1.el8.x86_64             git-core-2.27.0-1.el8.x86_64   git-core-doc-2.27.0-1.el8.noarch    

  perl-Error-1:0.17025-2.el8.noarch   perl-Git-2.27.0-1.el8.noarch   perl-TermReadKey-2.37-7.el8.x86_64  


Complete!

[opc@rdfgs ~]$ 

Swagger UIをGitよりインストールします。ユーザーopcのホーム・ディレクトリで実行します。

git clone https://github.com/swagger-api/swagger-ui.git

[opc@rdfgs ~]$ git clone https://github.com/swagger-api/swagger-ui.git

Cloning into 'swagger-ui'...

remote: Enumerating objects: 34525, done.

remote: Counting objects: 100% (2155/2155), done.

remote: Compressing objects: 100% (842/842), done.

remote: Total 34525 (delta 1399), reused 1985 (delta 1299), pack-reused 32370

Receiving objects: 100% (34525/34525), 377.08 MiB | 5.56 MiB/s, done.

Resolving deltas: 100% (21282/21282), done.

[opc@rdfgs ~]$ 


ユーザーopcのホーム・ディレクトリ以下に/home/opc/swagger-uiというディレクトリが作成され、Swagger UIのリポジトリが(丸ごと...)コピーされます。

続けてrfc-docというディレクトリを作成し、Oracle RDF Graph Serverのアーカイブに含まれているrdf-doc以下の2つのファイル(orardf_swagger.jsonは必須)を配置します。

[opc@rdfgs ~]$ mkdir rdf-doc

ファイルの配置作業を行う。

[opc@rdfgs ~]$ ls rdf-doc

orardf_doc_url.txt  orardf_swagger.json

[opc@rdfgs ~]$ 


jetty.homeのwebapps以下に静的ファイルを参照可能にする設定を加えます。

Swagger UIを参照可能にする設定として、swagger-ui.xmlを作成します。

RDF Graph Serverが提供するREST APIの定義を参照可能にする設定として、rdf-doc.xmlを作成します。


これらのファイルを作成したのち、jetty.homeよりwebappsの内容を確認します。以下のファイル構成になります。

[opc@rdfgs jetty-distribution-9.4.44.v20210927]$ ls webapps

README.TXT  orardf.war  orardf.xml  rdf-doc.xml  swagger-ui.xml

[opc@rdfgs jetty-distribution-9.4.44.v20210927]$ 


追加した設定はすぐにJettyに反映されます。Swagger UIにアクセスしてREST APIの定義を確認します。

以下のURLにアクセスします。

https://RDF Graph Serverのホスト名/swagger-ui/dist/

Swagger UIには以下のURLを入力します。

https://RDF Graph Serverのホスト名/rdf-doc/orardf_swagger.json


Swagger UIからGETで定義されているREST APIは発行できますが、POSTについてはCSRF(Cross Site Request Forgery)の対応がなされているため、Swagger UIから実行できません。同様に、APEXからも単純なAPEX_WEB_SERVICE.MAKE_REST_REQUESTでは呼び出せません。

POSTによるREST APIの呼び出しの例として、SPARQLクエリを実行してみます。以下、PL/SQLによる記述です。祖父とその孫をリストします。


最初に簡単なREST APIを呼び出し、ORACLE_RDFSERSVER_CSRFとして返されるクッキーの値を取得します。その値を、POST送信時にHTTPヘッダーX-CSRF-Tokenとして送信します。送信する形式はapplication/jsonとなっているのですが、SPARQLの問い合わせを単純な文字列として送信します。

SQLワークショップのSQLコマンドより実行すると、実行結果として以下が返されます。

X=http://www.example.org/family/John,Y=http://www.example.org/family/Cathy X=http://www.example.org/family/John,Y=http://www.example.org/family/Jack X=http://www.example.org/family/John,Y=http://www.example.org/family/Tom X=http://www.example.org/family/John,Y=http://www.example.org/family/Cindy


実行するSPARQLに依存して取り出される列が決まるので、ポリモーフィックテーブル関数として実装すると、どのようなSPARQLであってもひとつの関数で対応できそうです。とはいえ、APEXからの利用を考えるとSPARQLの実行を、毎回RDF Graph Serverに依頼するよりは、Query cacheにある変換済みのSQLを取得して、直接データベースでSQLを実行する方がコーディングが楽でパフォーマンスも良いと思われます。

Query cacheの参照はGETリクエストなので、比較的簡単です。

SQLコマンドから実行すると以下のような結果になります。
Cache ID: d16221c6-8f48-4e08-8926-490118b3a0c6
-------------- SPARQL ----------------
PREFIX  rdf: <http: rdf-syntax-ns="" www.w3.org="">
PREFIX rdfs: <http: rdf-schema="" www.w3.org="">
PREFIX     : <http: family="" www.example.org="">

SELECT ?x ?y
WHERE {?x :grandParentOf ?y . ?x rdf:type :Male}
-------------- Transalted SQL Start ----------------
SELECT * FROM (
SELECT /*+ NO_MERGE(R) NO_SWAP_JOIN_INPUTS(R) LEADING(R V0 V1) NO_SWAP_JOIN_INPUTS(V0) NO_SWAP_JOIN_INPUTS(V1) */ V0.VNAME_PREFIX || V0.VNAME_SUFFIX AS X, V0.VALUE_ID AS X$RDFVID, V0.VNAME_PREFIX AS X$_PREFIX, V0.VNAME_SUFFIX AS X$_SUFFIX,  (CASE WHEN V0.VALUE_TYPE IS NULL THEN NULL WHEN V0.VALUE_TYPE IN ('UR','URI') THEN 'URI'
 WHEN V0.VALUE_TYPE IN ('BN', 'BLN') THEN 'BLN'
 ELSE 'LIT'
END)  AS X$RDFVTYP, V0.LONG_VALUE AS X$RDFCLOB, V0.LITERAL_TYPE AS X$RDFLTYP, V0.LANGUAGE_TYPE AS X$RDFLANG,
V1.VNAME_PREFIX || V1.VNAME_SUFFIX AS Y, V1.VALUE_ID AS Y$RDFVID, V1.VNAME_PREFIX AS Y$_PREFIX, V1.VNAME_SUFFIX AS Y$_SUFFIX,  (CASE WHEN V1.VALUE_TYPE IS NULL THEN NULL WHEN V1.VALUE_TYPE IN ('UR','URI') THEN 'URI'
 WHEN V1.VALUE_TYPE IN ('BN', 'BLN') THEN 'BLN'
 ELSE 'LIT'
END)  AS Y$RDFVTYP, V1.LONG_VALUE AS Y$RDFCLOB, V1.LITERAL_TYPE AS Y$RDFLTYP, V1.LANGUAGE_TYPE AS Y$RDFLANG,
1 AS SEM$ROWNUM
FROM (SELECT T0.START_NODE_ID AS X$RDFVID,
T0.CANON_END_NODE_ID AS Y$RDFVID,
T0.START_NODE_ID AS BGP$1
FROM "APEXDEV"."NET1#SEMV_VFAMILY" T0, "APEXDEV"."NET1#SEMV_VFAMILY" T1
WHERE T0.P_VALUE_ID = 8440289324123914894 AND
T1.P_VALUE_ID = 834132227519661324 AND
T1.CANON_END_NODE_ID = 3746347748834679532 AND
T0.START_NODE_ID = T1.START_NODE_ID) R, "APEXDEV".NET1#RDF_VALUE$ V0, "APEXDEV".NET1#RDF_VALUE$ V1
WHERE (1=1)  AND (R.X$RDFVID = V0.VALUE_ID) AND (R.Y$RDFVID = V1.VALUE_ID)
) WHERE (1=1)
-------------- Transalted SQL End ----------------

以上で、Oracle RDF Graph ServerをAutonomous Databaseで使用する方法の紹介は終了です。

Oracle APEXのアプリケーション作成の参考になれば幸いです。