2020年2月28日金曜日

APEXからOCIオブジェクト・ストレージを操作する(0) - はじめに

OracleのブログにAdrian Pngさんが、Better File Storage in Oracle Cloudとして、Oracle APEXでOCI - Oracle Cloud Infrastructure - のオブジェクト・ストレージを操作するアプリケーションの作り方を寄稿しています。


Adrian PngさんはカナダのInsumという、Oracle APEXやオラクルのパートナーさんのメンバーで、Oracle APEXのコミュニティーへの有功者へこちらのコインを配布している方です。また、このブログポストの謝辞には、こちらもオラクルのパートナーであるAccenture EnkitecのメンバーであるChristoph Ruepprichさんと、オラクルのCarsten Czarskiの2名の名前がリストされています。InsumとAccenture Enkitecの両方ともOracle APEXとOCIの両方を使っているので、こういったOCI上のサービスのAPI呼び出しはニーズとして高いのでしょう。

さて、Oracle APEX 19.2より、Web資格証明のタイプにOracle Cloud Infrastructure (OCI)が追加されていて、これでOracle APEXからOCIのAPI呼び出しが容易になっています。
 

また、Oracle Cloudで提供されているAutonomous Databaseのインスタンスに構成されているOracle APEXも、19.2へ順次アップグレードされています。ですので、Always Freeのサービスとして提供されているAutonomous DatabaseのインスタンスのOracle APEXを使って、上記のアプリケーション作成を行ってみました。

(2022年12月1日追記:Autonomous Database上のOracle APEX 22.2で作業を再度実施し、記事を更新しています。)

元にした記事はOCIやOracle APEXの知識を前提としているところがあります。その部分は補完しつつ、元記事の内容をそのまま使う部分は重複しないようにしたいと思います。

OCIのテナントを取得した直後の状態からアプリケーションが完成するまでの作業を、全部で9本の記事で紹介しています。

  1. APIユーザーの作成では、 準備としてコンパートメント、グループ、ポリシー、ユーザー、それにユーザーにAPIキーを作成しています。
  2. バケットの作成では、OCIオブジェクト・ストレージにバケットを作成し、ファイルをひとつアップロードしています。
  3. ADBの作成からAPEXアプリの準備まででは、Always FreeのAutonomous Databaseをひとつ作成し、Oracle APEXのワークスペースを新規に作成した後、空のアプリケーションを作成しています。
  4. Web資格証明の作成では、APEXにOCIのオブジェクト・ストレージにアクセスするときに使用するWeb資格証明を登録しています。
  5. Web資格証明の作成では、アプリケーションにOCIのオブジェクト・ストレージを操作するために使用するWebソース・モジュールを作成しています。
  6. オブジェクトの一覧表示では、APEXのアプリケーションにOCIオブジェクト・ストレージのバケットを選んで、含まれるオブジェクトの一覧を表示する機能を実装しています。
  7. ファイルのアップロードでは、オブジェクト・ストレージにファイルをアップロードする機能を実装しています。この実装はダイアログ・ページのページの送信(HTTPのPOSTによる呼び出し)時に実行されるプロセスとして機能を実装するという、Oracle APEXで最も一般的な機能の実装手法を使っています。
  8. ファイルのダウンロードでは、オブジェクト・ストレージからオブジェクトをダウンロードする機能を実装しています。この実装は別ページへのリダイレクト(HTTPのGETによる呼び出し)時に処理を行う実装になっています。
  9. ファイルの削除では、オブジェクト・ストレージ内のオブジェクトの削除機能を実装しています。これはリンクに動的アクションを定義して、それからAjaxによってプロセスの呼び出しを行う実装になっています。

OCIオブジェクト・ストレージを操作するアプリケーションの作り方の紹介ですが、処理それぞれに異なるプロセスの呼び出し方を採用していて、参考になります。

続く

APEXからOCIオブジェクト・ストレージを操作する(9) - ファイルの削除

OCIオブジェクト・ストレージ上にあるオブジェクトを削除するリンクを、ホーム画面のレポートに追加します。

元ブログの内容をAPEX 22.2のActionインターフェースを使う実装に変えています。


オブジェクトを削除するリンクの追加


ダウンロード・リンクと同様に、仮想列をリージョンBucket Contentsに追加します。手順は同じです。

仮想列DERIVED$02が作成されるので、その識別タイプとしてプレーン・テキストを指定し、式の書式HTML式に以下を設定します。

