2021年1月23日土曜日

リモート・デプロイメントを試してみる

 TwitterでVincent Morneauさんが「リモート・デプロイメントを初めて使ったけど、魔法のようだ。」とツイートしていたので、試してみました。その作業ログです。

前提条件はアプリケーションをデプロイされる側に、Oracle REST Data Servicesが実装されていること、および、REST対応SQLが有効化されていることです。ちょうど、こちらの記事でREST対応SQLを有効にしたOracle APEXのワークスペースを作っていたので、それを流用しました。デプロイ先の構成については、リモート・データへのアクセス (2) - REST対応SQLの記事を参考にしてください。

無料で使える検証環境apex.oracle.comから、Autonomous Databaseへアプリケーションのリモート・デプロイメントを実行してみます。

準備

クイックSQLを用いて表を作成し、その表を扱うアプリケーションを生成します。生成したアプリケーションをリモート・デプロイメントの対象にします。

SQLワークショップよりユーティリティクイックSQLを開きます。表の定義は以下とします。

# db: "18c"
# PK: "identity"
# language: "JA"
# semantics: "default"
tst_employees /insert 30
  name vc80
  age number

SQLの生成を実行します。


これからアプリケーションの作成までは、すべてデフォルトの設定を選択します。SQLスクリプトの保存を一旦行い、レビューおよび実行実行即時実行、とボタンをクリックして進み、生成したSQLによって表TST_EMPLOYEESが作成されたことを確認したのち、アプリケーションの作成を起動します。

名前Remote Deploy Testとし、アプリケーションの作成を実行します。


アプリケーションの名前から導出されるアプリケーション別名を英数字にするため、名前を英数字にしています。日本語のアプリケーション名を付けたときは、アプリケーション作成後に別名を英数字だけのものに変更しておきます。

リモート・デプロイメントに必要なWeb資格証明の登録、および、REST対応SQLの登録は、こちらの記事とまったく同じ作業になります。手順については、そちらを参照してください。

両方とも、ワークスペース・ユーティリティから呼び出すこともできます。



リモート・デプロイメントの実行


作成したアプリケーションRemote Deploy Testより、エクスポート/インポートを開きます。


リモート・デプロイメントをクリックします。


デプロイメント・サーバーとして登録済みのREST対応SQLを選びます。今回はAPEXDEV on Ashburnになります。に進みます。


アプリケーションのエクスポートやインポート時に指定する項目が現れます。今回はデフォルトのまま、デプロイを実行します。


アプリケーションIDのオーバーライドが必要とエラーが返されたので、デプロイ先に存在していないアプリケーションIDをアプリケーションIDのオーバーライドに指定し直し(今回は202を指定)、再度、デプロイを実行しました。


デプロイ先にアプリケーションが作成されました。動作を確認してみます。

まずサインインします。


ホーム・ページと、Employeesのレポートができていることが確認できます。


Employeesレポートを開きます。ORA-00942: 表またはビューが存在しません。とエラーが表示されます。リモート・デプロイメントはOracle APEXのアプリケーションのみが対象なので、表やその表に含まれるデータは別途、デプロイ先に作成する必要があります。


デプロイの実行時に、既存のアプリケーションを上書きONにするとエラーが発生しました。


ORA-00001: 一意制約(APEX_200200.WWV_FLOW_LOV_DATA_PK)に反しています、というのがそのエラーです。


既存のアプリケーションの上書きをONにすると、デプロイ先でもアプリケーションIDは元のアプリケーションと同じになります。また、既存のアプリケーションの上書きインストールも可能になります。(アプリケーションIDのオーバーライドでは、すでにIDが使用中であるとエラーになります)そのため、本番環境のクローンとして開発環境が存在し、アプリケーションIDも一致させることができるのであれば、特に有用なオプションです。

内容はWWV_FLOW_LOV_PKの一意制約違反なので、LOVに問題があります。このアプリケーションに含まれるLOVはアプリケーション作成ウィザードによって作成されたLOGIN_REMENBER_USERNAMEだけなので、これを削除します。

ページ・デザイナにてログイン・ページ、ページ番号9999を開きます。


タイプ静的値に変更し、静的値として、表示値ユーザー名を記憶戻り値Yとする一行だけに変更します。OKをクリックし、値を保存したのち、ページも保存します。


共有コンポーネントLOVを開きます。LOGIN_REMEMBER_USERNAMEをクリックします。


先ほど、唯一このLOVを使用しているログイン・ページの設定を変更したので、使用状況は、このLOVは使用されていません。となっています。問題なくLOVの削除ができるので、削除を実行します。


LOVの問題については、以上で対処ができました。

同様に、ORA-00001: 一意制約(APEX_200200.WWV_FLOWS_ALIAS_IDX)に反しています、というエラーが発生する場合があります。



こちらは、アプリケーションの別名のオーバーライドで指定した別名が使用済み、というエラーなので、別名の指定を変更します。


サポートするオブジェクトの追加


アプリケーションのデプロイ時に、そのアプリケーションが必要としている表などのオブジェクトを作成することが可能です。アプリケーションのサポートするオブジェクトを開きます。


インストールに含まれるインストール・スクリプトを開き、表TST_EMPLOYEESを作成するDDLを追加します。


作成をクリックします。


