Oracle Spatial Studioで作成したプロジェクトを公開し、そのプロジェクトをOracle APEXのアプリケーションに埋め込みます。オラクルの以下のドキュメントで紹介されている手順を実施します。
Oracle Spatial Studio Guide, Release 25.1
7.4 Embedding a Published Project in an APEX Application
macOS上のpodmanで作業環境を構築しています。Oracle Database 26ai Free、Oracle REST Data Services、Oracle Spatial Studioをそれぞれコンテナとして実行します。また、APEXアプリケーションのページにOracle Spatial StudioのWebコンポーネントを埋め込んで操作をするため、CORS(Cross-Origin Resource Sharing)の制約を受けないように、ORDSとSpatial Studioの前段にNginxによるリバース・プロキシを配置し同一オリジンにします。Oracle Spatial Studioの要件に合わせて、すべてHTTPS(暗号化)で通信します。
Oracle APEXの環境構築は、こちらの記事「
podmanを使ってOracle Database FreeとOracle REST Data Servicesをコンテナとして実行する」で紹介しています。今回の作業にあたって、Nginxのリバース・プロキシをポッド
apex内で動作させる必要があったため、コンテナ・ポート:ホスト・ポートのペアに9443:9443を追加しています。作成済みのポッドにコンテナ・ポートは追加できないため、コンテナ・ポートを追加するにはポッドを再作成する必要があります。
これらの環境が構築済みであることを前提として、本記事の作業を始めます。
Nginxで使用する自己署名証明書と秘密キーの作成
NginxでのTLS接続を有効にするため、自己署名証明書と秘密キーを生成します。それぞれを保存するファイルの作成に、opensslコマンドを使用します。
openssl -v
% openssl -v
OpenSSL 3.5.2 5 Aug 2025 (Library: OpenSSL 3.5.2 5 Aug 2025)
%
以下のコマンドにより自己署名証明書をserver.crt、秘密キーをserver.keyに保存します。ブラウザからはホスト名をlocalhostとしてアクセスすることを前提として、証明書のサブジェクトのCN(Common Name)にlocalhost、subjectAltNameにもlocalhostを設定しています。
openssl req -x509 -newkey rsa:4096 -sha256 -days 365 -nodes \
-keyout ./server.key \
-out ./server.crt \
-subj "/C=JP/ST=Tokyo/L=Chiyoda/O=LocalDev/OU=IT/CN=localhost" \
-addext "subjectAltName=DNS:localhost,IP:127.0.0.1"
% openssl req -x509 -newkey rsa:4096 -sha256 -days 365 -nodes \
-keyout ./server.key \
-out ./server.crt \
-subj "/C=JP/ST=Tokyo/L=Chiyoda/O=LocalDev/OU=IT/CN=localhost" \
-addext "subjectAltName=DNS:localhost,IP:127.0.0.1"
.....+.+.....+....+.....+....+++++++++++++++++++++++++++++++++++++++++++++*.......+...+...+.+...+...+...+.....+....+++++++++++++++++++++++++++++++++++++++++++++*....+..+.............+.....+............+.........+...+.....................+......+.+..............+...+...............+......+......+...+.+............+........+................+...+..+......+...+....+....................+.+..+..................+.+...+..+...+.+......+......+...+.........+........+......................+........+.......+........+...+...................+.....+.......+......+...+......+...+.....................+.....+.........+.+...........+...+.+......+...+.....+...+.............+......+...........+.........+.............+........+.......+..+......+....+...+...........+++++
........+.......+......+...........+......+....+.....+....+..+....+.........+..+...+.........+.+...........+.........+.+..............+++++++++++++++++++++++++++++++++++++++++++++*.+++++++++++++++++++++++++++++++++++++++++++++*...+.+..............+.............+..+......+.+......+..+.+..+.....................................+.....+...+.........+...+..........+...+.....+.......+.......................+...+.+...+........+..........+...+..........................+.............+.....+...+...................+.....+...............+................+...+.....+.......+..+...+....+...............+........+...+...+.........+......+.......+..............+.............+...........+......+..........+.....+.....................+............+......+.......+...+.........+...+........+.......+...+.........+..+.+...+...........+....+..+........................+....+.................+....+...+...+++++
-----
% ls server.*
server.crt server.key
%
作成されたserver.crtをテキスト形式で表示します。SubjectのCNとx509 extensionsのSubject Alternative Nameとしてlocalhostが設定されていることを確認します。
openssl x509 -in server.crt -text -noout
% openssl x509 -in server.crt -text -noout
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
52:d4:c5:21:24:02:94:94:74:40:28:98:f9:63:da:cd:b1:8a:ca:5e
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=JP, ST=Tokyo, L=Chiyoda, O=LocalDev, OU=IT, CN=localhost
Validity
Not Before: Nov 7 00:57:32 2025 GMT
Not After : Nov 7 00:57:32 2026 GMT
Subject: C=JP, ST=Tokyo, L=Chiyoda, O=LocalDev, OU=IT, CN=localhost
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (4096 bit)
Modulus:
00:da:c5:65:cc:f9:64:af:63:01:59:d0:5a:f7:44:
fb:aa:dd:81:aa:0d:8c:6b:7e:ea:5e:6a:48:2c:1a:
3d:2b:d4:63:89:46:fb:9f:53:a1:2b:af:8a:c2:b6:
f9:44:b2:8a:69:41:f4:f5:e2:f2:c0:47:eb:5c:5a:
38:64:1d:b3:bc:5e:75:29:17:ae:f0:fd:df:a7:06:
a3:11:28:ac:d4:03:e7:d8:0b:4f:6f:f3:99:15:cd:
be:dc:33:b9:2d:6d:d7:1f:48:b6:ad:0f:ef:77:24:
4f:ef:70:d8:5e:55:27:bf:44:50:b4:c7:f4:39:88:
82:69:0c:46:97:84:2e:11:88:93:0c:11:d9:de:04:
89:c9:0e:cf:53:1a:1c:7b:1a:54:9e:d5:04:81:84:
f0:1a:77:ee:3e:8c:c4:bf:92:4d:bd:18:90:28:c1:
79:44:67:3e:23:69:ea:33:77:ff:b5:18:8a:95:56:
6d:ae:af:98:8f:27:c7:67:3a:ed:f3:64:d8:90:19:
4b:9a:cb:9b:df:0d:0a:7a:a5:2d:6c:b7:9d:bf:24:
6c:e4:b0:76:3a:95:2e:16:f2:5c:b7:cb:33:b2:a5:
0b:2a:08:e6:ba:04:48:1e:3e:dc:e5:92:d5:55:bf:
57:74:ad:15:7d:2a:8c:e9:85:62:26:40:4d:9f:96:
9e:e7:23:8f:77:15:65:13:c3:bc:3f:89:8a:56:84:
20:04:7a:d1:87:12:61:a2:7c:71:f5:38:cd:2d:e1:
83:2c:81:e5:7f:37:a5:18:26:6b:34:b4:dc:b0:7d:
84:44:9c:4d:d9:c1:51:e4:99:1b:e2:30:ee:d7:d2:
e1:c1:3a:c3:f3:d6:14:c0:d9:05:81:e1:d0:de:87:
2d:85:a3:e5:64:08:bd:37:3d:d5:5b:ea:55:7d:af:
70:b9:41:0c:b6:be:6a:45:4f:ec:90:28:e5:33:b8:
64:f3:9c:7e:af:18:2a:e8:5a:e4:4d:21:7c:d1:86:
fe:8d:07:4c:64:87:a1:80:68:ea:49:08:a1:73:b9:
83:f6:c9:67:67:89:e6:4a:17:8d:bf:ef:03:89:be:
9d:55:ce:e6:c9:37:b8:78:8f:ae:09:0c:0f:cc:25:
12:1c:94:6e:2f:fb:a2:01:76:01:bb:3f:b4:d4:cf:
3e:11:e9:11:93:27:34:98:56:f9:85:08:65:23:bb:
77:93:af:0a:3e:85:ce:c1:37:fa:44:a6:c8:ce:3f:
37:7e:dc:64:30:bc:8c:38:c7:e9:c3:d6:f2:7b:43:
0a:55:51:13:e9:35:32:d4:b1:58:0b:db:09:87:d1:
cb:4b:c3:a2:54:89:5f:35:75:6b:75:e1:cd:2a:f4:
19:d6:c7
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Key Identifier:
B2:9A:9F:7B:F4:4E:8C:BE:03:C2:5B:05:07:52:A1:0E:E1:A9:2E:36
X509v3 Authority Key Identifier:
B2:9A:9F:7B:F4:4E:8C:BE:03:C2:5B:05:07:52:A1:0E:E1:A9:2E:36
X509v3 Basic Constraints: critical
CA:TRUE
X509v3 Subject Alternative Name:
DNS:localhost, IP Address:127.0.0.1
Signature Algorithm: sha256WithRSAEncryption
Signature Value:
22:fd:bb:d3:95:08:04:e6:87:d9:40:34:40:20:f0:43:b3:38:
ec:50:af:38:c2:e6:97:43:6e:b1:e1:42:30:b9:af:19:06:32:
bc:df:f3:72:78:cd:d8:6f:f2:60:8f:75:92:25:4e:72:06:70:
b1:27:28:f0:24:03:60:f9:9e:54:d0:4b:a7:de:06:e7:ab:56:
eb:aa:a8:c6:af:18:cf:ea:9f:18:ae:b4:4c:f4:34:5e:8e:7e:
aa:60:ba:4e:33:46:08:85:e9:46:9f:89:16:0e:6f:c4:f0:d1:
a4:e2:27:34:75:20:ff:64:ac:13:1a:94:b6:8d:1b:9a:16:77:
6f:3b:bf:aa:3c:c9:17:4b:ab:56:80:66:c2:de:ba:d1:36:25:
1a:ad:94:b0:cd:67:bd:ff:be:4d:03:4a:fb:bb:32:03:bc:d2:
1e:48:e9:e0:eb:1c:fe:15:ce:96:de:f9:21:3a:f5:98:d2:89:
11:ff:7b:16:59:ee:07:ee:8f:0a:21:79:05:13:02:99:53:b6:
48:f5:51:61:f0:60:70:88:62:7b:cd:5a:62:7f:db:55:db:5a:
83:53:19:bd:bf:0c:b1:49:46:c3:0b:64:1b:23:53:92:a8:0b:
d2:6e:88:18:f1:6e:0a:dd:38:11:e8:cb:b8:b5:a7:18:ba:8c:
04:0f:b7:26:58:51:eb:e7:71:df:81:07:a1:8a:e2:43:d6:db:
93:78:d7:07:d5:95:3a:5e:60:be:2f:8d:89:ff:86:27:b0:57:
ac:68:3b:4f:c9:65:17:14:2f:ce:5c:bd:97:a7:74:8a:15:af:
bf:6c:d8:b1:55:07:42:73:d4:8e:cd:2b:3c:96:9e:ae:56:5f:
de:91:cc:2f:4a:6f:af:dc:33:3a:f2:b9:c4:bf:01:ac:47:a2:
b6:43:ee:1e:ab:ed:70:50:5b:c2:02:79:de:5b:c4:b6:5d:38:
59:50:dd:b4:dc:d1:37:c3:86:fd:03:8f:18:af:23:78:b3:42:
6b:91:90:67:97:c6:53:67:18:9d:40:e1:f8:bb:51:f0:b9:9d:
52:d1:a9:87:4b:38:dc:3d:3d:27:c0:f0:41:cf:fe:d2:60:da:
af:5c:0c:09:84:9b:19:60:30:fe:73:c1:ba:ee:eb:5e:38:8b:
eb:b6:86:c1:63:86:29:35:18:0b:d3:d6:a0:23:bf:c8:6d:13:
ee:46:a9:84:6f:a5:d9:0c:fd:3f:f4:40:35:8a:48:ae:e6:cc:
d6:e5:e5:01:f0:56:9e:d3:4a:af:01:70:e9:78:91:62:d8:6f:
f8:9d:8e:df:12:df:a1:1e:8e:9a:1a:5a:bf:c8:7d:c2:b4:7d:
c0:3d:47:88:b5:6a:42:8c
%
Oracle REST Data ServicesのHTTPS化
コンテナapex-ordsで動作しているOracle REST Data Servicesを、HTTPからHTTPSで通信するように変更します。
コンテナapex-ordsに接続します。
podman exec -it apex-ords sh% podman exec -it apex-ords sh
sh-5.1$
ORDSの設定の
standalone.https.portに
8443を設定します。ORDSは
standalone.https.portが設定されていれば、HTTPSで通信するように構成されます。
ords --config /etc/ords/config config set standalone.https.port 8443
sh-5.1$ ords --config /etc/ords/config config set standalone.https.port 8443
ORDS: Release 25.3 Production on Fri Nov 07 01:07:29 2025
Copyright (c) 2010, 2025, Oracle.
Configuration:
/etc/ords/config
The global setting named: standalone.https.port was set to: 8443
sh-5.1$
コンテナapex-ordsから抜けて、コンテナを再起動します。
podman restart apex-ords
sh-5.1$ exit
exit
% podman restart apex-ords
apex-ords
%
ORDSはstandalone.https.portを設定後の初回起動時に、HTTPSで通信できるようにディレクトリ/etc/ords/config/global/standalone以下に、自己署名証明書のファイルとしてself-signed.pem、秘密キーのファイルとしてself-signed.keyを生成します。これらはstandalone.https.certおよびstandalone.https.cert.keyが未設定の場合に、デフォルトとして参照されます。
今回の設定ではstandalone.https.portのみを設定していますが、ORDSをHTTPS化する場合は、他のstandard.https.で始まるプロパティも設定すべきです。
ブラウザから、プロトコルとしてhttps、ポート番号8443を指定して、APEXへの接続を確認します。
自己署名証明書による暗号化なので、証明書を信頼してもよいかどうか、ブラウザから確認を要求されます。
詳細情報を表示し、localhostにアクセスします。
APEXのサインイン画面が表示されれば、ORDSのHTTPS化は完了です。
今回はNginxのリバース・プロキシがHTTPS(暗号化)の通信を受け付けて、バックエンドのORDSにHTTPS(暗号化)で通信します。一般的には、リバース・プロキシがHTTPSで受け付けて、バックエンドのサーバーへはHTTP(非暗号化)で通信するように構成することが多いと思います。
このような構成をするために、ORDSには設定security.httpsHeaderCheckがあります。このプロパティにX-Forwarded-Proto: httpsを設定することにより、リバース・プロキシとの間ではHTTPで通信しているにも関わらず、ORDSから呼び出されるRESTサービスやAPEXはHTTPSで通信していると認識します。
ords --config /etc/ords/config config set security.httpsHeaderCheck "X-Forwarded-Proto: https"
しかし、この設定を行った場合、HTTPSの通信はポート番号443で受け付けているとバックエンドに伝えます。結果として、ブラウザからhttps://localhost:9443/(Nginxのリバース・プロキシが接続を受け付けるURL)でアクセスしていても、それがhttps://localhost:443/からのリクエストとして認識されるため、APEXは自サイトにアクセスするためのURLを適切に生成できません。
今回はリバース・プロキシの接続をポート番号9443で受け付けたかった(ローカルのPCではポート番号443を開けられない)ため、security.httpsHeaderCheckは設定せず、バックエンドとの通信はHTTPSで行うようにしています。リバース・プロキシがHTTPSの標準ポート番号である443で接続を受け付ける場合は、security.httpsHeaderCheckを設定して、HTTPS -> HTTPとなるリバース・プロキシを構成できます。
Nginxによるリバース・プロキシの構成
最初に注意ですが、Oracle APEXおよびOracle REST Data Servicesは公式にはリバース・プロキシの使用をサポートしていません。以下は、APEXやORDSに問題なくアクセスするために、リバース・プロキシの存在を隠すための設定です。
Nginxによるリバース・プロキシを構成します。Nginxのコンテナはポッドapexに含めます。
podman run --name nginx --pod apex -d nginx:alpine
% podman run --name nginx --pod apex -d nginx:alpine
9e724da5d19499f25102f48d7bff252063690e8fc798df708eeab217a7a292c9
%
コンテナnginxが作成されたので、接続してリバース・プロキシを構成します。
podman exec -it nginx sh
% podman exec -it nginx sh
/ #
ディレクトリ/etc/nginx/sslを作成し、その下に先ほど作成した自己署名証明書のファイルserver.crtと秘密キーのファイルserver.keyを配置します。
mkdir /etc/nginx/ssl
cd /etc/nginx/ssl
cat > server.crt
server.crtの内容をペーストしてCtrl+Dを入力
cat > server.key
server.keyの内容をペーストしてCtrl+Dを入力
chmod 400 server*
ls -l server*
/ # mkdir /etc/nginx/ssl
/ # cd /etc/nginx/ssl
/etc/nginx/ssl # cat > server.crt
-----BEGIN CERTIFICATE-----
MIIFwzCCA6ugAwIBAgIUUtTFISQClJR0QCiY+WPazbGKyl4wDQYJKoZIhvcNAQEL
[省略]
Vp7TSq8BcOl4kWLYb/idjt8S36EejpoaWr/IfcK0fcA9R4i1akKM
-----END CERTIFICATE-----
/etc/nginx/ssl # cat > server.key
-----BEGIN PRIVATE KEY-----
MIIJQgIBADANBgkqhkiG9w0BAQEFAASCCSwwggkoAgEAAoICAQDaxWXM+WSvYwFZ
[省略]
zwQl/5TGWf/KEODEVkvjtJtqXVD6ZA==
-----END PRIVATE KEY-----
/etc/nginx/ssl # chmod 400 server*
/etc/nginx/ssl # ls -l server*
-r-------- 1 root root 2057 Nov 7 01:53 server.crt
-r-------- 1 root root 3272 Nov 7 01:53 server.key
/etc/nginx/ssl #
Nginxの設定ファイル/etc/nginx/conf.d/default.confを以下の内容に置き換えます。ORDS+APEXおよびOracle Spatial Studioへのリバース・プロキシを構成しています。
APEXのパラメータ
IMAGE_PREFIXを設定し、
静的リソースについてはCDNを参照するように構成するとロケーション/i/へのリクエストはCDNに向かいます。そのように設定すると
/i/の設定は不要になり、リバース・プロキシおよびORDSへのアクセスを減らすことができます。
default.confを入れ替えて、nginxを再起動します。
nginx -s reload
/etc/nginx/conf.d # nginx -s reload
2025/11/07 02:13:55 [notice] 41#41: signal process started
/etc/nginx/conf.d #
リバース・プロキシ経由でのAPEXへのアクセスを確認します。この場合でも自己署名証明書を使用して暗号化を行なっているため、警告は表示されます。
APEXのサインイン・ページが表示されれば、APEXへのリバース・プロキシは正常です。