カスタム属性data-ationからアクションdelete-objectを呼び出すように定義しています。引数nameとしてオブジェクト名を渡しています。
 

アクションdelete-objectを定義します。以下のコードを、ページ・プロパティのJavaScriptページ・ロード時に実行に記述します。



リージョンBucket Contents詳細静的IDとしてR_BUCKET_CONTENTSを設定します。リフレッシュ対象のリージョンを指定するために使用します。


Ajaxのコールバックを作成するため、左ペインの表示にプロセス・ビューを選んで、Ajaxコールバックの上でコンテキスト・メニューを開き、プロセスの作成を実行します。
 

識別名前としてDELETE_OBJECT(この名前で処理が呼び出されるので必ずDELETE_OBJECTを指定してください)、識別タイプコードを実行ソース位置ローカル・データベースで、PL/SQLコードとして以下を記述します。元のブログのコードは日本語の扱いに不備があったので、その部分を修正しています。


 

これでオブジェクトの削除機能が実装できました。

アプリケーションを実行して、ファイルのアップロード、ダウンロード、削除などを実行してみましょう。

また、元となるブログの内容はここで終了です。

今回作成したアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/apex-with-oci-object-storage.zip

Oracle APEXのアプリケーション作成の参考になれば幸いです。

APEXからOCIオブジェクト・ストレージを操作する(8) - ファイルのダウンロード

OCIオブジェクト・ストレージにあるオブジェクトをダウンロードするリンクを、ホーム画面のレポートに追加します。
 

オブジェクトをダウンロードするリンクの追加


オブジェクトのダウンロード要求を処理するページを新規に作成します。このページは画面の表示には使われません。アプリケーションの開発画面よりページの作成を実行し、空白ページを選びます。

ページ番号として名前Download Objectページ・モード標準を選択します。ナビゲーションブレッドクラムナビゲーションともにOFFにし、ページの作成を実行します。
 

コンポーネントBodyに、プロセスへ渡す引数の役割をするページ・アイテムP3_BUCKET_NAMEP3_OBJECT_NAMEを作成します。識別タイプは双方とも非表示にします。
 

左ペインのレンダリング・ビューより、レンダリング前に含まれるヘッダーの前の上でコンテキスト・メニューを表示させ、プロセスの作成を実行します。
 

作成したプロセスの識別名前downloadObjectとし、識別タイプコードを実行を指定します。ソース位置ローカル・データベースPL/SQLコードとして以下を記述します。元のブログのコードは日本語の扱いに不備があったので、その部分を修正しています。



このコードの最後にapex_application.stop_apex_engine;の記載があります。downloadObjectプロセスはAPEXの標準的なページ処理を中断させているため、この後の処理は(どのような処理をページに追加していても)実行されません。

次にページ1のホーム画面をページ・デザイナで開き、オブジェクトの一覧にダウンロード・リンクを追加します。リージョンBucket Contentsの上でコンテキスト・メニューを開き、仮想列の作成を実行します。
 

作成された仮想列DERIVED$01を選択し、リンクが定義されていませんをクリックし、リンク/ターゲットを設定します。
 

リンクのターゲットは先ほど作成したDownload Objectのページなので、ターゲットのタイプこのアプリケーションのページページです。アイテムの設定として、P3_BUCKET_NAMEにはページ・アイテム&P1_BUCKET_NAME.を値として渡し、P3_OBJECT_NAMEにはレポートの出力である#NAME#を値として与えます。OKをクリックして、ターゲットを設定します。
 

最後にリンクリンク・テキストDownloadに変更し、保存をします。
 

これでダウンロード機能の実装ができました。アプリケーションを実行して、ホーム画面のレポートからオブジェクトのダウンロードを実行してみましょう。

続く

APEXからOCIオブジェクト・ストレージを操作する(7) - ファイルのアップロード

ファイルをOCIオブジェクト・ストレージにアップロードする画面を作成します。
 


ファイルをアップロードするダイアログ画面の作成



まず、空のページを作成します。開発中のアプリケーションのホームより、ページの作成を実行します。


ページ・タイプコンポーネントを選んで、空白ページを作成します。アイコンをクリックするか、選択してへ進みます。
 

ページ番号は(必ず2にしてください。後続のページ・アイテム名などに影響します)、名前File Uploadページ・モードモーダル・ダイアログを指定して、ページの作成をクリックします。モーダル・ダイアログなので、ブレッドクラム、ナビゲーションはOFFのままにします。
 

