2024年9月5日木曜日

APEX 24.1で追加されたアイテム・タイプ「1つ選択」と「複数選択」について

2025年2月4日追記: APEX 24.2ではポップアップLOVの検索設定が1つ選択複数選択およびコンボボックスと同じ設定に変更されました。よって、本記事で説明しているポップアップLOVの検索動作はAPEX 24.2以降には当てはまりません。

------

Oracle APEX 24.1では新しいアイテム・タイプとして、「1つ選択」(英語ではSelect One)および「複数選択」(英語ではSelect Many)が追加されています。この新しいアイテム・タイプについては、APEX Office Hoursの以下の回で、開発者のAlexis Galdamezさんが説明されています。

APEX Office HourのWhat's new in Oracle APEX 24.1 - Part 2
https://youtu.be/i4y0BzPOfrs?si=jB9kA6Wp_BuM2n5Z&t=1587

アイテム・タイプ「1つ選択」はその名前の通り、LOVから単一の値を選択するアイテム・タイプ、「複数選択」は、LOVから複数の値を選択するアイテム・タイプです。

LOVをソースとして、値をひとつまたは複数の値を選択するページ・アイテムとして、「選択リスト」と「ポップアップLOV」があります。新しく追加された「1つ選択」と「複数選択」との違いを確認してみます。

確認には以下のAPEXアプリケーションを使用しました。
https://github.com/ujnak/apexapps/blob/master/exports/select-one-select-many-component.zip

値をひとつ選択するページ・アイテムとして、選択リストポップアップLOV表示形式インライン・ポップアップ)、24.1で新しく追加された1つ選択の3つのページ・アイテムを横並びに配置しています。

その下に、値を複数選択するページ・アイテムとして、選択リストポップアップLOV、24.1で新しく追加された複数選択を配置しています。


すべてのページ・アイテムで、同じLOVソースとして設定しています。

共有コンポーネントLOVとして、サンプル・データセットのEMP/DEPTに含まれるビューEMP_DEPT_VをソースとしたLOVを、LOV_EMPとして作成しています。

ソースSQL問合せは以下です。
select
    empno
  , ename
  , job
  , mgr
  , hiredate
  , sal
  , comm
  , deptno
  , dname
  , loc
  , case deptno
    when 10 then 'fa-table-user'
    when 20 then 'fa-database-user'
    when 30 then 'fa-calendar-user'
    when 40 then 'fa-folder-user'
    else 'fa-lock-user'
    end icon 
from emp_dept_v

列のマッピング戻り値EMPNO表示値ENAMEです。その他にグループとしてJOBアイコンとしてICONを割り当てています。

追加表示列としてDNAMEEMPNOENAMELOCJOBICONを設定しています。



選択リスト(複数の値のタイプがいいえ)と「1つ選択」の比較



アイテム・タイプ選択リストは、ほぼHTMLのSELECT要素としてそのまま生成されています。そのため、選択リストの画面上の表示はデバイスに依存します。

macOS上のChromeブラウザ上では以下のように表示されます。


iOSのSafariでは以下のように表示されます。


Android上のChromeでは以下のように表示されます。


アイテム・タイプ1つ選択は、異なるデバイスでもほぼ同じ見かけになっています。

macOS上のChromeです。


iOS上のSafariです。


Android上のChromeです。


アイテム・タイプが選択リストの出力を確認してみます。

LOVとして選択できるすべての値がoptionの値として出力されていることが確認できます。モバイル・デバイス上での操作の一貫性という意味で、デバイス・ネイティブのユーザー・インターフェースが提供される選択リストは良い面もあります。しかし、選択肢となるLOVの値が多数の場合に向いているコンポーネントとは言えなさそうです。

LOVの値がすべて静的にHTML(のoption要素)として生成されるため、値の操作時にサーバーとの通信が発生しません。LOVの選択肢が少なく、かつ、その選択肢の更新頻度が高く無い場合に向いています。


アイテム・タイプの1つ選択は、a-selectというカスタム要素として実装されています。このコンポーネントはブラウザ上のJavaScriptにより描画されています。




ポップアップLOV(複数の値のタイプがいいえ)と「1つ選択」の比較



アイテム・タイプポップアップLOV表示形式モーダル・ダイアログであれば、値の選択画面がダイアログとして開くため、新しいアイテム・タイプ「1つ選択」とは異なるユーザー体験を提供しています。そのため、これは「1つ選択」で置き換えることはできません。

