Oracle FunctionsでAPEXのRestful Serviceと連携

Oracle Functionsって？という方は[こちら](https://qiita.com/y-araki-qiita/items/f73f815ea60a93978cac)。

Oracle FunctionsでORDSのRESTfulサービスで定義されているRest Endpointと連携することができます。
なので自作したOracle Application Express (APEX)アプリのRestful Serviceと連携、そこから更に他のツールと連携することも可能という事です。

今回Oracle Functionsで、APEXのRestful Dataを操作してみます。

### 前提 
・ATP(Autonomous Transaction Processing)をプロビジョニング
　⇒arakiatptestというDB名にしています。
・ATPからOracle APEXをセットアップし自身のワークスペースを作成していること。
　⇒testworkspaceというワークスペース名にしています。
・Oracle Functions開発、実行環境が構築されていること。
　⇒[・Oracle Functionsセットアップ](https://qiita.com/y-araki-qiita/items/d1ed0551d8943adc3bb5)

※こちらの手順で作成したATPは検証後、削除します。

## APEX Restful Service設定
APEXログイン後、SQLワークショップ >RESTfulサービスより
「Register Schema to ORDS」 をクリック(新しいワークスペースの場合スキーマをORDSに登録する必要があります)。
<img width="607" alt="キャプチ.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131627/a2d353c6-5c64-ccf8-fcb1-36420ff8fc51.png">

## スキーマ属性の保存
Schema Aliasに任意のスキーマ名を入れて「Save Schema Attributes」をクリック(ここではtestworkspaceという名前)。
<img width="299" alt="キャプチ2.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131627/a3bb71b4-7a62-6b98-fdd6-c91a110e833b.png">

ORDS RESTfulサービスページが表示されます。
<img width="555" alt="キャプチャ.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131627/015e73a0-0eb6-3c31-992a-f67296808a41.png">

Oracle APEXにプレインストールされたサンプルサービス「oracle.example.hr」
は従業員情報のリソースが提供されており、実体はjsonファイルとして格納されています。
これをエンドポイントを利用してOracle Funcitonsと連携し、操作することにします。

実際の中身を見てみます。
<img width="544" alt="キャプチャ3.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131627/c3a191bb-8989-fb39-5b9d-45ad972dcf12.png">
例えばサンプル内"employees"というテンプレート情報の"GET"ハンドラーには、
記載されたFull URL(RESTエンドポイント)でGETを実行した際のPL/SQLが記載されています。

ここでは、全従業員情報を取得するためのFULL URL(RESTエンドポイント)は以下となっています。
https://vhawxpz0akgqjtj-arakiatptest.adb.us-phoenix-1.oraclecloudapps.com/ords/testworkspace/hr/employees/

これを分割して詳しく説明すると、
インスタンス固有部分 ⇒ vhawxpz0akgqjtj-arakiatptest.adb.us-phoenix-1.oraclecloudapps.com
APEXワークスペース名 ⇒ testworkspace
残りのパスパラメータ ⇒ hr/employees/

## Oracle Functions実行
### 必要なリソースを準備
今回は以下を使用します。
https://github.com/abhirockzz/fn-atp-ords-sample

ファンクション開発環境にてソースをクローン

```
git clone https://github.com/abhirockzz/fn-atp-ords-sample
cd fn-atp-ords-sample
```

### エンドポイント設定
```
vi app.yaml
※以下編集。ORDS_REST_SERVICE_ENDPOINTに先ほどFull URL属性に記載されていた部分を記載します。
[変更前]
name: fn-atp-ords
config:
  ORDS_REST_SERVICE_ENDPOINT: <TO_BE_FILLED><img width="462" alt="キャプチャ1.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131627/7a5683c3-2b95-64b5-f076-19a083bb0743.png">

[変更後]
※エンドポイントのURLは/hr/まででOKです。
name: fn-atp-ords
config:
  ORDS_REST_SERVICE_ENDPOINT: https://vhawxpz0akgqjtj-arakiatptest.adb.us-phoenix-1.oraclecloudapps.com/ords/testworkspace/hr/
```

OCIコンソールでPhoenixリージョン、Oracle Functionsの画面に遷移します。
https://console.us-phoenix-1.oraclecloud.com/functions
Create Applicationより
<img width="462" alt="キャプチャ1.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131627/32bdd58b-468c-a6b1-5175-f5a9192ddb21.png">
NAME: fn-atp-ords
VCN: Fn用に作成したVCN
SUBNETS: PHX-AD-1から3まで選択
上記で「create」を押します。

### ファンクションのデプロイ
```
fn list apps
※作成したファンクションが表示されます
NAME            ID
fn-atp-ords     ocid1.fnapp.oc1.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

デプロイ(全ての起動をデプロイするコマンド)
fn -v deploy --all
```
### Rest Dataの操作
```
全従業員を表示(jqで整えてます)
fn invoke fn-atp-ords read-emps | jq

{
  "items": [
    {
      "uri": {
        "$ref": "https://vhawxpz0akgqjtj-arakiatptest.adb.us-phoenix-1.oraclecloudapps.com/ords/testworkspace/hr/employees/7369"
      },
      "rn": 1,
      "empno": 7369,
      "ename": "SMITH",
      "job": "CLERK",
      "hiredate": "1980-12-17T00:00:00Z",
      "mgr": 7902,
      "sal": 800,
      "comm": null,
      "deptno": 20
    }
…(以下省略)

IDで該当する従業員を取得
echo -n '7654' | fn invoke fn-atp-ords read-emps | jq
{
  "empno": 7654,
  "ename": "MARTIN",
  "job": "SALESMAN",
  "mgr": 7698,
  "hiredate": "1981-09-28T00:00:00Z",
  "sal": 1500,
  "comm": 1400,
  "deptno": 30
}

Employeeのレコードを更新(7654)
echo -n '{"empno":7654,"ename":"ARAKI","job":"ENGINEER","mgr":7698,"hiredate":"1981-09-28T00:00:00Z","sal":1500,"comm":1400,"deptno":30}' | fn invoke fn-atp-ords update-emps

更新確認
echo -n '7654' | fn invoke fn-atp-ords read-emps | jq
{
  "empno": 7654,
  "ename": "ARAKI",
  "job": "ENGINEER",
  "mgr": 7698,
  "hiredate": "1981-09-28T00:00:00Z",
  "sal": 1500,
  "comm": 1400,
  "deptno": 30
}

```

Oracle FunctionsでORDSのREST Endpointを利用しOracleツールと連携すれば、かなり色々な使い方ができると思いました。

## 関連記事
[・Oracle Functionsに関するメモ](https://qiita.com/y-araki-qiita/items/f73f815ea60a93978cac)
[・Oracle Functionsセットアップ](https://qiita.com/y-araki-qiita/items/d1ed0551d8943adc3bb5)
[・Oracle FunctionsでTensorFlowによる画像分類](https://qiita.com/y-araki-qiita/items/fefebb7e7b20d8573095)
[・Oracle FunctionsでEmail Deliveryと連携しメール送信](https://qiita.com/y-araki-qiita/items/dd8453f3fe46c9edc3f9)
[・Oracle FunctionsでObject Storage操作 (テキストを格納・取得+テキストをPDFに変換)](https://qiita.com/y-araki-qiita/items/e55bfe111794feda7716)
[・Fn Project - Fn Server構築 (Oracle Linux7.6)](https://qiita.com/y-araki-qiita/items/e11369243723792d1a6e)
[・Oracle FunctionsでOCI Go SDKを使いインスタンス操作](https://qiita.com/y-araki-qiita/items/c927aea9e743a4468c61)