作成されたページに2つの静的コンテンツのリージョンを追加します。

Content BodyタイトルFile Uploadタイプ静的コンテンツのリージョンを追加します。
 

Dialog FooterタイトルButtonsタイプ静的コンテンツのリージョンを追加します。外観/テンプレートとして、Buttons Containerを選択します。
 

File Uploadとして作成したリージョンに、タイプ非表示のページ・アイテムP2_BUCKET_NAMEを追加します。
 

次にタイプファイル参照...であるページ・アイテムP2_FILEを追加します。記憶タイプTable APEX_APPLICATION_TEMP_FILESとなっていることを確認します。ラベルFileとします。
 

Buttonsとして作成したリージョンに、ボタンを追加します。左ペインのレンダリング・ツリーにあるリージョンButtonsの上でコンテキスト・メニューを表示し、ボタンの作成を実行します。右ペインのプロパティ・エディタにて、識別ボタン名UPLOAD識別ラベルUpload、そして動作アクションとしてページの送信を指定します。
 

同様にボタンCANCELも作成します。識別ボタン名CANCEL識別ラベルCancel、そしてこちらの動作アクション動的アクションで定義を指定します。
 

ボタンCANCELに動的アクションを定義します。レンダリング・ツリーのCANCELボタンの上でコンテキスト・メニューを表示させ、そのメニューから動的アクションの作成を実行します。
 

動的アクションの識別/名前は任意の値でかまわないのですが、ここではClick CANCELを指定します。タイミングはデフォルトで(CANCELボタンのコンテキスト・メニューから動的アクションを作成したため)、イベントクリック選択タイプボタンボタンCANCELとなっているはずですが、確認してください。
 

実行するTrueアクションとして、ダイアログを取り消すを選択します。
 

左ペインにてプロセス・ビューの表示を選択し、プロセス・ビューのプロセス上でコンテキスト・メニューを開き、プロセスの作成を実行します。


作成したプロセスの識別名前uploadFileタイプコードを実行とします。ソースは位置ローカル・データベース、そしてPL/SQLコードとして以下を記述します。


元にしているブログのコードに、日本語の対応(apex_util.url_encodeの代わりにutl_url.escapeを使用)を追加しています。
 

続いて同様にプロセスを作成し、識別/名前としてcloseDialogタイプダイアログを閉じるを指定します。これにより、プロセスuploadFileの次にcloseDialogが実行され、本ダイアログ・ページが閉じて、ホーム画面に戻ります。
 

ここまででファイルのアップロードを行うページの作成が完了したので、保存を実行しておきましょう。

通常、ページが送信されたときに実行されるプロセスには、サーバー側の条件にて、どのボタン押下時なのか、条件としてボタンを指定しますが、今回の例ではUPLOADしかページ送信を行うボタンがないため省略しています。

uploadFileで指定したPL/SQLコードの中で、G_BASE_URLG_OCI_WEB_CREDENTIALという置換文字列を使用しています。これはアプリケーションの静的置換文字列として設定します。アプリケーションのトップ・ページにあるアプリケーション定義の編集をクリックします。
 

そして、アプリケーション定義の編集画面を開き、置換のセクションに以下の設定を行います。
  • G_BASE_URL: https://objectstorage.REGION.oraclecloud.com/n/NAMESPACE/(RESTデータ・ソースlist_bucketsのベースURLと同じです)
  • G_OCI_WEB_CREDENTIAL: OCI_API_ACCESS(Web資格証明の静的識別子です)
置換文字列を入力した後、変更の適用をクリックします。
 

ページ番号1のホームを開き、作成したダイアログを開くためのボタンを追加します。

左ペインのレンダリング・ツリーにあるリージョンBucket List上でコンテキスト・メニューを開き、ボタンの作成を実行します。識別ボタン名UPLOAD識別ラベルUploadレイアウトボタン位置Nextを指定し、動作アクションとしてこのアプリケーションのページにリダイレクトを選択します。 ターゲットの指定がリンクが定義されていません、となるので、それをクリックしてリンクを定義します。
 

ターゲットの指定を行うダイアログが表示されるので、ページアイテムの設定として、名前P2_BUCKET_NAME、その&P1_BUCKET_NAME.として設定します。その後OKをクリックします。
 