ポップアップLOV表示形式インライン・ポップアップの場合は、追加出力の機能を除いて、「1つ選択」の方がより良いユーザー体験を提供しているように思います。追加出力が不要であれば、アイテム・タイプ「1つ選択」が常に優先される選択肢になるでしょう。

ポップアップLOVの設定項目です。


ポップアップLOVの表示例です。値を入力するフィールドと検索フィールドは別に存在します。


1つ選択の設定項目です。


1つ選択の表示例です。値の入力フィールドへの入力でLOVの検索が行われます。また、入力した値をキャンセルするXボタンが追加されました。


選択リストおよびポップアップLOVでは、設定値を空白に戻すためにはNULL表示値として設定した文字列が表示されている領域を選択する必要がありました。NULL表示値として- Select Employee -といった値の選択を促するメッセージが設定されている場合、直感的には分からない操作になってしまいます。


1つ選択」の検索では、一致タイプとして次を含む次から始まるを選択できます。大/小文字を区別オン/オフの切り替えと最小文字数を設定できます。


ポップアップLOVでは入力時に検索オンにし、最小文字数を設定すると「1つ選択」と同様に、キー入力に従ってLOVの検索が行われます。入力は検索フィールドに行います。

入力時に検索オフにすると、検索フィールドに値を入力しEnterを押してLOVを検索できます。この動作は「1つ選択」のアイテムには実装されていませんが、最小文字数を超えると検索は実行されるため、無くても不便ではありません。サーバーの負荷の軽減という意味では有効ですが、「1つ選択」ではサーバーから取得した選択肢をブラウザでキャッシュすることにより、サーバーの負荷を軽減できます。


ポップアップLOVの設定に初期フェッチの設定があります。設定できる値はユーザー・リクエスト時自動自動(現在の値を使用) です。この設定により、LOVから値を選択する際に発生するデータベースへのリクエストを抑制することができます。


1つ選択」では設定検索時にフェッチおよびキャッシュの使用によって、データベースへのリクエストを制御します。また、リスト内の最大値を設定することにより、一回のリクエストで取得するLOVのエントリ数を制限することもできます。


リスト内の最大値は一度に表示されるLOVの選択肢の数を設定します。例えば、以下は5の場合です。


ポップアップLOVでは、ポップアップの高さを設定することはできますが、表示件数を制限することはできません。以下は高さを400ピクセルに設定した結果です。5件の選択肢が表示されていますが、スクロールすることで全ての選択肢を参照することができます。


1つ選択」では設定値HTML式にHTMLを記述することにより、選択リストの表示を変更することができます。HTML式にはテンプレート・ディレクティブを使用できます。


ポップアップLOVでも表示形式の変更は可能ですが、それは初期化JavaScriptにてオプションのrecordTemplateを設定する、という手間のかかる方法でした。

総じていうと、ポップアップLOVの欠点を補うように作られたのがアイテム・コンポーネントの「1つ選択」になっています。


選択リスト(複数の値のタイプが区切りリストまたはJSON配列)と「複数選択」の比較



複数の値を選択可能な選択リストは、multiple属性が設定されたSELECT要素として生成されています。選択肢が1つの場合と同様に、画面上の表示はデバイスに依存します。

macOS上のChromeブラウザ上では以下のように表示されます。


iOSのSafariでは以下のように表示されます。


Android上のChromeでは以下のように表示されます。


アイテム・タイプ複数選択では、異なるデバイスでも同じ見かけになります。


1つ選択の場合と同様に、選択肢が少なく、デバイス・ネィティブのユーザー・インターフェースが望ましいケースでは選択リストを使用し、それ以外の場合は「複数選択」が向いているでしょう。


ポップアップLOV(複数の値のタイプが区切りリストまたはJSON配列)と「複数選択」の比較



1つ選択と同様に、追加出力が不要であれば、アイテム・タイプ「複数選択」が常に優先される選択肢になるでしょう。

設定できる項目の比較は概ね1つ選択と同様です。

アイテム・タイプ複数選択では、選択肢を開いたままチェックボックスにより値の選択と解除が可能です。


ポップアップLOVでは、値をひとつ選択するたびにポップアップLOVを開く必要があります。また、値の削除は入力フィールドから削除する必要があります。


新しい複数選択のコンポーネントの方が使いやすいのは明らかなので、これからは複数選択のコンポーネントが優先して使用されるでしょう。