リバース・プロキシ経由でのOracle Spatial Studioへのアクセスを確認します。
Oracle Spatial Studioのサインイン画面が表示されれば、Oracle Spatial Studioへのリバース・プロキシは正常です。
以上で、同じURL(https://localhost:9443/)から、Oracle APEXとOracle Spatial Studioの双方にアクセスできる環境が構築できました。
シェープファイルをデータベースにロードする
再開発等促進区を定める地区計画のシェープファイルは
gis05_saikaihatsuchikukeikaku.zipとしてダウンロードされます。
シェープファイルのロード先となるOracle Databaseには、APEXのワークスペース・スキーマとしてWKSP_APEXDEVが作成済みとします。このスキーマにシェープファイルをロードします。
gis05_saikaihatsuchikukeikaku.zipが配置されているディレクトリで、GDALのコンテナを実行します。
podman run --rm -it -v $PWD:/home/oracle gdal
% podman run --rm -it -v $PWD:/home/oracle gdal
bash-5.1$ ls gis05*
gis05_saikaihatsuchikukeikaku.zip
bash-5.1$
Oracle Databaseのドライバが適切に呼び出せるように、以下の環境変数を設定します。
export LANG=ja_JP.utf8
export NLS_LANG=American_America.AL32UTF8
export PATH=/usr/local/bin:$PATH
export ORACLE_HOME=/usr/lib/oracle/23/client64
export LD_LIBRARY_PATH=${ORACLE_HOME}/lib:/usr/local/lib64:${LD_LIBRARY_PATH}
bash-5.1$ export LANG=ja_JP.utf8
export NLS_LANG=American_America.AL32UTF8
export PATH=/usr/local/bin:$PATH
export ORACLE_HOME=/usr/lib/oracle/23/client64
export LD_LIBRARY_PATH=${ORACLE_HOME}/lib:/usr/local/lib64:${LD_LIBRARY_PATH}
bash-5.1$
gis05_saikaihatsuchikukeikaku.zipを解凍します。
unar gis05_saikaihatsuchikukeikaku.zip
bash-5.1$ unar gis05_saikaihatsuchikukeikaku.zip
gis05_saikaihatsuchikukeikaku.zip: Zip
再開発等促進区を定める地区計画/ (dir)... OK.
再開発等促進区を定める地区計画/再開発等促進区を定める地区計画_R070331.dbf (23409 B)... OK.
再開発等促進区を定める地区計画/再開発等促進区を定める地区計画_R070331.prj (410 B)... OK.
再開発等促進区を定める地区計画/再開発等促進区を定める地区計画_R070331.sbn (1028 B)... OK.
再開発等促進区を定める地区計画/再開発等促進区を定める地区計画_R070331.sbx (164 B)... OK.
再開発等促進区を定める地区計画/再開発等促進区を定める地区計画_R070331.shp (146476 B)... OK.
再開発等促進区を定める地区計画/再開発等促進区を定める地区計画_R070331.shx (876 B)... OK.
Successfully extracted to "./再開発等促進区を定める地区計画".
bash-5.1$
取り出されたシェープファイル"
再開発等促進区を定める地区計画/再開発等促進区を定める地区計画_R070331.shp"を、
ogr2ogrコマンドを実行して、スキーマ
WKSP_APEXDEVに新規表
GIS_SAIKAIHATSUを作成しロードします。
ogr2ogr -f OCI -overwrite OCI:wksp_apexdev/oracle@host.containers.internal/freepdb1 \
"再開発等促進区を定める地区計画/再開発等促進区を定める地区計画_R070331.shp" \
-oo ENCODING=CP932 -nln GIS_SAIKAIHATSU -lco GEOMETRY_NAME=GEOM -lco SRID=4326 \
-lco DIM=2 -nlt PROMOTE_TO_MULTI -s_srs EPSG:2451 -t_srs EPSG:4326 \
-skipfailures
bash-5.1$ ogr2ogr -f OCI -overwrite OCI:wksp_apexdev/oracle@host.containers.internal/freepdb1 \
"再開発等促進区を定める地区計画/再開発等促進区を定める地区計画_R070331.shp" \
-oo ENCODING=CP932 -nln GIS_SAIKAIHATSU -lco GEOMETRY_NAME=GEOM -lco SRID=4326 \
-lco DIM=2 -nlt PROMOTE_TO_MULTI -s_srs EPSG:2451 -t_srs EPSG:4326 \
-skipfailures
bash-5.1$
特にエラーが発生しなければ、表GIS_SAIKAIHATSUにデータがロードされています。
Oracle Spatial Studioでのプロジェクト作成
リバース・プロキシ経由でOracle Spatial Studioに接続し、ログインします。
デフォルトの接続として、コンテナで動作しているapex-dbへの接続が作成済みとします。
Oracle Spatial Studioのコンテナはポッドapexに含まれていないため、データベースへの接続先ホストはhost.containers.internal、ポート番号は1521、サービス名はFREEPDB1になります。本記事では、接続するスキーマはAPEXのワークスペース・スキーマとしてWKSP_APEXDEVを想定しているため、WKSP_APEXDEVで接続します。
作成した表GIS_SAIKAIHATSUを元に、データセットを作成します。
データベース表/ビューを選択し、作成をクリックします。
データセットを作成するアイテムの選択としてGIS_SAIKAIHATSUを選び、作成をクリックします。
データセットとしてGIS_SAIKAIHATSUが作成されます。
続いてプロジェクトを作成します。
新規に作成されたプロジェクトに、先ほど作成したデータセットGIS_SAIKAIHATSUを、データセットの追加をクリックして追加します。
GIS_SAIKAIHATSUにチェックを入れ、OKをクリックします。
追加されたデータセットGIS_SAIKAIHATSUを開き、列GEOMをマップ上にドラッグ&ドロップします。
マップ上に再開発促進区に関する区域が表示されます。
プロジェクトを保存します。
保存するプロジェクトの
名前は
tokyo_saikaihatsuとします。
保存をクリックします。
プロジェクトがtokyo_saikaihatsuとして保存されます。
保存されたプロジェクトをパブリッシュします。
アクション・メニューを開き、プロジェクトの公開を実行します。
共有をクリックします。
以上で作成したプロジェクトtokyo_saikaihatsuがパブリッシュされました。
プロジェクトのページを開き、パブリッシュされたプロジェクトのプロジェクトIDを確認します。プロジェクトIDは、APEXアプリケーションへのプロジェクトの埋め込み時に使用します。
公開済プロジェクトを選択し、3点メニューを開きURLを選択します。
公開済プロジェクトのURLが表示されます。この
URLをコピーしてダイアログを
閉じます。
URLは以下の形式です。CGI引数のproj_idに指定されている値が、プロジェクトtokyo_saikaihatsuのプロジェクトIDになります。
https://localhost:9443/spatialstudio/published.html?proj_id=edc92249bfb9a70092d694056a813215&ui_elements=application_header,layers_list,project_header
アクセス・トークンの作成方法には2つの手順があります。
- 新規トークンの作成を実行し、個別にアクセス・トークンを生成する
- アクセスジェネレータ・トークンを使って、RESTサービスを呼び出してアクセス・トークンを生成する
今回はより柔軟にアクセス・トークンの生成が可能な、アクセスジェネレータ・トークンを使用します。
アクセスジェネレータ・トークンの表示をクリックします。
ダイアログが開き、表示されたアクセスジェネレータ・トークンをコピーします。アクセスジェネレータ・トークンがnullの場合は、トークンの再生成を実行します。
コピーしたトークンを記録し、ダイアログを閉じます。
Oracle APEXのSQLコマンドより、アクセス・トークンを発行するRESTサービスを呼び出します。
Oracle Spatial StudioのRESTサービスのエンドポイントはhttps://localhost:9443/になります。このエンドポイントは自己署名証明書を使って暗号化されているため、APEX_WEB_SERVICE.MAKE_REST_REQUESTを呼び出す際に、自己署名証明書を信頼する証明書として登録されたウォレットが必要になります。
そのため、Oracle Walletsを作成します。
コンテナapex-dbに接続します。
podman exec -it apex-db sh
% podman exec -it apex-db sh
sh-4.4$
Nginxのリバース・プロキシを構成する際に使用したserver.crtを、コンテナ内にコピーします。
cat > server.crt
server.crtの内容をペーストしてCtrl+D
sh-4.4$ cat > server.crt
-----BEGIN CERTIFICATE-----
MIIFwzCCA6ugAwIBAgIUUtTFISQClJR0QCiY+WPazbGKyl4wDQYJKoZIhvcNAQEL
[省略]
Vp7TSq8BcOl4kWLYb/idjt8S36EejpoaWr/IfcK0fcA9R4i1akKM
-----END CERTIFICATE-----
sh-4.4$
ディレクトリ
/home/oracle/walletsとして、Oracle Walletsを作成します。
orapki wallet create -wallet /home/oracle/wallets -pwd <パスワード> -auto_login
sh-4.4$ orapki wallet create -wallet /home/oracle/wallets -pwd ChangeMe5566 -auto_login
Oracle PKI Tool Release 23.0.0.0.0 - Production
Version 23.0.0.0.0
Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved.
Operation is successfully completed.
sh-4.4$
自己署名証明書
server.crtを信頼する証明書として、Oracle Walletsに追加します。
orapki wallet add -wallet /home/oracle/wallets -pwd <パスワード> -trusted_cert -cert ./server.crt
sh-4.4$ orapki wallet add -wallet /home/oracle/wallets -pwd ChangeMe5566 -trusted_cert -cert ./server.crt
Oracle PKI Tool Release 23.0.0.0.0 - Production
Version 23.0.0.0.0
Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved.
Operation is successfully completed.
sh-4.4$
以上で、Oracle Walletsは作成できました。
続いてOracle Spatial Studioのアクセスジェネレータ・トークンから、APEXのWeb資格証明を作成します。
ワークスペース・ユーティリティのWeb資格証明を開きます。
作成を開始します。
名前はSpatial Studio、静的IDはSPATIAL_STUDIOとします。認証タイプにHTTPヘッダーを選択し、資格証明名としてHTTPヘッダー名であるAuthorizationを選択します。
資格証明シークレットとして、Bearerで始めて空白で区切り、Oracle Spatial Studioのアクセスジェネレータ・トークンを記述します。
以上の設定で、作成を実行します。
Oracle Spatial Studioのアクセス・トークンの生成に使用するWeb資格証明として、SPATIAL_STUDIOが作成されました。
SQLコマンドを開き、RESTサービスを呼び出してアクセス・トークンを生成します。アクセス・トークンを生成するエンドポイントは以下です。
https://localhost:9443/spatialstudio/oauth/v1/user/token?name=<トークン名>&validTime=<1-99999または-1、単位は分)&action=<read_onlyまたはread_write>&resourceType=<dataset_streaming, dataset_streaming_refreshing , embedded_published_project, all>
今回は作成するトークンの名前をmyTokenとして、以下の条件でアクセス・トークンを生成します。
きちんと確認していませんが、APEXのページにOracle Spatial StudioのプロジェクトをWebコンポーネントとして埋め込み、外部のJavaScriptコードからWebコンポーネントの機能を呼び出す場合は、actionとしてread_writeである必要があり、その場合はresouceTypeもallにしないとエラーが発生します。
https://localhost:9443/spatialstudio/oauth/v1/user/token?name=myToken&validTime=9999&action=read_write&resourceType=all
以下のスクリプトを実行し、アクセス・トークンを生成します。
生成されたアクセス・トークンをコピーし、保管しておきます。
APEXのSQLコマンドからAPEX_WEB_SERVICE.MAKE_REST_REQUESTを実行する場合、コンテナapex-dbで実行しているOracle DatabaseからHTTPSのリクエストが発行されます。Nginxのリバース・プロキシがポッドapexに含まれていないと、RESTサービスのリクエストのリクエストはhost.containers.internalをエンドポイントのホストとして呼び出す必要があります。ホスト名にhost.containers.internalを指定すると、Nginxに設定した自己署名証明書のサブジェクトやSANに設定しているlocalhostと異なるため、RESTサービスのリクエストが失敗します。そのため、コンテナとして実行されているOracle Databaseから、localhostを宛先としてNginxを呼び出せるように、Nginxをポッドapexに含めています。
PL/SQLのコードよりアクセス・トークンを生成できますが、APEXアプリケーションへの組み込みは割愛します。
APEXアプリケーションの作成
Oracle Spatial Studioのプロジェクトを埋め込んだAPEXアプリケーションを作成します。APEXアプリケーションへの埋め込みは、以下のドキュメントの記述に沿って実施します。
7.4 Embedding a Published Project in an APEX Applicationhttps://docs.oracle.com/en/database/oracle/spatial-studio/25.1/spstu/embedding-published-project-apex-application.html
空のAPEXアプリケーションを作成します。名前は東京都再開発とします。
アプリケーションが作成されたら、
ページ・デザイナで
ホーム・ページを開きます。
ページ・プロパティのJavaScriptのファイルURLに以下を記述します。
[require requirejs]https://localhost:9443/spatialstudio/api/v1/embeddable.js?ex=kobinding
Spatial Studioの埋め込み先となるリージョンを作成します。名前はSpatial Studio、タイプは静的コンテンツとします。
ソースのHTMLコードには以下を記述します。project-idには、Spatial Studioの公開済プロジェクトのURLから取り出した値、tokenにはRESTサービスを呼び出して生成した、アクセス・トークンに置き換えます。
<div style="width:100%; height: 400px;">
<spatial-studio-project
id="spatial-studio-project-1"
server-url="https://localhost:9443/spatialstudio/"
project-id="edc92249bfb9a70092d694056a813215"
token="eyJ0eXAiOiJzZ3RlY2hfand0IiwiYWxnIjoiUlMyNTYifQ.eyJzdWIiOiI3YTYzMGU2ODhkZDQ0Y2YzYjhjYzgxNTQ3NzRhODJkYSIsInN0dWRpb190ZW5hbnRfaWRlbnRpZmllciI6IkdMT0JBTDpAZGF0YWJhc2VAOkBkZWZhdWx0QCIsIm5iZiI6MTc2MjQ5NjA1MCwic2NvcGUiOiJyZXNvdXJjZS5yZWFkX3dyaXRlOnJlc291cmNlLnR5cGUuYWxsIiwiaXNzIjoiT3JhY2xlU3BhdGlhbFN0dWRpbyIsImV4cCI6MTc2MzA5NTk5MCwiaWF0IjoxNzYyNDk2MDUwLCJqdGkiOiIwNjMxYzQ4NS02YjNiLTRiZGQtOWRkYy0xNjMzNTU1OWUzZDEiLCJzdHVkaW9fb2lkIjoiYmUxYWFmNTFhY2RmNDgyYWI3NTVkZTYxMTVmNzg1NDAifQ.qfNoxEto7SyvUijKDbyDYAz5G3hVWhPV047ys9XRqkUCBLkDgwvM62PiATW7UpZ7igbHC64bOomeywQ-2yMgSxQWvx6fdkxbpE9ihkUS5dUq3iJPSRODLJDKa7AWk1BC5ot2j6n1MkvAuqf6qb9sx0VuGc4fwO6sqi9lEe04DhZf_aVsShzHUYHwPrJnsMYL-9DbNfdoW6q9Mi4O9rtUZa5nreXuDiuMFx2SmluLL7jFzerpXPzy20mzw64GPUzs2s6RimH6elrWBSNpBRKLrScxqtSCyKpfiRLJ2UZJ-n4wvQdbkxJcQ4cXvYkvRx-hkdQQqWOBcnbd2Y77PzU-tg"
project-header="off"
layers-list="on">
</spatial-studio-project>
</div>

Spatial StudioのWebコンポーネントについては、ドキュメントの以下で説明されています。
7.2 Basic Usage of the Spatial Studio Web Component
以上でアプリケーションを実行します。以下のようにAPEXのページにSpatial Studioのプロジェクトが埋め込まれて表示されます。
エラーが発生するとコンソールに表示されるので、JavaScriptコンソールを開いた状態でAPEXアプリケーションを実行することをお勧めします。
プログラムから作成したアクセス・トークンであっても、Oracle Spatial Studioの設定のアクセス・トークンのページに一覧されます。トークンの末尾数文字は表示されるため、カスタム要素spatial-studio-projectに与えたtokenが有効かどうかを確認できます。
ドキュメントには以下のCSSが記載されていますが、ページ・プロパティのCSSのインラインに設定しても、APEXアプリケーションとOracle Spatial Studioの間で設定の不整合は解消しません。
body {
--sgtech-bg: var(--rbr-blue);
--oj-heading-text-color: white;
--ut-region-header-text-color: white;
--ut-region-border-color: white;
--ut-footer-text-color: white;
max-width: 100%;
--oj-core-spacing-3x: 0px;
--ut-region-body-padding-y: 0px;
--ut-region-body-padding-x: 0px;
}
div.sgtech-home-container {
max-height: 100%;
}
そのためCSSについては、ドキュメントの記述をそのまま採用はできず、調整が必要です。
APEXのページに埋め込んだOracle Spatial StudioのWebコンポーネントと、APEXの対話グリッドの連携を実装します。
対話グリッドのリージョンを作成します。名前は区域、ソースの表名にGIS_SAIKAIHATSUを設定します。
対話グリッドの属性を開きます。
複数行の選択ができるように、編集の有効をオンにし、実行可能な操作はすべてチェックを外します。
外観の最初の行の選択をオフ、ページ区切りのタイプをスクロール、ヘッダーの固定をリージョン、固定レポートの高さを400ピクセルにします。
対話グリッドを配置したページは、以下のように表示されます。
ここで、JavaScriptコンソールに
A polygon layer added to canvas:といったメッセージとともに
Layer IDが表示されます。このLayer IDを記録しておきます。
Spatial Studioと対話グリッドを連携させるために、動的アクションを設定します。
主にドキュメントの以下のページを参照します。
7.3 Interactive Usage with the Spatial Studio Web Componenthttps://docs.oracle.com/en/database/oracle/spatial-studio/25.1/spstu/interactive-usage-spatial-studio-web-component.html
名前はSelection Change、タイミングのイベントに選択の変更[対話グリッド]を選択します。
TRUEアクションとしてJavaScriptコードの実行を選択し、設定のコードに以下を記述します。LAYER_IDはJavaScriptコンソールより確認した値で置き換えます。
埋め込まれたSpatial Studioのプロジェクトが表示されている条件で実行するように、クライアント側の条件のタイプにJavaScript式を選択し、JavaScript式に以下を記述します。
document.querySelector('#spatial-studio-project-1 studio-application')
APEXアプリケーションを実行します。
対話グリッドで選択した区域のみが、埋め込まれたSpatial Studioのプロジェクトに表示されます。
対話グリッドにはすべてを選択するためのチェックボックスがありますが、これはすでに対話グリッドに読み込まれた行だけが対象になります。期待通りに動作させるには、対話グリッドを最終行までスクロールさせ、すべての行を読み込んでおく必要があります。
Layer IDはOracle Spatial Studioからも取得できますが、ここでコピーしたLayer IDはJavaScriptコンソールに表示されるLayer IDとは異なります。JavaScriptのコードに含めるLayer IDは、JavaScriptコンソールに表示される値を使用します。
今度は反対に、Spatialのプロジェクト上で選択した区域を対話グリッドに反映します。
ページ・プロパティのJavaScriptのページ・ロード時に実行に以下を記述します。Spatial StudioのWebコンポーネントのイベントfeatures_selecetedに、イベント・ハンドラを設定します。
対話グリッドの静的IDとしてTABLEREGIONを設定します。
以上ですべての実装は完了です。
領域で選択するツールなどを使用すると、Spatial StudioのWebコンポーネント上で選択した領域が、対話グリッドの行の選択に反映されることが確認できます。期待通りに動作させるには、対話グリッドを最下部までスクロールさせて、表のデータをすべて読み込んでおく必要があります。
features_selectedのイベントの値に
datasetIdが含まれます。今回はプロジェクトに追加したデータセットが1つだけなので、datasetIdの確認は行なっていません。データセットIDは、データセットのプロパティから確認できます。
今回の記事は以上になります。
今回作成したAPEXアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/sample-spatial-studio-web-component.zip
Oracle APEXのアプリケーション作成の参考になれば幸いです。
完