最後に作成したUPLOADボタンに動的アクションを追加します。UPLOADボタンの上でコンテキスト・メニューを開き、動的アクションの作成を実行します。新規に動的アクションとTrue条件で実行されるアクションが作成されます。動的アクションの識別名前を新規から、任意の値(この例ではClose Dialog)に変更します。タイミングのイベントダイアログのクローズ選択タイプボタンボタンUPLOADとなっていることを確認します。
 

また、True条件で実行されるアクションの識別アクションリフレッシュ影響を受ける要素リージョン、リージョンとしてBucket Contentsを指定します。
 

これでローカルに存在するファイルをOCIオブジェクト・ストレージにアップロードする機能が実装できました。いくつかファイルをアップロードして、動作を確認してみしょう。

続く

APEXからOCIオブジェクト・ストレージを操作する(6) - オブジェクトの一覧表示

APEXのアプリケーションに、選択したバケット内のオブジェクト一覧を表示するページを作成します。


バケット内のオブジェクト一覧表示



以下のホーム画面を作成します。
 



コンパートメント内のバケット一覧のLOVを定義します


Oracle APEX 19.2より動的なLOVのデータソースとして、SQLの実行以外に、RESTデータ・ソースを扱うことができるようになりました。先ほど作成したRESTデータ・ソースlist_bucketsをソースとしたLOVを作成します。

共有コンポーネントからLOVを開きます。LOVの作成最初からを選択し、へ進みます。以下の画面になります。 名前BUCKET_LISTを指定し、タイプDynamicを選択します。へ進みます。
 

データ・ソースとしてRESTデータ・ソースを選択し、RESTデータ・ソースとしてlist_bucketsを選択します。へ進みます。
 

戻り列表示列、共にNAMEを選択します。作成をクリックすると、LOVが作成されます。
 


バケットのセレクタをホーム画面に配置します


アプリケーションのページ1、ホーム画面をページ・デザイナで開きます。レンダリング・ツリーのBody上でコンテキスト・メニューを表示させ、リージョンの作成を実行します。
 

新規に作成されたリージョンを選択し、プロパティ・エディタより、識別タイトルBucket Listに変更します。タイトルの入力フィールドからフォーカスが外れると、レンダリング・ツリーの表記が新規からBucket Listに変更されます。そのBucket List上でコンテキスト・メニューを表示させ、アイテムの作成を実行します。
 

新規に作成されたページ・アイテムを選択します。プロパティ・エディタ上で、以下の設定を行います。
  • 識別/名前: P1_BUCKET_NAME
  • 識別/タイプ: 選択リスト
  • ラベル/ラベル: Bucket Name
  • 設定/選択時のページ・アクション: Submit Page
  • LOV/タイプ: 共有コンポーネント
  • LOV/LOV: BUCKET_LIST
  • LOV/追加値の表示: OFF
  • LOV/NULL値の表示: ON
  • LOV/NULL表示値: -- Select a bucket --


選択したバケットが含むオブジェクトのレポートをホーム画面に配置します


同様に新たにリージョンを作成します。新規に作成したリージョンを選択し、プロパティ・エディタより以下の値を設定します。
  • 識別/タイトル: Bucket Contents
  • 識別/タイプ: クラシック・レポート
  • ソース/位置: RESTソース
  • ソース/RESTソース: list_objects_in_bucket
  • ソース/送信するページ・アイテム: P1_BUCKET_NAME

リージョンのパラメータを開くと、bucket_nameという項目があります。それを選択して、プロパティ・エディタで以下の指定を行います。
  • 値/タイプ: アイテム
  • 値/アイテム: P1_BUCKET_NAME

このレポートのソースはlist_objects_in_bucketというRESTデータ・ソースです。そのRESTデータ・ソースはbucket_nameをパラメータとして指定可能であり、デフォルトは静的値でapex_file_storageでした。それをページ・アイテムP1_BUCKET_NAMEに指定された値を渡すように変更しています。

これで最初にあげたようにホーム画面に、指定したバケットに含まれるオブジェクトを一覧するレポートを追加することができました。

続く

2020年2月27日木曜日

APEXからOCIオブジェクト・ストレージを操作する(5) - RESTデータ・ソースの作成

これから2つのRESTデータ・ソースを作成します。ひとつはlist_bucketsとして、特定のコンパートメントに含まれるバケットの一覧を取得するためのもの、もうひとつは、list_objects_in_bucketとして、指定したバケットに含まれるオブジェクトの一覧を取得するためのものです。