コンポーネント複数選択設定として、値の表示形式というものがあります。チップカンマ区切りリストを選択できます。


チップを選択すると、選択された値は以下のように表示されます。


カンマ区切りリストを選択すると、以下のように表示されます。ただし、ページ・アイテムにフォーカスが当たると、表示はチップに変わります。


設定にはデフォルトの使用があり、これをオフにすると値の表示形式を選択できるようになります。

デフォルトの使用の設定は、共有コンポーネントコンポーネント設定に含まれる複数選択から行います。


値の表示形式のデフォルトは、ここで設定されています。


アイテム・タイプ「1つ選択」と「複数選択」の説明は以上になります。

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

apex.oracle.comの新機能紹介ではSelect Oneを「単一選択」と訳出しているため、製品の翻訳も「1つ選択」ではなく「単一選択」としてほしかったと思います。

2024年9月4日水曜日

生成AIを活用してOracle APEXのアプリケーションを作成する

Oracle APEXは、リレーショナル・データベースに定義されたスキーマをもとにアプリケーションを作成するシステムなので、アプリケーションを作成するにあたって作成済みのスキーマは必要です。JavaScriptやPL/SQLを書けば大抵のことはできますが、それらはAPEXが提供している機能というよりは、ブラウザやデータベースの機能です。

アプリケーションを作成するにあたって、データ・モデリングから初めて、それが完了するまでアプリケーションを作れないとなると、経験値が高くないと作業を始めるハードルが上がってしまいます。

そこで、生成AIを使ってスキーマを作成し、それをもとに叩き台となるAPEXのアプリケーションを作成してみます。

今回の作業ではGoogleのGemini Advancedを使ってみます。コード生成能力の高い生成AI(OpenAI GPT-4o、Anthropic Claude 3.5 Sonnetなど)であれば、同様の作業はできるでしょう。

まず、Geminiに以下のプロンプトを与えて、個人旅行管理アプリのスキーマを作成してもらいます。

個人旅行に必要な情報を管理するためのリレーショナル・データベースのスキーマを設計してください。
表やビューを作成するDDLは、オラクル・データベースで実行可能なスクリプトを生成してください。
表やビューの名前の接頭辞としてXXTRIP_を付加してください。
表の作成時にエラーが発生しないように、制約のない表が先に作成されるようにしてください。
表の名前や列の名前はすべて英語にしてください。
すべての表にサロゲート・キーを付与し、自動採番にしてください。


あまり具体的な指示、例えば作成する表を指示したり列を指示したりすると、生成AIはそれらの指示通りの表や列を含んだDDLを生成するようです。設計内容に自信がある場合は別ですが、それほどでもない場合は、最初はあまり細かい指定をせずに生成AIにまかせた方が、アイデア出しという面では良いように思います。

生成されたコードをコピーします。


SQLワークショップSQLスクリプトを開きます。


作成をクリックします。


スクリプト・エディタが開きます。

スクリプト名としてTrip_Managerを設定し、内容に生成されたDDLをペーストします。


続けて生成AIにテスト・データの生成を指示します。
表にテスト・データを投入するINSERT文を生成してください。オラクル・データベースで実行できるINSERT文を生成してください。

生成されたINSERT文を、SQLスクリプトに追記します。

スクリプトを実行します。


スクリプトを即時実行します。


スクリプトの実行結果を確認します。


継続してアプリケーションの作成をクリックします。


確認画面が開くので、再度アプリケーションの作成をクリックします。


アプリケーション作成ウィザードが開きます。

デフォルトで作成されるのは、それぞれの表をソースとしたフォーム付き対話モード・レポートのページです。

デフォルトのまま、アプリケーションの作成をクリックします。


アプリケーションが作成されます。


アプリケーションを実行すると、データ操作を行うことができる、簡素なアプリケーションを使うことができます。


生成されたDDLを見直してみたり、アプリケーションを使ってみて今ひとつと感じたら、プロンプトの指示を変えてDDLから生成しなおしてみます。

生成するオブジェクトの接頭辞としてXXTRIP_付けるように指示しているため、以下のスクリプトを実行することで、関連オブジェクトをすべて削除できます。


作成されたアプリケーションも削除し、再度、最初から作業を繰り返します。

今回の記事は以上になります。

Oracle APEXのアプリケーション作成で、生成AIを活用する参考になれば幸いです。

