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の呼出しとして呼び出せるようにします。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
create or replace package utl_apex_remote | |
as | |
CO_DBAPI_VERSION constant varchar2(8) default 'stable'; | |
CO_LIMIT constant number default 1000; | |
/** | |
* タイプがOAuth - Client CredentialsのWeb資格証明を作成する | |
* またはすでに同じタイプのWeb資格証明が作成済みであれば、Client IDとClient Secretを更新する。 | |
*/ | |
procedure create_or_update_web_credential( | |
p_credential_static_id in varchar2 | |
,p_credential_name in varchar2 | |
,p_client_id in varchar2 | |
,p_client_secret in varchar2 | |
); | |
/** | |
* インスタンスのURLとワークスペースを指定して、ワークスペースに作成されている | |
* アプリケーションの一覧を取得する。取得した一覧はAPEXコレクションに保存する。 | |
*/ | |
procedure load_apps_into_apex_collection( | |
p_collection_name in varchar2 | |
,p_instance_url in varchar2 | |
,p_workspace_name in varchar2 | |
,p_credential_static_id in varchar2 | |
,p_dbapi_version in varchar2 default CO_DBAPI_VERSION | |
,p_limit in number default CO_LIMIT | |
); | |
/** | |
* アップロードしたアプリケーションのエクスポートをリモートのAPEXインスタンスにインストールする。 | |
*/ | |
procedure import_application( | |
p_application_id in number | |
,p_file in varchar2 | |
,p_instance_url in varchar2 | |
,p_workspace_name in varchar2 | |
,p_credential_static_id in varchar2 | |
,p_dbapi_version in varchar2 default CO_DBAPI_VERSION | |
,p_refresh_collection in boolean default false | |
,p_collection_name in varchar2 default null | |
,p_limit in number default CO_LIMIT | |
); | |
/** | |
* リモートのAPEXインスタンスからアプリケーションをエクスポートする。 | |
*/ | |
procedure export_application( | |
p_application_id in number | |
,p_instance_url in varchar2 | |
,p_workspace_name in varchar2 | |
,p_credential_static_id in varchar2 | |
,p_dbapi_version in varchar2 default CO_DBAPI_VERSION | |
); | |
/** | |
* アプリケーションを削除する。 | |
*/ | |
procedure delete_application( | |
p_application_id in number | |
,p_instance_url in varchar2 | |
,p_workspace_name in varchar2 | |
,p_credential_static_id in varchar2 | |
,p_dbapi_version in varchar2 default CO_DBAPI_VERSION | |
,p_refresh_collection in boolean default false | |
,p_collection_name in varchar2 default null | |
,p_limit in number default CO_LIMIT | |
); | |
end; | |
/ | |
create or replace package body utl_apex_remote | |
as | |
/* | |
* Web資格証明の作成と更新。 | |
*/ | |
procedure create_or_update_web_credential( | |
p_credential_static_id in varchar2 | |
,p_credential_name in varchar2 | |
,p_client_id in varchar2 | |
,p_client_secret in varchar2 | |
) | |
as | |
l_credential_type_code apex_workspace_credentials.credential_type_code%type; | |
e_invalid_credential_specified exception; | |
begin | |
/* | |
* Web資格証明の静的IDは必須項目だが、NULLでないことを確認してから作成または更新する。 | |
*/ | |
if p_credential_static_id is not null then | |
begin | |
select credential_type_code into l_credential_type_code from apex_workspace_credentials | |
where static_id = p_credential_static_id; | |
exception | |
when no_data_found then | |
/* Web資格証明を新規作成する。 */ | |
apex_credential.create_credential( | |
p_credential_name => coalesce(p_credential_name, p_credential_static_id) | |
,p_credential_static_id => p_credential_static_id | |
,p_authentication_type => apex_credential.C_TYPE_OAUTH_CLIENT_CRED | |
/* 最低限のパラメータのみを設定している。 */ | |
); | |
end; | |
if l_credential_type_code <> apex_credential.C_TYPE_OAUTH_CLIENT_CRED then | |
/* Web資格証明が存在するがタイプがOAuthでない場合は更新できないので、例外をあげる */ | |
raise e_invalid_credential_specified; | |
end if; | |
/* | |
* Client IDとClient SecretによりWeb資格証明を更新する。 | |
*/ | |
if p_client_id is not null and p_client_secret is not null then | |
apex_credential.set_persistent_credentials( | |
p_credential_static_id => p_credential_static_id | |
,p_username => p_client_id | |
,p_password => p_client_secret | |
); | |
end if; | |
end if; | |
end create_or_update_web_credential; | |
/** | |
* アプリケーションの一覧をAPEXコレクションに保存する。 | |
*/ | |
procedure load_apps_into_apex_collection( | |
p_collection_name in varchar2 | |
,p_instance_url in varchar2 | |
,p_workspace_name in varchar2 | |
,p_credential_static_id in varchar2 | |
,p_dbapi_version in varchar2 | |
,p_limit in number | |
) | |
as | |
l_request_url varchar2(4000); | |
l_token_url varchar2(4000); | |
l_response clob; | |
e_call_api_failed exception; | |
begin | |
apex_collection.create_or_truncate_collection( | |
p_collection_name => p_collection_name | |
); | |
l_request_url := p_instance_url || '_/db-api/' || p_dbapi_version || '/apex/workspaces/' || p_workspace_name || '/applications/?limit=' || p_limit; | |
l_token_url := p_instance_url || 'oauth/token'; | |
/* | |
* Get all applications in the specified workspace | |
* https://docs.oracle.com/en/database/oracle/oracle-rest-data-services/23.4/orrst/op-apex-workspaces-workspace_name-applications-get.html | |
*/ | |
apex_web_service.clear_request_headers(); | |
apex_web_service.set_request_headers('Content-Type', 'application/json', p_reset => false); | |
l_response := apex_web_service.make_rest_request( | |
p_url => l_request_url | |
,p_http_method => 'GET' | |
,p_credential_static_id => p_credential_static_id | |
,p_token_url => l_token_url | |
); | |
if apex_web_service.g_status_code <> 200 then | |
raise e_call_api_failed; | |
end if; | |
/* | |
* l_responseにはアプリケーション一覧のJSONドキュメントが含まれる。 | |
*/ | |
for c in ( | |
select * from json_table(l_response, '$.items[*]' | |
columns( | |
application_id number path '$.application_id' | |
,application_name varchar2(255) path '$.application_name' | |
,application_alias varchar2(255) path '$.application_alias' | |
,application_group varchar2(255) path '$.application_group' | |
,application_owner varchar2(128) path '$.application_owner' | |
,page_count number path '$.page_count' | |
,workspace varchar2(255) path '$.workspace' | |
,availability_status varchar2(38) path '$.availability_status' | |
,last_updated_by varchar2(255) path '$.last_updated_by' | |
,last_updated_on date path '$.last_updated_on' | |
) | |
) | |
) | |
loop | |
apex_collection.add_member( | |
p_collection_name => p_collection_name | |
,p_n001 => c.application_id | |
,p_c001 => c.application_name | |
,p_c002 => c.application_alias | |
,p_c003 => c.application_group | |
,p_c004 => c.application_owner | |
,p_n002 => c.page_count | |
,p_c005 => c.workspace | |
,p_c006 => c.availability_status | |
,p_c007 => c.last_updated_by | |
,p_d001 => c.last_updated_on | |
); | |
end loop; | |
end load_apps_into_apex_collection; | |
/** | |
* アプリケーションをインポートする。 | |
*/ | |
procedure import_application( | |
p_application_id in number | |
,p_file in varchar2 | |
,p_instance_url in varchar2 | |
,p_workspace_name in varchar2 | |
,p_credential_static_id in varchar2 | |
,p_dbapi_version in varchar2 | |
,p_refresh_collection in boolean | |
,p_collection_name in varchar2 | |
,p_limit in number | |
) | |
as | |
l_request_url varchar2(4000); | |
l_token_url varchar2(4000); | |
l_response clob; | |
e_call_api_failed exception; | |
l_download apex_data_export.t_export; | |
begin | |
l_request_url := p_instance_url || '_/db-api/' || p_dbapi_version || '/apex/workspaces/' || p_workspace_name || '/applications/' || p_application_id; | |
l_token_url := p_instance_url || 'oauth/token'; | |
for f in ( | |
select blob_content from apex_application_temp_files where name = p_file | |
) | |
loop | |
/* | |
* Create or Update an APEX application, with a specific application id, in the specified workspace | |
* https://docs.oracle.com/en/database/oracle/oracle-rest-data-services/23.4/orrst/op-apex-workspaces-workspace_name-applications-application_id-put.html | |
*/ | |
apex_web_service.clear_request_headers(); | |
apex_web_service.set_request_headers('Content-Type', 'application/sql', p_reset => false); | |
l_response := apex_web_service.make_rest_request( | |
p_url => l_request_url | |
,p_http_method => 'PUT' | |
,p_body_blob => f.blob_content | |
,p_credential_static_id => p_credential_static_id | |
,p_token_url => l_token_url | |
); | |
if apex_web_service.g_status_code not in (200,201) then | |
raise e_call_api_failed; | |
end if; | |
end loop; | |
/* | |
* アプリケーション削除後にAPEXコレクションをリフレッシュする。 | |
*/ | |
if p_refresh_collection then | |
load_apps_into_apex_collection( | |
p_collection_name => p_collection_name | |
,p_instance_url => p_instance_url | |
,p_workspace_name => p_workspace_name | |
,p_credential_static_id => p_credential_static_id | |
,p_dbapi_version => p_dbapi_version | |
,p_limit => p_limit | |
); | |
end if; | |
end; | |
procedure export_application( | |
p_application_id in number | |
,p_instance_url in varchar2 | |
,p_workspace_name in varchar2 | |
,p_credential_static_id in varchar2 | |
,p_dbapi_version in varchar2 | |
) | |
as | |
l_request_url varchar2(32767); | |
l_token_url varchar2(4000); | |
l_export clob; | |
e_call_api_failed exception; | |
l_download apex_data_export.t_export; | |
begin | |
l_request_url := p_instance_url || '_/db-api/' || p_dbapi_version || '/apex/applications/' || p_application_id; | |
l_request_url := l_request_url || '?export_format=SQL_SCRIPT'; | |
l_token_url := p_instance_url || 'oauth/token'; | |
/* | |
* Get or export a specific APEX application | |
* https://docs.oracle.com/en/database/oracle/oracle-rest-data-services/23.4/orrst/op-apex-applications-application_id-get.html | |
*/ | |
apex_web_service.clear_request_headers(); | |
apex_web_service.set_request_headers('Content-Type', 'application/sql', p_reset => false); | |
l_export := apex_web_service.make_rest_request( | |
p_url => l_request_url | |
,p_http_method => 'GET' | |
,p_credential_static_id => p_credential_static_id | |
,p_token_url => l_token_url | |
); | |
if apex_web_service.g_status_code <> 200 then | |
raise e_call_api_failed; | |
end if; | |
l_download.file_name := 'f' ||p_application_id; | |
l_download.format := 'SQL'; | |
l_download.mime_type := 'application/sql'; | |
l_download.as_clob := true; | |
l_download.content_clob := l_export; | |
apex_data_export.download( p_export => l_download ); | |
apex_application.stop_apex_engine; | |
end export_application; | |
/** | |
* アプリケーションを削除する。 | |
*/ | |
procedure delete_application( | |
p_application_id in number | |
,p_instance_url in varchar2 | |
,p_workspace_name in varchar2 | |
,p_credential_static_id in varchar2 | |
,p_dbapi_version in varchar2 | |
,p_refresh_collection in boolean | |
,p_collection_name in varchar2 | |
,p_limit in number | |
) | |
as | |
l_request_url varchar2(4000); | |
l_token_url varchar2(4000); | |
l_response clob; | |
e_call_api_failed exception; | |
begin | |
l_request_url := p_instance_url || '_/db-api/' || p_dbapi_version || '/apex/workspaces/' || p_workspace_name || '/applications/' || p_application_id; | |
l_token_url := p_instance_url || 'oauth/token'; | |
/* | |
* Delete the specified APEX application | |
* https://docs.oracle.com/en/database/oracle/oracle-rest-data-services/23.4/orrst/op-apex-workspaces-workspace_name-applications-application_id-delete.html | |
*/ | |
apex_web_service.clear_request_headers(); | |
apex_web_service.set_request_headers('Content-Type', 'application/json', p_reset => false); | |
l_response := apex_web_service.make_rest_request( | |
p_url => l_request_url | |
,p_http_method => 'DELETE' | |
,p_credential_static_id => p_credential_static_id | |
,p_token_url => l_token_url | |
); | |
if apex_web_service.g_status_code <> 204 then | |
raise e_call_api_failed; | |
end if; | |
/* | |
* アプリケーション削除後にAPEXコレクションをリフレッシュする。 | |
*/ | |
if p_refresh_collection then | |
load_apps_into_apex_collection( | |
p_collection_name => p_collection_name | |
,p_instance_url => p_instance_url | |
,p_workspace_name => p_workspace_name | |
,p_credential_static_id => p_credential_static_id | |
,p_dbapi_version => p_dbapi_version | |
,p_limit => p_limit | |
); | |
end if; | |
htp.p('{ "status": "success" }'); | |
end delete_application; | |
end; | |
/ |
クイックSQLの以下のモデルより、表DBAPEX_WORKSPACESを作成します。操作対象とする別環境のAPEXワークスペースを保持します。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# prefix: dbapex | |
workspaces | |
workspace_name vc80 /nn | |
instance_url vc200 /nn | |
credential_name vc80 | |
credential_static_id vc80 /nn |
レビューおよび実行をクリックし処理を進め、表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には、アプリケーションのエクスポートと削除を呼び出すボタンを後で作成します。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
select | |
n001 as application_id | |
,c001 as application_name | |
,c002 as application_alias | |
,c003 as application_group | |
,c004 as application_owner | |
,n002 as page_count | |
,c005 as workspace | |
,c006 as availability_status | |
,c007 as last_updated_by | |
,d001 as last_updated_on | |
,'EXPORT' as EXP | |
,'DELETE' as DEL | |
from apex_collections | |
where collection_name = :G_WORKSPACE_APPLICATIONS |
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のページ・ロード時に実行に以下を記述します。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
apex.actions.add([ | |
{ | |
name: "delete-application", | |
action: function( event, element, args ) { | |
apex.message.confirm( | |
"Are you sure?", | |
(okPressed) => { | |
if (okPressed) { | |
let result = apex.server.process( | |
"DELETE", | |
{ | |
x01: args.id | |
} | |
); | |
result.done( | |
(data) => { | |
apex.message.showPageSuccess( | |
'application deleted successfully.', | |
); | |
apex.event.trigger( | |
"#APPLICATIONS", | |
"apexrefresh" | |
); | |
} | |
).fail( | |
(jqXHR, textStatus, errorThrown) => { | |
apex.message.alert('Failed to delete application.'); | |
} | |
); | |
} | |
} | |
) | |
} | |
} | |
]); |
対話モード・レポートの列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のアプリケーション作成の参考になれば幸いです。
完