RESTデータ・ソースの作成



今回の実装では、list_bucketsの対象はコンパートメントAPEXlist_objects_in_bucketの対象はコンパートメントAPEXに含まれるバケットapex_file_storageになります。RESTデータ・ソースを登録するにあたり、あらかじめ取得しておくべき情報が3つあります。

APIエンドポイントを取得します


オブジェクト・ストレージのAPIエンドポイントはこちらに定義されています。使用しているリージョン毎に異なります。北米アッシュバーン・リージョンのAPIエンドポイントを確認するとhttps://objectstorage.us-ashburn-1.oraclecloud.comになっていました。

オブジェクト・ストレージ・ネームスペースを取得します


ハンバーガー・アイコンをクリックし、ガバナンスと管理からテナンシ詳細を開きます。


オブジェクト・ストレージ・ネームスペースの文字列をメモしておきます。
 


コンパートメントIDを取得します


ハンバーガー・アイコンをクリックし、アイデンティティとセキュリティからコンパートメントを開きます。ポインタをOCID上に合わせるとツールチップとしてOCIDが表示されます。そこにあるコピークリックして、クリップボードに保存します。
 


RESTデータ・ソースlist_bucketsの作成



共有コンポーネントRESTデータ・ソースを開きます。
 

作成をクリックします。
 

RESTデータ・ソースの作成メソッドとして、最初からを選びます。

へ進みます。
 

RESTデータ・ソース・タイプOracle Cloud Infrastructure (OCI)を選び、名前list_bucketsを入力します。URLエンドポイントは次のような形式です。
https://objectstorage.REGION.oraclecloud.com/n/NAMESPACE/
リージョン毎のオブジェクト・ストレージのAPIエンドポイントに"/n/"を挟んで、オブジェクト・ストレージ・ネームスペースをつなげます。URLの最後は"/"で終了します。

へ進みます。
 

ベースURLは自動的に設定されます。サービスURLパスには/b/を指定します。

次へ進みます。
 

資格証明として先ほど作成したOCI API Accessを選択します。

詳細をクリックします。
 

パラメータをひとつ追加します。パラメータ・タイプ問合わせ文字列変数パラメータ名compartmentId(Iは大文字のアイ)、それに与える値は、コンパートメントAPEXのOCIDになります。静的ONにして、変更不可のパラメータとします。

検出をクリックします。
  

検出結果が問題なく表示されれば、OCIオブジェクト・ストレージのAPI呼び出しは成功しています。コンパートメントに含まれるバケットのリストから、apex_file_storageが返されていることを確認します。

RESTデータ・ソースの作成をクリックします。
 

作成されたRESTデータ・ソースlist_bucketsが一覧に表示されます。
 

この後に別のRESTデータ・ソースを作成するので、エンドポイントURLコピーしておくと良いです。


RESTデータ・ソースlist_objects_in_bucketの作成



手順はlist_bucketsのときと同じく、RESTデータ・ソースの一覧から作成をクリックし、作成メソッドは最初からを選択します。に進むと、個別のパラメータの設定になります。

RESTデータ・ソース・タイプOracle Cloud Infrastructure (OCI)名前list_objects_in_bucketURLエンドポイントとして、list_objectsのエンドポイントURLに続けて":bucket_name/o/"を追加します。次のような形式になります。
https://objectstorage.REGION.oraclecloud.com/n/NAMESPACE/b/:bucket_name/o/
URLにbucket_nameというパラメータが含まれたことにより、画面にURLパラメータ1として、の指定を求められます。としてapex_file_storageを指定します。すべて指定した後、へ進みます。
 

リモート・サーバーベースURLサービスURLパスは先ほどの指定から自動設定されます。へ進みます。
 

認証が必要ですONにし、資格証明としてOCI API Accessを選択します。詳細をクリックします。
 

パラメータをひとつ追加します。パラメータ・タイプ問合わせ文字列変数パラメータ名fields、そのname,size,timeCreated,md5になります。静的ONにして、変更不可のパラメータとします。検出をクリックします。
 

事前にアップロードしたファイルがリストされていることを確認します。確認した後、RESTデータ・ソースの作成をクリックします。
 

作成されたRESTデータ・ソースlist_objects_in_bucketが一覧に表示されます。
 

RESTデータ・ソースが作成できれば、実際はOCIオブジェクト・ストレージへのいくつかのREST APIの呼び出しが成功していることになります。

続く