Gradio JavaScript ClientをOracle APEXのアプリケーションに組み込む

Gradio JavaScript Clientを、Oracle APEXのアプリケーションに組み込んでみます。Getting Started with the Gradio JavaScript Clientのページに掲載されている、いくつかの例を実装してみます。

空のAPEXアプリケーションを作成し、ホーム・ページにGradio JavaScript Clientを呼び出すコードを埋め込みます。

最初にページ・プロパティHTMLヘッダーimportmapを設定します。
<script type="importmap">
    {
        "imports": {
            "@gradio/client": "https://cdn.jsdelivr.net/npm/@gradio/client/+esm"
        }
    }
</script>

Gradio JavaScript Clientを呼び出した結果を出力するページ・アイテムとしてP1_RESULTを作成します。タイプテキスト領域です。

外観高さ10に変更し、少し表示領域を広げます。また、セッション・ステートストレージリクエストごと(メモリーのみ)を選択し、以前の値が記憶されないようにします。


最初にWhisperを呼び出すサンプルを実装します。

静的コンテンツのリージョンを作成し、ソースHTMLコードに以下を記述します。
<script type="module">
import { Client, handle_file } from "@gradio/client";

const response = await fetch(
	"https://audio-samples.github.io/samples/mp3/blizzard_unconditional/sample-0.mp3"
);
const audio_file = await response.blob();

const app = await Client.connect("abidlabs/whisper");
const result = await app.predict("/predict", [handle_file(audio_file)]);
// 
let text = result.data[0];
apex.item("P1_RESULT").setValue(text);
</script>

ページを実行すると、ページ・アイテムP1_RESULTに以下が表示されます。


Using eventsのサンプルを実装します。
<script type="module">
import { Client } from "@gradio/client";

function log_result(payload) {
	const {
		data: [translation]
	} = payload;

	apex.item("P1_RESULT").setValue(`The translated result is: ${translation}`);
}

const app = await Client.connect("abidlabs/en2fr");
const job = app.submit("/predict", ["Hello"]);

for await (const message of job) {
	log_result(message);
}
</script>
ページを実行すると、ページ・アイテムP1_RESULTに以下が表示されます。


Statusのサンプルを実装します。
<script type="module">
import { Client } from "@gradio/client";

function log_status(status) {
	apex.item("P1_RESULT").setValue(
		`The current status for this job is: ${JSON.stringify(status, null, 2)}.`
	);
}

const app = await Client.connect("abidlabs/en2fr", {
	events: ["status", "data"]
});
const job = app.submit("/predict", ["Hello"]);

for await (const message of job) {
	if (message.type === "status") {
		log_status(message);
	}
}
</script>
ページを実行すると、ページ・アイテムP1_RESULTに以下が表示されます。


Generator Endpointsのサンプルを実装します。
<script type="module">
import { Client } from "@gradio/client";

const app = await Client.connect("gradio/count_generator");
const job = app.submit(0, [9]);

for await (const message of job) {
    console.log(message.data);
    apex.item("P1_RESULT").setValue(JSON.stringify(message.data));
}

setTimeout(() => {
	job.cancel();
}, 3000);
</script>
ページを実行すると、ページ・アイテムP1_RESULTに以下が表示されます。


Gradio JavaScript Clientの組み込み方法について、簡単に確認してみました。

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

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

Gradio LiteをOracle APEXのアプリケーションに組み込む

ブラウザ上で動作するGradio-liteを、Oracle APEXのアプリケーションに組み込んでみます。Gradio-liteのページで紹介されているGetting Staredのサンプルを動かしてみます。

空のAPEXアプリケーションを作成し、ホーム・ページにGradio-liteを組み込みます。

最初にJavaScriptとCSSのファイルのインポートを設定します。Gradio-liteのページで紹介されている設定では、JavaScriptファイルをインポートする際にcrossorigin属性を付与しています。そのため、ページ・プロパティJavaScriptファイルURLによる設定はできません。

CSSのファイルについては、ページ・プロパティCSSファイルURLで設定できますが、別々に設定しても仕方がないので、両方ともページ・プロパティHTMLヘッダーに設定します。
<script type="module" crossorigin src="https://cdn.jsdelivr.net/npm/@gradio/lite/dist/lite.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@gradio/lite/dist/lite.css" />

Gradio-liteが生成したボタンを押すと、APEXアプリケーションのデフォルトの動作であるページの送信が実行されてしまいます。そのため、Gradio-liteのカスタム要素に含まれるボタンをクリックした場合は、ページの送信を抑制します。

