n8nで定義したワークフローをOracle APEXのアプリケーションから呼び出してみます。また、ワークフローの処理に時間がかかる場合を想定して、n8nのワークフローよりOracle REST Data ServicesのREST APIを呼び出す手順を確認します。
n8nには色々なアプリケーションと連携するアクションが標準で含まれていますが、Oracle APEXやOracle Databaseと連携するアクションは見つかりませんでした。そのため、APEXアプリケーションからの呼び出しをWebhookで受け付け、HTTP RequestでORDSのREST APIを呼び出します。
以下のワークフローをn8nで作成しています。中間のCodeでは以下のJavaScriptのコードを実行し、受信したデータをそのまま出力に渡しています。
return $input.all();
APEXアプリからのn8nのWebhookの呼び出し、および、n8nのHTTP RequestでのORDS REST APIの呼び出しは、基本的にREST APIの呼び出しなので難しいことはありませんが、認証については少し工夫が必要です。本記事は、主に認証での工夫について説明しています。
以下より、実施した検証作業を紹介します。作業はApple SiliconのMacbook Proで実施しています。
n8nを動かすサーバーを準備します。n8n Community Editionをコンテナとして実行します。公式ドキュメントの
Docker Installationに記載されている手順に沿って、作業を実施します。
最初にボリュームを作成します。作成したボリュームにすべてのデータを保存するため、ボリュームが維持されていれば、コンテナを作り直してもそれまでの作業は維持されるようです。
podman volume create n8n_data
% podman volume create n8n_data
n8n_data
%
n8nを実行するコンテナをn8nという名前で作成します。
-e N8N_RUNNERS_ENABLED=true および -e N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=true のオプションについては、指定しないと警告が表示されたので追加しました。
podman run -it --rm --name n8n -e N8N_RUNNERS_ENABLED=true -e N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=true -p 5678:5678 -v n8n_data:/home/node/.n8n docker.n8n.io/n8nio/n8n
% podman run -it --rm --name n8n -e N8N_RUNNERS_ENABLED=true -e N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=true -p 5678:5678 -v n8n_data:/home/node/.n8n docker.n8n.io/n8nio/n8n
No encryption key found - Auto-generating and saving to: /home/node/.n8n/config
Initializing n8n process
n8n ready on ::, port 5678
Migrations in progress, please do NOT stop the process.
Starting migration InitialMigration1588102412422
Finished migration InitialMigration1588102412422
[中略]
n8n Task Broker ready on 127.0.0.1, port 5679
[license SDK] Skipping renewal on init because renewal is not due yet or cert is not initialized
Registered runner "JS Task Runner" (IFWQndGFfYn8ZyDN5Bma5)
Version: 1.104.1
Editor is now accessible via:
http://localhost:5678
Press "o" to open in Browser.
オプション
-p 5678:5678 を指定して、コンテナのポート5678をホストのポート5678にマップしています。ホストのブラウザからは、以下のURLでn8nにアクセスします。
今回の作業はAPEXアプリケーションからの呼び出しができれば良かったので、Get paid features for free (forever)についてはskipしました。
アカウントの設定が完了すると、n8nのコンソールが開きます。
ワークフローの作成はスクラッチから始めます。
最初のノードとしてWebhookを追加します。
Webhookの基本的な設定を行います。
HTTP MethodはPOST、RespondはWhen Last Node Finishes、Response DataはAll Entriesとします。
AuthenticationをクリックするとBasic Auth、Header Auth、JWT Auth、Noneの4つの選択肢が表示されます。認証が簡単なのはBasic Authですが、今回はJWT Authを選びます。
Credential for JWT Authをクリックして、+ Create new credentialを実行します。
JWTの署名の生成に関わる情報を設定します。今回は、APEX側では
APEX_JWT.ENCODEを呼び出してJWTを生成する予定です。そのため、署名アルゴリズム(
Algorithm)として選択できるのは
HS256のみになります。
HS256はハッシュ・アルゴリズムなので
Key Typeは
Passphraseになります。
Secretに
パスフレーズである文字列を入力します。この文字列を秘密キーとして、Oracle APEXのアプリケーションと共有します。
クリデンシャルの名前をAPEX Authに変更し、Saveします。
以上で、APEXアプリからの呼び出しを受け付けるWebhookが設定できました。
Webhook URLをコピーし、キャンバスに戻ります。
Webhookの後続のノードとしてCode(JavaScriptの実行)を追加します。
Modeは
Run Once for All items、
Languageは
JavaScript、
JavaScriptに以下を記述します。
return $input.all();
以上の設定を行い、キャンバスに戻ります。
この時点で一旦ワークフローをSaveします。
Execute Workflowをクリックします。WebhookにWaiting for you to call the Test URLと表示されているように、Webhookの呼び出し待ちになります。
APEXでの作業に移り、このn8nのワークフローを呼び出すAPEXアプリケーションを作成します。
空のAPEXアプリケーションを作成します。名前はCall n8n Workflowとします。
アプリケーションが作成されます。機能はすべてホーム・ページに作成します。
ホーム・ページをページ・デザイナで開きます。
最初にボタンSUBMITを作成します。n8nのWebhookを呼び出し、ワークフローを開始するボタンです。
外観のホットをオン、テンプレート・オプションのWidthをStretchにします。動作のアクションはデフォルトのページの送信です。
送信するデータを入力するページ・アイテムP1_REQUESTを作成します。タイプはテキスト領域です。外観の高さを15に拡張しておきます。
同様にn8nのワークフローからのレスポンスを表示するページ・アイテムP1_RESPONSEを作成します。P1_REQUESTの右隣に配置するため、レイアウトの新規行の開始をオフにします。
ボタンSUBMITをクリックしたときに実行されるプロセスを作成します。
プロセスの名前はCall n8n Workflowとします。タイプはコードを実行、ソースのPL/SQLコードとして以下を記述します。
サーバー側の条件のボタン押下時にSUBMITを指定します。
コード中でWebhook URLをG_WEBHOOK_URL、シークレットをG_SECRETから参照しています。これらはアプリケーション定義の置換文字列として設定します。
APEXをpodmanのコンテナとして実行している場合は、Webhook URLのlocalhostの部分は、host.containers.internalに置き換える必要があります。
置換文字列G_WEBHOOK_URLとしてWebhookのURL、G_SECRETとしてAPEX Auth作成時に設定したSecretの文字列を設定します。
シークレットのような秘密の値を置換文字列として設定するのは、安全な方法ではありません。実際に運用する場合は、Oracle CloudであればVaultなどにシークレットとして保存するなど、安全を確保するためにもう一工夫が必要です。
以上で、APEXアプリケーションからn8nのワークフローを開始できるようになりました。
n8nのワークフローがWaiting for triggering eventの状態であることを確認します。