表およびデータベース・オブジェクトを生成するDDLに限らず、データベースで実行できるどのようなスクリプトも、インストール・スクリプトとして作成することができます。今回はデータベース・オブジェクトから作成を実行します。


作成されるスクリプトの名前を指定します。名前は任意ですが、今回はDDL_tst_employeesとしています。DDLを生成する対象は表なので、オブジェクト・タイプからTABLEを選択します。へ進みます。

DDLの生成はデータベースにたいして負荷をかけるので、一度に多くのデータベース・オブジェクトを対象にすると処理がタイムアウトしてしまいます。ですので、対象が多い場合は、生成する対象を分けて、複数のスクリプトを生成するのが一般的です。


オブジェクトの選択画面が表示されます。多数のオブジェクトから選択する場合は、フィルタの指定を使って、選択可能なオブジェクトの選択肢を狭めることが可能です。表オプションInclude DDL related to tablesにチェックを入れておきます。トリガーなど、表に関連するオブジェクトのDDLを一度に生成させることができます。DDLの生成を複数回に分割し、表は表、トリガーはトリガーとして生成する場合はチェックは不要です。

DDLを生成するオブジェクトとしてTST_EMPLOYEES (TABLE) を選択し、に進みます。


警告にあるように、生成されるDDLはデータベースのバージョンに依存します。バージョンの高いデータベースで生成したDDLは、バージョンの低いデータベースでの実行に失敗する場合があります。その点については注意が必要です。

作成されたDDLを確認して、作成をクリックします。


デプロイ時に表TST_EMPLOYEESを作成するスクリプトが登録されました。


再度、リモート・デプロイメントを実行してみましょう。アプリケーションIDのオーバーライドアプリケーションの別名のオーバーライドは、前回とは異なる値を指定します。デプロイを実行します。


前回と同様に、正常にデプロイされました。とメッセージが表示されます。

デプロイ先で、アプリケーション・ビルダーからデプロイされたアプリケーションを開きます。


サポートするオブジェクトを開きます。


インストール・スクリプトの数が1となっていて、先ほど作成したスクリプトがコピーされていることを確認できます。右のメニューより、サポートするオブジェクトのインストールのリンクをクリックします。


サポートするオブジェクトのインストールONになっています。そのまま、へ進みます。


インストールを実行します。


表TST_EMPLOYEESの作成が完了したので、アプリケーションの実行を行って確認します。


サインインを行い、Employeesのレポートを開きます。レポートのソースである表TST_EMPLOYEESが作成されたので、ORA-00942: 表またはビューが存在しません。というエラーは発生しなくなりました。


しかし、データはコピーされていません。次のセクションにて、データのコピーに取り組みます。

今回はインストール・スクリプトのコピーだけを行い、実行はデプロイ後に呼び出しました。以下の設定、サポートするオブジェクトの定義をエクスポートをデフォルトののはいから、インポート時に自動的にインストールに変更すると、デプロイを実行したときにインストール・スクリプトも実行されるようになります。


データのコピー


せっかくREST対応SQLが登録されているので、INSERT文をリモート・データベースにたいして実行することにより、データのコピーを行ってみます。Oracle APEXが提供しているAPEX_EXECパッケージに含まれるプロシージャADD_PARAMETERおよびEXEC_REMOTE_PLSQLを利用します。
declare
  l_sql_parameters apex_exec.t_parameters;
begin
  for c in (select * from tst_employees)
  loop
      apex_exec.add_parameter( l_sql_parameters, 'ID', c.id);
      apex_exec.add_parameter( l_sql_parameters, 'NAME', c.name);
      apex_exec.add_parameter( l_sql_parameters, 'AGE', c.age);
      --
      apex_exec.execute_remote_plsql(
          p_server_static_id     => 'APEXDEV_on_Ashburn',
          p_plsql_code           => q'#begin insert into tst_employees(id, name, age) values(:ID, :NAME, :AGE); end;#',
          p_auto_bind_items => false,
          p_sql_parameters  => l_sql_parameters );
  end loop;
end;

SQLワークショップSQLコマンドより実行します。


結果に1行が挿入されました。と表示されますが、1行のプロシージャが実行されたという意味で、リモートにある表TST_EMPLOYEESに挿入された行は30行です。

リモートにデプロイしたアプリケーションのレポートを確認しましょう。

今度はデータもコピーされていることが確認できます。一行ごとにREST APIを発行しているため、かなり速度は遅いです。行数が多い場合はブラウザがタイムアウトするかもしれないので、処理を分割したりバックグラウンドで実行したりする必要があるかもしれません。また、apex.oracle.comのワークスペースでは一日で呼び出し可能なREST APIのコールアウト数に制限があるので(50から100くらい)、このようなデータのコピー方法を使うのは難しいです。

APEX_EXEC.ADD_PARAMETERで日付データを扱う際には、セッションのNLS_DATE_FORMATなどの影響や、デプロイ元とデプロイ先でのタイムゾーンの違いなどの影響を受けないように、TO_CHAR、TO_DATEといったファンクションによってコード内でフォーマット指定を行う方がよいでしょう。


以上で本記事は終了です。アプリケーションのリモート・デプロイメントと、スキーマの複製やデータのコピーを行う方法を紹介しました。

Oracle APEXを使ったアプリケーション開発の一助になれば幸いです。