Gradio-liteの初期化にはかなりの時間がかかります。ページ・ロードが完了した時点ではGradio-liteの初期化は完了していないため、その中にあるはずのボタン要素を取得することはできません。また、Gradio-liteの初期化が完了したときに発生するイベントを見つけることができなかったため、ドキュメントにたいしてclickイベントのハンドラを設定し、gradio-liteカスタム要素内のボタンから発生したclickイベントであれば、ページの送信を行わないようにします。

JavaScriptページ・ロード時に実行に以下を記述します。


後は静的コンテンツのリージョンを作成し、gradio-liteのカスタム要素を埋め込んでいきます。

リージョンFirst Sampleを作成し、ソースHTMLコードとして以下を記述します。
<gradio-lite>
import gradio as gr

def greet(name):
	return "Hello, " + name + "!"

gr.Interface(greet, "textbox", "textbox").launch()
</gradio-lite>

ページを実行すると、以下のようにGradio-liteのアプリケーションが埋め込まれていることが確認できます。


Multiple Filesのサンプルを静的コンテンツとして埋め込むと、以下のように表示されます。
<gradio-lite>

<gradio-file name="app.py" entrypoint>
import gradio as gr
from utils import add

demo = gr.Interface(fn=add, inputs=["number", "number"], outputs="number")

demo.launch()
</gradio-file>

<gradio-file name="utils.py" >
def add(a, b):
	return a + b
</gradio-file>

</gradio-lite>


Additional Requirementsのサンプルを静的コンテンツとして埋め込むと、以下のように表示されます。
<gradio-lite>

<gradio-requirements>
transformers_js_py
</gradio-requirements>

<gradio-file name="app.py" entrypoint>
from transformers_js import import_transformers_js
import gradio as gr

transformers = await import_transformers_js()
pipeline = transformers.pipeline
pipe = await pipeline('sentiment-analysis')

async def classify(text):
	return await pipe(text)

demo = gr.Interface(classify, "textbox", "json")
demo.launch()
</gradio-file>

</gradio-lite>

Playgroundを埋め込むと、以下のように表示されます。
<gradio-lite playground layout="horizontal">
import gradio as gr

gr.Interface(fn=lambda x: x,
			inputs=gr.Textbox(),
			outputs=gr.Textbox()
		).launch()
</gradio-lite>


Gradio-liteの組み込み方法について、簡単に確認してみました。

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

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

2024年9月2日月曜日

APEX 24.1でのデータベース資格証明のサポートを確認する

Oracle APEX 24.1から、Web資格証明の属性としてデータベース資格証明の使用が追加されました。基本認証OAuth2クライアント資格証明認証タイプが対応しています。


データベース資格証明は、一般的にDBMS_CLOUD.CREATE_CREDENTIALを呼び出して作成します。マニュアルに構文が記載されていますが、基本認証(いわゆるHTTPのBasic認証)については、以下の構文で作成したデータベース資格証明を参照すればよいことは分かります。
DBMS_CLOUD.CREATE_CREDENTIAL (
	credential_name   IN VARCHAR2,
	username          IN VARCHAR2,
	password          IN VARCHAR2 DEFAULT NULL);
DBMS_COUD.CREATE_CREDENTIALには、OAuth2のクライアントIDとクライアント・シークレットを保存するシグネチャはありません。

Oracle APEXのWeb資格証明OAuth2クライアント資格証明として使用するデータベース資格証明は、usernameクライアントIDpasswordクライアント・シークレットを指定して作成します。

AWSのARNを使ったデータベース資格証明(参考記事)、Azureのリソース・プリンシパルを使ったデータベース資格証明(参考記事)、Googleのサービス・アカウントを使ったデータベース資格証明(参考記事)を元にAPEXのWeb資格証明を作ることができるのかと当初は考えたのですが、そのような機能ではありませんでした。

OAuth2のClient Credentialsフローでは、認証サーバーはクライアント認証を行う際にBasic認証の実装は必須です(RFC 6749 2.3.1 Client Password)。そのため、Oracle APEXのWeb資格証明の認証タイプの基本認証とOAuth2の両方で、内部的にBasic認証(認証の対象は基本認証ではリソース・サーバー、OAuth2では認証サーバー)を使用していると思われます。Autonomous DatabaseのドキュメントではパッケージUTL_HTTPにSET_CREDENTIALというプロシージャが定義され、このプロシージャを呼び出すことによりBasic認証に必要なAuthorizationヘッダーが追加されると説明されています。

