ORDS Database APIには、APEXのワークスペースを操作するREST APIが含まれています。主要なAPIにアプリケーションの一覧/エクスポート/インポート/削除があり、これらのREST APIを呼び出すことにより、インスタンスの異なるワークスペースに含まれるアプリケーションを操作することができます。
異なるAutonomous DatabaseのAPEXワークスペースにあるアプリケーションの一覧、アプリケーションのインポート、エクスポートおよび削除を行なうAPEXアプリケーションを作成してみました。以下のように動作します。
ORDS Database APIについて、以下の記事を参考にしています。
ORDSのProduct ManagerのJeff Smithさんによる以下の記事
ORDS and our APEX REST APIsOracle APEXのArchitectのCarsten Czarskiさんによる以下の記事
Oracle APEX App Deployments made easy: Use the ORDS REST APIsインスタンスURLとワークスペース名により操作するAPEXのワークスペースを特定し、ユーザー認証にはOAuthのクライアント・クリデンシャル・フローのクライアントIDとクライアントシークレットを使用します。
アプリケーションを作成するAPEXワークスペースと作成したアプリケーションから操作するAPEXワークスペースの両方に、Always FreeのAutonomous Databaseを使用して作業を進めます。ORDS Database APIはORDSに実装されている機能であるためネットワークとして接続できれば、オンプレミスの環境も操作の対象にできます。
これから作成するAPEXアプリケーションの操作対象となるインスタンスを準備します。操作対象となるAutonomous DatabaseのORDSに接続します。
https://ADBのホスト名/ords/
SQL Developer Webを開きます。
ADBの管理者ユーザーADMINでサインインします。パスワードはADBの作成時に設定しています。
RESTを開きます。
OAuthクライアントの作成を実行します。
クライアント定義のタブを開き、必要な情報を入力します。付与タイプはCLIENT_CREDです。
名前、説明、サポート電子メールを入力します。これらの値は、ORDS Database APIを呼び出す際の認証情報としては使われません。
ロールのタブを開き、ORDS Database APIの実行に必要なロールSQL Developerを選択します。
作成をクリックします。
OAuthクライアントが作成されます。
クライアントIDとクライアントシークレットをコピーし、安全に保存します。この値からORDS Database APIを呼び出す際に指定するAPEXのWeb資格証明を作成します。
操作対象とするAPEXワークスペースの準備は以上で完了です。
リモートのワークスペースを操作するAPEXアプリケーションを作成します。
最初にORDS Database APIを呼び出すパッケージUTL_APEX_REMOTEを作成します。ORDS Database APIの呼び出しをPL/SQLのプロシージャにラップすることにより、プロセス・タイプAPIの呼出しとして呼び出せるようにします。
クイックSQLの以下のモデルより、表DBAPEX_WORKSPACESを作成します。操作対象とする別環境のAPEXワークスペースを保持します。
レビューおよび実行をクリックし処理を進め、表DBAPEX_WORKSPACESを作成します。
表が作成された時点で、その表を元にしたアプリケーションの作成を実行します。
アプリケーション作成ウィザードが起動します。
アプリケーションの名前はSample APEX DBAPIとします。ホーム・ページは不要なので削除します。結果として表DBAPEX_WORKSPACESを対象としたフォーム付き対話モード・レポートのページが作成されます。
以上の設定でアプリケーションの作成を実行します。
アプリケーションが作成されたら、とりあえず実行してみます。
作成ボタンをクリックします。
画面右に操作対象のAPEXワークスペースを登録するドロワーが開きます。
ワークスペース名(Workspace Name)、インスタンスのURL(Instance URL)、Web資格証明の名前(Credential Name)、Web資格証明の静的ID(Credential Static ID)を入力するページ・アイテムはありますが、OAuthのクライアントIDとクライアントシークレットを入力するページ・アイテムは表DBAPEX_WORKSPACESの列として存在していないため、ありません。
OAuthのクライアントIDとクライアントシークレットを入力するページ・アイテムを追加し、それらの値からWeb資格証明を作成するプロセスを作成します。
ページ・デザイナでページ番号2のドロワーのページを開きます。
クライアントIDを入力するページ・アイテムP2_CLIENT_IDを作成します。
識別のタイプはテキスト・フィールド、ラベルはClient IDとします。セッション・ステートのストレージとしてリクエストごと(メモリーのみ)を選択します。
クライアントシークレットを入力するページ・アイテムP2_CLIENT_SECRETを作成します。
識別のタイプはパスワード、ラベルはClient Secretとします。セッション・ステートのストレージとしてリクエストごと(メモリーのみ)を選択します。
パスワードの設定の[Enter]を押すと送信はオフにします。
左ペインでプロセス・ビューを開きます。
新規にプロセスを作成し、プロセスの先頭に配置します。識別の名前はWeb資格証明の作成または更新とし、タイプはAPIの呼出しとします。
設定のタイプにPL/SQLパッケージを選択し、パッケージは作成済みのUTL_APEX_REMOTEを選択します。プロシージャまたはファンクションとしてCREATE_OR_UPDATE_WEB_CREDENTIALを選択します。
パラメータ名に一致するようにページ・アイテム名を決めているため、デフォルトで適切なページ・アイテムがパラメータに紐づきます。
サーバー側の条件のタイプにリクエストは値に含まれるを選択し、値としてCREATE SAVEを設定します。ボタン作成および変更の確定をクリックしたときに実行されます。削除に関する処理は実装していないため、登録しているAPEXワークスペースを削除しても、紐づいているWeb資格証明は削除されずAPEXのワークスペースに残ります。
以上でAPEXワークスペースを登録するページは完成です。
アプリケーションよりWeb資格証明を作成できるように、アプリケーション定義のセキュリティの詳細に含まれるランタイムAPIの使用状況のワークスペース・リポジトリを変更をチェックします。
アプリケーションを実行し、操作対象のワークスペースを登録します。
作成をクリックし、先ほどOAuthのクライアントIDとクライアントシークレットを作成したインスタンスとワークスペースを登録します。
Autonomous Databaseの場合、インスタンスURLは以下の形式で設定します。管理者ユーザーADMINの権限で実行するためインスタンスURLの末尾はadmin/になります。
https://ホスト名/ords/admin/
Oracle APEX REST Endpointsの一覧は/apex/から始まっています。最終的に呼び出すREST APIのエンドポイントは、インスタンスURLに_/db-api/stableとOracle APEX REST Endpointsを繋げたURLになります。
https://ホスト名/ords/admin/_/db-api/stable/apex/...
Credential Nameの指定がない場合は、静的IDをWeb資格証明の名前にしています。今回の例ではDBAPI_CRED_APEXDEVをWeb資格証明の静的IDとしています。
続けて別環境のワークスペースに含まれるアプリケーションの一覧とエクスポート/インポート/削除を行なうページを作成します。
取得したアプリケーションの一覧はAPEXコレクションに保存します。使用するAPEXコレクションの名前を変えられるように、アプリケーション定義の置換に置換文字列としてG_WORKSPACE_APPLICATIONSを作成します。置換値はWORKSPACEAPPSとします。この値が実際のコレクション名になります。
新規にページを作成します。
空白ページを選択します。
ページ番号は3、名前はApplicationsとします。その他はデフォルトから変更せず、ページ・モードは標準、ナビゲーションは両方ともオンとします。
ページの作成をクリックします。
空白ページが作成されます。
ORDS Database APIの引数となる値を保持するページ・アイテムを作成します。ページ・アイテムのタイプは非表示です。セッション・ステートのストレージはセッションごと(永続)を選択し、ページを送信した後も値が維持されるようにします。
作成するページ・アイテムはP3_WORKSPACE_NAME、P3_INSTANCE_URL、P3_CREDENTIAL_STATIC_IDの3つです。
ORDS Database APIのGet all applications in the specified workspaceのAPIを発行し、取得したアプリケーションでAPEXコレクションを初期化するプロセスを作成します。
新規にプロセスを作成しレンダリング前のヘッダーの前に配置します。
識別の名前はAPEXコレクションの初期化とします。タイプはAPIの呼出しです。設定のタイプにPL/SQLパッケージを選び、パッケージとしてUTL_APEX_REMOTE、プロシージャまたはファンクションとしてLOAD_APPS_INTO_APEX_COLLECTIONを選択します。
アプリケーションの一覧を表示する対話モード・レポートを作成します。
識別のタイトルはApplicationsとします。タイプは対話モード・レポートです。ソースのタイプをSQL問合せとし、SQL問合せとして以下を記述します。列EXPとDELには、アプリケーションのエクスポートと削除を呼び出すボタンを後で作成します。
JavaScriptよりレポートのリフレッシュを実行するため、詳細の静的IDとしてAPPLICATIONSを設定します。
変更を一旦保存します。
列WORKSPACE_NAMEをクリックすることにより、先ほど作成したページ番号3を開いて別環境にあるワークスペースに含まれるアプリケーションの一覧を表示するようにします。
識別のタイプをリンクに変更します。リンクのターゲットを開きます。
OKをクリックします。
ページ番号3が開き、そのワークスペースに作成されているアプリケーションが一覧されます。
変更を保存し、アプリケーションを実行して動作を確認します。
ワークスペース名をクリックします。
ページ・アイテムとしてP1_APPLICATION_IDを作成し、インポートするアプリケーションに割り当てるアプリケーションIDを指定します。ORDS Database APIによるインポートではアプリケーションIDは必須であり、空いているIDを自動で割り当てる機能はないようです。空いているIDを見つけるようにすると親切ですが今回はその機能は実装を見送り、アプリケーションIDは明示的に指定するようにします。同じアプリケーションIDのアプリケーションがある場合は上書きされるため注意が必要です。
識別のタイプは数値フィールド、ラベルはApplication IDとします。設定の数字の位置合せは開始、仮想キーボードは数値を選択します。
検証の必須の値はオン、セッション・ステートのストレージはリクエストごと(メモリーのみ)を選択します。
識別のタイプはファイルのアップロード、ラベルはFileとします。ストレージのタイプは表APEX_APPLICATION_TEMP_FILESを選択し、ファイルをパージするタイミングはリクエストの終わりとします。
検証の必須の値はオン、セッション・ステートのストレージはリクエストごと(メモリーのみ)を選択します。
アプリケーションのインポートを実行するボタンIMPORTを作成します。
識別のラベルはImportとします。外観のホットをオンにし、テンプレート・オプションのWidthにStretchを設定します。
動作のアクションはデフォルトのページの送信のまま、変更しません。
識別の名前はアプリケーションのインポート、タイプはAPIの呼出しとします。設定のタイプとしてPL/SQLパッケージを選択し、パッケージにUTL_APEX_REMOTE、プロシージャまたはファンクションとしてIMPORT_APPLICATIONを選びます。
成功メッセージはアプリケーションはインポートされました。とします。サーバー側の条件のボタン押下時にIMPORTを設定します。
以上でアプリケーションのインポート処理が実装できました。
続いてアプリケーションのエクスポートを実装します。
アプリケーションをエクスポートするプロセスを、Ajaxコールバックとして作成します。
識別の名前はEXPORT、タイプはコードの実行を選びます。Ajaxコールバックとして作成したプロセスの場合、タイプにAPIの呼出しを選ぶことはできません(不具合か仕様かは不明です)。そのためソースのPL/SQLコードとして、プロシージャUTL_APEX_REMOTE.EXPORT_APPLICATIONの呼び出しを記述します。
utl_apex_remote.export_application(
p_application_id => :P3_APPLICATION_ID
,p_instance_url => :P3_INSTANCE_URL
,p_workspace_name => :P3_WORKSPACE_NAME
,p_credential_static_id => :P3_CREDENTIAL_STATIC_ID
);
対話モード・レポートの列EXPより、このAjaxコールバックのプロセスEXPORTを呼び出します。
列EXPを選択し、識別のタイプをリンクに変更します。次のスクリーンショットにあるようにターゲットを設定したのち、リンク・テキストに以下を設定します。リンクをボタンとして表示します。
<button type="button" class="t-Button">Export</button>
ターゲットのページは3、アイテムの設定の名前にP3_APPLICATION_ID、値に#APPLICATION_ID#を設定します。クリックしたボタンEXPORTがある行のアプリケーションIDがページ・アイテムP3_APPLICATION_IDに設定されます。AjaxコールバックEXPORTはP3_APPLICATION_IDの値より、エクスポートするアプリケーションを決定します。
詳細のリクエストにAPPLICATION_PROCESS=EXPORTを設定することにより、AjaxコールバックEXPORTが呼び出されます。
アプリケーションを削除するプロセスを、Ajaxコールバックとして作成します。
識別の名前はDELETE、タイプはコードの実行、ソースのPL/SQLコードとして以下を記述します。
utl_apex_remote.delete_application(
p_application_id => apex_application.g_x01
,p_instance_url => :P3_INSTANCE_URL
,p_workspace_name => :P3_WORKSPACE_NAME
,p_credential_static_id => :P3_CREDENTIAL_STATIC_ID
,p_refresh_collection => true
,p_collection_name => :G_WORKSPACE_APPLICATIONS
);
JavaScriptによるAPEXアクションとしてdelete-applicationを作成し、そのアクションの引数idにアプリケーションIDを渡してAjaxコールバックのプロセスDELETEを呼び出すようにします。
ページ・プロパティのJavaScriptのページ・ロード時に実行に以下を記述します。
対話モード・レポートの列DELを選択し、列の書式のHTML式として以下を記述します。カスタム属性data-actionを指定し、APEXアクションdelete-applicationを呼び出しています。
<button type="button" class="t-Button t-Button--danger" data-action="#action$delete-application?id=#APPLICATION_ID#">Delete</button>
以上でアプリケーションは完成です。これで記事の先頭にあるGIF動画のように、別環境のワークスペースにあるアプリケーションの一覧、アプリケーションのインポート/エクスポート/削除ができるようになりました。
今回作成したAPEXアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/sample-apex-dbapi.zip
Oracle APEXのアプリケーション作成の参考になれば幸いです。
完