RequestにJSONを入力し、ボタンSubmitをクリックします。ワークフローは入力をエコーバックするだけなので、正しいJSONであれば内容はなんでも構いません。
ワークフローが返すレスポンスが表示されます。内容を見ると、送信したリクエストの他にHTTPヘッダーやJWTに含まれるiss、sub、audoの値なども参照できることが確認できます。
n8nのコンソールではWorkflow executed successfullyと表示され、ワークフローが終了します。
以上で、APEXアプリからn8nのワークフローを開始できるようになりました。
次にn8nのワークフローからのコールバックを実装します。
最初にn8nからコールバックされた内容を保持する表N8N_CALLBACKを作成します。
n8nから呼び出すOracle REST Data ServicesのREST APIを作成します。
モジュールとしてn8n、テンプレートとしてcallback、POSTハンドラとして以下のコードを記述しています。
begin
insert into n8n_callback(response) values(:body_text);
commit;
end;
作成したREST APIをOAuth2で保護します。
コードを実行するとclient_idとclient_secretが印刷されます。一度しか印刷されないので、コピーして保存します。この値をn8n側に設定します。
コピーを忘れてしまった場合は、スクリプトを再実行します。
APEXアプリケーションのホーム・ページに、表N8N_CALLBACKの内容を表示する対話モード・レポートを追加します。
識別の名前はn8n Callback、ソースの表名にN8N_CALLBACKを設定します。
以上でAPEXアプリケーションの準備は完了です。
n8nのワークフローにHTTP Requestのノードを追加します。
HTTP Requestに、以下の設定を行います。
MethodはPOST、URLはORDSのREST APIのURLを指定します。モジュール・パスが/n8n/、テンプレート名がcallbackとして作成しているため、以下の形式になります。
http://ホスト:ポート/ords/ワークスペース名/n8n/callback
今回の作業ではワークスペース名がapexdev、n8nはコンテナで動作しているため、以下を設定しています。
http://host.containers.internal:8181/ords/apexdev/n8n/callback
AuthenticationはGeneric Credential Type、Generic Auth TypeにOAuth2 APIを選択します。OAuth2 APIにAPEX OAuth2 Credを設定していますが、この設定については、この後に紹介します。
Send Bodyをオンにし、Body Content TypeにJSON、Specify BodyにUsing JSON、JSONに{{ $json.body }}を設定します。入力されたJSONドキュメントを、ORDS REST APIの呼び出しの本体としてそのまま返しています。
APEX OAuth2 Credとして、以下を設定しています。
Grant TypeはClient Credentialsです。Access Token URLはORDSが標準で提供しているトークンURLで、以下の形式になります。
http://ホスト:ポート/ords/ワークスペース名/oauth/token
今回の作業ではワークスペース名がapexdev、n8nはコンテナで動作しているため、以下を設定しています。
http://host.containers.internal:8181/ords/apexdev/oauth/token
Client IDおよびClient Secretは、APEX側でOAuth2による保護を行なうスクリプトを実行した時にclient_idおよびclient_secretとして印刷された値を設定します。
ScopeにはORDSのモジュールの保護に使用した権限名を設定します。今回はn8n.privを設定します。
ORDSのトークンURLは、client_idおよびclient_secretはAuthorizationヘッダーとして送信されることを期待しているため、AuthenticationにはHeaderを設定します。
以上で、n8nのワークフローの更新は完了です。
ワークフローを実行します。
改変したAPEXアプリケーションからワークフローを開始します。
Requestに以下を入力し、ボタンSubmitをクリックします。
{
"name": "my first request"
}
ワークフローがすぐに終了するため、ページの再描画前にn8nのワークフローからのコールバックが完了するようです。
そのため、対話モード・レポートにRequestとして与えた文字列がすぐに表示されます。
今回の記事は以上になります。
簡単なアプリケーションですが、作成したAPEXアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/call-n8n-workflow.zip
Oracle APEXのアプリケーション作成の参考になれば幸いです。
完