手短に説明すると、APEXのWeb資格証明として基本認証やOAuth2クライアント資格証明を作成するのと、これらをデータベース資格証明を元に作成するのとで、できることできないことに違いはありません。ユーザー名とシークレットの保存先が変わるだけです。異なる点は、データベース資格証明を元にしたWeb資格証明では、URLに対して有効を設定できないことと、HTTPのリクエストを発行するプリンシパルが、APEXのインストール・ユーザーではなくワークスペース・スキーマになることです。

以前の記事「ORDS REST APIのOAuth2による保護とAPEXからの呼び出し」で作成したアプリケーションを使って、Web資格証明データベース資格証明を元にしたものに変えてみます。

以下のアプリケーションをダウンロードして、ワークスペースにインポートします。
https://github.com/ujnak/apexapps/blob/master/exports/ords-rest-test.zip

アプリケーションをインポートする際に、このアプリケーションで参照しているWeb資格証明としてHR Example Credが作成されます。また、ORDSのREST APIを指すリモート・サーバーとしてRemote Server for Cred HR ExampleおよびRemote Server for RDS HR Exampleが作成されます。


記事に従ってRESTサービスのセットアップが完了していれば、OAuth2のクライアントIDとクライアント・シークレットが作成されています。

ビューUSER_ORDS_CLIENTSを検索し、CLIENT_IDCLIENT_SECRETを確認します。

select name, client_id, client_secret from user_ords_clients;


アプリケーションのインポート時に作成されたWeb資格証明HR Example Credを開き、クライアントIDクライアント・シークレットを更新します。


共有コンポーネントリモート・サーバーを開きます。

Remote Server for Cred HR Example(タイプが認証のリモート・サーバー)、Remote Server for RDS HR Example(タイプがRESTデータ・ソースのリモート・サーバー)を編集します。


それぞれのリモート・サーバーエンドポイントURLを環境に合わせて変更します。


Web資格証明とリモート・サーバーの設定を変更すると、テスト用のアプリケーションを実行できます。

ホーム・ページの表示です。


RESTデータ・ソースのレポートです。


これから、Web資格証明HR Example Credデータベース資格証明を使うように変更します。

DBMS_CREDENTIAL.CREATE_CREDENTIALを呼び出し、データベース資格証明としてHR_EXAMPLE_CREDを作成します。
begin
    dbms_cloud.create_credential(
        credential_name => 'HR_EXAMPLE_CRED'
        ,username       => 'クライアントID'
        ,password       => 'クライアント・シークレット'
    );
end;

作成したデータベース資格証明を確認します。

select * from user_credentials


今回は実行しませんが、データベース資格証明の削除には、DBMS_CREDENTIAL.DROP_CREDENTIALを呼び出します。

 Web資格証明HR Example Credを開き、データベース資格証明を参照するように設定を変更します。

データベース資格証明の使用オンにし、データベース資格証明名前としてHR_EXAMPLE_CREDを設定します。ストアド・トークンが存在する場合は、認証済みのセッションが継続しないようにトークンのクリアを実施しておきます。

変更の適用をクリックします。


データベース資格証明を元にしたWeb資格証明を使用する場合、HTTPのリクエストはAPEXがインストールされているスキーマではなく、ワークスペース・スキーマがプリンシパルとなります。

そのためネットワークACLを、ワークスペース・スキーマにたいして追加する必要があります。
begin
    DBMS_NETWORK_ACL_ADMIN.APPEND_HOST_ACE(
        host => '*',
        ace  =>  xs$ace_type(
            privilege_list => xs$name_list('connect', 'resolve'),
            principal_name => 'ワークスペース・スキーマ',
            principal_type => xs_acl.ptype_db
        )
    );
end;
ユーザーADMINにて実行します。


変更は以上です。

APEXアプリケーションについては対応は不要で、そのまま動作します。

DBMS_CLOUD.CREATE_CREDENTIALで作成したデータベース資格証明を使ってAPEXのAPEX_WEB_SERVICE.MAKE_REST_REQUESTを呼び出し、例えばAWSのBedrockやGoogleのVertex AIのAPIが呼び出せるのかと思って調査を始めたので、そういう機能ではなかったことは少々残念です。