Skip to Main Content
 

Search Results

APEX Neue Funktionen in der Übersicht (ab 21.1)

Bereich:APEX, Version: ab APEX 22.2, Letzte Überarbeitung: 20.10.2023

Keywords:APEX, New Features, Neuerungen in APEX 22.1, APEX 22.2, APEX 23.1

In vielen unserer Oracle APEX Kursen kommt die Frage auf: In welcher Version gibt es denn eigentlich die Funktion XY?
Deswegen hier mal eine kurze Auflistung der neuen Funktionen, die in den letzten Versionen hinzugekommen sind:

APEX 21.1

  • Einführung von CSS Variablen
  • Neuer Date Picker
  • Verbesserte Karteneinbindung (Maps)
  • Datenupload in JSON, CSV, XML oder XLSX möglich
  • Export und Import von Apps im Zip Format
  • 95 neue Icons
  • Dynamic Action mit Client Side oder Server Side Conditions
  • Farbige Banner (Links) im Workspace
  • Eingebauter Texteditor dür JS oder CSS Dateien

APEX 21.2

  • Export Scripts Data Package ( Inhalt von Tabellen kann mit exportiert werden)
  • Neue Items: Display Map und Gecoded Address
  • Neue Region: Smart Filters
  • Neue Regionen Positionen: Banner, After Logo, ...
  • Einführung Progressive Web Applications
  • Verbesserter Breadcrumb Wizard


APEX 22.1

  • Verbesseruneg bei der Textsuche (Multi-Word Suche)
  • Approvals (Genehmigungprozesse mit 4 Augen-Prinzip)
  • Verbesserte Region Image Unterstützung
  • Rest Enabled SQL Query
  • Verbesserungen in der Developer Toolbar
  • Workspace Files lassen sich getrennt exportieren
  • Exportformat für Appliaktion in JSON oder YAML möglich
  • Neuer Richtext Editor
  • Verbesserte Applikations-Icons (Farbe, Art, Größe)
  • Persisstent Authentication (Rember me Checkbox)
  • Verbesserte Debug Einstellung
  • Session Overrides (Länder oder Zeiteinstellungen sind sofort änderbar und werden in APP angezeigt)



APEX 22.2

  • Application Search: Es kann eine Suchmenge definiert werden (auf Basis von Tabelle / View / REST / Liste), die dann in einer Kachelform (Badge) ausgegeben wird
  • Invoking API: PL/SQL Objekte können einfacher mit ihren Parametern aufgerufen werden
  • Genehmigungkomponente wurde verbessert in Bezug auf Fälligkeitstermine, Ablauf Policy, Aktionslogging
  • Datumsauswahl (Datepicker) "Heute" Schaltfläche kommt hinzu, schnellere Ladezeit
  • Region dynamischer Inhalt: Alte Region "PL/SQL dynamic Content" wird ersetzt durch Region die eine Funktion aufruft mit Rückgabetyp Varchar2 oder CLOB, der
    dann mittels htp.p in der Region ausgegeben wird
  • TextItem, Textarea und Richtext unterstützen nun den Datentyp CLOB
  • PWA Verbesserungen: Installationsprozess vereinfacht, Anzeige von Screenshots, Verknüpfungen für Seiten verfügbar
  • Gerätegeolokation verfügbar
  • Share Funktion für PWA
  • Dynamic Actions: Debounce (verzögerte Ausführung von Aktionen)
  • Map Region: Wechsel zwischen Vektor und Raster Tile möglich


APEX 23.1

  • Template Komponenten (Plugins auf Templates)
  • 6 Neue Template Komponenten
  • Avatare und Badges in Interactiven Reports
  • PWA Push Benachrichtungen
  • Überarbeiteter Object Browser
  • Hintergrundprozess als Kettenprozesse definieren
  • Status der Hintergrundprozesse anzeigen
  • Rest Sources nun für Items SQL Expressions verfügbar
  • Raw Selector für Rest Data Source Profiles verfügbar
  • Rest Sources auf Basis der Antwort von Swagger / OpenAPI verfügbar
  • Copy Page nun auch aus dem Create Page Wizard erreichbar
  • Save & Run aus dem Code-Editor verfügbar
  • Export / Import im Theme Roller für Themes verfügbar
  • Color Picker Item wurde überarbeitet
  • TinyMCE ersetzt den RichTextEditor
  • Friendly URLs auch im App Builder

APEX 23.2

  • Applikations-Arbeits Kopien (diese können wieder zusammengeführt werden mit dem Original)
  • Workflow Verbesserungen (Automatisierung von Business-Prozessen) mit Einbindung von Email-Versendungen, PL/SQL API, Push Nachrichten und REST Aufrufen
  • Neue Items: Combobox
  • Geänderte Items: File Upload (Zuschneiden von Bildern und deren Größe anpassen) Selfie-Aufnahmen werden unterstützt
  • QR Code Generator für Text, URLs, Telefonnummern, SMS, Email oder Geo-Daten
  • Benutzerdefinierte Hintergrundbilder bei Landkarten (Maps)
  • Faceted Search Verbesserungen: Auf- und Absteigende Sortierung, Unterstützung von Operatoren wie >= , <=, <, > bei der Suche
  • Template Komponenten Verbesserungen: Unbegrenzt viele Atrribute (bisher 25)
  • Neue Javascript Bibliotheken: Oracle JET 15.0.0, jQuery 3.6.4, jQuery Migrate 3.4.1, FullCalendar 6.1.8, MarkedJS 5.1.2, DOMPurify 3.0.5, Terser 5.19.2, and TinyMCE 6.6.1


Für eine genauere Beschreibung der neuen Funktion in Oracle APEX empfehlen wir natürlich einen unserer (inzwischen 8 verschiedenen) APEX Kurse 
(z.B. den APEX New Features Kurs, dieser wird gerade für APEX 23.2 überarbeitet)



Weitere Interessente Artikel zum Thema:


Empfohlene Schulungen zum Thema:


OAUTH2 Authentifizierung mit ORDS 23.1.4 in APEX 23.1

Bereich:APEX:REST, Version: ab APEX 23.1, Letzte Überarbeitung: 05.07.2023

Keywords:OAUTH2, APEX, REST

Als wir auf die Oracle APEX 23.1 Version upgegraded haben, gingen plötzlich unsere REST Authentifizierungen mittels Basic Authent nicht mehr.

Also die richtige Zeit auf etwas neueres zu wechseln, und damit auf OAUTH2.

Vorbereitungen auf der Server Seite:

Wir erstellen einen Client, der sich dann am REST Webservice anmelden soll/darf.

BEGIN 
 OAUTH.create_client( 
    p_name           => 'ora_rest_client', 
    p_grant_type     => 'client_credentials', 
    p_owner          => 'MUSO_REST', 
    p_support_email  => 'info@muniqsoft-training.de', 
    p_privilege_names=> 'muso_rest_priv' ); 
COMMIT; 
END; 
/

Wir verbinden den Client mit der Rolle, die unser Modul schützt. (z.B. i
Hinweis: Wenn Sie es noch nicht erledigt haben, dann erstellen Sie sich bitte eine REST Rolle (z.B. in APEX unter SQL Workshop / Restful Services) und erzeugen zusätzlich ein Privileg, dass die Rolle mit den gewünschten Modulen Verbindet


BEGIN
 OAUTH.grant_client_role(
   p_client_name => 'ora_rest_client',
   p_role_name   => 'muso_role'
 );
COMMIT;
END;
/

Nun können Sie ermitteln, welche Client ID und welches Secret zur Verfügung gestellt werden. 

SELECT id, name, client_id, client_secret 
FROM user_ords_clients;
=> 1,ora_rest_client,YYY..,ZZZ..

Diese beiden Informationen setzen Sie bitte im nächsten Select ein.
Wenn der REST Service via SSL angesprochen wird (sehr zu empfehlen!!!!), dann brauchen Sie auch noch das Zertifikat vom Server, 
dass Sie dann in Ihr lokales Wallet einspielen müssen.
Das Wallet wird mit einem Passwort gesichert, dass hier im Parameter l_wallet_pwd angegeben werden kann. Auch der Pfad zum Wallet wird benötigt. 
Er sollte existieren und Oracle sollte wenigstens Leserechte auf dem Ordner besitzen

WITH FUNCTION get_rest (rest_path IN VARCHAR2) RETURN CLOB
IS
  l_wallet_path     VARCHAR2(255):='file:/opt/oracle/admin/XE/https_wallet';
  l_wallet_pwd      VARCHAR2(255):='XXX';
  l_client_id       VARCHAR2(255):='YYY..';
  l_client_secret   VARCHAR2(255):='ZZZ..';
  l_base_url        VARCHAR2(255):='https://www.muniqsoft-training.de/ords/oracle/muso_training/';
  l_clob    clob; 
WITH FUNCTION get_rest (rest_path IN VARCHAR2) RETURN CLOB
IS
  l_wallet_path     VARCHAR2(255):='file:/opt/oracle/admin/XE/https_wallet';
  l_wallet_pwd      VARCHAR2(255):='XXX';
  l_client_id       VARCHAR2(255):='YYY..';
  l_client_secret   VARCHAR2(255):='ZZZ..';
  l_base_url        VARCHAR2(255):='https://www.muniqsoft-training.de/ords/oracle/muso_training/';
  l_clob    clob; 
  
BEGIN
  -- Token holen
  apex_web_service.oauth_authenticate(
        p_token_url     => l_base_url||'oauth/token',
        p_client_id     => l_client_id,
        p_client_secret => l_client_secret,
        p_wallet_path   => l_wallet_path,
		p_wallet_pwd    => l_wallet_pwd );  
 
  -- Request Authorization header setzen
  apex_web_service.g_request_headers.delete();
  apex_web_service.g_request_headers(1).name  := 'Authorization';
  apex_web_service.g_request_headers(1).value := 'Bearer ' || apex_web_service.oauth_get_last_token;
  -- REst Request absetzen:
  l_clob := apex_web_service.make_rest_request (
                p_url         => l_base_url||rest_path, 
                p_http_method => 'GET',
				p_wallet_path => l_wallet_path,
				p_wallet_pwd  => l_wallet_pwd);
 
RETURN l_clob;
END; 
SELECT get_rest('/muso/getTabCount') FROM dual;


Weitere Interessente Artikel zum Thema:


Empfohlene Schulungen zum Thema:


Export Private Reports einen interactive Report in APEX

Bereich:APEX, Version: ab APEX 22.1, Letzte Überarbeitung: 17.12.2022

Keywords:Interactiver Report, Apex private Report

Wenn Sie eine Seite mit private Reports exportieren möchten, gibt es da einen Trick:
 

1. Exportieren Sie die komplette Applikation. Wählen Sie aber bitte an:
a, [x] Split into Multiple Files
b, optional [X] Export Public Reports
c, [X] Export Private Reports
2. Nun wird ein Zip File exportiert, das Sie bitte entpacken.
3. Nun gehen Sie in SQL*Plus oder SQL*Developer und starten bitte folgende Skripte
a, f??? (??? für Ihre App ID) / Application / set_environment.sql
b, f??? / Application / Pages / page_00??.sql für alle Seiten die Sie mit interakiven Report mit Public und/oder Private Reports wieder einspielen möchten
c, f??? / Application / end_environment.sql


FERTIG, alle gewünschten Seiten mit interactiven Report sind wieder in Ihrer Applikation

 



Weitere Interessente Artikel zum Thema:


Empfohlene Schulungen zum Thema:


Installation der Oracle 23c FREE Edition auf Rocky Linux mit APEX 22.2 und ORDS 23.1

Bereich:APEX, Version: ab APEX 22.2:ORDS 23.1, Letzte Überarbeitung: 14.08.2023

Keywords:Rocky Linux, Oracle 23c, Free Edition, APEX Installation

Als vor zwei Wochen die Oracle Version 23c FREE Edition herauskam, waren wir sehr (positiv) überracht, dass die kostenlose Version vor der Produktiv Version veröffentlicht wurde.
Es wurde also mal wieder Zeit einen Artikel für die jeweils neusten Oracle Versionen zu schreiben. et voila …

Wir installieren auf einem Server mit der Ip Adresse 172.30.30.99. Sie können natürlich eine andere IP Adresse wählen, sollten dann aber an allen Stellen wo wir diese IP verwenden Ihre eintragen.
Da man ja seit Version Oracle 21c nun mit Pluggable Database Containern arbeiten muss, verwenden wir hier den Container apex222. Auch den können Sie natürlich umbenennen.

Wir empfehlen mit mindestens 2 SSH Sessions parallel zu arbeiten um die Zeit drastisch zu verkürzen.
Wir nennen im folgenden die beiden Sessions SES_1 und SES_2. Bitte lesen Sie die folgenden Schritte zuerst komplett durch
weil einige Punkte weiter unten zusammengefasst werden :-)

1. Redhat 8 / Centos 8 / Rocky 8 Preinstall Packages für Oracle 23c herunterladen:

https://yum.oracle.com/repo/OracleLinux/OL8/developer/x86_64/getPackage/oracle-database-preinstall-23c-1.0-0.5.el8.x86_64.rpm

2. FREE Edition herunterladen
https://download.oracle.com/otn-pub/otn_software/db-free/oracle-database-free-23c-1.0-1.el8.x86_64.rpm

3. Wir benennen den Pluggable Database Container um( muss man nicht, wenn man mit dem Namen freepdb1 zufrieden ist)

ALTER PLUGGABLE DATABASE freepdb1 CLOSE;
ALTER PLUGGABLE DATABASE freepdb1 OPEN RESTRICTED;
ALTER SESSION SET CONTAINER=freepdb1;
ALTER PLUGGABLE DATABASE RENAME GLOBAL_NAME TO apex222;


Laden Sie APEX 22.2 (oder neuer) herunter:
https://download.oracle.com/otn_software/apex/apex_22.2.zip

Laden Sie den neusten Patch für APEX herunter (dazu ist ein gültiger Support-Vertrag mit Oracle notwendig):
https://support.oracle.com/epmos/faces/PatchDetail?patchId=34628174

Laden Sie die ORDS-Version herunter (April 2023 war Version 23.1.1 aktuell):
https://download.oracle.com/otn_software/java/ords/ords-23.1.1.109.1003.zip

Laden Sie die neueste Apache TomCat 9 Version herunter. Version 10 wird aktuell (01.05.2023) nicht von ORDS unterstützt:
https://dlcdn.apache.org/tomcat/tomcat-9/v9.0.74/bin/apache-tomcat-9.0.74.zip

Session SES_1
dnf -y install wget
dnf -y update

Download Skript für alle Dateien (bis auf Patch, da müssen Sie beim Support angemeldet sein) in SES_2:

mkdir -p /tmp/oracle
cd /tmp/oracle
wget https://yum.oracle.com/repo/OracleLinux/OL8/developer/x86_64/getPackage/oracle-database-preinstall-23c-1.0-0.5.el8.x86_64.rpm
wget https://download.oracle.com/otn-pub/otn_software/db-free/oracle-database-free-23c-1.0-1.el8.x86_64.rpm
wget https://download.oracle.com/java/17/latest/jdk-17_linux-x64_bin.rpm
wget https://download.oracle.com/otn_software/apex/apex_22.2.zip
wget https://download.oracle.com/otn_software/java/ords/ords-23.1.1.109.1003.zip
wget https://dlcdn.apache.org/tomcat/tomcat-9/v9.0.74/bin/apache-tomcat-9.0.74.zip

 

Nun kann mit der Installation der in SES_2 heruntergeladenen Programme begonnen werden

Session SES_1:

dnf -y install oracle-database-preinstall-23c*
dnf -y localinstall oracle-database-free-23c*
export DB_PASSWORD=mein_password_fuer_2023
(echo "${DB_PASSWORD}"; echo "${DB_PASSWORD}";) | /etc/init.d/oracle-free-23c configure

In der Datei /etc/oratab die Datenbank auf Autostart (N durch Y in der letzten Zeile am Ende ersetzen)

FREE:/opt/oracle/product/23c/dbhomeFree:Y

Wenn die Oracle Datenbank Instanz und der Oracle Listener beim Start des Betriebssystem mitstarten sollen:

systemctl enable oracle-free-23c

Wenn Oracle DB + Listener manuell gestoppt und gestartet werden sollen:

systemctl stop oracle-free-23c
systemctl start oracle-free-23c

Wenn Ihnen der Name oracle-free-23 zulange ist, können Sie auch stattdessen “oracle”als Servicename einrichten

Kopieren Sie dazu nur die Datei /etc/rc.d/init.d/oracle-free-23c in die Datei oracle um:

cp /etc/rc.d/init.d/oracle-free-23c /etc/rc.d/init.d/oracle

... dauert wieder ein paar Minuten .. wir wechseln in SES_2

Session SES_2:

mkdir -p /opt/tomcat
mv apache-tomcat-9.0.74.zip /opt/tomcat/
cd /opt/tomcat
unzip apache*
ln -s apache-tomcat-9.* latest
useradd -r tomcat --shell /bin/false
chown -R tomcat /opt/tomcat
chmod +x /opt/tomcat/latest/bin/*.sh
# Passen Sie die Firewall an Ihre Bedürfnisse an. Hier werden in Zone Public einige Ports freigegeben
firewall-cmd --zone=public --permanent --add-port=1521/tcp
firewall-cmd --zone=public --permanent --add-service=https
firewall-cmd --zone=public --permanent --add-service=http
firewall-cmd --zone=public --permanent --add-port 8080/tcp
firewall-cmd --reload

dnf -y localinstall jdk-17*
java -version
which java

Datei anlegen zum Autostart von TomCat
vi /etc/systemd/system/tomcat.service

[Unit]
Description=Tomcat 9 servlet container
After=network.target
[Service]
Type=forking
User=tomcat
Group=tomcat
Environment="JAVA_HOME=/usr"
Environment="JAVA_OPTS=-Djava.security.egd=file:///dev/urandom -Dconfig.url=/opt/oracle/ords"
Environment="CATALINA_BASE=/opt/tomcat/latest"
Environment="CATALINA_HOME=/opt/tomcat/latest"
Environment="CATALINA_PID=/opt/tomcat/latest/temp/tomcat.pid"
Environment="CATALINA_OPTS=-Xms512M -Xmx1024M -server -XX:+UseParallelGC"
ExecStart=/opt/tomcat/latest/bin/startup.sh
ExecStop=/opt/tomcat/latest/bin/shutdown.sh
[Install]
WantedBy=multi-user.target

Tomcat als Autostart einrichten

systemctl daemon-reload
systemctl enable tomcat
systemctl start tomcat
systemctl status tomcat

 

Bash Profile für Oracle Benutzer anlegen:

cat << EOF > /home/oracle/.bash_profile
export TERM=vt220
export EDITOR=vi
export PS1="[\u@\h:\w]>"
export DISPLAY=:0.0
export ORACLE_BASE=/opt/oracle
export ORACLE_HOME=\$ORACLE_BASE/product/23c/dbhomeFree
export ORACLE_SID=FREE
export ORACLE_INSTANCE=free
export ORACLE_TERM=vt220
export ORA_NLS10=\$ORACLE_HOME/nls/data
export LD_LIBRARY_PATH=\$LD_LIBRARY_PATH:\$ORACLE_HOME/lib
export NLS_LANG=GERMAN_GERMANY.WE8MSWIN1252
export PATH=\$ORACLE_HOME/bin:\$PATH:/usr/sbin:/usr/ccs/bin

alias cdo="cd \$ORACLE_HOME; pwd"
alias cdd="cd \$ORACLE_BASE/oradata"
alias cda="cd \$ORACLE_BASE/diag/rdbms/\$ORACLE_INSTANCE/\$ORACLE_SID/trace; pwd"
alias cdn="cd \$ORACLE_HOME/network/admin; pwd"
alias cde="cd \$ORACLE_BASE/admin/\$ORACLE_SID/dpdump"
alias sp="\$ORACLE_HOME/bin/sqlplus '/ as sysdba'"
alias l="ls -l"
alias ll="ls -la"
alias ipconfig="/sbin/ifconfig | grep Bcast"
echo Folgende Einstellungen wurden gesetzt:
env | grep ORA
ps aux | grep [t]omcat | awk '{print "Tomcat-Prozess:" \$2}'
ps aux | grep [d]b_pmon | awk '{print "Oracle-Prozess:" \$2}'
ps aux | grep [t]ns | awk '{print "Listener-Prozess:" \$2}'
EOF
. .bash_profile

APEX und ORDS auspacken:

cd /tmp/oracle
unzip apex_22*
chown -R oracle:oinstall apex*
mkdir ords
unzip ords-2*.zip -d ords

Session SES_1

APEX muss in der anderen Session bereits ausgepackt worden sein!

su - oracle

 

REM Bei uns wurde bei der Installation ein exotischer Port für den Listener benutzt. 
Wenn Sie den Oracle Standard-Port 1521 wieder möchten, ersetzen Sie ihn in der Datei listener.ora

lsnrctl stop
IP=$(hostname -I)

 

cat << EOF >$ORACLE_HOME/network/admin/listener.ora
# listener.ora Network Configuration File: /opt/oracle/product/23c/dbhomeFree/network/admin/listener.ora
# Generated by Oracle configuration tools.
DEFAULT_SERVICE_LISTENER = FREE
LISTENER =
 (DESCRIPTION_LIST =
   (DESCRIPTION =
     (ADDRESS = (PROTOCOL = TCP)(HOST = \$IP)(PORT = 1521))
   )
 )
EOF

Nun wird APEX installiert. Hier können verschiedene Passwörter für die Oracle APEX Benutzer gesetzt werden. Wir haben aber bis auf den Internal Workspace Admin Benutzer
das gleiche Passwort gesetzt.

Auch kann ein eigener Tablespace für die Installation verwendet werden. Wir haben hier APEX jedoch in den Tablespace SYSAUX installiert.

lsnrctl start
cd /tmp/oracle/apex
cat << EOF >preinstall.sql
alter system set local_listener='(ADDRESS = (PROTOCOL = TCP)(HOST = \$IP)(PORT = 1521))';
alter system register;
host lsnrctl status
define pwd_apx=apex
define pwd_ws_int=Apex2023#
@apxsilentins.sql SYSAUX SYSAUX TEMP /i222/ &pwd_apx. &pwd_apx. &pwd_apx. &pwd_ws_int.
EOF
sqlplus sys/sys@172.30.30.99/apex222 as sysdba
@preinstall.sql

Während die APEX Installation läuft, kann wieder in die andere Session gewechselt werden, dort installieren wir den ORDS…

cd /tmp/oracle/ords
bin/ords --config /opt/oracle install
[2] Datenbankpool erstellen oder aktualisieren ...
[1] Basis (Hostname, Port, Servicename)
=> 172.30.30.99
=> 1521
=> apex222
=> sys
=> <Ihr sys-pwd>
=> SYSAUX
=> TEMP
[1] Datenbankaktionen (aktiviert alle Features)
[2] Überspringen

Nun kopieren wir den ORDS in den TomCat Ordner:

cp ords.war /opt/tomcat/latest/webapps/

Dateien von APEX auch in den TomCat Ordner verschieben:

mv /tmp/oracle/apex/images/ /opt/tomcat/latest/webapps/i222

So, das war´s. gar nicht so schwer, oder ? :-)

Wenn man mit zwei Sessions arbeitet und in keine Probleme läuft, sollte das in ca. einer Stunde erledigt sein.

Bonus-Track:

Apache TomCat hat leider keine Redirect Funktion, dazu braucht man den Apache Webserver. Aber Sie können mit einem kleinen Trick dafür sorgen, dass Sie gleich auf Ihre Lieblingsapp weitergeleitet werden, sobald Sie die folgende URL eingeben:

http://172.30.30.99:8080

Wir machen dazu einfach einen Refresh als Meta-Tag auf die Datei index.html

cp /opt/tomcat/latest/webapps/ROOT/index.html /opt/tomcat/latest/webapps/ROOT/index.html.old
echo '<html><head><meta http-equiv="refresh" content="0; url=http://172.30.30.99:8080/ords/f?p=100" /></head></html>'>/opt/tomcat/latest/webapps/ROOT/index.html

oder wenn Sie TEST-Maschine haben und kein Problem damit haben, dass Ihr Password im Klartext in einer Datei steht…. können Sie die Anmeldedaten für den Applikation Builder bereits eintragen

echo '<html><head><meta http-equiv="refresh" content="0; url=http://172.30.30.100:8080/ords/f?p=4550:1:1::::F4550_P1_COMPANY,F4550_P1_USERNAME,F4550_P1_PASSWORD:schulung,admin,ganzschöngeheim2023" /></head></html>'>/opt/tomcat/latest/webapps/ROOT/index.html

Hier sind eingetragen:

Workspace-Name (F4550_P1_COMPANY) = schulung
Username (F4550_P1_USERNAME) = admin
Password: (F4550_P1_PASSWORD) = ganzschöngeheim2023

Das sollte natürlich von Ihnen angepasst werden :-)

Rufen Sie nun im Browser die Seite http://172.30.30.99:8080/ords auf bzw. wenn der Bonustrack installiert wurde: http://172.30.30.99:8080

Bonus-Bonus-Track:

Unter Windows können Sie auch gleich eine Portweiterleitung einrichten, dann wird Port 80 auf Port 8080 weitergeleitet. Dies geschieht (als Administrator) mit:

netsh interface portproxy add v4tov4 listenaddress=172.30.30.99 listenport=80 connectaddress=172.30.30.99 connectport=8080

Dann lautet der Aufruf nur noch:

http://172.30.30.99

und dann besuchen Sie uns doch bald mal in einer von unseren 48 verschiedenen Oracle Schulungen in München-Unterhaching :-)

 



Weitere Interessente Artikel zum Thema:


Empfohlene Schulungen zum Thema:


Oracle APEX Interactive Grid Javascript Snippets

Bereich:APEX, Version: ab APEX 22.2:APEX 23.1, Letzte Überarbeitung: 20.09.2023

Keywords:APEX Javascript, Grid , Interactive Grid

In unseren Schulungen werden immer mal Fragen zum Interactiven Grid gestellt, die sehr interessant sind. Hier eine kleine Auswahl:

Vorraussetungen:

  1. Es gibt ein Grid auf die Scott.emp Tabelle mit der Static ID EMP
  2. Es gibt eine Selectbox mit Namen P1_JOB

 

  1. Es soll im Grid für die EMP Tabelle, der Job für alle Mitarbeiter auf einen einheitlichen Wert gesetzt werden, der in einem Item ausserhalb des Grids steht:
var model = apex.region("EMP").widget().interactiveGrid("getViews", "grid").model;
    model.forEach(function(r) {
       model.setValue(r, "JOB", $v("P1_JOB" )); // Setzen des Jobs pro Zeile
    })

2. Es sollen nur die mit der im Grid enthaltenen Checkbox (Spalte 1) ausgewählten Einträge geändert werden:

var grid = apex.region("EMP").widget().interactiveGrid("getViews","grid");
var model   = grid.model;
var selectedRecords = grid.getSelectedRecords();
//console.log("Records" +selectedRecords.length);
for (idx = 0; idx < selectedRecords.length; idx++) {
   record = model.getRecord(selectedRecords[idx][0]); 
     model.setValue(record, "JOB", $v( "P1_JOB" ));
    //console.log(idx+ " " + selectedRecords[idx][1] ); //Felder [1] EMPNO [2] ENAME, [3] JOB ...
}

3. Sie möchten das zurückschreiben in die DB selbst erledigen, kein Problem. Ersetzen Sie den Prozeß durch:

IF :APEX$ROW_STATUS='C' THEN
    INSERT INTO emp (empno,ename,job,mgr,hiredate,sal,comm,deptno)
    VALUES (:EMPNO,:ENAME,:JOB,:MGR,:HIREDATE,:SAL,:COMM,:DEPTNO);
ELSIF :APEX$ROW_STATUS='U' THEN
    UPDATE emp SET
    ename=:ENAME,job=:JOB, mgr=:MGR,hiredate=:HIREDATE ,sal=:SAL,comm=:COMM, deptno=:DEPTNO
    WHERE empno=:EMPNO ;
ELSIF :APEX$ROW_STATUS='D' THEN
    DELETE FROM emp
    WHERE empno=:EMPNO;
END IF;

Das war ein kleiner Auszug aus den vielen Fragen in unseren APEX Kursen. Sie haben auch Fragen? Dann kommen Sie doch in einen unserer Kurse…. wir freuen uns auf Sie !



Weitere Interessente Artikel zum Thema:


Empfohlene Schulungen zum Thema:


Oracle ORDS 22.x Installation und Fehlerbehebung / ORDS Troubleshooting

Bereich:APEX:ORDS, Version: ab ORDS 22.2:ORDS 23.1:ORDS 23.2, Letzte Überarbeitung: 12.03.2024

Keywords:Oracle, ORDS 22.x/23.x , Installation

Seit einiger Zeit  ist die neue Oracle ORDS Version 23.x zum Download verfügbar. 
Wie heisst ein berühmtes Zitat: Mann muss in einem System jeden Fehler gemacht haben um das System verstanden zu haben.         
Na dann sind wir kurz davor alles zu wissen :-) …

  1. Installation
  2. Prüfung im OS
  3. Silent Installation (Unix)
  4. Weitere Datenbank in ORDS eintragen (Unix)
  5. Silent Installation (Win)
  6. Zusätzliche Datenbank in ORDS eintragen (win)
  7. Prüfungen Im Betriebssystem
  8. Prüfungen in der Datenbank
  9. Gängige Fehler des ORDS

1. Installation

Laden Sie die Software von Oracle herunter und packen Sie das ZIP File in einem eigenen Ordner aus.      

 

2. Prüfung im OS

   
Prüfen Sie nun Ihre installierte Java Version:

Unix / Linux

java --version
    java 11.0.16.1 2022-08-18 LTS
    Java(TM) SE Runtime Environment 18.9 (build 11.0.16.1+1-LTS-1)
    Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.16.1+1-LTS-1, mixed mode)
                                    

Das sieht gut aus … OpenJDK wird offiziell von Oracle nicht unterstützt und kann Probleme verursachen! Verwenden Sie Java 11 oder Java 17

Windows:

java.exe --version
    openjdk 11 2018-09-25
    OpenJDK Runtime Environment 18.9 (build 11+28)
    OpenJDK 64-Bit Server VM 18.9 (build 11+28, mixed mode)

Das ist schlecht, weil Oracle unterstützt wie gesagt keine Java OpenJDK Version. KEINE !         
Es kann funktionieren, bei uns trat meist ein Webserver Fehler 500 auf (ohne große Begründung)         
Unterstützt werden nur die Oracle Java Versionen 11 und 17.

Nach erfolgreicher Installation der Oracle Java Version gehen Sie in den ausgepackten Ordner (z.B. cd c:\temp\ords)

Dort sollte ein “bin” Ordner liegen und da drin eine ords.exe und eine ords Datei

Tragen Sie Java in Ihren Pfad ein:

Windows:

set PATH=%PATH%;"C:\Program Files\Java\jdk-11\bin"

UNIX:

export PATH=$PATH:/usr/bin/

Wenn Java in Ihrem Pfad eingetragen wurde, starten Sie die Installation mit:

Windows:
    bin/ords.exe --config c:\oracle\ords install

Tipp: Sie sollten auch nach der Installation des Ords das “bin” Verzeichnis des ORDS und die Datei ords.war nicht wegwerfen. Für nachtägliche Wartungsarbeiten benötigt man die Dateien eventuell nochmal. 
Sie können die Dateien z.B in den Hauptordner des Config-Verzeichnisses kopieren, also z.B. C:\oracle\ords für Windows, oder /opt/oracle für Linux.

Ab ORDS Version 22.2.x wird der Pfad für den Config Ordner beim Tomcat unter UNIX im Service File eingetragen:

cat /etc/systemd/system/tomcat.service:

…
    Environment="JAVA_HOME=/usr/lib/jvm/jre"
    Environment="JAVA_OPTS=-Djava.security.egd=file:///dev/urandom -Dconfig.url=/opt/oracle/ords"
…

 

Windows (wird im Tomcat (tomcat9w.exe) Eigenschaftsfenster Reiter “Java” im Bereich “Java Options” (nicht “Java 9 Options” !!!) eingetragen)

-Dconfig.url=c:\oracle\ords

Unix/Linux:

 bin/ords --config /opt/oracle/ords install

Interaktion mit dem Skript:

# bin/ords --config /opt/oracle/ords install
    ORDS: Release 23.4 Produktion am Mi. Dez 15 06:49:08 2023
    Copyright (c) 2010, 2023, Oracle.
    Konfiguration:/opt/oracle/ords/
    Der Konfigurationsordner /opt/oracle/ords enthält keine Konfigurationsdateien.
    Oracle REST Data Services - Interaktive Installation
    Geben Sie eine Zahl zur Auswahl des Installationstyps ein
    [1] ORDS nur in der Datenbank installieren oder upgraden
    [2] Datenbankpool erstellen oder aktualisieren und ORDS in der Datenbank installieren/upgraden
    [3] Nur Datenbankpool erstellen oder aktualisieren
    Choose [2]:
    Geben Sie eine Zahl zur Auswahl des zu verwendenden Datenbankverbindungstyps ein
    [1] Basis (Hostname, Port, Servicename)
    [2] TNS (TNS-Alias, TNS-Verzeichnis)
    [3] Benutzerdefinierte Datenbank-URL
    Choose [1]:
    Geben Sie den Hostnamen der Datenbank ein [localhost]: 172.30.30.141
    Listener-Port der Datenbank eingeben [1521]:
    Datenbankservicename eingeben [orcl]: apex222
    Geben Sie einen Datenbankbenutzernamen mit Administratorberechtigungen an.
    Geben Sie den Administratorbenutzernamen ein: sys
    Datenbankkennwort für SYS AS SYSDBA eingeben:
    Verbindung zu Datenbankbenutzer: SYS AS SYSDBA URL: jdbc:oracle:thin:@//172.30.30.141:1521/apex222 wird hergestellt
    Informationen werden abgerufen.
    Geben Sie den Default Tablespace für ORDS_METADATA und ORDS_PUBLIC_USER ein [SYSAUX]:
    Geben Sie den Temporary Tablespace für ORDS_METADATA und ORDS_PUBLIC_USER ein [TEMP]:
    Geben Sie eine Zahl ein, um zusätzliche Features zum Aktivieren auszuwählen:
     [1] Datenbankaktionen (aktiviert alle Features)
     [2] REST-fähige SQL und Datenbank-API
     [3] REST-fähige SQL
     [4] Datenbank-API
     [5] Kein Wert
    Choose [1]:
     Geben Sie eine Zahl zum Konfigurieren und Starten von ORDS im Standalone-Modus ein
     [1] ORDS im Standalone-Modus konfigurieren und starten
     [2] Überspringen
     Choose [1]: 2
     …
     INFO: 08:19:07 Validating objects for Oracle REST Data Services.
     VALIDATION: 08:19:07 Starting validation for schema: ORDS_METADATA
     VALIDATION: 08:19:07 Validating objects
     VALIDATION: 08:19:08 Validating roles granted to ORDS_METADATA and
     ORDS_PUBLIC_USER
     VALIDATION: 08:19:08 Validating ORDS Public Synonyms
     VALIDATION: 08:19:08 Total objects: 306, invalid objects: 0, missing objects: 0
     VALIDATION: 08:19:08     94  INDEX
     VALIDATION: 08:19:08      3  LOB
     VALIDATION: 08:19:08     15  PACKAGE
     VALIDATION: 08:19:08     14  PACKAGE BODY
     VALIDATION: 08:19:08      1  PROCEDURE
     VALIDATION: 08:19:08     52  PUBLIC SYNONYM
     VALIDATION: 08:19:08      1  SEQUENCE
     VALIDATION: 08:19:08     32  TABLE
     VALIDATION: 08:19:08     32  TRIGGER
     VALIDATION: 08:19:08     20  TYPE
     VALIDATION: 08:19:08      6  TYPE BODY
     VALIDATION: 08:19:08     36  VIEW
     VALIDATION: 08:19:08 Validation completed.
     INFO: 08:19:08 Completed validation for Oracle REST Data Services.
     PL/SQL-Prozedur erfolgreich abgeschlossen.
     Commit abgeschlossen.
     ------------------------------------------------------------
     Containername: APEX222
     Skripts für scheduler werden ausgeführt
     ------------------------------------------------------------
     …
     PL/SQL-Prozedur erfolgreich abgeschlossen.
     Commit abgeschlossen.
     2023-03-15T07:19:15.030Z INFO        Installation für Oracle REST Data Services Version 22.4.4.r0411526 wurde abgeschlossen. Verstrichene Zeit: 00:00:27.496
     [*** Informationen: Installation für Oracle REST Data Services Version 22.4.4.r0411526 wurde abgeschlossen. Verstrichene Zeit: 00:00:27.496
     ]
     ------------------------------------------------------------
     Containername: APEX222
     ------------------------------------------------------------
     [*** script: ords_configure_gateway.sql]
     Configured PL/SQL Gateway user APEX_PUBLIC_USER to be proxiable from
     ORDS_PUBLIC_USER
     PL/SQL-Prozedur erfolgreich abgeschlossen.
     2023-03-15T07:19:15.130Z INFO        Konfiguration von PL/SQL-Gatewaybenutzer für Oracle REST Data Services Version 22.4.4.r0411526 wurde abgeschlossen. Verstrichene Zeit: 00:00:00.95
     [*** Informationen: Konfiguration von PL/SQL-Gatewaybenutzer für Oracle REST Data Services Version 22.4.4.r0411526 wurde abgeschlossen. Verstrichene Zeit: 00:00:00.95
     ]

3. Silent Installation (Unix)

export DB_PORT=1521
    export DB_SERVICE=apex231
    export SYSDBA_USER=SYS
    export SYSDBA_PASSWORD=sys
    export ORDS_PASSWORD=ords
    export ORDS_HOME=/opt/oracle/ords
    export ORDS_CONFIG=/opt/oracle/ords
    export ORDS_LOGS=$ORDS_CONFIG/logs
    export PATH=$PATH:$ORDS_HOME/bin
ords --config $ORDS_CONFIG install \
    --log-folder $ORDS_LOGS \
    --admin-user $SYSDBA_USER \
    --db-hostname 127.0.0.1 \
    --db-port $DB_PORT \
    --feature-db-api true \ 
    --feature-rest-enabled-sql true \
    --feature-sdw true \
    --gateway-mode proxied \
    --gateway-user APEX_PUBLIC_USER \
    --proxy-user 

Zugriff dann im Browser via: http:server:8080/ords

4. oder neue Datenbank bzw. Alias zusätzlich in ORDS (Unix) eintragen:

ords --config $ORDS_CONFIG install \
    --db-pool $DB_SERVICE \
    --admin-user $SYSDBA_USER \
    --db-hostname 127.0.0.1 \
    --db-port $DB_PORT \
    --db-servicename $DB_SERVICE \
    --feature-db-api true \ 
    --feature-rest-enabled-sql true \
    --feature-sdw true \
    --gateway-mode proxied \
    --gateway-user APEX_PUBLIC_USER \
    --proxy-user 
     Zugriff dann via: http:server:8080/ords/$DB_SERVICE

5. Silent Installation unter Windows:

set DB_PORT=1521
    set DB_SERVICE=apex231
    set SYSDBA_USER=SYS
    set SYSDBA_PASSWORD=sys
    set ORDS_PASSWORD=ords
    set ORDS_HOME=c:\oracle\ords
    set ORDS_CONFIG=c:\oracle\ords
    set ORDS_LOGS=%ORDS_CONFIG%\logs
    set PATH=%PATH%;%ORDS_HOME%\bin
ords --config %ORDS_CONFIG% install ^ 
    --log-folder %ORDS_LOGS% ^
    --admin-user %SYSDBA_USER% ^
    --db-hostname 127.0.0.1 ^
    --db-port %DB_PORT% ^
    --db-servicename %DB_SERVICE% ^
    --feature-db-api true ^
    --feature-rest-enabled-sql true ^
    --feature-sdw true ^
    --gateway-mode proxied ^
    --gateway-user APEX_PUBLIC_USER ^
    --proxy-user 
    

6. Zusätzliche Datenbank oder Alias in ORDS eintragen (Windows)

ords --config %ORDS_CONFIG% install ^ 
    --log-folder %ORDS_LOGS% ^
    --db-pool %DB_SERVICE% ^
    --admin-user %SYSDBA_USER% ^
    --db-hostname 127.0.0.1 ^
    --db-port %DB_PORT% ^
    --db-servicename %DB_SERVICE% ^
    --feature-db-api true ^
    --feature-rest-enabled-sql true ^
    --feature-sdw true ^
    --gateway-mode proxied ^
    --gateway-user APEX_PUBLIC_USER ^
    --proxy-user 
    Zugriff dann im Browser via: http:server:80/ords/%DB_SERVICE%
    Hinweis: der Tomcat Dienst benötigt Leserechte im ORDS Config Verzeichnis !!!
    icacls %ORDS_CONFIG% /T /grant Benutzer:R

7. Prüfung im OS

Wir oben beschrieben muss die richtige Java Version installiert worden sein (Oracle Java 11 oder 17)         
Kann der config Ordner von Oracle/Tomcat Benutzer gelesen werden? Wenn nicht bitte Lese/Schreibrechte an die Dateien vergeben.

 

8. Prüfung in der Datenbank

Sind alle notwendigen Accounts NICHT gesperrt und stimmt das Passwort ?

select username,account_status,lock_date,expiry_date
    from dba_users
    where username like '%PUBLIC%';
    USERNAME                 ACCOUNT_STATUS     LOCK_DATE           EXPIRY_DATE        
    ------------------------ ------------------ ------------------- -------------------
    APEX_PUBLIC_USER         LOCKED             15.03.2023 07:57:59                    
    APEX_REST_PUBLIC_USER    OPEN                                   11.09.2024 08:08:32

Das schaut hier nicht gut aus, der Benutzer APEX_PUBLIC_USER ist gesperrt!.

Entsperren mittels:

ALTER USER apex_public_user ACCOUNT UNLOCK IDENTIFIED BY <mein_geheimes_passwort>;

Danach starten wir dem TomCat nochmal durch.

Windows:

net stop TomCat9
net start TomCat9

Für den Fall, dass Sie das Passwort vom ORDS_PUBLIC_USER in der DB geändert haben und das im ORDS nachtragen möchten:

Für den Default Pool: (wenn der Config Ordner unter /opt/oracle/ords liegt)

ords --config /opt/oracle/ords config --db-pool default secret db.password

Für einen anderen Pool (hier apex231)

ords --config /opt/oracle/ords config --db-pool apex231 secret db.password

 

Fehlermeldung: Benutzer oder Kennwort für den Verbindungspool namens |default|lo| ist ungültig oder abgelaufen, oder der Account wurde gesperrt 

Die naheliegenden Lösungen wären natürlich:

  • Passwort falsch
  • Account abgelaufen

aber in unserem Fall war die Datenbank (pluggable Database Container) im restricted Modus:

Die Lösung war:

alter pluggable database <containername> close immediate;
alter pluggable database <containername> open;

 

Fehlermeldung: Service Unavailable

ORDS_Fehler_503.jpeg

HTTP Status Code: 503

Request ID: bI7hBYBLvXJ1aZXhH61iMA

Request Timestamp: 2023-10-21T08:58:05.233483445Z

Das Datenbankkennwort-Secret fehlt in dem mit dem Pool |default|lo| verknüpften Wallet


Hier fehlt das Passwort für den ORDS_PUBLIC_USER, oder es ist veraltet oder abgelaufen. 
Die Lösung unter LINUX ist, das Wallet mit dem Passwort neu anzulegen mittels:

cd /opt/oracle/ords
    REM dort liegt der Ordner bin aus der Installtion des ORDS!, wenn nicht, gehen Sie bitte in den entsprechenden Ordner
    sudo bin/ords --config /opt/oracle/ords config secret db.password
    REM zweimal das Passwort eingeben
    REM wenn Sie noch weitere Pools besitzen, muss auch hier das Passwort geöndert werden (Pool-Name apex231)
    sudo bin/ords --config /opt/oracle/ords config --db-pool apex231 secret db.password
    REM TomCat durchstarten
    sudo systemctl restart tomcat

 

Für Windows würde die Lösung so aussehen:

cd c:\oracle\ords
    bin\ords --config c:\oracle\ords config --db-pool default secret db.password
    bin\ords --config c:\oracle\ords config --db-pool apex231 secret db.password

Unsere Ordnerstruckur für den Ords sieht wie folgt aus:

ORDS_Ordner.png

 

Mehr Tipps & Tricks erfahren Sie in unserem Oracle ORDS und im APEX II Kurs. Wir freuen uns auf Sie! 
 



Weitere Interessente Artikel zum Thema:


Empfohlene Schulungen zum Thema:


Informationssystem für APEX-Applikationen

Bereich:APEX, Version: ab APEX 5.x, Letzte Überarbeitung: 26.06.2018

Keywords:APEX

Hatten Sie auch schon einmal den Wunsch, den Anwendern einer Applikation etwas mitzuteilen? Und wäre es nicht manchmal gut, wenn jeder Anwender nachweislich die Information gelesen hat? Die Informationen sollen sofort, also auch in einer laufenden Session, in einem modalen Popup- Fenster angezeigt werden. Dieses Problem stellte sich vor einiger Zeit in einem APEX-Projekt und aus diesem Grund haben wir ein Informationssystem für APEX-Anwendungen entwickelt.

Um die Anforderungen abzudecken brauchen wir im ersten Schritt zwei Tabellen. In der ersten werden die "Nachrichten" gespeichert, in der zweiten die Information, wer wann das Lesen bestätigt hat.

CREATE TABLE INFORMATIONEN
(
  ID          NUMBER,        -- Eindeutige ID, Trigger und Sequence
  APP_ID      NUMBER,        -- Applikations ID der Apexanwendung
  STATUS      CHAR(1),       -- A für aktiv oder I für inaktiv
  INFORMATION VARCHAR2(500), -- Freitext für die Informationsn
  CONSTRAINT PK_INFORMATIONEN PRIMARY KEY (ID)
);

CREATE TABLE INFORMATION_READ
(
  INFO_ID     NUMBER,        -- ID der Information die gelesen wurde  
  APP_USER    VARCHAR2(30),  -- Welcher User hat gelesen
  READ_DATE   DATE           -- Wann wurde gelesen, Trigger mit SYSDATE
);


Der nächste Schritt ist, eine Seite in der Applikation zu erstellen auf der die Informationen angezeigt werden sollen. Als Template wählen wir Popup. Im Bereich "Page HTML Body Attribute" kommt noch folgende Anweisung dazu:

style="background:none;background-image:none;background-color:transparent;padding:0;margin:0;overflow:scroll"


Jetzt sollte man sich auch überlegen wie viele Informationen gleichzeitig angezeigt werden müssen. Entsprechend viele Items müssen erzeugt werden.
Wir benötigen je Info ein "Display only" Item (PX_INFOTEXT_X). Dabei sollte beachtet werden, dass die Eigenschaft "Escape special characters" auf NO steht, dadurch können HTML Formatierungen in den Text integriert werden. Zu jedem Infotext kommt noch eine Checkbox (return 1 when checked), damit können die Nachrichten einzeln bestätigt werden. Infotext und Checkbox werden nur angezeigt, wenn Infotext "NOT NULL" ist. Schließlich fehlt noch je ein Hidden Item zum Speichern der ID und ein Button zum Bestätigen der Seite.

Jetzt fehlen noch zwei Prozesse, der erste "On Load - Before Header" mit dem die Inhalte gefüllt werden:

declare
 v_cnt number := 1;
 v_trenner varchar2(30) := '<p><hr><p>';
begin
 for rec in (select id, information from informationen
               where app_id = :APP_ID and status = 'A'
               and id not in (select info_id
                from information_read where app_user = :APP_USER)
                order by id) loop
  if v_cnt = 1 then
   :PX_ID1 := rec.id;
   :PX_INFOTEXT_1 := rec.information;
  end if;
  if v_cnt = 2 then
   :PX_ID2 := rec.id;
   :PX_INFOTEXT_2 := rec.information;
  end if;
  v_cnt := v_cnt + 1;
 end loop;
end;


Dann kommt der Prozess zum Speichern der Informationen, wenn der Button gedrückt wurde:

begin
 if :PX_CHECK1 = 1 then
  insert into information_read values(:PX_ID1, :APP_USER, SYSDATE);
 end if;
 if :PX_CHECK2 = 1 then
  insert into information_read values(:PX_ID2, :APP_USER, SYSDATE);
 end if;
 :FXXX_HIDE := 'TRUE';
 :FXXX_INFO := '0';
end;


Hier tauchen erstmals die Applikations Items FXXX_HIDE und FXXX_INFO auf. Diese werden für die Steuerung des Infofensters benötigt. Bei Betätigung des Buttons wird auf jeden Fall das Item HIDE auf TRUE gesetzt, damit wird eine weitere Anzeige innerhalb der gleichen Session verhindert. Die Nachrichten können separat bestätigt werden, das heißt der Anwender kann entscheiden, ob sie in der nächsten Session wieder erscheinen sollen.

Nachdem es sich um ein modales Popup-Fenster handelt brauchen wir noch einen Branch, um es nach der Verarbeitung zu schließen. Der Branch Typ ist "Branch to PL/SQL Procedure".

begin
 htp.p('<body>');
 htp.p('<script type="text/java-script">');
 htp.p('parent.$("#modalDialog").dialog("close");');
 htp.p('</script>');
 htp.p('</body>');
end;


Kommen wir nun zur Steuerung. Bedingung war ja, dass es auch in einer laufenden Session erscheinen soll. Dafür müssen wir bei jedem Neuladen einer Seite nachsehen, ob es eine Nachricht gibt die der jeweilige User noch nicht gelesen hat. Weiterhin soll es die Möglichkeit geben, das modale Fenster zu schließen ohne die Nachrichten zu bestätigen. Dafür werden die Applikationsitems FXXX_HIDE und FXXX_INFO angelegt.
Dazu gehört auch ein Applikations Prozess mit dem Zündpunkt "On Load: Before Header".

begin
 select count(*)into :FXXX_INFO
             from informationen
             where app_id = :APP_ID
             and status = 'A'
             and id not in (select info_id from information_read where app_user = :APP_USER);
end;


Jetzt der zentrale Punkt: wann und wie zeige ich das modale Fenster an!

Dazu wird auf der Seite 0 eine "Dynamic Action" mit folgenden Einstellungen angelegt.

When:      Event = Page Load
           Condition = No Condition
Advanced:  Event Scope = once
Condition: Type = PL/SQL Expression
           Expression1 = NVL(:FXXX_HIDE,'F') != 'TRUE' and :FXXX_INFO > 0 and :APP_PAGE_ID not in (101,X)


Es müssen Loginseite und die Seite die als Popup erscheint ausgeschlossen werden.

TRUE ACTION: Execute Java-ScriptCode (In diesem Beispiel wird in der Applikation 100 die Seite 7 als modales Popup aufgerufen)

var ev = this.browserEvent;
ev.preventDefault;
var horizontalPadding = 20;
var verticalPadding = 20;
$('<iframe id="modalDialog" src="f?p=100:7:&APP_SESSION.::NO::" />').dialog(
       {title: "APEX System Info",
        autoOpen: true,
        width: 700,
        hight: 350,
        modal: true,
        close: function(event, ui) { $(this).remove();},
        overlay: {opacity: 0.5, background: "black"}
        }
  ).width(700 - horizontalPadding).height(350 - verticalPadding);
return false;

Der Anwender bekommt "neue Informationen" auch während einer laufenden Session sofort angezeigt und er muss aktiv werden und die Meldungen bestätigen, um sie dauerhaft auszublenden.

Achtung! Ab der APEX Version 4.1 sind aus Sicherheitsgründen Frames per default nicht erlaubt. Damit dieses Beispiel funktioniert muss in den Security Attributen "Embed in Frames" auf "Allow from same origin" umgestellt werden.

 

Weitere Informationen und Tipps zur Entwicklung mit APEX bekommen Sie auch in unseren Schulungen Entwicklung mit Application Express.



Weitere Interessente Artikel zum Thema:


Empfohlene Schulungen zum Thema:


Itemcheck in APEX Anwendungen über alle Items einer Seite

Bereich:APEX, Version: ab RDBMS 12.x, Letzte Überarbeitung: 18.12.2018

Keywords:APEX Itemcheck

Seit APEX Version 5.1 können ja nun zusätzliche Standard-Prüfungen für die Items durchgeführt werden. Diese sind:

  • Whitelist for a-z 0-9       Nur Zeichen und Zahlen sind erlaubt (Leider sind auch keine Umlaute möglich)
  • Blacklist HTML Command Characters (<> '')
  • Blacklist &<>"/;*|=% and --
  • Blacklist &<>"/;*|=% or -- and new line

Wenn das aber alles nicht passt, können wir uns eine eigene Validation schreiben:

DECLARE
stmt VARCHAR2(32000);
v_sqlerrm varchar2(32000);
BEGIN
FOR c IN (SELECT   PAGE_ID,  PAGE_NAME,  ITEM_NAME
FROM APEX_APPLICATION_PAGE_ITEMS
WHERE application_id=:APP_ID and page_id=:APP_PAGE_ID  ) LOOP
     stmt:=q'!BEGIN
     IF instr(v('!'||c.item_name||q'!'),'<')>0 OR
        instr(v('!'||c.item_name||q'!'),'>')>0 OR
        instr(v('!'||c.item_name||q'!'),'^')>0 OR
        instr(v('!'||c.item_name||q'!'),'&')>0 OR
        instr(v('!'||c.item_name||q'!'),'"')>0 OR
        instr(v('!'||c.item_name||q'!'),chr(39))>0
    THEN
      RAISE_APPLICATION_ERROR(-20500,'Ungültige Zeichen verwendet (^<>&")');
     END IF;
      EXCEPTION WHEN OTHERS THEN
       IF sqlcode=-20500 then raise; end if;
     END; !';
commit;
    EXECUTE IMMEDIATE stmt;

END LOOP;
  RETURN true;
EXCEPTION WHEN OTHERS THEN
   v_sqlerrm:=sqlerrm;
  RETURN false;
END;


Wenn jetzt jemand in irgendein Item eines der Zeichen <>'" &^ einträgt, wird diese Eingabe abgewiesen.



Weitere Interessente Artikel zum Thema:


Empfohlene Schulungen zum Thema:


Oracle ORDS Parameter der Datei defaults.xml

Bereich:APEX, Version: ab ORDS 21.2, Letzte Überarbeitung: 02.06.2020

Keywords:Oracle ORDS Parameter

Wer mit APEX und ORDS zusammenarbeitet ist immer  froh, wenn er eine Übersicht über die aktuellen ORDS Parameter findet.
Anbei haben wir einige zusammengestellt:
Sie erhalten eine Komplett-Übersicht aller Oracle ORDS Parameter für die Oracle Version 19.4 hier.
Aktuell ist derzeit die Oracle ORDS Version 19.4.6 (1.6.2020)

Parameter in der Datei defaults.xml können manuell mit einem Texteditor geändert werden, oder auch durch:

$JAVA_HOME/bin/java -jar ords.war set-property <parametername> <parametervalue>
also z.B.
$JAVA_HOME/bin/java -jar ords.war set-property jdbc.auth.enabled true



Die folgenden Parameter betreffen die Datenbank

<entry key="db.connectionType">basic</entry>
<entry key="db.hostname">my_db_server</entry>
<entry key="db.port">1521</entry>
<entry key="db.sid">o20c</entry>


oder bei einem Failover Eintrag

<entry key="db.connectionType">customurl</entry>
<entry key="db.customURL">jdbc:oracle:thin:@(DESCRIPTION=(FAILOVER=ON)(ADDRESS_LIST=
  (LOAD_BALANCE=ON)(ADDRESS=(PROTOCOL=TCP)(HOST=muniqsoft-training.de)(PORT=1521)))
  (CONNECT_DATA=(SERVICE_NAME=ISPRD)))|</entry>


Wenn es Probleme beim Verbinden gibt (z.B. Could not map a database) sollte versucht werden, eine Verbindung der Datenbank von der Shell/DOS direkt zur Datenbank durchzuführen mit:

sqlplus apex_public_user/<pwd>@my_db_server:1521/o20c


Die folgenden 4 Parameter sind verantwortlich für das Debugging und Logging
Hinweiß: Für Produktivmaschinen sollte Debuggung auf "false" stehen !

<entry key="debug.debugger">true</entry>
<entry key="debug.printDebugToScreen">true</entry>
<entry key="log.logging">true</entry>
<entry key="log.maxEntries">500</entry>


Wenn Sie eine eigene Datei in einem selbst gewählten Pfad für die Fehlermeldungen verwenden möchten:

<entry key="error.externalPath">/opt/tomcat/latest/logs</entry>


Diese Datei muss das Format {servererrorcode}.html besitzen
also z.B 404.html oder 500.html

Die nächsten 4 Parameter kümmern sich um die Konfiguration der internen Java Parameter und spielen für die Performance des REST Service eine wichtige Rolle:

<entry key="jdbc.InitialLimit">20</entry>
<entry key="jdbc.MaxConnectionReuseCount">3000</entry>
<entry key="jdbc.MaxLimit">100</entry>
<entry key="jdbc.MaxStatementsLimit">100</entry>


Maximale Anzahl der Zeilen definieren,die bei einer Abfrage zurückommen dürfen (Default: 500)

<entry key=”misc.pagination.maxRows”>2500</entry>


REST Enables SQL freischalten:

<entry key="restEnabledSql.active">true</entry>


Datenbank API via REST freischalten: 

<entry key="database.api.enabled">true</entry>

oder auf der Kommandozeile: 

java -jar ords.war set-property database.api.enabled true


Pluggable Database API abschalten (ab 19.2):

<entry key="database.api.management.services.disabled">true</entry>

 

oder wieder auf der Kommandozeile: 

java -jar ords.war set-property database.api.management.services.disabled true


Weitere Interessente Artikel zum Thema:


Empfohlene Schulungen zum Thema:


Oracle APEX Patch für 20.1 (30990551)

Bereich:APEX, Version: ab APEX 20.1, Letzte Überarbeitung: 09.07.2020

Keywords:APEX, Patch 20.1

Oracle APEX 20.1 ist gerade mal 4 Wochen heraus und schon gibt es den ersten Patch, der ein paar praktische Bugfixes mitbringt (u.A. die falsche Timeout Warnung wird behoben)
Sie können den Patch von Oracles Support Seite herunterladen und in einer Minute installieren.

Vorgehensweise:
1. Webserver stoppen
1 a, Sie haben das EPG im Einsatz:

SELECT dbms_xdb.gethttpport FROM dual;

Wenn ein Port <>0 zurückommt, dann haben Sie das EPG im Einsatz. Dann merken Sie sich den Port bitte.

EXEC dbms_xdb.sethttpport(0); -- EPG abschalten


1 b, Sie haben den TomCat im Einsatz

systemctl stop tomcat


1 c, Sie haben TomCat und Apache als Reverse Proxy im Einsatz:

systemctl stop httpd      # z.B. für Centos / RedHat Linux
systemctl stop apache2    # z.B. für SUSE Linux


2. Patch einspielen (z.B. in den Ordner /u01/software)

cd /u01/software
unzip p30990551_2010_Generic.zip
cd /u01/software/30990551
sqlplus "/ as sysdba" @catpatch.sql

Falls Sie in einer CDB installieren möchten:
sqlplus "/ as sysdba" @catpatch_con.sql

oder in einer CDB in einem Application Container:
sqlplus "/ as sysdba" @catpatch_appcon.sql


3. Image Ordner aktualisieren

3 a. bei EPG (hier werden die Bilder in der datenbank gespeichert)

sqlplus "/ as sysdba" @epg_install_images.sql /u01/software/30990551


3 b, bei TomCat (ohne Apache)
Prüfen Sie bitte zuerst, ob das Verzeichnis dort existiert (kann je nach Installation auch auf einem anderem Pfad liegen)

find /opt/tomcat/latest/webapps/i -type f | wc -l
=> da sollten dann mehr als 14.000 Dateien liegen
cp -rf /u01/software/30990551/images /opt/tomcat/latest/webapps/i


3 c, Bei TomCat (mit Apache)

find /var/www/html/i -type f | wc -l
=> da sollten dann mehr als 14.000 Dateien liegen (bei uns waren es ca 20.000)
cp -rf /u01/software/30990551/images/* /var/www/html/i


4. Webserver wieder starten
4 a. Bei EPG:

EXEC dbms_xdb.sethttpport(<port aus 1a>);
Beispiel:
EXEC dbms_xdb.sethttpport(8080);


4 b, Tomcat ohne Apache

systemctl start tomcat


4 c, Sie haben TomCat und Apache als Reverse Proxy im Einsatz:

systemctl start httpd      # z.B. für Centos / RedHat Linux
systemctl start apache2    # z.B. für SUSE Linux


5. Schlußprüfungen:
 5 a. Patch installiert:

SELECT patch_version, installed_on
FROM apex_patches
WHERE patch_number = 30990551;
 

PATCH_VERSIONINSTALLED_ON
2020.05.202020-05-25 08:45:24

Gibt es ungültige Objekte?

select count(*) from dba_objects
where status='INVALID';
=> hier sollte 0 zurückkommen


Dies und noch mehr lernen Sie bei einem unserer fünf verschiedenen APEX-Kurse, die wir seit 2005 unterrichten!



Weitere Interessente Artikel zum Thema:


Empfohlene Schulungen zum Thema:


Oracle APEX 20.2 Installation

Bereich:APEX, Version: ab APEX 20.2, Letzte Überarbeitung: 20.11.2020

Keywords:Oracle APEX

Mit dem Datum 21.10.2020 kam die Oracle APEX 20.2 Version nun doch sehr überrraschend frühzeitig heraus (im Vergleich zu den letzten Jahren). Aber gute Nachrichten kann man in den aktuell schweren Zeiten ja immer gebrauchen ... :-). Wir haben uns natürlich gleich am Tag 1 der Veröffentlichung um eine Migration unserer APPs auf das neue Release gekümmert.

1. Herunterladen und Auspacken der Software

APEX 20.2 Download
 

unzip apex_20.2.zip


2. Installation / Upgrade auf Oracle APEX 20.2 (in einer Non-CDB Datenbank)

wir haben mal das relativ neue Installationsskript apexsilentins.sql für die Installation verwendet.
Es ersetzt die folgenden Skripte:

  • apexinsql.sql
  • apex_rest_config.sql
  • apxchpwd.sql

Ausserdem erstellt es eine neue ACL (power_users.xml) und der Benutzer APEX_PUBLIC_USER wird automatisch entsperrt (endlich!)
Dadurch benötigt es jedoch auch mehr Parameter als das alte apexins.sql Skript. Der Aufruf lautet hier:
 

sqlplus "sys/syspass as sysdba" @apxsilentins <tablespace_1> <tablespace_2> <temp_tablespace> </image_path/> <pwd_1>  <pwd_2> <pwd_3> <pwd_4> <pwd_5>


Parameter 1: Name des Tablespace für den Application Express Application Benutzer (APEX_200200)
Parameter 2: Name des Tablespace für den Application Express files user (FLOWS_FILES)
Parameter 3: Name des temporären Tablespace (bzw. Tablespace Gruppe) für Sortierungen / Indexerstellung / Sort Merge Joins u.v.w.
Parameter 4: Virtuelles Verzeichnis für APEX Bilder/CSS/Javascript Dateien
Parameter 5: Passwort für APEX_PUBLIC_USER
Parameter 6: Passwort für APEX_LISTENER
Parameter 7: Passwort für APEX_REST_PUBLIC_USER
Parameter 8: Passwort für Workspace Internal APEX internal ADMIN user (Achtung, Sie müssen sich hier an strenge Passwort-Richtlinien erhalten, also bitte nicht APEX123 verwenden :-) )

Also als Beispiel:
 

sqlplus "sys/syspass as sysdba" @apxsilentins SYSAUX SYSAUX TEMP /i/ apex apex apex Super13#


Die Installationszeit betrug auf unserem Server: 15 min

Wenn Sie einen Webserver verwenden z.B. Apache TomCat Version 9.x, dann kopieren Sie bitte den images Ordner aus dem Apex Zip File auf
Windows: C:\Program Files\Apache Software Foundation\Tomcat 9.0\webapps
Linux: /opt/tomcat/latest/webapps
als Ordner i !, bzw. den Namen, den Sie bei der Installation als Parameter 4 angegeben haben. Wenn es dort schon einen Ordner gibt, bietet es sich an, den erstmal nur umzubennen und nicht gleich zu löschen!
 

z.B. mv i i_old_22_10_2020
bzw für Windows.
move i i_old_22_10_2020


Wenn Sie das interne EPG verwenden (also keinen externen Werserver), muss noch zusätzlich das folgende Skript gestartet werden:
@apex_epg_config.sql <Pfad zu den Images>

Achten Sie aber darauf, den Ordner-Namen apex nicht mit im Pfad anzugeben, weil das Skript ihn selbst dazufügt, also wenn die Bilder unter (Windows: c:\temp\apex oder Linux: /tmp/apex) liegen, lautet der Aufruf:
 

Windows: @apex_epg_config c:\temp
Linux: @apex_epg_config /tmp


 



Weitere Interessente Artikel zum Thema:


Empfohlene Schulungen zum Thema:


Dynamic Actions für Reportspalten

Bereich:APEX, Version: ab APEX 5.x, Letzte Überarbeitung: 12.12.2018

Keywords:APEX, APEX Reports

In vielen Datenmodellen werden Schalter für die Aktivierung oder Gültigkeit von Datensätzen verwendet. Hier kann zum Beispiel eine Spalte mit 0/1 oder Y/N belegt werden, um damit zu steuern, welchen Status ein Datensatz haben soll.

Im Normalfall hinterlegen wir so eine Spalte in einem Formular mit einer Selectlist, in der "Ja" oder "Nein" oder ähnliches ausgewählt werden kann. Wie wäre es aber, wenn wir den Anwendern die Möglichkeit geben würden diesen Schalter direkt im Report zu ändern? Er könnte mehrere Datensätze hintereinander verändern ohne die Seite neu laden zu müssen.

Gehen wir einmal von folgender Tabelle aus.

CREATE TABLE  "EMP" (
                "EMPNO" NUMBER(4,0) NOT NULL, 
                "ENAME" VARCHAR2(10), 
                "JOB" VARCHAR2(9), 
                "MGR" NUMBER(4,0), 
                "HIREDATE" DATE, 
                "SAL" NUMBER(7,2), 
                "COMM" NUMBER(7,2), 
                "DEPTNO" NUMBER(2,0), 
                "ACTIVE" VARCHAR2(1), 
                PRIMARY KEY ("EMPNO")
)
/

Es handelt sich dabei um die bekannte EMP-Tabelle, ergänzt um die Spalte "ACTIVE", die mit "Y" oder "N" befüllt werden soll. Idealerweise verwenden Sie eine bereits bestehende EMP-Tabelle und erweitern sie um die neue Spalte.

 

Um einen Default-Wert für den Status der Mitarbeiter zu setzen, feuern wir einmalig noch ein Update-Statement, um alle Mitarbeiter auf aktiv zu setzen.

update EMP set ACTIVE = 'Y';


In APEX erstellen wir einen klassischen Report über alle Spalten der EMP Tabelle.


Nun ist es unsere Idee, auf das "Y" zu klicken und ein "N" daraus zu machen, und natürlich auch anders herum.

Um auf den Mausklick eines Anwenders reagieren zu können müssen wir einen Eventhandler aktivieren, der auf das anzuklickende Objekt "horcht" und dann bei "Klick" eine Aktion ausführt.

Im APEX-Umfeld haben wir die Möglichkeiten dies mit den Dynamic Actions umzusetzen. Das Problem dabei ist, dass wir die Spalte eines Reports nicht als "Selection Type", als Ziel eines "Klicks", auswählen können.


Also müssen wir uns mit der HTML-Struktur der Tabelle auseinandersetzen. Diese kann je nach gewählten Theme unterschiedlich sein. In unserem Beispiel handelt es sich um das Theme 25 in der APEX Version 4.2.6.

Eine Analyse des von APEX erzeugten HTML-Codes erfolgt am besten mit den Entwicklertools der aktuellen Browsergenerationen. Die Browser Firefox und Chrome bringen ausgereifte und mit vielen Funktionen versehene Oberflächen mit. Um sie zu aktivieren genügt es, mit der rechten Maustaste auf das zu untersuchende Objekt auf der Webseite zu klicken und "Element untersuchen" auszuwählen.

Es öffnet sich in der Regel am unteren Bildschirmrand ein zweigeteilter Bereich, in dem links der HTML-Code und rechts die CSS-Befehle angezeigt werden, die auf das angeklickte HTML-Tag wirken.

Bewegt man die Maus über den Quellcode wird der Bereich der Webseite markiert, der durch diesen Code definiert wird.


So erhalten wir die Information, dass die Ausgabe von "Y" oder "N" in einem "td" erfolgt, das mit dem Parameter "headers" und dem Wert "ACTIVE" versehen wird. Es handelt sich dabei um die von uns gewählte Überschrift der Spalte. Das gilt für alle Zeilen unseres Reports.

Mit dieser Information ausgerüstet können wir einen jQuery Selektor definieren, den wir in der Dynamic Action verwenden können.

Die Java Script-Bibliothek bietet sich an, da es sich zu einem "Quasi-Standard" im Internet etabliert hat und auch von APEX selbst verwendet wird. Mit einer leicht zu erlernenden Notation können wir einen Bereich innerhalb des HTML Codes definieren, der als Anker oder Startpunkt für unsere gewünschten Aktionen dienen kann.

In diesem konkreten Fall möchten wir gerne auf einen "td" klicken können, der den "Header" "ACTIVE" besitzt. Also definieren wir den Selektor für jQuery folgendermaßen:

td[headers="ACTIVE"]

Erstellen wir also nun eine neue Dynamic Action und verpassen ihr einen sprechenden Namen.


Nun ist es unsere Idee, auf das "Y" zu klicken und ein "N" daraus zu machen, und natürlich auch anders herum.

Um auf den Mausklick eines Anwenders reagieren zu können müssen wir einen Eventhandler aktivieren, der auf das anzuklickende Objekt "horcht" und dann bei "Klick" eine Aktion ausführt.

Im APEX-Umfeld haben wir die Möglichkeiten dies mit den Dynamic Actions umzusetzen. Das Problem dabei ist, dass wir die Spalte eines Reports nicht als "Selection Type", als Ziel eines "Klicks", auswählen können.


Also müssen wir uns mit der HTML-Struktur der Tabelle auseinandersetzen. Diese kann je nach gewählten Theme unterschiedlich sein. In unserem Beispiel handelt es sich um das Theme 25 in der APEX Version 4.2.6.

Eine Analyse des von APEX erzeugten HTML-Codes erfolgt am besten mit den Entwicklertools der aktuellen Browsergenerationen. Die Browser Firefox und Chrome bringen ausgereifte und mit vielen Funktionen versehene Oberflächen mit. Um sie zu aktivieren genügt es, mit der rechten Maustaste auf das zu untersuchende Objekt auf der Webseite zu klicken und "Element untersuchen" auszuwählen.

Es öffnet sich in der Regel am unteren Bildschirmrand ein zweigeteilter Bereich, in dem links der HTML-Code und rechts die CSS-Befehle angezeigt werden, die auf das angeklickte HTML-Tag wirken.

Bewegt man die Maus über den Quellcode wird der Bereich der Webseite markiert, der durch diesen Code definiert wird.


So erhalten wir die Information, dass die Ausgabe von "Y" oder "N" in einem "td" erfolgt, das mit dem Parameter "headers" und dem Wert "ACTIVE" versehen wird. Es handelt sich dabei um die von uns gewählte Überschrift der Spalte. Das gilt für alle Zeilen unseres Reports.

Mit dieser Information ausgerüstet können wir einen jQuery Selektor definieren, den wir in der Dynamic Action verwenden können.

Die Java Script-Bibliothek bietet sich an, da es sich zu einem "Quasi-Standard" im Internet etabliert hat und auch von APEX selbst verwendet wird. Mit einer leicht zu erlernenden Notation können wir einen Bereich innerhalb des HTML Codes definieren, der als Anker oder Startpunkt für unsere gewünschten Aktionen dienen kann.

In diesem konkreten Fall möchten wir gerne auf einen "td" klicken können, der den "Header" "ACTIVE" besitzt. Also definieren wir den Selektor für jQuery folgendermaßen:

td[headers="ACTIVE"]

Erstellen wir also nun eine neue Dynamic Action und verpassen ihr einen sprechenden Namen.


Sobald der Event "Click" auftritt auf dem gewählten jQuery Selector soll ...


... die Action "Java script" ausgeführt werden. Um unsere Eventhandler zu testen geben wir zuerst nur einen Alert aus der bei Klick angezeigt werden soll.

alert('ok');

 


Den Haken bei "Fire On Page Load" deaktivieren wir, da wir nicht möchten, dass die Aktion beim Laden der Seite gefeuert wird.

Da wir alle Aktionen mit JavaScript ausführen werden, benötigen wir im nächsten Schritt kein Element, das benutzt werden soll und wählen hier nichts aus und schließen die Erstellung der Dynamischen Aktion ab.


Wir haben den Test bestanden, wenn wir nun im Report auf das "Y" klicken können und eine Alert-Box erscheint. Ein Klick auf einen anderen Bereich der Webseite sollte dagegen den Event nicht auslösen.

Jetzt haben wir zwar den Klick auf "Y" mit dem Eventhandler abgefangen, wir wissen aber noch nicht, auf welches "Y", sprich welche Zeile angeklickt wurde. Wir müssen ja in der Lage sein, ein Update-Statement an die Datenbank zu senden, um den angeklickten Datensatz zu verändern. Dazu benötigen wir den Primary Key des Datensatzes.

In unserem Fall müssen wir die "EMPNO" der angeklickten Zeile ermitteln. Wir können das auf eine einfache aber "gefährliche" Art und Weise mit jQuery erreichen, da die Empno in diesem Fall mit im Report angezeigt wird.

Wenn wir uns im Browser noch einmal den Quellcode anzeigen lassen, entdecken wir den von uns gesuchten Wert in dem ersten "td" einer jeden Zeile.


Hinweis: 
Sollten Sie einen Report mit Editiermöglichkeit gewählt haben, könnte es sich bei der Empno-Spalte auch um das zweite "td" handeln. Das ist für die weitere Vorgehensweise sehr wichtig. Aus diesem Grund sollten Sie unbedingt unsere weiterführenden Tipps beachten, darin verwenden wir eine Möglichkeit, die von der Reihenfolge der Spalten unabhängig ist.

Die Idee ist nun, ausgehend von dem angeklickten "td", den ersten "td" der Zeile ("tr") zu ermitteln. Zurück in der von uns angelegten Dynamic Action ersetzen wir unsere Debug-Ausgabe mit folgendem jQuery-Selector.

alert(
  $(this.triggeringElement).parent().children().html()
);

Das Dollarzeichen ($) ist die Kurzform der Java script-Funktion, mit der wir jQuery aufrufen können. Dieser Funktion geben wir das von APEX befüllte Object "this.triggeringElement" als Selector mit. Dann ermitteln wir mit der Funktion "parent" das Elternelement unseres angeklickten "td"s. Es handelt sich dabei um das übergeordnete "tr". Von dort springen mit der Funktion "children" wieder zum ersten Kind-Element zurück. Von diesem geben wir mit der Funktion "html" den HTML-Inhalt aus.

Wenn es sich bei der Empno-Spalte um das zweite "td" handelt können wir folgenden Selektor verwenden.

alert(
  $(this.triggeringElement).parent().children().next().html()
);

Hier wird mit ".next()" auf das zweite Kind-Element gezeigt.

Wer sich ein bisschen mit jQuery beschäftigt hat, wird sicherlich wissen, dass es noch einundreißig weitere Wege gegeben hätte, sich mit jQuery in der HTML-Struktur zu bewegen. So hätten wir mit Kombinationen der Funktionen "first", "next" oder "prev" auf dasselbe Ergebnis kommen können. Auch der Einsatz des bereits verwendeten aber leicht abgewandelten "td[headers='EMPNO']" wäre möglich gewesen. Dabei ist aber zu beachten, dass alle Bewegungen in der Struktur immer ausgehend vom angeklickten Element starten müssen.

Nun haben wir also erreicht, dass bei Klick in der Alert-Box die Empno der angeklickten Zeile ausgegeben wird. Wir benötigen diese Information aber in einem von APEX verwendbaren Element, um es an die Datenbank senden zu können.

Dazu bietet sich ein Hidden-Element an, das wir mit JavaScript befüllen und dann mit PL/SQL auslesen und unseren Update formulieren.

Erster Schritt dazu ist das Anlegen eines Page Items im Format Hidden. Da wir in diesem Element den Wert der Empno zwischenspeichern wollen und wir uns mit unserem Report auf der Seite 5 befinde, nennen wir das Hidden Element "P5_EMPNO_CACHE".

Nach einer kurzen Analyse des HTML-Outputs unserer Seite erkennen wir, dass das von uns erzeugte Element von APEX mit dem Parameter ID versehen wurde, mit dem von uns vergebenen Namen.


Damit haben wir alle Informationen um dem Hidden-Item den Wert mit JavaScript zu übergeben. Wir ersetzen also in der Dynamic Action den JavaScript-Code mit folgendem Inhalt:

$('#P5_EMPNO_CACHE').val(
  $(this.triggeringElement).parent().children().html()
);

Hier kommt wieder ein jQuery Selektor zum Einsatz. Das Dollarzeichen ist die jQuery-Funktion selbst. Als Parameter übergeben wir in Hochkommas die Information, dass es sich um eine ID handelt - mit der Raute (#) und den Namen der ID "P5_EMPNO_CACHE". Dann setzen wir mit der Funktion "val" die "Value" des schon vorher ermittelten Wertes.

Um das Ganze zu debuggen geben wir noch zusätzlich den folgenden Code in den JavaScript-Bereich:

console.log(
  "EMPNO: " + $('#P5_EMPNO_CACHE').val()
);

Mit dem Befehl "console.log" können wir Ausgaben in die JavaScript-Konsole der Entwicklungsumgebung veranlassen. Das ist in der Regel angenehmer als die Ausgabe über den Alert Befehl.

Aufrufen können wir die Console über die rechte Maustaste und "Element untersuchen", danach klicken wir im Menü der Entwicklungsumgebung auf den Punkt "Console".


Dort sehen wir nach einem Klick auf ein "Y" die Ausgabe unseres Log-Befehls. Da wir damit sichergestellt haben, dass das Hidden Element die richtige Empno enthält, müssen wir jetzt den nächsten Schritt gehen.

Übergabe des Hidden-Wertes zur Datenbank. Natürlich könnten wir einfach einen "Submit" ausführen und der Wert wäre der Datenbank bekannt. Wir möchten aber gerne ohne Neuladen der Webseite auskommen. Daher erzeugen wir eine weitere "True Action" in unserer bestehenden Dynamic Action.


Diesmal möchten wir PL/SQL-Code ausführen. Bei den Optionen lassen wir "Fire On Page Load" deaktiviert. Die Optionen "Stop Execution On Error" und "Wait For Result" lassen wir ebenfalls auf dem Default-Wert (angehakt). Vor allem letztere ist wichtig, da erst der PL/SQL-Teil abgearbeitet werden soll und dann der nächste Schritt ausgeführt werden soll.

Als PL/SQL-Code tragen wir folgendes ein.

update emp set ACTIVE = case 
                          when ACTIVE = 'Y' then 'N'
                          when ACTIVE = 'N' then 'Y'
                        end
where empno = :P5_EMPNO_CACHE;

Damit die Datenbank mit diesem PL/SQL-Code, aber auch auf den Wert in P5_EMPNO_CACHE zugreifen kann, muss das Item noch bei "Page Items to Submit" eingetragen werden. Die Dynamic Action stellt jetzt sicher, dass der Wert auch per AJAX übertragen wird.


Wenn wir jetzt auf ein "Y" oder "N" klicken, wird der Wert in der Datenbank geändert. Wir sehen das Ergebnis aber erst wenn wir den Report neu laden, es fehlt also noch ein automatischer Refresh des Reports.

Dazu legen wir einen eine neue "True Action" in unserer Dynamic Action an, diesmal vom Typ "Refresh". Als "Affected Element" wählen wir "Region" und dann die von uns verwendete Region aus.

Beim Test stellen wir fest: es funktioniert. Aber es funktioniert nur einmal. Das liegt daran, dass wir einen Eventhandler für das Abfangen des Klicks aufbauen, dieser aber beim Refresh des Reports "zerstört" wird. Daher müssen wir in unserer Dynamic Action unter "Advanced" den "Event Scope" auf "Dynamic" setzen, dann klappt das Verändern des Status auch mehrere Male hintereinander.

Hinweis:
Sollte der Refresh überhaupt nicht funktionieren kann es sein, dass im Report unter "Report Attributes" im Bereich "Layout and Pagination" der Schalter "Enable Partial Page Refresh" auf "Nein" steht. Das sollte man dann ändern. :)

In den weiterführenden Tipps erfahren Sie, wie Sie ein HTML-Attribut setzen können, um der Reihenfolgenproblematik zu entkommen. Oder aber Sie verbessern die Darstellung mit Icons aus einem Web-Font.

In unseren APEX-Schulungen und Workshops erfahren Sie weitere Möglichkeiten, um benutzerfreundliche APEX Anwendungen zu erstellen.



Weitere Interessente Artikel zum Thema:


Empfohlene Schulungen zum Thema:


Dynamic Actions Vorlagen und Beispiele für APEX

Bereich:APEX, Version: ab APEX 21.1:APEX 21.2:RDBMS 12.x, Letzte Überarbeitung: 02.04.2022

Keywords:Dynamic Actions, Javascript, APEX

Ich habe schon oft versucht Dynamic Actions Vorlagen für APEX im Internet zu finden. Aber es gibt nur sehr wenige und viele sind nicht für den Anwendungsfall passend oder zu kompliziert. Ziel dieses Artikels ist es, einfache Dynamic Action in Oracle APEX als Vorlagen für den täglichen Hausgebrauch zur Verfügung zu stellen.

Fangen wir an...

1.Ein Item soll nach der Eingabe, sofort wieder mit dem Session State synchronisiert werden.
Das bedeutet der Inhalt des Items wird sofort wieder mit der Datenbank, Tabelle wwv_flow_data synchronisiert. Das hat den Vorteil, von einem anderen Item wieder auf den Inhalt des Items über die Notation :Px_ITEM zugreifen zu können.
Voraussetzungen. Ein Text Item (P1_TEXT) existiert in einer Region.

Dynamic Action erstellen:
 Rechte Maus auf P1_TEXT / Create Dynamic Action
 Name: Submit_Val (oder egal)
 Event: On Change
 Selection Type: Item
 Item(s): P1_TEXT
 
 Als True Bedingung:
 Identification
  Action: Execute PL/SQL Code
   PL/SQL Code:
    NULL;
  Items to Submit: P1_TEXT

Fertig. Sobald Sie das Item ändern und verlassen, steht es sofort im Session State zur Verfügung.
 
2. Ein Zweites Item soll erst dann auf der Seite erscheinen, wenn das erste Item mit Inhalt gefüllt wurde:
Wir brauchen dazu ein zweites Textfeld (P1_NAME).

Rechte Maus auf P1_TEXT / Create Dynamic Action
 Name: Show_Name (oder egal)
 WHEN
  Event: On Change
  Selection Type: Item
  Item(s): P1_TEXT
  Client-side Condition
    Type: Item is not null
    Item: P1_TEXT
 
 Als True Bedingung:
  Identification
  Action: Show
  Affected Elements
    Selection Type: Item(s)
    Item(s): P1_NAME
  Execution Options:
    Fire ony Initialization: NO
 Neue False Bedingung: Rechte Maus auf False / Create False Action oder
 auf Show / Create Opposite False Action
 Action: Hide
 Affected Elements
    Selection Type: Item(s)
    Item(s): P1_NAME
 Execution Options:
    Fire on Initialization: YES


Wenn man es noch schöner haben möchte legt man eine weitere True Bedingung fest,
 die den Cursor in das nächste/richtige Item setzt.

  Action: Set Focus
  Affected Elements
    Selection Type: Item(s)
    Item(s): P1_NAME
  Execution Options:
    Fire ony Initialization: NO 

 

3. Sie geben im ersten Item eine Mitarbeiternummer ein und bekommen in einem anderen
Item den Namen des dazugehörigen Mitarbeiters zurück:

Name: Setze_Name (oder egal)
  WHEN
   Event: On Change
   Selection Type: Item
   Item(s): P1_TEXT
 Client-side Condition
    Type: Item is not null
    Item: P1_TEXT
    
Als True Bedingung:
 Identification
  Action: Set Value
  Set Type: SQL Statement
  SQL Statement: SELECT ename FROM emp WHERE empno=to_number(:P1_TEXT);
  Items to Submit: P1_TEXT
 
 Affected Elements
    Selection Type: Item(s)
    Item(s): P1_NAME
 Execution Options:
    Fire ony Initialization: NO

   
4. Beim Klick in eine Textbox, sollen in zwei andere Textboxen neue Werte (mit/ohne Datenbankbezug) eingetragen werden.
Wir brauchen dazu die Textboxen P1_TEXT, P1_NAME und P1_GEHALT

Name: Setze_Werte (oder egal)
 WHEN
  Event: On Click
  Selection Type: Item
  Item(s): P1_TEXT
 
 Als True Bedingung:
 Identification
  Action: Execute PL/SQL Code
  Settings
    PL/SQL Code: /*ohne Datenbank-Bezug */
     :P1_NAME:='MARCO';
   :P1_GEHALT:=9999;
    Items to Return: P1_NAME,P1_GEHALT
    PL/SQL Code: /*mit Datenbank-Bezug */
     SELECT ename,sal
   INTO :P1_NAME,:P1_GEHALT
   FROM emp
   WHERE empno=:P1_EMPNO;
    Items to Return: P1_NAME,P1_GEHALT
    Items to Submit: P1_EMPNO

 

5. Modales Fenster gibt Wert an Hauptfenster zurück:
Wir brauchen dazu eine normale Seite (Seite 1)    
mit einer Textbox (P1_TEXT)
und einem Button (Modal_Fenster)

Ausserdem eine Modale Seite (Seite 2) mit einer Selectliste (P2_EMPS)
und einem Button (Zurueck)

Der Button Modal_Fenster macht einen Redirect auf Seite 2
Auf den Button legen wir eine Dynamic Action

Name: Close_Dialog (oder egal)
 WHEN
  Event: Dialog Closed
  Selection Type: Button
  Button: Modal_Fenster
 
 True Action:
  Identification
    Action: Set Value
  Settings:    
    Set Type: Dialog Return Item
    Return Item: P2_EMPS
  Affected Elements
    Selection Type: Items
    Item(s): P1_TEXT
    
Auf der Modalen Seite:
Die Select Liste hat folgende Query: select ename,empno from emp;
Und der Zurueck Button     verwendet als Action: Redirect to URL
Target: javascript:apex.navigation.dialog.close(true, {'P2_EMPS': '&P2_EMPS!JS.'});


6. Bei einem Doppelklick auf die Textbox P1_ENAME soll der Inhalt dieser Textbox
sofort in die Datenbank zurückgeschrieben werden.


Wir brauchen dazu eine Normale Seite mit zwei Items:
P1_EMPNO vom Typ Hidden
P1_ENAME vom Typ Text Field

Name: Update_table (oder egal)
 WHEN
  Event: Double Click
  Selection Type: Item
  Item(s): P1_ENAME
 
 True Action:
  Identification
  Action: Execute PL/SQL Code
 Settings
 PL/SQL Code:
  UPDATE emp SET ename=:P1_ENAME
  WHERE empno=:P1_EMPNO;
  COMMIT;
 Items to Submit: P1_ENAME


7. Textbox Eingabe in Großbuchstaben umwandeln:


 In der Textbox eintragen unter
Advanced / Custom Attributes: style='text-transform:uppercase'
 
 Trotzdem muss das Item auch nach dem Verlassen in Großbuchstaben gewandelt werden!
 

 Name: TO_UPPER (oder egal)
 WHEN
  Event: Change
  Selection Type: Item
  Item(s): P1_ENAME
 
 True Action:
  Identification
   Action: Execute Javascript Code
  Code
   $x('P1_ENAME').value=$x('P1_ENAME').value.toUpperCase();
  Affected Elements
   Selection Type: Items
   Item(s): P1_TEXT


8. Beim Klick auf ein Button sollen zwei Textfelder geleert werden:
 

Wir brauchen dazu:
Button ("Clear")
Text Feld P1_NAME und P1_TEXT

Gehen Sie mit der rechten Maus auf den Button / Create Dynamic Action
WHEN
  Event: Clear
  Selection Type: Button
  Button: Clear
 
  True Action:
  Identification
   Action:  Clear
  Affected Elements
   Selection Type: Items
   Item(s): P1_TEXT,P1_TEXT 

 Damit das nun nicht aus Versehen ausgewählt wird, bauen wir eine Sicherheitsabfrage ein
 Dazu muss eine weitere True Action erzeugt werden mit einer niedrigeren Sequenz Nummer (z.B. 5)

 True Action:
  Identification
   Action:  Confirm
  Settings
  Text: Wollen Sie wirklich löschen?
  Fire On Initialization: No


 Zum Schluß noch ein paar praktische Javascript Snippets:
 Abfrage mit YES/NO und dem Text "Mitarbeiter löschen?". Bei YES wird REQUEST = DELETE gesendet
 apex.confirm( "Mitarbeiter löschen?", 'DELETE' );
 
 Abfrage mit YES/NO und dem Text "Mitarbeiter löschen?". Bei YES wird REQUEST = DEL gesendet
 und die Items P1_DEPTNO = 10 und P1_EMPNO=7788 gesetzt.
 apex.confirm( "Mitarbeiter löschen?", {
    request: "DEL",
    set: {
        "P1_DEPTNO": 10,
        "P1_EMPNO": 7788
    }
} );

 Submit ausführen mit REQUEST=GO
 apex.submit( "GO" );

9. In einem Tabular Form soll in einer neu hinzugefügten Zeile in einer Spalte immer bereits ein Defaultwert stehen.

Gehen Sie in die Eigenschaften der gewünschten Spalte (bei uns im Beispiel DEPTNO) in den Bereich Advanced / CSS Classes und tragen dort ein:

mydeptno

Der Defaultwert soll aus einem Item stammen mit Namen :P1_DEPTNO

Legen Sie nun eine Dynamic Action auf den "ADD" Button in der Seite, der bei einem Click reagiert:

Event: Click
Selection Type: Button
Button: ADD
True Action:
Action: Execute Javascript
Code:
apex.widget.tabular.addRow();
$(".mydeptno").last().val($v("P1_DEPTNO"));

 

10. In einem Autocomplete Item soll ein Wert eingesetzt werden, der dazu führt das eine Select Liste sich eine neue Query ausführt mit dem Autocomplete Wert als Filter.

Legen Sie dazu ein Autocomplete Item (P1_DEPT) und eine Select Liste an (P1_EMPS)

Die Query für P1_DEPT:

select deptno from dept

Die Query für P1_EMPS:

select ename,empno from emp
where deptno=:P1_DEPT

Legen Sie nun eine Dynamic Action auf P1_DEPT:

Event: Loose Focus
Selection Type: Item(s)
Item: P1_DEPT
True Action: Execute PL/SQL Code
PL/SQL Code:  NULL;
Items to Submit: P1_DEPT
 
Zweite True Action:
Event: Refresh
Selectin Type: Item(s)
Items: P1_EMPS

 

11. Ein Zweites Item soll mit dem ersten Item synchronisiert werden:
Wir brauchen dazu zwei Textfelder (P1_NAME und P1_NAME2).

Rechte Maus auf P1_NAME / Create Dynamic Action

Name: SYNC_Name (oder egal)
 WHEN
  Event: On Change [oder On Key Press]
  Selection Type: Item
  Item(s): P1_NAME
  Client-side Condition
    Type: Item is not null
    Item: P1_NAME
 
 Als True Bedingung:
  Identification
  Action: Set Value
Javascript Expression:
$v("P1_NAME");
  Affected Elements
    Selection Type: Item(s)
    Item(s): P1_NAME2
  Execution Options:
    Fire ony Initialization: NO


12. Automatische Erzeugung eines Primärschlüssels in einem interactiven Grid

Sehr häufig benötigt man eine automatische Generierung eines Primary Schlüssels (Primary Keys) in einer Tabelle
Folgende Möglichkeiten bieten sich hier an:
Tabelle hat einen Before Row Insert Trigger mit einer Sequenz
Tabelle hat eine Identity Spalte (ab 12.1)
PK wird durch APEX mit Hilfe einer Sequenz gefüllt

Wir wollen uns den letzten Fall ansehen
a., Erstellen Sie einen interactiven Grid auf Ihrer Tabelle (bei uns die EMP Tabelle)
b, Erstellen Sie eine Sequenz:

create sequence emp_seq start with 8000;

c, Erstellen Sie auf der Spalte EMPNO im Grid (rechte Maustaste, Create Dynamic Action) eine neue Dynamic Action

Event: Row Initializiation
Name: Erzeuge_PK
Selecion Type: Column
Column: EMPNO
Client Side Condition:
Type: Item/ Column is in List
Component Type: Column
Column: EMPNO
List: t1000,t1001,t1002,t1003,t1004,t1005,t1006,t1007,t1008,t1009
Anmerkung: Damit können bis zu 10 Zeilen auf einmal eingetragen werden, das sollte normalerweise reichen :-)

True Action (1):
Action: Enable
Selection Type: Column
Column: EMPNO

True Action (2):
Action: Set Value
Set Type: SQL Statement
SQL Statement: SELECT emp_seq.nextval FROM dual;
Selection Type: Column
Column: EMPNO

True Action (3):
Action: DISABLE
Selection Type: Column
Column: EMPNO

und noch eine weitere Dynamic Action vom Typ:
Event: Report Change [ Interactive Grid]
Name: Disable_PK_Col
True Event
Action: DISABLE
Selection Type: Column
Column: EMPNO
Fire on Initialization: Ja!!

Nun passiert folgendes:
Bei jeder neu eingefügten Zeile im Grid wird kurz der Spaltenschutz aufgehoben,
dann wird aus der Sequenznummer eine neue Nummer in die Zeile eingetragen,
danach wird die Spalte wieder gegenüber Änderungen geschützt.



Weitere Interessente Artikel zum Thema:


Empfohlene Schulungen zum Thema:


Template Substitutions in Apex

Bereich:APEX, Version: ab APEX 5.x, Letzte Überarbeitung: 12.12.2018

Keywords:Apex, Apex Layouts

Für einige der Universal Theme-Templates in APEX 5.0 sind die Template Substitutions besonders interessant - deswegen wollen wir diese Variablenart einmal genauer unter die Lupe nehmen...

In APEX lassen sich Variablen auf fünf verschiedene Arten referenzieren: 

  • Substitution Strings in HTML Umgebungen (&APP_USER.)
  • Bindvariablen für SQL oder PL/SQL Blöcke (:APP_ID)
  • V/NV Funktionen im PL/SQL Kontext (V('APP_USER')
  • Shortcuts für Regionen und Items ("HELP_TEXT") 
  • Template Substitutions (#HOME_LINK#)

Für einige der Universal Theme-Templates in APEX 5.0 sind die Template Substitutions besonders interessant - deswegen wollen wir diese Variablenart einmal genauer unter die Lupe nehmen.

Wichtig ist dabei, dass die gewünschten Template Substitutions im aktuellen Template Ihrer Seite, Region, Liste, etc. enthalten sind, um sie in der Applikation definieren und nutzen zu können!

GLOBAL_NOTIFACTION UND FAVICONS


Im Shared Components Menü "Application Definition Attributes" lässt sich so beispielsweise der Substitution String #GLOBAL_NOTIFICATION# im Seiten-Template füllen. Der dort eingefügte Text wird nun automatisch auf allen Seiten Ihrer Applikation angezeigt.

Auch sogenannte Favicons (das sind die kleinen Symbole in Ihrem Webbrowser-Tab oder der Adresszeile) können Sie an dieser Stelle ganz einfach für Ihre gesamte Applikation festlegen: Geben Sie als Substitution String "APP_FAVICONS" und den dazugehörigen Bildwert, verpackt in einem Link-Tag, an.

Voraussetzung ist hier der String #FAVICONS# im Seiten-Template!

REPORT TEMPLATES


Das Universal Theme in APEX 5.0 bietet uns einige neue Report-Templates - und auch hier kommen Substitution Strings zum Einsatz! 

Klären wir zunächst noch, was genau mit "Report-Templates" gemeint ist: Im Gegensatz zu Region-Templates werden Report-Templates im "Attributes"-Bereich einer Report-Region definiert. 

In diesem Tipp zeigen wir die Nutzung von Report-Templates unter Verwendung von Substitution Strings am Beispiel des Templates "Timeline".

TEMPLATE ERKUNDEN
Ein Blick in das entsprechende Template (Shared Components -> Templates -> Report Timeline) verrät, welche Substitution Strings grundsätzlich verfügbar sind und durch einen Report gefüllt werden können.

Die Strings in schwarzer Farbe stehen für Daten, die später im Report sichtbar dargestellt werden. In unserem Beispiel: #USER_AVATAR#, #USER_NAME#, #EVENT_DATE#, #EVENT_TYPE#, #EVENT_TITLE#, #EVENT_DESC#.

Substitution Strings in roter Farbe dagegen sind Teil von HTML Klassen und können zur HTML- und CSS Bearbeitung genutzt werden: #EVENT_MODIFIERS#, #USER_COLOR#, #EVENT_STATUS#, #EVENT_ICON#.

Erstellt man einen Bericht mit dem Report-Template "Timeline" und der simplen SQL Query:

select 1 from dual

so werden auch in der laufenden Applikation die im Template definierbaren Substitution Strings angezeigt:

TEMPLATE BEFÜLLEN


In der Report-Query können diese Substitution Strings nun als Spaltenaliasse verwendet und dadurch gefüllt werden:

select 

     'IQ'             as USER_AVATAR, 

     'Muniqsoft'      as USER_NAME, 

     '07.11.2016'     as EVENT_DATE, 

     'Kurs'           as EVENT_TYPE, 

     'APEX I'         as EVENT_TITLE, 

     'Grundlagen der Anwendungsentwicklung mit APEX' 

                      as EVENT_DESC, 

     'user_blue'      as USER_COLOR, 

     'kurs_status'    as EVENT_STATUS, 

     'fa-book'        as EVENT_ICON 

from dual;

Jetzt fehlt nur noch die Definition der CSS Klassenselektoren, die sich auf die HTML/CSS Substitution Strings #USER_COLOR# und #EVENT_STATUS# beziehen. Diese kann beispielsweise im Custom CSS Bereich des Theme Rollers oder in den Seiten-Eigenschaften unter CSS/Inline erfolgen:

.user_blue {
    background-color: #58D3F7;
}
.kurs_status {
    background-color: #82FA58;
}

TEMPLATE VERWENDEN


Und hier ist er, unser "Timeline"-Report: 

Und hier ist er, unser "Timeline"-Report: 

Anhand dieser Vorgehensweise können Sie natürlich auch alle anderen Report-Templates wie "Badge List", "Cards", "Comments" oder "Search Results" in Ihrer Applikation nutzen!

 

Weitere Erklärungen zu Substitutions Strings und Templates sowie Tipps und Tricks rund um APEX erhalten Sie in unseren APEX-Schulungen (Grundlagen / Fortschritt / Neuerungen in APEX 5.x/18x)!

Schauen Sie doch einfach mal vorbei! 



Weitere Interessente Artikel zum Thema:


Empfohlene Schulungen zum Thema:


Oracle ORDS (bis 21.1) Installation für APEX

Bereich:APEX:ORDS, Version: ab APEX 20.1, Letzte Überarbeitung: 06.07.2023

Keywords:ORDS, ords.war, APEX, Installation, Oracle REST Data Services

Nachdem wir in den letzten Jahren schon viele Male den Ords installiert haben und in diverse Probleme gelaufen sind, wird es Zeit hier mal etwas Licht ins Dunkel zu bekommen... :-)

1. Wie installiert man die Java-Applikation "ords.war"?

Zuerst muss wie immer die neueste Version heruntergeladen werden.

Idealerweise hat man bereits eine JDK Version 1.8 (wir hatten mit 1.9 und ords 18.1 ein paar Probleme...) installiert.

Vorbereitung: Wir richten ein config-Verzeichnis für die folgende Installation ein:

Windows:
    java -jar ords.war configdir c:\app\oracle

 

Linux:

java -jar ords.war configdir /opt/oracle

Achtung: Dann wird dort bei der Installation ein Verzeichnis "ords/" angelegt mit folgendem Inhalt:

  • conf (Verzeichnis)
  • defaults.xml

Die Datei "defaults.xml" besteht z.B. aus folgenden Zeilen:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
    <properties>
    <comment>Saved on Thu Jul 05 06:20:04 CEST 2018</comment>
    <entry key="cache.caching">false</entry>
    <entry key="cache.directory">/tmp/apex/cache</entry>
    <entry key="cache.duration">days</entry>
    <entry key="cache.expiration">7</entry>
    <entry key="cache.maxEntries">500</entry>
    <entry key="cache.monitorInterval">60</entry>
    <entry key="cache.procedureNameList"/>
    <entry key="cache.type">lru</entry>
    <entry key="db.hostname">localhost</entry>
    <entry key="db.port">1521</entry>
    <entry key="db.servicename">o12c2</entry>
    <entry key="debug.debugger">false</entry>
    <entry key="debug.printDebugToScreen">false</entry>
    <entry key="error.keepErrorMessages">true</entry>
    <entry key="error.maxEntries">50</entry>
    <entry key="jdbc.DriverType">thin</entry>
    <entry key="jdbc.InactivityTimeout">1800</entry>
    <entry key="jdbc.InitialLimit">3</entry>
    <entry key="jdbc.MaxConnectionReuseCount">1000</entry>
    <entry key="jdbc.MaxLimit">10</entry>
    <entry key="jdbc.MaxStatementsLimit">10</entry>
    <entry key="jdbc.MinLimit">1</entry>
    <entry key="jdbc.statementTimeout">900</entry>
    <entry key="log.logging">false</entry>
    <entry key="log.maxEntries">50</entry>
    <entry key="misc.compress"/>
    <entry key="misc.defaultPage">apex</entry>
    <entry key="security.disableDefaultExclusionList">false</entry>
    <entry key="security.maxEntries">2000</entry>
    <entry key="security.requestValidationFunction">wwv_flow_epg_include_modules.authorize</entry>
    <entry key="security.validationFunctionType">plsql</entry>
    </properties>

Falls Sie https einsetzen und beim Aufruf einer Seite in Google Chrome erhalten Sie die Fehlermeldung:

The Request cannot be processed because this resource doest not support Cross Origin Sharing request...

Dafür gibt es auch ein MOS Doc:

403 Forbidden Error" When Trying To Access The Apex Application Configured with ORDS 3.0.4 Or Higher Using the Google Chrome Browser 
(Doc ID 2139195.1)

dann sollten Sie als Lösung zusätzlich noch folgenden Parameter in die Datei defaults.xml eintragen:

<entry key="security.forceHTTPS">true</entry>

Interessant sind in der Datei die folgenden Parameter für das Debugging (bitte ggf. von "false" auf "true" setzen):

<entry key="debug.debugger">true</entry>
    <entry key="debug.printDebugToScreen">true</entry>

Mögliche Parameter (Auswahl) beim Aufruf von "ords.war":

Hilfe ausgeben:

java -jar ords.war help

Config Verzeichnis vorab angeben:

java -jar ords.war configdir <path>

Oracle Rest Data Service installieren:

java -jar ords.war install

Hinweis: Wenn Sie schon ein erfolglose Installation hinter sich haben, oder eine neue ORDS Version installieren, empfihelt es sich unserer Erfahrung nach, zuvor die alte Version zu deinstallieren:

java -jar ords.war uninstall

Datenbank Verbinding einrichten:

java -jar ords.war setup

ORDS_METADATA,, Proxy Benutzer und zugehörige Objekte wieder deinstallieren:

java -jar ords.war uninstall

ORDS Konfiguration prüfen:

java -jar ords.war validate

Kommen wir zur Installation von ORDS:

Folgende Vorüberlegungen / Vorbereitungen sollten Sie machen:

1. Welche Datenbank soll am Applicationserver (Tomcat) angebunden werden (Hostname/IP, Portnummer, Instanzname)? 
2. Welche Passwörter möchten Sie verwenden für die Benutzer APEX_PUBLIC_USER, APEX LISTENER, APEX_REST_PUBLIC_USER)?

Hinweis: Ein bereits vorhandener APEX_PUBLIC_USER berkommt nur ein neues Passwort, wird aber nicht automatisch entsperrt!

java -jar ords.war
    Name des Datenbankservers eingeben [localhost]:
    Listener-Port der Datenbank eingeben [1521]:
    1 eingeben, um den Servicenamen der Datenbank anzugeben, oder 2, um die Datenbank-SID anzugeben [1]:
    Datenbankservicename eingeben:o12c2
    Datenbankkennwort für ORDS_PUBLIC_USER eingeben:***
    Kennwort bestätigen:***
    Erfordert SYS AS SYSDBA, um das Oracle REST Data Services-Schema zu verifizieren.
    Datenbankkennwort für SYS AS SYSDBA eingeben:***
    Kennwort bestätigen:***
    Informationen werden abgerufen.
    Geben Sie 1 ein, wenn Sie das PL/SQL-Gateway verwenden möchten, oder 2, um diesen Schritt zu überspringen.
    Wenn Sie Oracle Application Express verwenden oder eine Migration von mod_plsql durchführen, müssen Sie 1 eingeben [1]:
    Datenbankkennwort für APEX_PUBLIC_USER eingeben:***
    Kennwort bestätigen:***
    Geben Sie 1 ein, um Kennwörter für Application Express RESTful Services-Datenbankbenutzer anzugeben (APEX_LISTENER, APEX_REST_PUBLIC_USER), oder 2, um diesen Schritt zu überspringen [1]:
    Datenbankkennwort für APEX_LISTENER eingeben:***
    Kennwort bestätigen:***
    Datenbankkennwort für APEX_REST_PUBLIC_USER eingeben:***
    Kennwort bestätigen:***
    Jul 05, 2018 6:20:04 AM
    INFORMATION: Updated configurations: defaults, apex, apex_pu, apex_al, apex_rt
    Oracle REST Data Services Version 18.2.0.r1831332 wird installiert
    ... Logdatei in C:\Users\vaiomarco\ords_install_core_2018-07-05_062004_00605.log geschrieben
    ... Datenbankvoraussetzungen wurden verifiziert
    ... Oracle REST Data Services-Schema wurde erstellt
    ... Oracle REST Data Services-Proxybenutzer wurde erstellt
    ... Berechtigungen für Oracle REST Data Services wurden erteilt
    ... Oracle REST Data Services-Datenbankobjekte wurden erstellt
    ... Logdatei in C:\Users\vaiomarco\ords_install_datamodel_2018-07-05_062017_00179.log geschrieben
    ... Logdatei in C:\Users\vaiomarco\ords_install_apex_2018-07-05_062019_00485.log geschrieben
    Installation für Oracle REST Data Services Version 18.2.0.r1831332 wurde abgeschlossen. Verstrichene Zeit: 00:00:17.460

Nun wurde die "ords.war" Datei konfiguriert und muss MANUELL in folgendes Verzeichnis kopiert werden:

Windows: 
C:\Program Files\Apache Software Foundation\Tomcat 9.0\webapps

 

Linux:
    /opt/tomcat*/webapps

Wenn Sie den Applicationserver (Tomcat) durchgestartet haben, sollte er aus dem "ords.war" einen Ordner "ords" mit einigen Unterordnern angelegt haben.

Verzeichnisse des ORDS

2. Troubleshooting / Fehlerbehebung von ORDS-Problemen:

ORDS 404 Fehler

Der Klassiker ... ein "404 not Found"-Fehler. Wir schalten mal das Debugging ein (siehe oben) und starten Tomcat durch.

ORDS DEBUG 404

Na, das ist doch gleich viel besser :-) "Could not find any dispatcher to handle request..." heisst also u.a. APEX_PUBLIC_USER Account ist nicht offen:

Wir prüfen das Mal:

SELECTusername,account_status,lock_date from dba_users
    WHERE username like 'APEX%'
    OR username like 'ORDS%'
    OR username like 'FLOWS%'
    OR username ='ANONYMOUS'
    order by 1;
USERNAMEACCOUNT_STATUSLOCK_DATE  
ANONYMOUSOPEN   
APEX_INSTANCE_ADMIN_USEREXPIRED   
APEX_LISTENEROPEN   
APEX_PUBLIC_USERLOCKED05.07.2018 07:46:00  
APEX_REST_PUBLIC_USEROPEN   
ORDSYSEXPIRED & LOCKED08.03.2017 17:06:16  
APEX_180100EXPIRED & LOCKED29.06.2018 06:25:44  
FLOWS_FILESEXPIRED & LOCKED29.06.2018 06:25:45  
ORDS_METADATAEXPIRED & LOCKED05.07.2018 06:20:06  
ORDS_PUBLIC_USEROPEN   
     

 

Na da haben wir ja den Schuldigen: APEX_PUBLIC_USER ist gesperrt.

ALTER USER APEX_PUBLIC_USER ACCOUNT UNLOCK;

Vergessen Sie nicht nach jeder Änderung, den Applicationserver (Tomcat) durchzustarten!

2. Problem: Die Bilder-/ CSS-/ Java-Script-Dateien fehlen, oder liegen im falschen Verzeichnis.

APEX Fehlende Bilder

Prüfen Sie bitte, ob ein Ordner mit Namen "i" im Verzeichnis .. tomcat/WebApps/ROOT liegt, ansonsten könnte die Seite (weil die CSS-Dateien nicht geladen werden) so aussehen:

APEX Fehler ohne CSS

Wenn dann aber die Bilder-/ CSS-/ Java-Script-Dateien an richtiger Stelle liegen, haben wir zur Belohnung die Anmeldemaske:

APEX Anmeldung

3. Es kommt die Fehlermeldung, dass die Version der Bilder, nicht zur Version von APEX passt.

Da muss einfach der Browser Cache geleert werden.

4. Die "ords.war"-Datei funktioniert in Verbindung mit Tomcat einfach nicht:

Prüfen Sie die Konsistenz der Datei mit:

java -jar ords.war validate

Dann sollte folgende Ausgabe erscheinen:

Name des Datenbankservers eingeben [localhost]:
    Listener-Port der Datenbank eingeben [1521]:
    Datenbankservicename eingeben [o12c2]:
    Erfordert SYS AS SYSDBA, um das Oracle REST Data Services-Schema zu verifizieren.
    Datenbankkennwort für SYS AS SYSDBA eingeben:
    Kennwort bestätigen:
    Informationen werden abgerufen.
    Retrieving information.
    Oracle REST Data Services will be validated.
    Validating Oracle REST Data Services schema version 18.4.0.r3541002
    ... Log file written to /root/ords_validate_core_2019-01-16_133103_00877.log
    Completed validating Oracle REST Data Services version 18.4.0.r3541002.  Elapsed time: 00:00:04.798

Sie können natürlich auch noch die dazugehörige Log-Datei analysieren. Da sollte dann z.B. u.a. folgendes zu finden sein:

INFO: 08:27:22 Validating objects for Oracle REST Data Services.
    VALIDATION: 08:27:22 Starting validation for schema: ORDS_METADATA
    VALIDATION: 08:27:22 Validating objects
    VALIDATION: 08:27:23 Validating ORDS Public Synonyms
    VALIDATION: 08:27:24 Total objects: 259, invalid objects: 0
    VALIDATION: 08:27:24     72  INDEX
    VALIDATION: 08:27:24      1  JOB
    VALIDATION: 08:27:24     11  PACKAGE
    VALIDATION: 08:27:24     11  PACKAGE BODY
    VALIDATION: 08:27:24     43  PUBLIC SYNONYM
    VALIDATION: 08:27:24      1  SEQUENCE
    VALIDATION: 08:27:24     14  SYNONYM
    VALIDATION: 08:27:24     27  TABLE
    VALIDATION: 08:27:24     26  TRIGGER
    VALIDATION: 08:27:24     19  TYPE
    VALIDATION: 08:27:24      6  TYPE BODY
    VALIDATION: 08:27:24     28  VIEW
    VALIDATION: 08:27:24 Validation completed.
    INFO: 08:27:24 Completed validating objects for Oracle REST Data Services.

Zu guter letzt: Ein Problem, was mir vier Wochen Suche beschert hat. Wir hatten bei der Installation von ORDS immer das Problem, dass sich die Installation an einer Stelle aufgehängt hatte. Sie hing ca. 15 min und stüzte dann ab mit " IO Error: Connection reset by Peer". 
Das Problem war, dass Java auf unserem System (CentOS 7) mit "/dev/random" nicht genügend viele Zufallszahlen berechnen konnte und stattdessen "/dev/urandom" nehmen musste.

Dazu müssen Sie bei der Installation folgendes zuätzlich angeben:

java -Djava.security.egd=file:///dev/urandom -jar ords.war

Allerdings kann man auch dem Pool der Zufallszahlen von "/dev/random" etwas mehr Entropie verleihen und daher weiterhin "/dev/random" nutzen. Dazu installiert man sich ein entsprechendes Tool:

yum install haveged 
systemctl enable haveged; systemctl start haveged;

5. Eine ominöse CSS Datei wird nicht gefunden z.B. 56437564376.css

Hier war eine fehlerhafte ords Installation Schuld, es fehlte die Datei apex_rt.xml

Prüfen Sie nach der Installation, ob die folgenden Dateien im angegebenen Config Verzeichnis liegen:

drwxr-xr-x 2 tomcat tomcat 4096 Jan 16 13:16 conf
    -rw-r--r-- 1 tomcat tomcat  478 Jan 16 13:16 defaults.xml

und im conf Unterordner:

-rw-r--r-- 1 tomcat tomcat 357 Jan 16 13:16 apex_al.xml
    -rw-r--r-- 1 tomcat tomcat 360 Jan 16 13:16 apex_pu.xml
    -rw-r--r-- 1 tomcat tomcat 365 Jan 16 13:16 apex_rt.xml
    -rw-r--r-- 1 tomcat tomcat 360 Jan 16 13:16 apex.xml

Die apex_rt.xml datei sieht z.B. so aus:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
    <properties>
    <comment>Saved on Wed Jan 16 09:37:29 CET 2019</comment>
    <entry key="db.password">@0529A217A76655C4328127B3215A50F0D1EF46AB65FEB176BE9E0220</entry>
    <entry key="db.username">APEX_REST_PUBLIC_USER</entry>
    </properties>

Fehlerhafte / fehlende Dateien weden auch in der log Datei catalina.out angezeigt:

Caused by: oracle.dbtools.url.mapping.TargetNotAvailableException: The connection pool named: apex_rt does not exist
            at oracle.dbtools.url.mapping.db.PoolInjector.inject(PoolInjector.java:60)
            at oracle.dbtools.url.mapping.db.DatabaseURLMappingImpl.addServices(DatabaseURLMappingImpl.java:311)
            at oracle.dbtools.url.mapping.URLMappingBase.doFilter(URLMappingBase.java:80)

Kürzlich hatten wir einen neuen Fehler, der stellte sich wie folgt da: 
Eine CSS Datei des Theme Rollers konnte auf einem Server teilweise nicht mehr gefunden werden. Teilweise ist immer spannend ... 
Ein Blick in die catalina.out brachte etwas Licht ins Dunkel: Einige ORDS_METADATA Views waren invalid- Bei genauerer Betrachtung der Views, stellte sich heraus, dass die dazu passenden Tabellen gar nicht (mehr) da waren. 

Nur wo werden diese angelegt. Nach einiger Suche habe ich beim Auspacken des ords.war Files die Datei ords_database.objects.sql im Ordner scripts/install/core gefunden. 
Nachdem das Skript nochmal installiert wurde (bitte im Schema ORDS_METADATA) lief wieder alles perfekt. 
Sicherheitshalber kann man natürlich einen Zusatzcheck durchführen (hoer mir ORDS Version 19.2 (Stand 26.09.2019))

select object_type,count(valid),count(invalid) from (
    select object_type,
    CASE WHEN status='VALID' THEN 1 END  as valid,
    CASE WHEN status<>'VALID' THEN 1 END  as invalid
    from dba_objects
    where owner='ORDS_METADATA')
    group by Object_type
    order by 1;


Das Ergebnis sollte dann so aussehen:

OBJECT_TYPEVALIDINVALID
INDEX750
JOB10
LOB30
PACKAGE120
PACKAGE BODY120
SEQUENCE10
SYNONYM140
TABLE270
TRIGGER260
TYPE190
TYPE BODY60
VIEW280



So, das war es mit einer Kurzübersicht :-) zur Installation und Troubleshooting. Weitere Tipps erhalten Sie in einem unserer beliebten APEX-Kurse.

 



Weitere Interessente Artikel zum Thema:


Empfohlene Schulungen zum Thema:


Gesperrte Schemata in Application Express

Bereich:APEX, Version: ab APEX 5.x, Letzte Überarbeitung: 12.12.2018

Keywords:APEX

Ist es Ihnen schon passiert, dass Sie in Application Express ein Schema einem Workspace zuordnen wollten, aber dieses Schema wurde Ihnen nicht angeboten? Und wenn Sie den Schemanamen trotzdem manuell eingetragen haben, wurde der Versuch mit folgender Fehlermeldung quittiert: "The requested schema is reserved or is restricted and the site administrator does not have the privilege to assign restricted schemas to workspaces.".

Das liegt daran, dass standardmäßig alle vordefinierten Schemata (z.B. SYSTEM, SCOTT, RMAN, HR, SH ....) für den Zugriff über Application Express gesperrt sind. Die Liste aller gesperrten Schemata erhalten Sie mit folgendem Select:

SELECT schema FROM APEX_180200.WWV_FLOW_RESTRICTED_SCHEMAS;

Anmerkung: Hier wie im folgenden wird von der Application Express Version 2.0 ausgegangen. Bei anderen Versionen muss der Schemaname entsprechend angepasst werden.

Schemanamen der Unterschiedlichen Apex Versionen:

APEX_050000Version 5.0
APEX_050100Version 5.1
APEX_180100Version 18.1
APEX_180200Version 18.1
APEX_190100Version 19.1 (in Planung)

 Über das Package APEX_180200.APEX_INSTANCE_ADMIN.UNRESTRICT_SCHEMA kann ein Datenbankadministrator Schemata freigeben oder sperren.

Es beinhaltet folgende Prozeduren:

UNRESTRICT_SCHEMA: Dadurch wird ein Schema generell freigegeben für die Verwendung.

RESTRICT_SCHEMA: Dadurch wird ein Schema generell gesperrt für die Verwendung.

CREATE_EXCEPTION: Dadurch wird ein an sich gesperrtes Schema für einen bestimmten Workspace freigegeben.

REMOVE_EXCEPTION: Dadurch wird eine solche Freigabe für einen bestimmten Workspace wieder aufgehoben.

REMOVE_SCHEMA_EXCEPTIONS: Dadurch werden alle über CREATE_EXCEPTION gemachte Freigaben für ein bestimmtes Schema zurückgenommen.

REMOVE_WORKSPACE_EXCEPTIONS: Dadurch werden alle über CREATE_EXCEPTION gemachte Freigaben für einen bestimmten Workspace zurückgenommen.

  • REPORT: Dadurch wird ein SELECT erzeugt, über den angezeigt werden kann, welche Sperren und Ausnahmen es gibt. 

Alle Freigaben und Sperren über das Package müssen mit COMMIT abgeschlossen werden, um in Kraft zu treten. Wird ein Schema gesperrt, so sind bereits getroffene Workspace-Zuordnungen davon nicht betroffen. Generell freigegebene Schemata verschwinden aus WWW_FLOW_RESTRICTED_SCHEMAS, begrenzt freigegebene jedoch nicht. Mit CREATE_EXCEPTION erzeugte Ausnahmen sind in WWV_FLOW_RSCHEMA_EXCEPTIONS zu finden:

SELECT schema_id, workspace_name FROM APEX_180200.WWV_FLOW_RSCHEMA_EXCEPTIONS;

Die Prozedur REPORT erzeugt nur einen SELECT-Befehl, der die beiden Tabellen verknüpft und gibt diesen SELECT-Befehl über DBMS_OUTPUT aus, nicht jedoch dessen Ergebnis. Der ausgegebene Select lautet (unabhängig vom angemeldeten User):

SELECT a.schema "SCHEMA", b.workspace_name "WORKSPACE"
FROM WWV_FLOW_RESTRICTED_SCHEMAS a, WWV_FLOW_RSCHEMA_EXCEPTIONS b
WHERE b.schema_id(+) = a.id;

Beispiele: 

BEGIN
   FLOWS_020000.HTMLDB_SITE_ADMIN_PRIVS.UNRESTRICT_SCHEMA(p_schema => 'SCOTT');  
   COMMIT;
END;
/

BEGIN
   FLOWS_020000.HTMLDB_SITE_ADMIN_PRIVS.RESTRICT_SCHEMA(p_schema => 'HAS');
   COMMIT;
END;
/

BEGIN
   FLOWS_020000.HTMLDB_SITE_ADMIN_PRIVS.CREATE_EXCEPTION
     (p_schema => 'HAS',
      p_workspace => 'SCHULUNG');
   COMMIT;
END;
/

BEGIN
   FLOWS_020000.HTMLDB_SITE_ADMIN_PRIVS.REMOVE_EXCEPTION
       (p_schema => 'HAS',
        p_workspace =>'SCHULUNG');
    -- oder:
   FLOWS_020000.HTMLDB_SITE_ADMIN_PRIVS.REMOVE_WORKSPACE_EXCEPTIONS
     (p_workspace => 'SCHULUNG');
    -- oder:  
   FLOWS_020000.HTMLDB_SITE_ADMIN_PRIVS.REMOVE_SCHEMA_EXCEPTIONS
     (p_schema => 'HAS');
   COMMIT;
END;
/



Weitere Interessente Artikel zum Thema:


Empfohlene Schulungen zum Thema:


Reguläre Ausdrücke in Oracle

Bereich:APEX:PL/SQL, Version: ab RDBMS 12.x, Letzte Überarbeitung: 05.09.2023

Keywords:PL/SQL

Diesmal soll es vor allem um einfache Anwendungsbeispiele für die Funktionen REGEXP_LIKE, REGEXP_SUBSTR und REGEXP_REPLACE gehen.

Wenn man sich mit der gewöhnungsbedürftigen Syntax (einen Überblick finden Sie am Schluss) erst einmal vertraut gemacht hat, können reguläre Ausdrücke beim Formatieren und Bereinigen von Tabelleninhalten, bei der Formulierung von komplizierten Check-Constraints u.a sehr gute Dienste leisten.

Ausgangspunkt für die Beispiele ist die folgende Tabelle (s. Anhang), die mit den regexp-Funktionen überprüft, bereinigt und ggf. vor falschen Eingaben geschützt werden sollte:

NAME         TELEFON             EMAIL                       PLZ     STRASSE
Maier        +49/012-345678-012  johann.maier@chaos.de       00000   24 a, Langstr.
meyer        012-345678-013      peter.meyer@chaos.de        a0674   1a,Langstr. G
Mayerhöfer   012-345678-014      frank.mayerhoefer@chaos.de  00345   10-11, Langstr.
MEYR         012-345678-015      tomas.meyr@chaos.de         19387   16b, Waldgasse
Mayer        012-345678016       richard.mayer@chaos.de      11028    22, Richterstr.
Müller       012-345678-017      martin.mueller@chaos.de     -       235b, Langstr.
Mair         012-345678-018      wilhelmine.mair@chaos.de    12345    35a, Langstr.
meir         0049/012-345678-019 sabine.meir@chaos.de         12345  101, Langstr.
myers        0049-12-345678-029  jeff.myers@chaos.de         03927   10, Schlossallee
müller       D012-345678-021     kurt.müller2@chaos.de       12098   10 c, Langstr.
Hintermeier    012-345678-022    hansi.hintermeier@chaos.de   11937  180, Holzweg  
MEIER        #012-345678023      eva.meier@chaos.de          12346   301, Langstr.
mAYR         ?49-12-345678-024   klaus.mayr@chaos.de         19207  5d, Gärtnerplatz  
MILLER       345678025           oscar.miller@chaos.de       1525    10  a, Langstr.

 
1. Prüfung auf unerwünschte Zeichen mit REGEXP_LIKE

REGEXP_LIKE vergleicht den Suchstring mit einem Muster und gibt true oder false zurück.

REGEXP_LIKE(Suchstring, Muster, Match-Parameter)

Die Angabe des Match-Parameters (siehe Anhang) ist optional.

Fangen wir mit der PLZ-Spalte an, in der nur 5 Ziffern stehen sollen und nichts anderes (wenn die PLZ mit einer 0 anfängt, darf an der 2. Stelle keine stehen):

SELECT name, plz, strasse FROM firma
WHERE NOT REGEXP_LIKE(plz, '^0[1-9][0-9]{3}$|^[1-9][0-9]{4}$');

 

NAME        PLZ   STRASSE
Maier       00000 24 a, Langstr.
meyer       0674  1a,Langstr.
Mayerhöfer  00345 10-11, Langstr.
Müller      -     235b, Langstr.
meir        12345 101, Langstr.
müller      12098 10 c, Langstr.
Hintermeier 11937 180, Holzweg
mAYR        19207 5d, Gärtnerplatz
MILLER      1525  10 a, Langstr.

Erläuterungen:

    eckige Klammern schließen eine Auswahl von Zeichen ein, [0-9] steht für die Ziffern von 0 bis 9, (alternative Formulierungen sind \d (ab 10g2) oder [[:digit:]]).
    Die Zahlen in geschweiften Klammern geben die Anzahl der Wiederholungen an, [0-9]{3} steht für 3 Ziffern.
    ^ und $ stehen für Anfang und Ende eines Ausdrucks. ^0 passt auf alle Muster, die mit einer 0 anfangen,[0-9]{3}$ auf alle, die mit 3 Ziffern aufhören.
    Vorsicht: Das Caret-Zeichen ^ hat diese Bedeutung nur, wenn es außerhalb von eckigen Klammern steht.
    Die Postleitzahlen mit einer Null am Anfang passen auf das Muster
    ^0[1-9][0-9]{3}$ (hier darf an der 2. Stelle keine 0 vorkommen), alle anderen auf ^[1-9][0-9]{4}$.
    Die beiden alternativen Muster werden durch das Oder-Zeichen | getrennt.

 
2. Beseitigung von unerwünschten Zeichen mit REGEXP_REPLACE

Die Oracle-Funktion REGEXP_REPLACE ersetzt das Muster im Suchstring durch den Ersatzstring.

REGEXP_REPLACE(Suchstring, Muster, Ersatzstring, Position, Vorkommen, Match-Parameter)

  • Position:         Position im Suchstring, an dem der Mustervergleich anfängt, default ist 1.
  • Vorkommen:  das nte Vorkommen des Musters im Suchstring, default ist 1.

Die Angabe von Position, Vorkommen und Match-Parameter ist optional.

Die störenden Leerzeichen und Buchstaben in der PLZ-Spalte kann man mittels REGEXP_REPLACE in einem Rutsch entfernen. (Wenn der Ersatzstring leer bleibt, kann man ihn auch weglassen):

UPDATE firma SET plz = REGEXP_REPLACE(plz, '[^0-9]','')
WHERE NOT REGEXP_LIKE(plz, '^0[1-9][0-9]{3}$|^[1-9][0-9]{4}$'); 
9 Zeilen wurden aktualisiert.

    Ein Caret-Zeichen innerhalb eines Klammerausdrucks kehrt die Zeichenauswahl um,
    [^0-9] steht also für alle Zeichen außer Ziffern, statt [^0-9] kann man auch \D oder [^[:digit:]] schreiben (s. Anhang).

Kontrolle:

SELECT name, plz, strasse FROM firma
WHERE not REGEXP_LIKE(plz, '^0[1-9][0-9]{3}$|^[1-9][0-9]{4}$')OR plz IS NULL;
NAME       PLZ    STRASSE
Maier      00000  24 a, Langstr.
meyer      0674   1a,Langstr.
Mayerhöfer 00345  10-11, Langstr.
Müller            235b, Langstr.
MILLER     1525   10 a, Langstr.

Diese 5 Felder muss man von Hand korrigieren, bevor man einen Check-Constraint einrichten kann:

UPDATE firma SET plz = ... WHERE name = ...

 
3. Verwendung von REGEXP_LIKE in Check-Constraints

Nach der Korrektur lässt sich durch Hinzufügen eines check-Constraints sicherstellen, dass in Zukunft keine Buchstaben, Sonder- oder Leerzeichen eingegeben werden:

ALTER TABLE firma
ADD CONSTRAINT firma_plz_check
CHECK (REGEXP_LIKE(plz, '^0[1-9][0-9]{3}$|^[1-9][0-9]{4}$'));

Ähnlich funktioniert die Einrichtung eines Check-Constraints der e-mail-Adressen, z.B.:

ALTER TABLE firma
ADD CONSTRAINT firma_mail_check
CHECK(REGEXP_LIKE(email, '^\w+\.\w+@\w+\.de$'));

    \w (ab 10g2)  steht für alle alphanumerischen Zeichen inklusive "_", + für eine beliebige Anzahl davon. Oracle akzeptiert \w nicht innerhalb der Zeichenlisten in eckigen Klammern.
    Der Punkt muss durch einen Backslash maskiert werden, weil er sonst als beliebiges Zeichen interpretiert würde. (Nur innerhalb von eckigen Klammern muss man die Metazeichen wie Punkt, Stern und Plus etc. nicht maskieren).
    Das @ steht für sich selbst.
    Statt de könnte man auch eine Auswahl angeben: [de|com|org] oder dem User mit \d{2,4} noch freiere Wahl lassen.

Wenn man auch Bindestriche oder ähnliches in den e-mail-Adressen zulassen will, muss man das Muster anders formulieren (dafür kann man Name und Vorname in einem Klammerausdruck unterbringen), z. B.:

^[-._0-9a-zA-Z]+@[-_0-9a-zA-Z]+\.[A-Za-z]{2,4}$'

 
4. Einfache Extraktion von Teilstrings mit REGEXP_SUBSTR

REGEXP_SUBSTR gibt einem dem Muster entsprechenden Teilstring des Suchstrings aus.

Was vor 10g mitunter komplizierte Kombinationen der Funktionen instr, SUBSTR und length erforderte, läßt sich mit REGEXP_SUBSTR in sehr kurzen Ausdrücken bewerkstelligen.

REGEXP_SUBSTR(Suchstring, Muster, Position, Vorkommen, Match-Parameter)

  • Position:         Position im Suchstring, an dem der Mustervergleich anfängt, default ist 1.
  • Vorkommen:  das nte Vorkommen des Musters im Suchstring, default ist 1.

Die Angabe von Position, Vorkommen und Match-Parameter ist wiederum optional.

Die Sekretärin möchte eine Adressenliste der Mitarbeiter als View erstellen, die folgende Informationen enthalten soll: Vorname, Nachname, PLZ, Straße und Hausnummer.

Die Vornamen kann man aus den e-mail-Adressen extrahieren und mit den Nachnamen verknüpfen:

SELECT INITCAP(REGEXP_SUBSTR(email, '[^.]+')||' '||name) AS Name FROM firma;

Aus johann.maier@chaos.de wird somit Johann Maier u.s.w. ...

    [^.] steht für alle Zeichen außer dem Punkt (innerhalb der Klammer steht der Punkt für sich selbst), per default wird der erste Teilstring ausgegeben, der dem Muster entspricht (vorkommen = 1).
    Wollte man den Nachnamen aus der Adresse holen, so müsste man REGEXP_SUBSTR(email, '[^.@]+',1,2) schreiben, (Position = 1, Vorkommen =2)
    REGEXP_SUBSTR(email, '[^.@]+',2) dagegen gibt den Vornamen ab dem 2. Zeichen aus (Position = 2, Vorkommen = default =1).
    Die Oracle-Funktion INITCAP sorgt für Großbuchstaben am Anfang und Kleinschreibung für den Rest.

 
5. Drehung am Komma mit REGEXP_REPLACE

Die umgedrehte Reihenfolge von Hausnummer und Strasse im amerikanischen Stil läßt sich durch mittels REGEXP_REPLACE umkehren:

SELECT LTRIM(REGEXP_REPLACE(strasse, '([^,]+),([^,]+)','\2 \1'))
AS strasse FROM firma;
Langstr. 24 a
Langstr. 1a
Langstr. 10-11
......

    Das Komma teilt den String in 2 Hälften, die runden Klammern dienen der Gruppierung.
    [^,]+ steht für ein bis beliebig viele Zeichen mit Ausnahme des Kommas.
    Durch die negative Formulierung läuft man nicht Gefahr, eine Art von Zeichen zu vergessen, zudem kann man sie für beide Seiten verwenden.
    Positiv formuliert müsste man das Muster z.B. so schreiben: '([- 0-9a-z]+),([a-zA-Z. ]+)'
    \1 und \2 sind sogenannte Rückwärtsreferenzen (back references), die sich auf die Gruppierungen im Suchstring beziehen. Der Ausdruck '\2 \1' zieht aus dem Muster die Gruppen 1 und 2 heraus (ohne das Komma), dreht sie um und fügt zwischen beiden ein Leerzeichen ein.
    Die Oracle-Funktion LTRIM entfernt führende Leerzeichen.

Jetzt können wir die View erstellen:

CREATE OR REPLACE VIEW adressen
AS SELECT
INITCAP(REGEXP_SUBSTR(email, '[^.]+')||' '||name) AS Name, plz,
LTRIM(REGEXP_REPLACE(strasse, '([^,]+),([^,]+)','\2 \1')) AS strasse
FROM firma;
SELECT * FROM adressen;
NAME             PLZ   STRASSE
Johann Maier     12345 Langstr. 24 a
Peter Meyer      12345 Langstr. 1a
Frank Mayerhöfer 12345 Langstr. 10-11
.......

 
6. Aufteilung von Strings in 2 Spalten mit REGEXP_SUBSTR

Die folgende View stellt alle Informationen in getrennten Spalten dar:

CREATE OR REPLACE VIEW adressen
AS SELECT INITCAP(REGEXP_SUBSTR(email, '[^.]+')) AS Vorname,
          INITCAP(name) as Nachname, plz,
          LTRIM(REGEXP_SUBSTR(strasse, '([^,]+)',1,2)) AS strasse,
          LTRIM(REGEXP_SUBSTR(strasse, '([^,]+)')) AS Nr
FROM firma;

Aus einem String wie z.B. '24 a, Langstr.' extrahiert

REGEXP_SUBSTR(strasse, '([^,]+)',1,2))das 2. Vorkommen des Musters (Strasse), und REGEXP_SUBSTR(strasse, '([^,]+)',1,1)) das 1. Vorkommen (Hausnummer, die beiden Einser können hier auch wegfallen, weil sie der Default sind):

SELECT * FROM adressen;
VORNAME NAME       PLZ   STRASSE  NR
Johann  Maier      12345 Langstr. 24 a
Peter   Meyer      12345 Langstr. 1a
Frank   Mayerhöfer 12345 Langstr. 10-11
....

 
7. Sortierung von alphanumerischen Einträgen mit REGEXP_SUBSTR

Alle Angestellten, die in der Langstrasse wohnen, möchten eine Fahrgemeinschaft bilden. Der Fahrer hätte gern eine nach Hausnummern geordnete Liste der Namen. Wegen der Buchstaben und Leerzeichen etc. funktioniert der direkte Ansatz nicht, auch wenn man die vorangehenden Leerzeichen mit LTRIM eliminiert:

SELECT name, strasse FROM firma
WHERE strasse LIKE '%Lang%'
ORDER BY LTRIM(strasse);

NAME       STRASSE
meyer      1a,Langstr.
MILLER     10 a, Langstr.
müller     10 c, Langstr.
meir       101, Langstr.
Mayerhöfer 10-11, Langstr.
....

Eine Kombination dieser alphabetischen Sortierung mit der Sortierung nach dem Zahlenteilstring bringt dagegen das erwünschte Ergebnis:

SELECT INITCAP(name) Name, LTRIM(REGEXP_SUBSTR(strasse,'[^,]+')) Nr
FROM firma
WHERE strasse LIKE '%Lang%'
ORDER BY TO_NUMBER(REGEXP_SUBSTR(strasse, '[0-9]+')), LTRIM (strasse);

 

NAME       NR
Meyer      1a
Miller     10 a
Müller     10 c
Mayerhöfer 10-11
....

REGEXP_SUBSTR(strasse, '[0-9]+') extrahiert die erste zusammenhängende Zahl aus dem String,(z.B. 10-11 ' 10) was die Umwandlung mit TO_NUMBER und damit die richtige Sortierung ermöglicht.

 
8. Entfernung von doppelten Leerzeichen mit REGEXP_REPLACE

Die Ausgabe kann man noch etwas verschönern, indem man die doppelten Leerzeichen in der Hausnummern-Spalte entfernt:

SELECT INITCAP(name) Name,
       LTRIM(REGEXP_REPLACE(REGEXP_SUBSTR(strasse,'[^,]+'),'( ){2,}',
       ' ')) Nr
FROM firma
WHERE strasse LIKE '%Lang%'
ORDER BY TO_NUMBER(REGEXP_SUBSTR(strasse, '[0-9]+')), LTRIM (strasse);
NAME    NR
Meyer   1a
Miller  10 a
Müller  10 c
....

    '( ){2,}' findet Gruppen von mindestens 2 Leerzeichen und ersetzt sie durch eins: ' '. Die runden Klammern dienen nur der Übersichtlichkeit.

 
9. Formatierung von Ausdrücken mit REGEXP_REPLACE

Die Telefonnummern sollen von Leer-, Sonderzeichen u. ä. befreit werden und folgendes Format erhalten: (+49-12)345-6789-029. Die zu bereinigenden Einträge findet man mit:

SELECT telefon FROM firma WHERE REGEXP_LIKE(telefon, '[^-0-9]');
TELEFON
+49/012-345678-012
0049/012-345678-019
0049-12-345678-029
D012-345678-021
  012-345678-022
#012-345678023
?49-12-345678-024

[^-0-9] steht für alles außer Bindestrich und Ziffern. Mit REGEXP_REPLACE kann man so alle Zeichen außer den Ziffern entfernen, indem man den Ersatzstring einfach wegläßt.:

UPDATE firma SET telefon = REGEXP_REPLACE(telefon, '[^0-9]');
14 Zeilen wurden aktualisiert

Für die Formatierung gibt es 2 Möglichkeiten:

a)   Verwendung der Oracle-SUBSTR-Funktion (weil sich nur die Durchwahl ändert):

UPDATE firma SET telefon = '(+49-12)345-678-' || SUBSTR(telefon,-3);

SUBSTR(telefon,-3) startet beim dritten Zeichen von hinten und gibt den Rest aus.

b)   Verwendung von REGEXP_REPLACE, komplizierter, aber allgemeingültiger:

UPDATE firma SET telefon = REGEXP_REPLACE(telefon,
          '(0*49)?(0?12)?(\d{3})(\d{3})(\d{3})', '(+49-12)\3-\4-\5');
Gruppe:      1       2      3      4      5

Hier werden wieder Backreferences verwendet. Die Gruppen von Zeichen, die man umformatieren will, werden durch runde Klammern gekennzeichnet.

Die Gruppen 1 (beliebig viele Nullen gefolgt von 49) und 2 (eine oder keine Null gefolgt von 12) die jeweils ein oder kein Mal vorkommen, werden durch (+49-12) ersetzt, die folgenden 3 Gruppen 3 - 5 mit Bindestrich aneinandergehängt.

Hinweis; Oraclle unterstützt maximal 9 Gruppen (1-9)

Die Säuberung und Formatierung kann man mit einem geschachtelten REGEXP_REPLACE auch in einem Zug erledigen:

ROLLBACK;
UPDATE firma SET telefon =
REGEXP_REPLACE(REGEXP_REPLACE(telefon,'[^0-9]'),
               '(0*49)?(0?12)?(\d{3})(\d{3})(\d{3})','(+49-12)\3-\4-\5');
SELECT telefon FROM FIRMA;
TELEFON
(+49-12)345-678-012
(+49-12)345-678-013
(+49-12)345-678-014
(+49-12)345-678-015

 
10. Suche nach Wörtern mit verschiedener Schreibweise über REGEXP_LIKE:

Angenommen, die Tabelle hätte 100000 Datensätze und wir wollen alle Angestellten suchen, die Maier oder so ähnlich heißen, unabhängig von Groß- und Kleinschreibung und Schreibweise:

SELECT name FROM firma WHERE REGEXP_LIKE (name, '^m[ae][yi].?r$','i');

    Hier wird nach einem m am Anfang, gefolgt von a oder e, gefolgt von y oder i gefolgt von 0-1 weiteren Buchstaben und einem r am Schluss gesucht.
    Der Parameter 'i' steht für case insensitive.

Zusammenfassung der wichtigsten Metazeichen und ihrer Bedeutung:

    Der Punkt steht für ein beliebiges Zeichen (ausser einen Zeilenumbruch).
    eckige Klammern stehen für eine Auswahl von Zeichen,   [g-l] z. B. für g, h, i, j, k oder l
    [0-9A-G] für eine beliebige Ziffer oder einen Großbuchstaben von A bis G .
    Statt die Zeichenauswahl explizit anzugeben, kann man mit den sog. Charakterklassen arbeiten.
    Die wichtigsten sind:
    [:alnum:]   alle alphanumerischen Zeichen, [[:alnum:]] entspricht  also [0-9A-Za-z]
    \w                  alle alphanumerischen Zeichen und der Unterstrich "_"
    [:alpha:]   alle Buchstaben, [[:alpha:]] entspricht [A-Za-z]
    [:digit:] bzw. \d    alle Ziffern, [[:digit:]] entspricht [0-9]  
    [:space:] bzw.  \s    alle Zeichen, die man nicht sieht, Leerzeichen, Tabzeichen, Enter...
    \W, \D und S\   sind die Umkehrungen von  \w, \d und \s
    Die Abkürzungen \d, \w etc. stehen seit Version 10.2 zur Verfügung.
    Das pipe-Symbol | bedeutet "oder", z.B.  [ae|ä], [Otto|Emma], etc.
    Das Dollarzeichen $ verankert das vorausgehende Zeichen am Ende einer Zeile bzw. des Suchstrings,
    'r$' passt z.B. auf 'Müller' oder 'Herr', aber nicht zu 'rau' oder 'Karren'
    Das Caret-Zeichen ^ hat je nachdem, wo es steht, unterschiedliche Bedeutungen
        ein Caret-Zeichen außerhalb eckiger Klammern  verankert das nachfolgende Zeichen am Beginn einer Zeile bzw. des Suchstrings
        ('^z.*' passt auf 'ziel', 'zeichen' etc, aber nicht auf 'platz', 'setzen')
        ein Caret-Zeichen innerhalb eckiger Klammern schließt die nachfolgenden Zeichen aus.
        dementsprechend bedeutet:
        ^[:alnum:]] alle nicht-alphanumerischen Zeichen (Sonderzeichen, Leerzeichen...)
        [^0-9]                 alles ausser Ziffern
    Der Stern *   steht für keine oder beliebig viele Wiederholungen des vorausgehenden Elements (Zeichen oder Gruppe), '.*' passt also auf jeden String
    Das Fragezeichen ?  steht für keine oder eine Wiederholung
    Das Pluszeichen +   steht für eine oder beliebig viele Wiederholungen
    {n}   steht für n Wiederholungen
    {min,max}  steht für min bis max Wiederholungen des Elements ,
    {3,6} z. B für 3 bis 6,
    {3,}  für mindestens 3

Außerhalb von eckigen Klammern bzw. in Kombinationen mit Charakterklassen muss man den Metazeichen einen Backslash voranstellen, wenn man explizit nach ihnen sucht,

z.B. \+, \?, \* etc.

 
Match-Parameter für die Oracle-REGEXP-Funktionen:

    i (case insensitive)
    Groß- und Kleinschreibung wird nicht berücksichtigt
    c (case sensitive)
    Groß- und Kleinschreibung wird berücksichtigt
    n (newline)
    Der Punkt kann in diesem Fall auch für einen Zeilenumbruch stehen.
    m (multiline)
    Die Zeichenkette wird als mehrzeilige Eingabe betrachtet.^und $ können dann auf jede Zeile angewandt werden und nicht nur für Anfang und Ende des Strings.

Mit dem folgenden SQL-Code können Sie sich die Übungstabelle selbst erstellen:

DROP TABLE firma;
CREATE TABLE firma(
name       VARCHAR2(20),
telefon    VARCHAR2(20),
email      VARCHAR2(30),
plz        VARCHAR2(10),
strasse    VARCHAR2(50));
INSERT INTO firma VALUES ('Maier','+49/012-345678-012','johann.maier@chaos.de','00000','24 a,Langstr.');
INSERT INTO firma VALUES ('meyer','012-345678-013','peter.meyer@chaos.de','a0674','1a,Langstr. ');
INSERT INTO firma VALUES ('Mayerhöfer','012-345678-014','frank.mayerhoefer@chaos.de','00345','10-11,Langstr.');
INSERT INTO firma VALUES ('MEYR','012-345678-015','tomas.meyr@chaos.de','19387','16b,Waldgasse');
INSERT INTO firma VALUES ('Mayer','012-345678016','richard.mayer@chaos.de','11028',' 22,Richterstr.');
INSERT INTO firma VALUES ('Müller','012-345678-017','martin.mueller@chaos.de','-','235b,Langstr.');
INSERT INTO firma VALUES ('Mair','012-345678-018','wilhelmine.mair@chaos.de','12345',' 35a,Langstr.');
INSERT INTO firma VALUES ('meir','0049/012-345678-019','sabine.meir@chaos.de',' 12345','101,Langstr.');
INSERT INTO firma VALUES ('myers','0049-12-345678-029 ','jeff.myers@chaos.de','03927','10,Schlossallee');
INSERT INTO firma VALUES ('müller','D012-345678-021','kurt.müller2@chaos.de','12098 ','10 c,Langstr.');
INSERT INTO firma VALUES ('Hintermeier',' 012-345678-022','hansi.hintermeier@chaos.de',' 11937','180,Holzweg ');
INSERT INTO firma VALUES ('MEIER','#012-345678023','eva.meier@chaos.de','12346','301,Langstr.');
INSERT INTO firma VALUES ('mAYR','?49-12-345678-024','klaus.mayr@chaos.de',' 19207','5d,Gärtnerplatz ');


Weitere Interessente Artikel zum Thema:


Empfohlene Schulungen zum Thema:


APEX 20.2 Backups selbst konfigurieren

Bereich:APEX, Version: ab APEX 20.1:APEX 20.2, Letzte Überarbeitung: 29.04.2020

Keywords:APEX Backup

Das neue Oracle APEX 20.1 hat uns ja wieder mit vielen neuen Funktionen überrascht. Eines davon ist die autoamtische Backup-Funktionalität.
Nur leider ist diese sehr wenig konfigurierbar.

Sie können einstellen, wieviele Backups pro APP behalten werden sollen.

Der Default sind 25 Backups pro App

SELECT apex_200100.WWV_FLOW_PLATFORM.GET_PREFERENCE('MAX_APPLICATION_BACKUPS')
FROM dual;
--oder für die neuere Version APEX 20.2
SELECT apex_200200.WWV_FLOW_PLATFORM.GET_PREFERENCE('MAX_APPLICATION_BACKUPS')
FROM dual;

=>25
Ändern können Sie die Anzahl mittels:

BEGIN
apex_instance_admin.set_parameter('MAX_APPLICATION_BACKUPS','5');
END;


Eine Übersicht der bereits existierenden Backups erhalten Sie durch:

SELECT flow_id,name,apex_util.filesize_mask(doc_size) as doc_size,created_on
FROM flows_files.wwv_flow_file_objects$ f
WHERE file_type='FLOW_BACKUP'
ORDER BY created_on ;


Für die nächtlichen Backup verantwortlich, ist der Job mit Namen wwv_flow_backup.main:


SELECT job_name,job_action,repeat_interval,run_count
FROM dba_scheduler_jobs
WHERE owner='APEX_200200';


Dieser läuft jede Nacht um 02:00 Uhr

Sie können jedich auch manuell ein Backup erstellen durch:

BEGIN wwv_flow_backup.application (
p_batch_id          =>1,
p_application_id    =>100,
p_application_name  =>'MyApp',
p_security_group_id =>1234567890,
p_last_updated_on   =>sysdate,
p_description       =>'Mein Montags Backup ');
COMMIT;
END;


Auch können Backup manuell gelöscht werden (Hier die Appliaktionen 11000 und 11020:

BEGIN
FOR c In (select  b.id,f.security_group_id,f.flow_id,f.created_on
FROM flows_files.wwv_flow_file_objects$ f, apex_200200.WWV_FLOW_BACKUPS$ b
WHERE f.id=b.object_id
AND file_type='FLOW_BACKUP'
AND flow_id IN (11000,11020))  LOOP
dbms_output.put_line('Remove :'||c.flow_id);
wwv_flow_api.set_security_group_id(c.security_group_id);
apex_200100.wwv_flow_backup.remove(
  p_application_id=>c.flow_id,
  p_security_group_id=>c.security_group_id,
  p_backup_id=>c.id);
END LOOP;
COMMIT;
END;


Oder alternativ löschen wir alle APEX Backups, die älter als 100 Tage sind:

DECLARE
v_tage IN:=100;
BEGIN
FOR c In (select  b.id,f.security_group_id,f.flow_id,f.created_on
FROM flows_files.wwv_flow_file_objects$ f, apex_200200.WWV_FLOW_BACKUPS$ b
WHERE f.id=b.object_id
AND file_type='FLOW_BACKUP'
AND b.created_on<sysdate-v_tage)  LOOP
dbms_output.put_line('Remove :'||c.flow_id);
wwv_flow_api.set_security_group_id(c.security_group_id);
apex_200200.wwv_flow_backup.remove(
  p_application_id=>c.flow_id,
  p_security_group_id=>c.security_group_id,
  p_backup_id=>c.id);
END LOOP;
COMMIT;
END;


Weitere Tipps und Tricks zu APEX 20.1 und APEX 20.2 erhalten Sie natürlich in einen unserer 6 verschiedenen APEX-Kurse... Online oder bei uns Vorort



Weitere Interessente Artikel zum Thema:


Empfohlene Schulungen zum Thema:


REST Beispiele mit apex_web_service

Bereich:APEX:PL/SQL:REST, Version: ab RDBMS 19.3:RDBMS 21.1:ORDS 20.3, Letzte Überarbeitung: 06.07.2023

Keywords:Oracle apex_web_service Beispiele, APEX

Nachdem das Thema REST immer mehr an Schwung gewinnt, wird es Zeit darüber einen Tipp zu schreiben.
Wir haben aus eigener Erfahrung lange im Internet gesucht und nur selten etwas gefunden.
Deswegen haben wir ein paar Beispiele gesammelt:

Der Einfachheit halber, wird mit nicht mit SSL Verschlüsselung gearbeitet, ansonsten muss noch ein Wallet eingerichtet werden

1. CLOB Übertragen (upload)

l_clob:=APEX_WEB_SERVICE.MAKE_REST_REQUEST(      
 p_url=>'http://www.muniqsoft-training.de/ords/my_rest/muso/putCLOB',
 p_http_method        =>'PUT',
 p_transfer_timeout   =>720,
 p_username           =>'rest_user',
 p_password           =>'rest_password'
 p_body               =>text_lob,  --CLOB Datentyp übertragen         
);


Auf dem Zielserver dann einen Rest-Service anlegen (Typ PUT):

BEGIN
 my_proc(:body_text);
END;


Die Procedure my_proc könnte dann wie folgt aussehen:

CREATE OR REPLACE PROCEDURE my_proc (p_clob IN CLOB)
IS
...
BEGIN
...
END;


2. BLOB übertragen (upload)

l_clob:=APEX_WEB_SERVICE.MAKE_REST_REQUEST(      
p_url=>'http://www.muniqsoft-training.de/ords/my_rest/muso/putBLOB',
 p_http_method      =>'PUT',
 p_transfer_timeout =>720,
 p_username         =>'rest_user',
 p_password         =>'rest_password'
 p_body_blob        =>pdf_lob, --BLOB Datentyp übertragen 
);


Auf dem Zielserver dann einen Rest-Service anlegen (Typ PUT):

BEGIN
my_proc(:body);
END;


Die Procedure my_proc könnte dann wie folgt aussehen:

CREATE OR REPLACE PROCEDURE my_proc (p_blob IN BLOB)
IS
...
BEGIN
...
END;


3. Zwei Parameter übertragen (Upload)

DECLARE
l_clob CLOB;
BEGIN
    apex_web_service.g_request_headers.delete();
     apex_web_service.g_request_headers(1).name  := 'Content-Type';  
     apex_web_service.g_request_headers(1).value := 'application/octet-stream'; --'application/x-www-form-urlencoded';
     apex_web_service.g_request_headers(2).name  := 'PARAMETER_A';  
     apex_web_service.g_request_headers(2).value := '12345';
     apex_web_service.g_request_headers(3).name  := 'PARAMETER_B';  
     apex_web_service.g_request_headers(3).value := to_char(sysdate,'DD.MM.YYYY');
l_clob:=APEX_WEB_SERVICE.MAKE_REST_REQUEST(
        p_url=>'http://www.muniqsoft-training.de/ords/my_rest/muso/putDATA',
        p_http_method       =>'PUT',
        p_transfer_timeout  =>180,
        p_username          =>'rest_user',
        p_password          =>'rest_passwort',
        p_body              =>my_clob_text);
 if apex_web_service.g_status_code = 200 then
    dbms_output.put_line('Übertragung erfolgreich abgeschlossen.');
 else
    dbms_output.put_line('Fehler aufgetreten: ' || apex_web_service.g_status_code);
 end if;
END;


Auf dem Zielserver dann wieder ein REST Service anlegen (TYP: PUT)

BEGIN
:status:=my_func(
p_parameter1=>:PARAMETER_A,
p_parameter1=>:PARAMETER_A,
p_clob=>:BODY_TEXT);
END;


REST Parameter:

NameBind-ParameterZugriffm.QuelltypDatentyp
PARAMETER_APARAMETER_AINHTTP HEADERSTRING
PARAMETER_BPARAMETER_BINHTTP HEADERSTRING
STATUSSTATUSOUTRESPONSESTRING


Die Funktion könnte dann wie folgt aussehen:

CREATE OR REPLACE FUNCTION my_func(
p_parameter1 IN VARCHAR2,
p_parameter2 IN VARCHAR2,
p_clob IN CLOB) RETURN VARCHAR2
IS
BEGIN
...
RETURN 200;
EXCEPTION WHEN OTHERS THEN
  RETURN 500;
END;


 



Weitere Interessente Artikel zum Thema:


Empfohlene Schulungen zum Thema:


CGI Parameter unter APEX auslesen

Bereich:APEX, Version: ab RDBMS 21.1:ORDS 20.3, Letzte Überarbeitung: 06.04.2022

Keywords:owa_util, APEX Parameter

Manchmal ist es sehr nützlich, herauszufinden auf welchem Server man gerade arbeitet. Dann kann man z.B. auf einem Testserver eine andere Seiten-Region ausgeben, als auf dem Produktivserver.
Leider funktioniert der Tipp nur innerhalb von APEX und nicht via SQL*Plus, SQL Developer oder anderen Tools:

Gehen Sie daher in APEX und erstellen Sie eine Dynamische PL/SQL Content Region in APEX und legen Sie dort folgenden Code ab:

BEGIN
FOR i  IN 1.. owa.num_cgi_vars LOOP
htp.p(owa.cgi_var_name(i)||' = '||owa.cgi_var_val(i)||'<BR>');
END LOOP;
END;

Nun wird beim Aufbau der Seite z.B. folgende Ausgabe erscheinen:

REMOTE_IDENT =
REMOTE_USER = APEX_PUBLIC_USER
host = 172.30.30.230:8080
user-agent = Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:98.0) Gecko/20100101 Firefox/98.0
accept = text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
accept-language = de,en-US;q=0.7,en;q=0.3
accept-encoding = gzip, deflate
referer = http://172.30.30.230:8080/
connection = keep-alive
cookie =
upgrade-insecure-requests = 1
APEX_LISTENER_VERSION = 21.4.1.r0250904
DAD_NAME =
DOC_ACCESS_PATH =
DOCUMENT_TABLE =
GATEWAY_IVERSION = 3
GATEWAY_INTERFACE = CGI/1.1
HTTP_ACCEPT = text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
HTTP_ACCEPT_ENCODING = gzip, deflate
HTTP_ACCEPT_LANGUAGE = de,en-US;q=0.7,en;q=0.3
HTTP_ACCEPT_CHARSET =
HTTP_IF_MODIFIED_SINCE =
HTTP_IF_NONE_MATCH =
HTTP_HOST = 172.30.30.230:8080
HTTP_ORACLE_ECID =
HTTP_PORT = 8080
HTTP_REFERER = http://172.30.30.230:8080/
HTTP_USER_AGENT = Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:98.0) Gecko/20100101 Firefox/98.0
PATH_ALIAS =
PATH_INFO = /rest-template-erstellung
PLSQL_GATEWAY = WebDb
QUERY_STRING = session=1647342785893
REMOTE_ADDR = 172.30.30.30
REQUEST_CHARSET = AL32UTF8
REQUEST_IANA_CHARSET = UTF-8
REQUEST_METHOD = GET
REQUEST_PROTOCOL = http
REQUEST_SCHEME = http
SCRIPT_NAME = /ords/scott/r/oracle-rest
SCRIPT_PREFIX =
SERVER_NAME = 172.30.30.230
SERVER_PORT = 8080
SERVER_PROTOCOL = HTTP/1.1
SERVER_SOFTWARE = Mod-Apex
WEB_AUTHENT_PREFIX =
X-APEX-METHOD = GET
X-APEX-BASE = http://172.30.30.230:8080/ords/scott/
X-APEX-PATH = r/oracle-rest/rest-template-erstellung?session=1647342785893
X-APEX-REMOTE-ADDRESS = 172.30.30.30
X-APEX-CHARSET = UTF-8
HTTP_COOKIE =

Damit kann man nun in einer Condition wunderbar arbeiten, z.B. mit einer Exists SQL Query

SELECT 1 FROM dual
WHERE OWA_UTIL.get_cgi_env('REMOTE_ADDR')='172.20.20.1';

 

Weitere Tipps und Tricks erfahren Sie in einem unserer APEX Kurse in Unterhaching bei München.



Weitere Interessente Artikel zum Thema:


Empfohlene Schulungen zum Thema:


Interessante APEX Parameter, die über die Kommandozeile gesetzt werden können

Bereich:APEX, Version: ab APEX 20.1:APEX 20.2:APEX 5.x, Letzte Überarbeitung: 12.01.2021

Keywords:APEX

Wenn Sie sich mal im Internal Workspace ausgetobt haben und dabei einige Parameter so verstellt worden sind, dass man sich nicht mehr anmelden kann, hilft Ihnen evtl. der folgende Tipp.

Auch lassen sich viele schöne APEX Einstellungen über ein kleines Skript schneller umsetzen, als die jeweilige Option wieder grafisch in einem der Untermenues zu finden.

Die Quelle alle internen Parameter ist die Tabelle wwv_platform_prefs;

SELECT    name||'='||value
FROM
    apex_200200.wwv_flow_platform_prefs
ORDER BY 1;
ACCOUNT_LIFETIME_DAYS = 365
ALLOW_DB_MONITOR = N
ALLOW_PUBLIC_FILE_UPLOAD = N
ALLOW_RAS = N
APEX_BUILDER_AUTHENTICATION = APEX
APEX_LISTENER_FOP_PATH = _/fop2pdf
APEX_PATCH_STATUS = APPLIED
APEX_REST_PATH_PREFIX = r
APEX_19_1_0_PATCH_29369869 = 2019-04-08_08-56-37
APEX_19_2_0_PATCH_30392181 = 2020-03-09_10-40-49
APP_EXPORT_TO_DB_ENABLED = Y
APPLICATION_ACTIVITY_LOGGING = U
APPLICATION_ID_MIN = 100
AUDIT_LOG_RETENTION = 90
AUTOAPPROVE_STORAGE_LIMIT = 0
AUTOEXTEND_TABLESPACES = Y
AUTO_SCHEMA_NAME = N
AUTO_WORKSPACE_NAME = N
BIGFILE_TABLESPACES_ENABLED = N
CHECK_FOR_UPDATES = Y
CLONE_SESSION_ENABLED = Y
CONTENT_CACHE_MAX_FILE_SIZE = 1048576
CONTENT_CACHE_SIZE_TARGET = 104857600
DEBUG_MESSAGE_PAGE_VIEW_LIMIT = 50000
DEFAULT_THEMES = 42,51
DELETE_UPLOADED_FILES_AFTER_DAYS = 14
DISABLE_ADMIN_LOGIN = N
DISABLE_WORKSPACE_LOGIN = N
DISABLE_WS_PROV = N
EMAIL_IMAGES_URL = https://172.30.30.8/i/
EMAIL_INSTANCE_URL = https://172.30.30.8/muso/
ENABLE_TRANSACTIONAL_SQL = N
ENCRYPTED_TABLESPACES_ENABLED = N
EXPIRE_FND_USER_ACCOUNTS = Y
GET_STARTED_URL = https://apex.oracle.com/go/get_started_apex
GETTING_STARTED_ENABLED = N
HPROF_DIRECTORY = -
HTTP_ERROR_STATUS_ON_ERROR_PAGE_ENABLED = N
IGNORED_FRIENDLY_URL_PARAMETERS = utm_campaign,utm_source,utm_medium,utm_term,utm_content,fbclid
INSTANCE_ID = 248274626595597
KEEP_SESSIONS_ON_UPGRADE = N
LOGIN_THROTTLE_DELAY = 5
LOGIN_THROTTLE_METHODS = USERNAME_IP
MAX_APPLICATION_BACKUPS = 25
MAX_LOGIN_FAILURES = 5
MAX_SCRIPT_SIZE = 500000
MAX_SESSION_IDLE_SEC = 7200
MAX_SESSION_LENGTH_SEC = 28800
MAX_WEBSERVICE_REQUESTS = 1000
MLE_LANGUAGES = JAVASCRIPT  -- Neu in 20.2
MOBILE_DEVELOPMENT_ENABLED = N
PASSWORD_ALPHA_CHARACTERS = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
PASSWORD_MIN_LENGTH = 0
PASSWORD_NEW_DIFFERS_BY = 0
PASSWORD_NOT_LIKE_USERNAME = N
PASSWORD_NOT_LIKE_WORDS = oracle:hello:welcome:guest:user:database
PASSWORD_NOT_LIKE_WS_NAME = N
PASSWORD_ONE_ALPHA = N
PASSWORD_ONE_LOWER_CASE = N
PASSWORD_ONE_NUMERIC = N
PASSWORD_ONE_PUNCTUATION = N
PASSWORD_ONE_UPPER_CASE = N
PASSWORD_PUNCTUATION_CHARACTERS = !"#$%&()``*+,-/:;<=>?_
PKG_APP_AUTH_ALLOW_HHEAD = N
PKG_APP_AUTH_ALLOW_LDAP = N
PKG_APP_AUTH_ALLOW_SSO = N
PKG_APP_ENABLED = Y
PLSQL_EDITING = Y
PRINT_BIB_LICENSED = APEX_LISTENER
PRINT_SVR_TIMEOUT = 300
REJOIN_EXISTING_SESSIONS = P
REQ_NEW_SCHEMA = N
REQUIRE_HTTPS = N
REQUIRE_OUT_HTTPS = N
REQUIRE_VERIFICATION_CODE = N
RESTFUL_SERVICES_ENABLED = Y
SELF_SERVICE_SCHEMA_PREFIX = WKSP_  -- Neu in 20.2
SERVICE_REQUEST_FLOW = MANUAL
SERVICE_REQUESTS_ENABLED = Y
SMTP_HOST_ADDRESS = 172.30.30.8
SMTP_HOST_PORT = 25
SMTP_TLS_MODE = N
SQL_SCRIPT_MAX_OUTPUT_SIZE = 200000
STATS_LAST_SENT = 20210104
STRONG_SITE_ADMIN_PASSWORD = N
SYSTEM_HELP_URL = https://apex.oracle.com/doc202
TOP_THEMES = 42,51
TRACING_ENABLED = Y
UPGRADE_DEFER_DAYS = 30
UPGRADE_DEFERRED = N
USERNAME_VALIDATION = *
WALLET_PATH = file:///opt/oracle/admin/o21c/https_wallet
WEBSERVICE_LOGGING = U
WEBSHEET_CREATE_ENABLED = N -- Neu in 20.2
WEBSHEET_SQL_ACCESS = N
WORKSPACE_EMAIL_MAXIMUM = 1000
WORKSPACE_ISSUE_FILES_YN = Y
WORKSPACE_ISSUE_FS_LIMIT = 15728640
WORKSPACE_MAX_OUTPUT_SIZE = 2000000
WORKSPACE_NAME_USER_COOKIE = Y
WORKSPACE_PROVISION_DEMO_OBJECTS = N
WORKSPACE_TEAM_DEV_FILES_YN = N
WORKSPACE_TEAM_DEV_FS_LIMIT = 15728640
WORKSPACE_WEBSERVICE_REQUEST_MAX = 1000
WORKSPACE_WEBSHEET_OBJECTS = N
WS_REQUEST_USAGE_Q = N

 

Wir wollen mal zwei interessante Parameter herausgreifen:
Der erste verhindert ein anmelden am INTERNAL Workspace:


EXEC apex_instance_admin.set_parameter('DISABLE_WORKSPACE_LOGIN','Y');
COMMIT;

 

Der zweite stellt die Idle Time auf 4800 Sekunden um:


EXEC apex_instance_admin.set_parameter('MAX_SESSION_IDLE_SEC','4800');

 

Mit folgenden Select können Sie für einen Parameter den aktuellen Inhalt hoch offiziell auslesen:


select APEX_INSTANCE_ADMIN.GET_PARAMETER('DISABLE_ADMIN_LOGIN') from dual;

 

Viel Spass beim Ausprobieren und ich hoffe wir sehen uns in einem unserer schönen APEX Kurse:-)



Weitere Interessente Artikel zum Thema:


Empfohlene Schulungen zum Thema:


ORDS Standalone Installation unter Windows

Bereich:APEX, Version: ab RDBMS 12.x, Letzte Überarbeitung: 28.02.2019

Keywords:

Im heutigen Tipp beschäftigen wir uns mit der Installation von ORDS 18.4 unter Windows 10.

Folgende Schritte werden zur Installation durchgeführt:

1. Herunterladen der aktuellen Version (Download vom Oracle Server)
2. Auspacken in den Ordner c:\oracle\ords (oder einen beliebig anderen)
3. Sehen Sie sich die Oracle Datenbank Parameter db_domain,service_names,instance_name an:

show parameter db_domain
show parameter service_names
show parameter instance_name


4. Lassen Sie sich die Listener-Daten der Oracle Datenbank anzeigen:

lsnrctl status


5. Laden Sie sich eine aktuelle Java Version runter (Wir verwenden aus Protest zur neuen Lizenzbestimmung von Oracle das Open JDK:Download)

6. Besorgen Sie sich den images Ordner aus einer APEX Installation

7. Nun wird die Installation gestartet und interaktiv ausgeführt:

C:\Oracle\ords>C:\Oracle\Java\jdk-11.0.2\bin\java -jar ords.war

Diese Oracle REST Data Services-Instanz wurde noch nicht konfiguriert.

Nehmen Sie an den folgenden Prompts die entsprechenden Einstellungen vor

Geben Sie den Speicherort für Konfigurationsdaten ein:c:\oracle\ords_conf

Name des Datenbankservers eingeben [localhost]:myserver

Listener-Port der Datenbank eingeben [1521]:

1 eingeben, um den Servicenamen der Datenbank anzugeben, oder 2, um die Datenbank-SID anzugeben [1]:

Datenbankservicename eingeben:XE

Datenbankkennwort für ORDS_PUBLIC_USER eingeben:

Kennwort bestätigen:

Geben Sie 1 ein, wenn Sie das PL/SQL-Gateway verwenden möchten, oder 2, um diesen Schritt zu überspringen.

Wenn Sie Oracle Application Express verwenden oder eine Migration von mod_plsql durchführen, müssen Sie 1 eingeben [1]:

Datenbankkennwort für APEX_PUBLIC_USER eingeben:

Kennwort bestätigen:

Geben Sie 1 ein, um Kennwörter für Application Express RESTful Services-Datenbankbenutzer anzugeben (APEX_LISTENER, APEX_REST_PUBLIC_USER), oder 2, um diesen Schritt zu überspringen [1]:

Datenbankkennwort für APEX_LISTENER eingeben:

Kennwort bestätigen:

Datenbankkennwort für APEX_REST_PUBLIC_USER eingeben:

Kennwort bestätigen:

Feb. 28, 2019 7:53:53 VORM.

INFO: reloaded pools: []

Geben Sie 1 ein, wenn Sie im Modus "Standalone" starten möchten, oder 2 zum Beenden [1]:

Geben Sie das Speicherot der statischen APEX-Ressourcen ein:C:\Oracle\ords\images

Geben Sie 1 ein, wenn Sie HTTP verwenden, oder 2, wenn Sie HTTPS verwenden [1]:2

Geben Sie den HTTPS-Port ein [8443]:

Geben Sie den SSL-Hostnamen ein:dozent4

Geben Sie 1 ein, um das selbstsignierte Zertifikat zu verwenden, oder 2, wenn Sie das SSL-Zertifikat angeben [1]:


Danach sollte der ORDS Listener starten und kann mit CTRL-Z abgebrochen werden. Achtung das Beenden des DOS Fenster stoppt auch den ORDS Listener!

Bei Problemen:

Man sollte zwei Parameter in die Datei defaults.xl (im ords_conf Ordner)  einsetzen und durchstarten

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>Saved on Thu Feb 28 07:53:53 CET 2019</comment>
<entry key="db.hostname">DOZENT4</entry>
<entry key="db.port">1521</entry>
<entry key="db.servicename">XE.ad.muniqsoft-training.de</entry>
<entry key="security.requestValidationFunction">wwv_flow_epg_include_modules.authorize</entry>
<entry key="security.validationFunctionType">plsql</entry>
<entry key="debug.debugger">true</entry>
<entry key="debug.printDebugToScreen">true</entry>
<entry key="error.keepErrorMessages">true</entry>
<entry key="error.maxEntries">100</entry>
</properties>

 

 

Weitere Tipps erhalten Sie in unserem APEX II Kurs.



Weitere Interessente Artikel zum Thema:


Empfohlene Schulungen zum Thema:


Oracle APEX Export auf Kommandozeile

Bereich:APEX, Version: ab APEX 20.2:APEX 5.0, Letzte Überarbeitung: 30.12.2020

Keywords:APEX, DBA, Oracle Backup & Recovery

Haben Sie sich auch schon mal gefragt, wie man seine schönen APEX Applikationen sichert?

Ja natürlich, Sie können das über die grafische Oberflächen machen. Aber zeitgesteuert, nachts um 3.00 Uhr zusammen mit der Datenbank?
Na, dann stellen Sie mal den Wecker... oder verwenden Sie den folgenden Tipp:

Erst schauen wir mal, welche schönen APEX Applikationen wir haben:

SELECT application_id,application_name
FROM apex_applications;


Als ersten Schritt, können wir eine Applikation über deren Nummer in ein Directory exportieren. APEX liefert schon über eine Routine die komplette App als CLOB zurück. Jetzt musste nur noch ein Package her, welches CLOB´s direkt in das Betriebssystem schreibt. Fündig geworden bin ich im Package DBMS_XSLPROCESSOR.CLOB2FILE.
Das spart einem viele lästige Schritte :-)

Wir verwenden hier das DATA_PUMP_DIR Directory zum Schreiben, weil das meistens schon vorhanden ist. Sie können jedoch auch jedes andere Verzeichnis benutzen.
Vergeben Sie das Schreibrecht am Directory an den Benutzer, der den Export ausführt (dem sollte auch die APEX Applikation gehören).

GRANT WRITE ON DIRECTORY data_pump_dir TO scott;


APEX App exportieren:

DECLARE
my_app_id INT:=100;
BEGIN
DBMS_XSLPROCESSOR.CLOB2FILE (
wwv_flow_utilities.export_application_to_clob(my_app_id ), 'DATA_PUMP_DIR', 'APEX_' || my_app_id  || '_'||
to_char(sysdate,'DDMMYYYY_HH24MISS')||'.sql');
END;
/


Im zweiten Beispiel werden alle APEX Apps gesichert, die sich in den letzten 24 Stunden geändert haben. Führen Sie den Export z. B. als System durch (NICHT als SYS):

DECLARE
-- In welches Directory sollen die Exports erfolgen?
v_dir VARCHAR2(255):=upper('DATA_PUMP_DIR');
-- Wenn eine Applikation in den letzten 24 Stunden geändert worden ist
-- wird ein neues Backup erzeugt
v_stunden NUMBER:=24;
BEGIN
FOR r IN (select application_id,last_updated_on
          from apex_applications
          WHERE APPLICATION_ID<3000) LOOP
          IF r.last_updated_on>sysdate-(v_stunden/24) THEN
          -- Apex App in Clob wandeln und als Datei in Directory legen
            DBMS_XSLPROCESSOR.CLOB2FILE (
            wwv_flow_utilities.export_application_to_clob(r.application_id), v_dir,
            'APEX_'||r.application_id||'_'||to_char(sysdate,'DDMMYYYY_HH24MISS')||'.sql');
          END IF;
END LOOP;
END;
/


Nun wollen wir Seiten einzeln sichern, aber erst schauen wir mal, wann es Änderungen in den Seiten gab:

select application_id,max(last_updated_on)
          from apex_applications
          WHERE APPLICATION_ID<3000
          group by application_id
REM Nur eine einzelne Seite (App 100, Seite 1) sichern:
REM Nur der Eigentümer der App darf exportieren (auch SYS nicht)
DECLARE
app_id INT:=100;
app_page_id INT:=1;
BEGIN
DBMS_XSLPROCESSOR.CLOB2FILE (
wwv_flow_utilities.export_page_to_clob(app_id,app_page_id), 'DATA_PUMP_DIR', 'apex_f'|| app_id ||'p' || app_page_id ||'.sql');
END;
/


Nun können wir prüfen, welche Seiten in den letzten 30 Tage geändert wurden:

SELECT application_id,application_name,page_id,page_name,page_title,last_updated_on
FROM apex_application_pages
WHERE last_updated_on>sysdate-30
AND application_id<3000;


Zu guter Letzt ein Beispiel als automatischer Export aller Seiten, die sich in den letzten 30 Tagen geändert haben:

DECLARE
v_dir VARCHAR2(255):=upper('DATA_PUMP_DIR');
BEGIN
FOR r IN (SELECT a.application_id,ap.page_id
            FROM apex_application_pages ap,apex_applications a
            WHERE ap.application_id=a.application_id
            AND ap.last_updated_on>sysdate-30
            AND a.application_id<3000
            AND a.owner=user) LOOP
                DBMS_XSLPROCESSOR.CLOB2FILE (
                cl=>wwv_flow_utilities.export_page_to_clob(
                r.application_id,r.page_id),
                FLOCATION=>v_dir,
                FNAME=>'APEX_'||r.application_id||'_'||r.page_id||'_'||
                to_char(sysdate,'DDMMYYYY_HH24MISS')||'.sql');        
END LOOP;
END;
/

 

Wenn Sie APEX nicht durch mühsames Probieren selbst erlernen wollen, kommen Sie doch in eine unserer beiden 5 Tages-Schulungen.



Weitere Interessente Artikel zum Thema:


Empfohlene Schulungen zum Thema:


APEX Datenbank Initialisierungsparameterempfehlungen

Bereich:APEX, Version: ab RDBMS 12.x, Letzte Überarbeitung: 11.12.2018

Keywords:APEX Initialisierungsparameter

Bei manchen (äh fast allen) Applikationen gibt es die geliebten ReadMe (RTFM) Dateien. Jeder von uns liest diese Dateien natürlich ordnungsgemäß komplett von vorne bis hinten durch. :-)

Sollten durch die Installation einer Applikation diverse Initialisierungsparameter auf bestimmte Werte gesetzt werden müssen, könnte man dem Benutzer folgenden kleinen SQL-Befehl (natürlich angepasst an Ihre Wünsche) mitgeben:

Beispielempfehlung für die Installation von Apex 5.1/18.x mit dem EPG Gateway auf Oracle 12.x/18.x Datenbanken:

SELECT * FROM (
                SELECT name, nvl(display_value,'NULL') as Wert, CASE
                WHEN name='db_create_file_dest'
                   THEN (select substr(name,1,instr(name,'\',-1)-1)
                FROM v$datafile where rownum=1)
                WHEN name='shared_servers'
                   THEN '>=10 bei EPG'
                WHEN name='max_shared_servers'
                   THEN '>=20 bei EPG'
                WHEN name='job_queue_processes'
                   THEN '>=10'
                WHEN name='session_cached_cursors'
                   THEN '>=100'
                WHEN name='sga_max_size'
                   THEN '>=550M'
                WHEN name='sga_target'
                   THEN '>=550M'
                WHEN name='dispatchers'
                   THEN (select'(PROTOCOL=TCP) (SERVICE='||value ||'XDB)
                         (DISPATCHERS=3)' from v$parameter where
                         name='instance_name')
                WHEN name='audit_trail'
                   THEN 'db,extended oder xml,extended'
                END as empfehlung
                FROM v$parameter)
                WHERE empfehlung IS NOT NULL;


Ausgabe:

NAME                   Wert   EMPFEHLUNG
---------------------- ------ ----------------------------------------
sga_max_size           440M   >=350M
sga_target             440M   >=350M
db_create_file_dest    NULL   C:\ORACLE\PRODUCT\10.2.0\ORADATA\O10G
dispatchers            NULL   (PROTOCOL=TCP)(SERVICE=o10gXDB)
                              (DISPATCHERS=3)
shared_servers         0      >=5 
max_shared_servers     NULL   >=20 
session_cached_cursors 20     >=50 
job_queue_processes    10     >5
audit_trail            NONE   db,extended oder xml,extended


Oder Sie basteln dem Benutzer ein Skript, das die Parameter gleich selber umsetzt:

SELECT * FROM (
                SELECT CASE
                WHEN name='db_create_file_dest'
                   THEN (select 'ALTER SYSTEM SET db_create_file_dest='
                         ||substr(name,1,decode(instr(name,'\'),0,
                         instr(name,'/',-,2),instr(name,'\',-1,2))-1)
                         ||';' from v$datafile where rownum=1)
                WHEN name='shared_servers'
                   THEN 'ALTER SYSTEM SET shared_servers=5;'
                WHEN name='max_shared_servers'
                   THEN 'ALTER SYSTEM SET max_shared_servers=20;'
                WHEN name='job_queue_processes'
                   THEN 'ALTER SYSTEM SET job_queue_processes=10;'
                WHEN name='session_cached_cursors'
                   THEN 'ALTER SYSTEM SET session_cached_cursors=50;'
                WHEN name='sga_max_size'
                   THEN 'ALTER SYSTEM SET sga_max_size=350M SCOPE=SPFILE;'
                WHEN name='sga_target'
                   THEN 'ALTER SYSTEM SET sga_target=350M SCOPE=SPFILE;'
                WHEN name='dispatchers'
                   THEN (select 'ALTER SYSTEM SET dispatchers=
                         (PROTOCOL=TCP)(SERVICE='|| value || 'XDB)
                         (DISPATCHERS=3) scope=spfile;' from v$parameter
                         where name='instance_name')
                WHEN name='audit_trail'
                   THEN 'ALTER SYSTEM SET audit_trail='||chr(39)||
                        'db,extended'||chr(39)||'scope=spfile;'
                END as empfehlung
                FROM v$parameter)
                WHERE empfehlung IS NOT NULL;


Ausgabe:

ALTER SYSTEM SET sga_max_size=350M SCOPE=SPFILE;
ALTER SYSTEM SET sga_target=350M SCOPE=SPFILE;
ALTER SYSTEM SET db_create_file_dest=/opt/oracle/oradata;
ALTER SYSTEM SET dispatchers=(PROTOCOL=TCP) (SERVICE=orclXDB) (DISPATCHERS=3) scope=spfile;
ALTER SYSTEM SET shared_servers=5;
ALTER SYSTEM SET max_shared_servers=20;
ALTER SYSTEM SET session_cached_cursors=50;
ALTER SYSTEM SET job_queue_processes=10;
ALTER SYSTEM SET audit_trail='db,extended' scope=spfile;


Natürlich können Sie die Parameterempfehlungen mit Ihren eigenen Wünschen optimieren.

Auch ganz praktisch ist Netzwerk und Konfig Check, der (fast) alles beinhaltet:

SELECT * FROM (
SELECT 1,'Username' as Info1, 'Account Status' as Info2,
'Lock Date' as Info3, 'Expirary Date' as Info4 FROM dual
UNION ALL
SELECT 2,'------------','---------------','--------------','------------------' FROM dual
UNION ALL
SELECT 3,u.username,u.account_status,to_char(u.lock_date,'DD.MM.YY HH24:MI'),
to_char(u.EXPIRY_DATE,'DD.MM.YY HH24:MI')
FROM dba_users u
WHERE (u.username IN ('ANONYMOUS','FLOWS_FILES')
OR u.username LIKE 'APEX%'
OR u.username LIKE 'ORDS%') AND u.username<>'ORDSYS'
UNION ALL
SELECT 4,'#################','#############','#############','#################' FROM dual
UNION ALL
SELECT 5,'COMPO_NAME','VERSION','Status','Modified' FROM dual
UNION ALL
SELECT 6,'------------','---------------','--------------','------------------' FROM dual
UNION ALL
SELECT 7,replace(comp_name,'Oracle ',''),version,status,modified
FROM dba_registry
WHERE comp_id='APEX'
UNION ALL
SELECT 8,'#################','#############','#############','#################' FROM dual
UNION ALL
SELECT 9,'HTTP Port','FTP Port','Image Count','Allow Anonymus Repo Access'
FROM dual
UNION ALL
SELECT 10,'------------','---------------','--------------','------------------' FROM dual
UNION ALL
SELECT 11,to_char(dbms_xdb.gethttpport ),to_char(dbms_xdb.getftpport),
(SELECT count(*)||' ' FROM PATH_VIEW
WHERE UNDER_PATH(res, '/images/',1)>0),(select extractValue(dbms_xdb.cfg_get(), '/xdbconfig/sysconfig/protocolconfig/httpconfig/allow-repository-anonymous-access')  
from dual) FROM dual
UNION ALL
SELECT 12,'#################','#############','#############','#################' FROM dual
UNION ALL
SELECT 14,'Workspace','Username','Admin/Dev','Account Locked' FROM dual
UNION ALL
SELECT 15,'#################','#############','#############','#################' FROM dual
UNION ALL
SELECT 16,workspace_display_name,user_name,is_admin||'/'||is_application_developer,account_locked
FROM apex_workspace_developers
UNION ALL
SELECT 17,'Parameter','Value','--------------','------------------' FROM dual
UNION ALL
SELECT 18,'------------','---------------','--------------','------------------' FROM dual
UNION ALL
SELECT 19,name,value,null,null from v$parameter where name in ('local_listener','session_cached_cursors')
UNION ALL
SELECT 20,'#################','#############','#############','#################' FROM dual
UNION ALL
SELECT 21,'DAD Names','-----------','--------------','------------------' FROM dual
UNION ALL
SELECT 22,'------------','---------------','--------------','------------------' FROM dual
UNION ALL
SELECT 23, u.dad ,null,null,null FROM XMLTable(XMLNAMESPACES (
DEFAULT 'http://xmlns.oracle.com/xdb/xdbconfig.xsd' ),
'//servlet-list/*[servlet-language="PL/SQL"]' PASSING DBMS_XDB.CFG_GET()
COLUMNS DAD varchar2(15) PATH '/servlet/servlet-name/text()') u
)
ORDER BY 1,2;

 

Diese und noch viele weitere Tricks lernen Sie in einem unserer schönen APEX Kurse!



Weitere Interessente Artikel zum Thema:


Empfohlene Schulungen zum Thema:


Oracle APEX 19.2 installieren für Oracle XE 18c

Bereich:APEX:DBA, Version: ab APEX 19.2, Letzte Überarbeitung: 05.05.2020

Keywords:APEX 19.2, Oracle XE 18c, Installation von Oracle APEX

Wenn Sie die APEX Version 19.2 (Stand November 2020)  in die kostenlose Oracle XE Datenbank Version 18c installieren möchten, gehen Sie bitte wie folgt vor:

Laden Sie sich zuerst APEX und die Oracle Expres (XE) Version 18c herunter.

Für LINUX verwenden wir den Installationspfad /u01/software. Dort sollte dann die APEX Zipdatei ausgepackt liegen

Für die Installation APEX starten Sie:

UNIX> cd /u01/software
UNIX> sqlplus / as sysdba

Sie können für APEX bei Bedarf einen eigenen Tablespace anlegen, oder den SYSAUX Tablespace verwenden.

SQL> CREATE TABLESPACE apex_main_tbs DATAFILE '/opt/oracle/oradata/XE/apex_main01.dbf'
SIZE 512M AUTOEXTEND ON NEXT 64M MAXSIZE 2048M;

Nun starten wir das APEX Installations-Hauptskript:

SQL> @apexins APEX_MAIN_TBS APEX_MAIN_TBS TEMP /i/

oder der bereits vorhandene SYSAUX Tablespace kommt zum Einsatz:

SQL> @apexins SYSAUX SYSAUX TEMP /i/

Wenn Die Datenbank als Webserver Ersatz verwendet werden soll, starten Sie bitte folgendes Skript:
Hinweis: Der Schritt ist nicht nötig, wenn mit dem ORDS (Apache TomCat, Glassfish, Bea Weblogic oder ORDS Standalone gearbeitet wird)

SQL> @apex_epg_config /u01/software

Dies legt einen DAD an und lädt alle Bilder/CSS und JS Dateien in die Datenbank (in die Tabelle xdb$resource)

dann wird noch der Datenbank Benutzer ANONYMOUS entsperrt:

Hinweis: Der Schritt ist nicht nötig, wenn mit dem ORDS (TomCat, Glassfish, Bea Weblogic oder ORDS Standalone gearbeitet wird)

SQL> ALTER USER ANONYMOUS ACCOUNT UNLOCK IDENTIFIED BY neverchangearunninguser;

Wenn Sie einen speziellen Port für den HTTP Zugriff benötigen, können Sie das auch noch ändern:

Hinweis: Der Schritt ist nicht nötig, wenn mit dem ORDS (TomCat, Glassfish, Bea Weblogic oder ORDS Standalone gearbeitet wird)

EXEC dbms_xdb.sethttpport(8080)
ALTER SYSTEM REGISTER;

Das letzte Skript setzt das Passwort für INTERNAL Workspace ADMIN Benutzer fest.

SQL> @apxchpwd

Sie werden 3 Parameter gefragt:

  • Benutzername (MUSS nicht ADMIN heissen)
  • Email-Adresse: info@muniqsoft-training.de ( Bitte verwenden Sie Ihre eigene, oder dürfen wir Ihren APEX Server verwalten? (für Geld machen wir fast alles :-) )
  • Passwort (muss ein komplexes Passwort mit Groß und Kleinschreibung, Zahlen und Sonderzeichen sein)

Das letzte Problem (Passwortkomplexität) kann man aber umgehen, wenn man zuvor den folgenden Befehl laufen lässt:

EXEC APEX_INSTANCE_ADMIN.SET_PARAMETER('STRONG_SITE_ADMIN_PASSWORD','N');


Zusätzlich wird die REST Schnittstelle benötigt, die man für alle REST Aufgaben uns auch die Application und Workspace Files benötigt:

SQL>@apex_rest_config


Nun können Sie sich anmelden:

http://servername/ords/f?p=4550


Legen Sie sich zuerst einen Workspace mit einem Administrationsbenutzer an.
Hinweis: Seit April 2020 ist die Version 20.1 bereits verfügbar.



Weitere Interessente Artikel zum Thema:


Empfohlene Schulungen zum Thema:


Export von allen APEX Komponenten

Bereich:APEX, Version: ab APEX 20.1:APEX 20.2, Letzte Überarbeitung: 23.12.2020

Keywords:APEX, EXPORT

Zu einem guten APEX-Projekt gehört auch ein gutes Backup-Konzept. Sie möchten ja keine Ihrer wichtigen Projektänderungen verlieren oder?

Schön wäre es, wenn dies auch noch automatisch erfolgen würde, also legen wir gleich mal los:

Voraussetzungen:

1. Sie haben ein Oracle Directory angelegt (wir nehmen hier mal das Directory DATA_PUMP_DIR, das ist meistens schon vorhanden)
Sonst legen Sie ein neues Directory an mittels:

CREATE DIRECTORY apex_backup_dir AS 'C:\oracle\apex'; -- für Windows
CREATE DIRECTORY apex_backup_dir AS '/u01/oracle/apex'; -- für UNIX/LINUX


2. Der Benutzer, der den Export durchführt, hat mindestens Schreibrechte auf dem Directory. Sonst vergeben Sie ihm die Rechte bitte durch:

GRANT WRITE ON DIRECTORY data_pump_dir TO SCOTT;


Nun zu einigen Beispielen von APEX Applikationsbackups.

Beispiel 1: Sicherung aller Apps mit ID<3000, die sich in den letzten 24 Stunden geändert haben

DECLARE
-- In welches Directory sollen die Exports erfolgen?
v_dir VARCHAR2(255):=upper('DATA_PUMP_DIR');
-- Wenn eine Applikation in den letzten 24 Stunden geändert worden ist
-- wird ein neues Backup erzeugt
v_stunden NUMBER:=24;
BEGIN
FOR r IN (select application_id,last_updated_on
          from apex_applications
          WHERE APPLICATION_ID<3000) LOOP
          IF r.last_updated_on>sysdate-(v_stunden/24) THEN
          -- Apex App in Clob wandeln und als Datei in Directory legen
            DBMS_XSLPROCESSOR.CLOB2FILE (
            wwv_flow_utilities.export_application_to_clob(p_application_id=>r.application_id), v_dir,
            'APEX_'||r.application_id||'_'||to_char(sysdate,'DDMMYYYY_HH24MISS')||'.sql');
          END IF;
END LOOP;
END;
/
Hinweis: ab Version 19c kann statt dem Package DBMS_XSLPROCESSOR.CLOB2FILE auch DBMS_LOB.CLOB2FILE verwendet werden

Weitere interessante Parameter des Packages wwv_flow_utilities.export_application_to_clob:       

p_export_ir_public_reports  default 'N'
p_export_ir_private_reports default 'N'
p_export_ir_notifications   default 'N'
p_export_translations       default 'N'
p_export_pkg_app_mapping    default 'N'
p_with_original_ids         default false
p_exclude_subscriptions     default false


Beispiel 2: Einzelne APEX Seite exportieren:

DECLARE
v_page_id INT:=1; -- Seite 1
v_app_id INT:=100; -- Applikation ID 100
BEGIN
DBMS_XSLPROCESSOR.CLOB2FILE (
wwv_flow_utilities.export_page_to_clob(v_app_id,v_page_id), 'DATA_PUMP_DIR', 'apex_f'||v_app_id||'_p'||v_page_id||'.sql');
END;
/
Hinweis: ab Version 19c kann statt dem Package DBMS_XSLPROCESSOR.CLOB2FILE auch DBMS_LOB.CLOB2FILE verwendet werden


Beispiel 3: Alle Seiten exportieren, die sich in den letzten 24 Stunden geändert haben:

DECLARE
v_dir VARCHAR2(255):=upper('DATA_PUMP_DIR');
BEGIN
FOR r IN (SELECT a.application_id,ap.page_id
            FROM apex_application_pages ap,apex_applications a
            WHERE ap.application_id=a.application_id
            AND ap.last_updated_on>sysdate-interval '24' hour
            AND a.application_id<3000
            AND a.owner=user) LOOP
                DBMS_XSLPROCESSOR.CLOB2FILE (
                cl=>wwv_flow_utilities.export_page_to_clob(
                r.application_id,r.page_id),
                FLOCATION=>v_dir,
                FNAME=>'APEX_'||r.application_id||'_'||r.page_id||'_'||
                to_char(sysdate,'DDMMYYYY_HH24MISS')||'.sql');      
END LOOP;
END;
/
Hinweis: ab Version 19c kann statt dem Package DBMS_XSLPROCESSOR.CLOB2FILE auch DBMS_LOB.CLOB2FILE verwendet werden

 

Beispiel 4: Workspace Export (Achtung, der exportiert keine APEX Apps)

BEGIN
    FOR r IN (SELECT distinct workspace_id w_id FROM apex_applications) LOOP
      wwv_flow_api.set_security_group_id(r.w_id);
      -- set the apex_application.g_user global variable...
      -- the username you use as argument needs admin privileges in the workspace
      -- apex_custom_auth.set_user('admin');
    DBMS_XSLPROCESSOR.CLOB2FILE (
       cl                         => wwv_flow_utilities.export_workspace_to_clob(
       p_workspace_id             => r.w_id,                     
       p_include_team_development => TRUE),
       FLOCATION                  =>upper('DATA_PUMP_DIR'),                               
       FNAME  => 'APEX_WORKSPACE_'||to_char(sysdate,'DDMMYYYY_HH24MISS')||'.sql');
    END LOOP;
END;
/
Hinweis: ab Version 19c kann statt dem Package DBMS_XSLPROCESSOR.CLOB2FILE auch DBMS_LOB.CLOB2FILE verwendet werden


Beispiel 5: Workspace Dateien exportieren:

BEGIN
  FOR r IN (
    SELECT distinct workspace_id w_id
    FROM apex_applications
    where application_id=100) LOOP
    DBMS_XSLPROCESSOR.CLOB2FILE (
    cl=>wwv_flow_utilities.export_files_to_clob (r.w_id),
    FLOCATION=>upper('DATA_PUMP_DIR'),
    FNAME=>'APEX_WORKSPACE_'||to_char(sysdate,'DDMMYYYY_HH24MISS')||'.sql');
  END LOOP;
END;
/
Hinweis: ab Version 19c kann statt dem Package DBMS_XSLPROCESSOR.CLOB2FILE auch DBMS_LOB.CLOB2FILE verwendet werden

 

Für weitere Tipps & Tricks besuchen Sie doch einen unserer APEX Kurse (APEX I, APEX II, APEX Security, APEX für Admins oder Neuerungen in 19.x/20x) .



Weitere Interessente Artikel zum Thema:


Empfohlene Schulungen zum Thema:


Blobs in Apex

Bereich:APEX, Version: ab APEX 5, Letzte Überarbeitung: 16.04.2020

Keywords:Apex

In Oracle Application Express (APEX) kann man BLOBs über „Formulare“ in die Datenbank abspeichern oder über „Reporte“ aus der Datenbank herausladen und Bilder anzeigen lassen.

Hier wird erklärt, wie man vorgehen könnte.

Voraussetzung:

CREATE TABLE "LOAD_BLOB" 
   ("BLOB_ID" NUMBER(10,0), 
    "ATTACH_FILENAME" VARCHAR2(255 BYTE), 
    "DOCUMENT" BLOB, 
    "ATTACH_MIMETYPE" VARCHAR2(255 BYTE), 
    "ATTACH_LAST_UPDATE" DATE, 
    "ATTACH_CHARSET" VARCHAR2(128 BYTE), 
     PRIMARY KEY ("BLOB_ID")
     
CREATE SEQUENCE SQ_LOAD_BLOB START WITH 1;     

Zuerst wird in APEX eine leere Seite vom Type „Report“ mit der Vorlage „Report with Form on Table“ erstellt:

Dann werden für den Report von der Tabelle LOAD_BLOB die Spalten BLOB_ID, ATTACH_FILENAME und DOCUMENT (Blob) ausgesucht.

Nach dem Next werden für das Formular „Select Primary Key“ (BLOB_ID) und alle Spalten gewählt. Außerdem benötigt man die „Existing Sequence“ SQ_LOAD_BLOB.

Weil die BLOB-Attribute Mime-Type, Filename, Last Updated und Character-Set im Hintergrund mit abgespeichert werden, werden die Items, die beim Erstellen des Formulars angelegt wurden und die diese Attribute beinhalten sollen, auf „Display Only“ gesetzt, so dass man sieht, was abgespeichert wird:

(Bitte passen Sie P58, das hier für Seite 58 steht, entsprechend an.)

P58_ATTACH_FILENAME: Type:           Display Only
P58_ATTACH_MIMETYPE: Type:          Display Only
P58_ATTACH_LAST_UPDATE: Type:   Display Only
P58_ATTACH_CHARSET: Type:            Display Only


Das Item P58_DOCUMENT ist vom Type “File Browse...“, so dass man darüber die entsprechende Datei, die ins BLOB geladen werden soll, auswählen kann.

Folgende Settings sind für dieses Item noch notwendig:

Automatisch werden vom Assistent der Pre-Rendering-Prozess “Fetch Row from LOAD_BLOB”, sowie die Prozesse „Process Row of LOAD_BLOB“, “Get PK” und “reset page” angelegt.

Nun wird die SQL-Query vom Source im Report angepasst:

SELECT "BLOB_ID", "ATTACH_FILENAME", DBMS_LOB.GETLENGTH("DOCUMENT") "DOCUMENT",
 CASE 
   WHEN NVL(DBMS_LOB.GETLENGTH(DOCUMENT),0) = 0 THEN
    NULL
   WHEN ATTACH_MIMETYPE LIKE 'image%' THEN
    '<img alt="Image" src="' || 
    APEX_UTIL.GET_BLOB_FILE_SRC('P54_DOCUMENT',BLOB_ID) || 
    '" height="50" width="50" />'
   WHEN ATTACH_MIMETYPE LIKE '%pdf%' THEN
    '<img src="#APP_IMAGES#application-pdf.png" height=50 width=50 />' 
   WHEN ATTACH_MIMETYPE LIKE '%powerpoint%' THEN
    '<img src="#APP_IMAGES#PowerPoint.ico" height=50 width=50 />' 
   WHEN ATTACH_MIMETYPE LIKE '%word%' THEN
    '<img src="#APP_IMAGES#docx.png" height=50 width=50 />' 
   WHEN ATTACH_MIMETYPE LIKE '%excel%' THEN
    '<img src="#APP_IMAGES#Excel.ico" height=50 width=50 />'
   WHEN ATTACH_MIMETYPE LIKE '%zip%' THEN
    '<img src="#APP_IMAGES#zip-icon.png" height=50 width=50 />' 
   ELSE
    NULL
 END Application
FROM "#OWNER#"."LOAD_BLOB"

Bei diesem Statement wird ein Bild vom Type „image“, wie z. B. bei einer png- oder jpg-Datei, als Bild im Report dargestellt. Dagegen werden Dokumente wie pdf-, powerpoint-, word- oder excel-Dateien mit einem eigenen Bild abgebildet. Diese Dateien (application-pdf.png, PowerPoint.ico, docx.png, Excel.ico, zip-icon.png) werden vorher in „Shared Components“ über „Static Application Files“ in Apex hochgeladen und so der Anwendung zur Verfügung gestellt

Wichtig ist außerdem, dass man bei der Spalte Application in Security die „Escape special characters“ auf „No“ setzt, da man sonst nur HTML und nicht die Bilder sieht.

Die Spalte DOCUMENT ist vom Type „Download BLOB“ und man kann über diesen Download-Link in der Spalte die jeweilige Datei aus dem BLOB-Feld herausladen.

Die „BLOB_ID“-Spalte im Report könnte man „Hidden“ stellen.

Über das Pencil-Icon im Report kann man nun im Formular den zugehörigen Datensatz sehen bzw. löschen. Der „Create“-Button im Report leert das Formular, so dass man dort einen neuen Datensatz mit einer Datei im BLOB-Feld anlegen kann.

Hinweis:

Wenn man einen Datensatz in der Form-Region löscht, kann es passieren, dass die Session die BLOB_ID weiterhin speichert, obwohl der Datensatz nicht mehr existiert, dadurch kann es zu einem ORA-1403 „No Data found“ kommen. 

Deshalb ist es ratsam, einen Pre-Rendering-Prozess vom Type „Clear Session State“, Point: „Before Header“ anzulegen, um alle Items auf der Seite zu löschen.

 

Viele weitere Informationen, Erklärungen und Beispiele erhalten Sie in unseren APEX Kursen! Schauen Sie doch einfach mal vorbei!



Weitere Interessente Artikel zum Thema:


Empfohlene Schulungen zum Thema:


Die Neuerungen APEX 5.1

Bereich:APEX, Version: ab APEX 5.x, Letzte Überarbeitung: 13.01.2021

Keywords:APEX

Es war ein schönes Weihnachtsgeschenk der Oracle APEX-Entwickler: Die heiß ersehnte Application Express Version 5.1 wurde am 21. Dezember 2016 veröffentlicht.

APEX 5.1 bietet u. a. diese neuen Features:

  • Interactive Grid
  • Oracle JET Charts
  • Erweiterungen des Universal Themes
  • Verbesserungen des Page Designers
  • neue und überarbeitete Packaged Apps
  • Vereinfachung der Wizard-Schritte im App Builder
  • anpassbarer Kalender (FullCalendar jQuery)

Nun geht es natürlich darum, sich mit den Neuerungen und erweiterten Funktionen vertraut zu machen und diese in der eigenen Umgebung einzusetzen und zu testen. In diesem Artikel stellen wir einige der wichtigsten Verbesserungen vor.

Um einen ersten Überblick über die neuen Features von APEX 5.1 zu erhalten, lohnt es sich, die neuen sowie überarbeiteten Packaged Apps – in der APEX-Installation enthaltene Beispiel-Anwendungen – zu installieren.

Neu sind die Beispiel-Applikationen "Sample REST Services", "REST Client Assistant" und "Sample Interactive Grids", wobei Letztere das wohl wichtigste Feature der Version 5.1 vorstellt: Die sogenannten Interactive Grids.

INTERACTIVE GRIDS

Hinter diesem Begriff versteckt sich ein neuer Report-Typ, dessen einzelne Felder ähnlich wie in Excel bearbeitet und modifiziert werden können. Dabei vereint das Interactive Grid die Anpassungsmöglichkeiten des Interactive Reports mit den Optionen der Tabular Form (nun veraltet), in der man Daten direkt auf der Report-Seite hinzufügen, bearbeiten oder löschen kann.

Für Interactive Grids mit Bearbeitungsfunktion können bereits in der Report-Query bestimmte Zeilen der Tabelle geschützt werden: So wird genau festgelegt, auf welchen Datensätzen welche DML-Operationen ("U", "D", "UD") durchgeführt werden dürfen. Geschützte Zeilen werden im Bearbeitungsmodus ausgegraut. 

Der Benutzer hat im Interactive Grid nun auch die Möglichkeit, den Report durch Drag & Drop individuell zu gestalten und so beispielsweise die Spaltenreihenfolge und -breite nach Belieben zu definieren. Über das Menü der Spaltenüberschriften kann die Option "Freeze" angewählt werden: Damit fixiert der Benutzer einzelne Spalten rechts im Report, die auch während horizontalen Scrollens immer angezeigt werden.

Für die Definition einer Spalte stehen im Interactive Grid nun übrigens alle Item-Typen (Ausnahme: Rich Text Editor) sowie Item-Plugins zur Verfügung. Mehrere Report-Spalten lassen sich zudem deklarativ in einer Spalten-Gruppe zusammenfassen. Der Benutzer erhält auf diese Weise einen besseren Überblick über die Daten.

Das Interactive Grid bietet unterschiedliche Varianten der Report-Pagination, wobei hier insbesondere die Scroll Pagination, auch "Infinite Scrolling" genannt, als neues Features hervorsticht. Während des Scroll-Prozesses werden dabei immer nur die für den Benutzer aktuell sichtbaren Datensets geladen, um so eine bestmögliche Performance bei konstanter Benutzerfreundlichkeit zu gewährleisten.  

In den bisherigen APEX-Versionen konnte lediglich eine Master-Detail-Beziehung pro Seite abgebildet werden. Das Interactive Grid bringt auch in diesem Punkt eine Erweiterung mit sich: Es lassen sich nun beliebig viele Master-Detail-Beziehungen über beliebig viele Ebenen hinweg darstellen.

Neu im Bereich Dynamic Actions ist der Auswahltyp "Columns", der sowohl in einem Event, als auch in einer bestimmten Aktion genutzt werden kann. Ändert der Benutzer beispielsweise einen Spaltenwert im Interactive Grid, kann jetzt mit einer Dynamic Action entsprechend darauf reagiert werden.

ORACLE JET CHARTS

Die Packaged App "Sample Chart" ist zwar schon aus früheren APEX-Versionen bekannt, wurde jedoch für das neue Release erweitert und dient nun der Vorstellung eines weiteren APEX 5.1 Features: Oracle JET Charts.

Dem APEX-Entwickler stehen nun verschiedene neue Diagrammtypen wie beispielsweise Polar, Funnel oder Radar zur Verfügung. Alle grafischen Darstellungen erscheinen im modernen HTML5-Design, können in den Einstellungen oder auch über Java-Script APIs individuell angepasst werden und reagieren responsiv auf Änderungen der Displaygröße oder weitere Eigenheiten des jeweiligen Endgeräts.

Ermöglicht wird das durch eine neue Chart-Engine, die auf Komponenten der Oracle Java-Script Extension Toolkit (JET) Data Visualizations, einem Open Source Java-Script Framework, basiert. AnyChart-Diagramme aus älteren APEX-Versionen können über einen Migrations-Wizard in JET Charts umgewandelt werden (Ausnahme: MapCharts).

UNIVERSAL THEME

Die Packaged App "Universal Theme" wurde komplett überarbeitet und präsentiert nun im neuen Design die diversen Erweiterungen des Universal Themes unter APEX 5.1.

Interessant ist dabei vor allem die neue Font APEX Icon-Bibliothek, die den früheren Font Awesome um viele Symbole (u.a. zu den Themen Datenbank, Diagramme, Webgestaltung, Barrierefreiheit und Emojis) ergänzt.

Das Icon-Präfix "fa" wurde beibehalten, um den Umstieg auf Font APEX zu erleichtern. Die neuen Icons besitzen verschiedenste Anpassungsmöglichkeiten und können beispielsweise animiert, beliebig gedreht bzw. gespiegelt oder durch zusätzliche kleine Icons ergänzt werden. 

Außerdem bietet das Universal Theme sogenannte Live Template Options, die über die Entwickler-Toolbar Option "Quick Edit" erreichbar sind. Damit können durch eine dem Theme Roller ähnliche Vorgehensweise die Template Options des gewünschten Elements zur Laufzeit geändert werden - das umständliche Hin- und Herschalten zwischen Page Designer und laufender Applikation fällt damit weg.

PAGE DESIGNER

Auch der Page Designer hält einige Neuerungen für APEX-Entwickler bereit: Zunächst wurde die frühere Seitenbearbeitungsansicht "Component View" in den Layout Editor des Page Designers integriert. Damit können Entwickler ihre gewohnte Bearbeitungsansicht, gleichzeitig aber auch die Vorteile des Page Designers nutzen.

Die Darstellung des Page Designers kann zudem beliebig angepasst werden: Zur Auswahl steht hier nicht nur die Anzeige von drei bzw. nur zwei Ausschnitten (Layout und Property Editor), die einzelnen Menü-Tabs im Page Designer können auch per Drag & Drop an einen anderen Bereich geheftet werden.

Praktisch ist auch, dass konditionierte Seitenelemente in APEX 5.1 deutlich mit einem lila Punkt gekennzeichnet werden, was dem Entwickler einen schnelleren Überblick ermöglicht.

Viele weitere Informationen, Erklärungen und Beispiele zu den neuen Features der Version 5.1 erhalten Sie in unserem APEX 5.x/18.1 Kurs Grundlegendes Wissen zur Anwendungsentwicklung mit Oracle Application Express bieten Ihnen außerdem unsere APEX-Schulungen.

Schauen Sie doch einfach mal vorbei! Inwischen sind wir schon bei der APEX Version 20.2 angekommen, auch da gibt es viele neue spannende Features.



Weitere Interessente Artikel zum Thema:


Empfohlene Schulungen zum Thema:


Tooltipps in APEX5.x

Bereich:APEX, Version: ab APEX 5.x, Letzte Überarbeitung: 11.12.2018

Keywords:APEX

Tooltipps sind eine schöne Gestaltungsmöglichkeit, um Texte an verschiedenen Stellen in einer Webseite einzubauen.

Der HTML Befehl dazu lautet:

<span TITLE="Hier zum Beispiel">Stellen</span>


Wie sieht das Ganze in APEX aus? Wenn Sie den Tooltipp in einem Report verwenden möchten, können Sie aus mehreren Varianten wählen:

Im SELECT Statement:

SELECT ename,job,sal,'<span TITLE="Abteilung:'||d.dname||'">'||e.deptno||'</span>'
  FROM emp e, dept d
 WHERE e.deptno=d.deptno;


Oder in der jeweiligen Spaltenformatierung:

--> Bereich (APEX 5.x!): Column Formating / HTML Expression

Wenn der Tooltipp statisch sein soll lautet die Syntax:

<span TITLE="Hier könnte Ihr Tooltipp stehen">#ENAME#</span>


Wenn man eine andere Spalte im Tooltipp darstellen möchte, referenziert man sie einfach mit #SPALTENNAME#:

<span TITLE="Verdienst:#SAL#">#ENAME#</span>


Wenn der Tooltipp in der Spaltenüberschrift stehen soll:

Gehen Sie auf den Tree-Punkt Attributes (dieser hängt im Report unter dem Punkt Columns).
Dort im Bereich Heading kann der Type auf "PL/SQL Function Body" gesetzt werden.

Danach gibt man als PL/SQL Function Body an:

wenn es statisch sein soll:

RETURN
'<span TITLE="Hier steht der Nachname">ENAME</span>:
<span TITLE="Hier steht der Beruf">JOB</span>:
<span TITLE="Hier steht das Gehalt">SAL</span>:
<span TITLE="Hier steht die Abt.Nr.">DEPTNO</span>';


wenn Sie es lieber dynamisch haben möchten (mit nur einem Tooltipp auf einer Spaltenüberschrift):

DECLARE
s CLOB;
BEGIN
SELECT listagg(dname,',') within group (order by dname) INTO s FROM dept;
s:='ENAME:JOB:SAL:
<span TITLE="Abts:'||s||'">DEPTNO</span>';
RETURN s;
END;

 

Hinweis: Der Select des Reports lautete dazu:

SELECT ename,job,sal,deptno FROM emp;

 

 

 



Weitere Interessente Artikel zum Thema:


Empfohlene Schulungen zum Thema:


Oracle APEX Friendly URL ab 20.1

Bereich:APEX, Version: ab APEX 20.1, Letzte Überarbeitung: 31.03.2021

Keywords:Oracle Friendly URL Neuerungen, APEX 20.2

Das Feature war lange überfällig und wurde nun ab APEX 20.1 endlich implementiert: Friendly URL.
Ich vermute ja, dass die URL hauptsächlich freundlicher gestaltet wurde um die "bösen" SEO Geister der Google Suchmaschine zu besänftigen...
Mit der alten Session Notation konnte Google nämlich nichts anfangen und hat bei jedem "spidern" eine neue Session ID bekommen, die Seite dann intern gespeichert
und mit den bereits beim letzten Mal gespiderten Seiten verglichen um dann festzustellen, dass die Seite "in einer anderen Version" schon gibt.
Das führt dann gnadenlos zum Downgrade (bei uns 20 Plätze) mit der Begründung: Kanonische Seiten !

Zurück zur URL:

Altes APEX URL Format (bis 19.2):

https://server:8080/ords/f?p=101:1:123456789:myRequest:YES1,2P1_A,P1_BA,1YES 

 

 https://server:Name des Servers oder IP Adresse
 8080Port des Webservers (TomCat / Apache / Nginx / Bea WebLogic)
 /ordsName des Ords War files
 /f?p=Aufruf der Procedure f mit Parameter p
1101:Appliaktions-Alias oder Applikations ID
21:Seiten-Alias oder Seitennummer
3123456789:Session ID oder 0 für Public Pages
4myRequestName des Request für die Ziel-Seite (beliebiger Text, der mit :REQUEST oder &REQUEST. weiterverarbeitet werden kann
5YESDebug der Seiten (YES/NO)
61,2Clear Cache für die Seiten 1 und 2 (Reset der Items der Seiten)
7P1_A,P1_BSetzt die Items P1_A und P1_B auf ...
8A,1die Werte A und 1
9YESSeiten in druckfreundlichen Format ausgeben (YES/NO)


Neue Oracle APEX URL Format (ab 20.1):
 

https://server:8080/ords/muso_training/r/myapp/mypage?session=123456&p1_a=A&p1_b=1&request=myTest


Erklärung der URL Parameter:

 https://server:Servername oder IP
 8080Port des Webservers (TomCat / Apache / Nginx / Bea WebLogic)
 /ordsName des Rest Service (Default ords)
1/muso_trainingÄnderbar durch "Internal Workspace": Manage Workspaces / Existing Workspace / Edit Workspace Information / => Component Availability / RESTful Path Prefix
oder
begin apex_instance_admin.get_parameter(
'PATH_PREFIX','xyz');
end;
2/rImmer fest auf "r" gesetzt. Kann aber geändert werden durch:
BEGIN apex_instance_admin.get_parameter('APEX_REST_PATH_PREFIX','r');
END;
3/myappApplikationname (myapp) oder App Nummer (z.B. 100)
4/mypage?Seitenalias (mypage) oder Seitennummer (z.B. 1)
5session=123456Session ID oder 0 für Public Pages
6&p1_a=A
&p1_b=1
Name der zu setzenden Items oder deren Wert:
:P1_A:='A' und :P1_B:=1;
7&request=myTestName des Requests (hier myTest)
8&clear=1,2zu resetende Seiten-Items (hier alle Items auf Seiten 1 und 2)
CR = Clear Region, RR = Reset Region, RP = Reset Pagination
9#myANKERSeitenanker anspringen


Hinweis: Die Rehenfolge der Parameter von Position 5 bis 8 ist austauschbar, nur beginnt der erste Parameter mit ?xxx
und die folgenden werden mittels &yyy drangehängt. Achten Sie bitte darauf, dass bei der Itemersetzung im HTML Kontex
weiterhin die Syntax &ITEM. (Betonung auf dem Punkt!) lautet.
Sie sollten die Seiten URL weiterhin erzeugen durch das Package: APEX_PAGE.GET_URL!
Die Syntax lautet:

FUNCTION GET_URL (
    p_application        IN VARCHAR2 DEFAULT NULL,
    p_page               IN VARCHAR2 DEFAULT NULL,
    p_session            IN NUMBER   DEFAULT APEX.G_INSTANCE,
    p_request            IN VARCHAR2 DEFAULT NULL,
    p_debug              IN VARCHAR2 DEFAULT NULL,
    p_clear_cache        IN VARCHAR2 DEFAULT NULL,
    p_items              IN VARCHAR2 DEFAULT NULL,
    p_values             IN VARCHAR2 DEFAULT NULL,
    p_printer_friendly   IN VARCHAR2 DEFAULT NULL,
    p_trace              IN VARCHAR2 DEFAULT NULL )
    RETURN VARCHAR2;


Beispiel:

SELECT apex_page.get_url(
p_application=>100,p_page=>1, p_session=>:APP_SESSION,p_items=>'P1_A,P1_B',p_values=>'A,B')
FROM dual;


Weitere spannende Themen erwarten Sie in einem unserer APEX Kurse.
Fun Fakt: Wir haben vermutlich weltweit die meisten verschiedenen APEX Kurse im Program (APEX Kompakt, APEX I, APEX II, APEX New Features, APEX Security, APEX im Internet)
macht 6 Stück, wer bietet mehr ? Unser Dozent arbeitet schon seit 1997 mit APEX Techniken (ja da gab es APEX noch gar nicht ...)



Weitere Interessente Artikel zum Thema:


Empfohlene Schulungen zum Thema:


APEX 21.1 für Oracle XE 18c installieren

Bereich:APEX, Version: ab APEX 21.1, Letzte Überarbeitung: 02.04.2022

Keywords:Oracle APEX 21.1, Installation, Oracle XE

Auch 2021 gibt es natürlich ein neues APEX Release, das nur durch den tragischen Tod eines der Mitbegründer von APEX überschattet wird: Joel Kallmann
Ich durfte Ihn zwar leider nicht persönlich kennen lernen, hatte aber mehrfach via Forum Kontakt zu Ihm. Meine Hochachtung vor seiner Lebensleistung!

 

Hinweis: Bei unseren Test mit APEX 21.1 haben einige "Kleinigkeiten" nicht funktioniert, evtl sollten Sie noch warten bis der erste Patch rauskommt (Update: es gibt den ersten Patch 32598392):
Wenn Sie die APEX Version 21.1 (Stand 12. Mai 2021)  in die kostenlose Oracle XE Datenbank Version 18c installieren möchten, gehen Sie bitte wie folgt vor:

Laden Sie sich zuerst APEX und die Oracle Expres (XE) Version 18c herunter. Wir installieren immer die NON-CDB Variante (so lange es noch geht :-) )
Update vom 2.4.2022: Ab Version 21c XE ist nun nur noch eine Pluggable Database Installation möglich!

Für LINUX verwenden wir den Installationspfad: /u01/software. Dort sollte dann die APEX Zipdatei ausgepackt liegen

Für die Installation APEX starten Sie:

UNIX> cd /u01/software
UNIX> sqlplus / as sysdba

Sie können für APEX bei Bedarf einen eigenen Tablespace anlegen, oder den SYSAUX Tablespace verwenden.

SQL> CREATE TABLESPACE apex_main_tbs DATAFILE '/opt/oracle/oradata/XE/apex_main01.dbf'
SIZE 512M AUTOEXTEND ON NEXT 64M MAXSIZE 2048M;

Nun gehen wir in das Installtionsverzeichnis und starten wir das APEX Installations-Hauptskript:

$#> cd /u01/software/apex
$#> sqlplus / as sysdba
SQL> @apexins APEX_MAIN_TBS APEX_MAIN_TBS TEMP /i/

oder der bereits vorhandene interne SYSAUX Tablespace soll zum Einsatz kommen:

SQL> @apexins SYSAUX SYSAUX TEMP /i/


Kopieren Sie die Bilder in den entsprechenden Webserver Ordner:

export APEX_IMG=/var/www/html/i
mv $APEX_IMG $APEX_IMG.old
cp -R /u01/software/apex/images $APEX_IMG
chmod -R oracle:tomcat $APEX_IMG
passen Sie den Ordner ggf an, wenn bei Ihnen ein anderer verwendet wird

Das letzte Skript setzt das Passwort für INTERNAL Workspace ADMIN Benutzer fest.
Wenn Sie migrieren von einer niedrigeren Version von APEX (19.x oder 20.x), ist dieser Schritt nicht notwendig.

SQL> @apxchpwd

Sie werden 3 Parameter gefragt:

  • Benutzername (MUSS nicht ADMIN heissen)
  • Email-Adresse: info@muniqsoft-training.de ( Bitte verwenden Sie Ihre eigene, oder dürfen wir Ihren APEX Server verwalten? (für Geld machen wir fast alles :-) )
  • Passwort (muss ein komplexes Passwort mit Groß und Kleinschreibung, Zahlen und Sonderzeichen sein)

Das letzte Problem (Passwortkomplexität) kann man aber umgehen, wenn man zuvor den folgenden Befehl laufen lässt:

EXEC APEX_INSTANCE_ADMIN.SET_PARAMETER('STRONG_SITE_ADMIN_PASSWORD','N');


Zusätzlich wird die REST Schnittstelle benötigt, die man für alle REST Aufgaben uns auch die Application und Workspace Files benötigt.
Wenn Sie von einer niedrigeren Version von APEX (19.x oder 20.x) migrieren, ist dieser Schritt nicht notwendig.

SQL>@apex_rest_config


Nun können Sie sich anmelden:

http://servername:port/ords/f?p=4550


Legen Sie sich zuerst einen Workspace mit einem Administrationsbenutzer an.



Weitere Interessente Artikel zum Thema:


Empfohlene Schulungen zum Thema:


Oracle APEX 20.2 installieren in einer Oracle XE 18c Datenbank

Bereich:APEX:DBA, Version: ab APEX 20.2:RDBMS 18.3, Letzte Überarbeitung: 11.01.2021

Keywords:APEX 20.2

Alle hatten noch mit einer Oracle Express Edition 20c im Jahre 2020 gerechnet, nur nachdem es kein OnPremise Release von Oracle im Jahre 2020 gegeben hat, wurde natürlich auch kein neues Express Edition Release veröffentlicht. Unsere Hoffnung ist, das im Sommer eine Oracle XE 21c Edition verfügbar ist. In der Zwischenzeit nehmen wir die Oracle XE 18c Edition füt unsere APEX Installation.

Wenn Sie die APEX Version 20.2 (Stand Dezember 2020) in die kostenlose Oracle XE Datenbank Version 18c installieren möchten, gehen Sie bitte wie folgt vor:

Laden Sie sich zuerst APEX und die Oracle Expres (XE) Version 18c herunter.

Für LINUX verwenden wir den Installationspfad /u01/software. Dort sollte dann die APEX Zipdatei ausgepackt liegen

Für die Installation APEX starten Sie:

UNIX> cd /u01/software
UNIX> sqlplus / as sysdba

Sie können für APEX bei Bedarf einen eigenen Tablespace anlegen, oder den SYSAUX Tablespace verwenden.

SQL> CREATE TABLESPACE apex_main_tbs DATAFILE '/opt/oracle/oradata/XE/apex_main01.dbf'
SIZE 512M AUTOEXTEND ON NEXT 64M MAXSIZE 2048M;

Nun starten wir das APEX Installations-Hauptskript:

SQL> @apexins APEX_MAIN_TBS APEX_MAIN_TBS TEMP /i/

oder der bereits vorhandene SYSAUX Tablespace kommt zum Einsatz:

SQL> @apexins SYSAUX SYSAUX TEMP /i/


Hinweis: Der nächste Schritt installiert die notwenifen Einstllungen für den REST Betrieb (APEX verwendet den z.B. für die Application oder Workspace Images)

SQL> @apex_rest_config.sql


Das letzte Skript setzt das Passwort für INTERNAL Workspace ADMIN Benutzer fest.

SQL> @apxchpwd

Sie werden 3 Parameter gefragt:

  • Benutzername (MUSS nicht ADMIN heissen)
  • Email-Adresse: info@muniqsoft-training.de ( Bitte verwenden Sie Ihre eigene, oder dürfen wir Ihren APEX Server verwalten? (für Geld machen wir fast alles :-) )
  • Passwort (muss ein komplexes Passwort mit Groß und Kleinschreibung, Zahlen und Sonderzeichen sein)

Das letzte Problem (Passwortkomplexität) kann man aber umgehen, wenn man zuvor den folgenden Befehl laufen lässt:

EXEC APEX_INSTANCE_ADMIN.SET_PARAMETER('STRONG_SITE_ADMIN_PASSWORD','N');


Nun können Sie sich anmelden:

http://servername/ords/f?p=4550


Legen Sie sich zuerst einen Workspace mit einem Administrationsbenutzer an.
 



Weitere Interessente Artikel zum Thema:


Empfohlene Schulungen zum Thema:


Oracle ORDS (bis 21.4.3.x) Fehler und Lösungsvorschläge

Bereich:APEX, Version: ab APEX 18.1, Letzte Überarbeitung: 21.09.2023

Keywords:Oracle, ORDS 21.x, REST, Fehler, Probleme, Lösungen, Lösungsvorschläge

Das heutige Thema beschäftigt mit häufigen ORDS Problemen und Fehlern. Da ich schon mehrere Stunden/Tage auf der Suche nach Fehlern mit der Oracle ORDS Schnittstelle verbracht habe, möchte ich versuchen etwas zu den möglichen Lösungen beizutragen... 

Übersicht: 
0. Debugging einschalten 
1. Datenbankbenutzer prüfen 
2. Problem: Die Bilder-/ CSS-/ Java-Script-Dateien fehlen, oder liegen im falschen Verzeichnis. 
3. Es kommt die Fehlermeldung, dass die Version der Bilder, nicht zur Version von APEX passt. 
4. Die "ords.war"-Datei funktioniert in Verbindung mit Tomcat einfach nicht: 
5. Eine ominöse CSS Datei wird nicht gefunden z.B. 56437564376.css 
6. Mehrere Webserver belegen den gleichen Port 
7. Ein oder mehrere Benutzer sind gesperrt oder das Passwort ist abgelaufen 
8. defaults.xml Datei nicht lesbar/vorhanden 
9. ORDS komplett neu aufsetzen 
10. Fehler 404 The request could not be mapped to any database 
11. 404 Not Found  Die Anforderung konnte keiner Datenbank zugeordnet werden  
12. Fehler 503 Service Unavailable 
13. Internal Server Error 500 

0. Debugging einschalten 

Es hat sich bewährt, bei Problemen rund um APEX, REST oder dem Webserver zuerst mal Debugging einzuschalten: 
Gehen Sie dazu in die Datei defaults.xml (im Ordner den sie bei der ersten Frage der Installation von ords.war angegeben haben), 
dort stehen u.a. evtl folgende Zeilen:

<entry key="db.connectionType">basic</entry>
<entry key="db.hostname">my_db_server</entry>
<entry key="db.port">1521</entry>
<entry key="db.sid">o23c</entry>


Wir ergänzen die folgenden Zeilen, bzw. editieren sie, falls bereits vorhanden.

<entry key="debug.debugger">true</entry> 
<entry key="debug.printDebugToScreen">true</entry> 
<entry key="log.logging">true</entry> 
<entry key="log.maxEntries">500</entry>


Wenn Sie Tests machen möchten, ob die Verbindung funktioniert, können sie auch das Kommandozeilen Tool curl verwenden:

curl http://myserver:8080/ords



1. Datenbankbenutzer prüfen 


Prüfen Sie die Verfügbarkeit der DB-Benutzer mit folgenden SELECT:

SELECT 
    username, lock_date, expiry_date, account_status 
FROM 
    dba_users 
WHERE 
    username IN ( 
        'ANONYMOUS', 
        'APEX_PUBLIC_USER', 
        'APEX_LISTNER', 
        'APEX_REST_PUBLIC_USER', 
        'ORDS_METADATA', 
        'ORDS_PUBLIC_USER' 
    ) 
ORDER BY 1;

Da sollte dann z.B. folgendes als Rückgabe erscheinen: 

USERNAME LOCK_DATE EXPIRY_DATE  ACCOUNT_STATUS 
ANONYMOUS                     28.04.2023 OPEN 
APEX_PUBLIC_USER          30.04.2023  OPEN 
APEX_REST_PUBLIC_USER 30.04.2023 OPEN 
ORDS_METADATA              30.04.202330.04.2023OPEN
ORDS_PUBLIC_USER         30.04.2023 OPEN 



Erklärung: 
Wenn Sie das interne Gateway (Oracle EPG) via Oracle Listener ohne Webserver verwenden, muss der Benutzer ANONYMOUS den Status OPEN besitzen. 
Wenn ein Webserver verwendet wird, kann der Benutzer ANONYMOUS gesperrt sein (LOCKED), jedoch muss der Benutzer APEX_PUBLIC_USER auf OPEN stehen. 
Wenn Sie eine höhere APEX Version besitzen (5.1) werden viele interne Funktionen (auch das Bereitstellen von Bildern, CSS und Javascript z.B. bei den Application Files) via REST Schnittstellen zur Verfügung gestellt. Hier muss auch der Benutzer APEX_REST_PUBLIC_USER entsperrt sein. 
Sollte die Spalte LOCK_DATE bereits ein Datum besitzen, muss der Benutzer entsperrt werden.

ALTER USER <user> ACCOUNT UNLOCK;


Sollte die Spalte EXPIRY_DATE schon in der baldigen Zukunft liegen, sollte die Account-Lebensdauer auch gleich verlängert werden: 
a, Sollte das gleiche Passwort verwendet werden, hier am Beispiel mit Benutzer ANONYMOUS:

select q'!ALTER USER anonymous IDENTIFIED BY VALUES '!'||spare4||q'!' ACCOUNT UNLOCK;!' 
from sys.user$ 
where name='ANONYMOUS';

Führen Sie das zurückgegebene Statement aus, dann wird die Lebensdauer des Accounts verlängert. 
b, wenn Sie das Passwort ändern möchten (Achtung dann muss es auch in einer ORDS XML Datei synchron geändert werden!

ALTER USER ORDS_PUBLIC_USER IDENTIFIED BY owiegutdasniemandmeinpwdweiss;


2. Problem: Die Bilder-/ CSS-/ Java-Script-Dateien fehlen, oder liegen im falschen Verzeichnis. 


Die Fehlermeldung lautet dann z.B. 
There is a problem with your enviroment because the Application Files have not been loaded. 
Prüfen Sie bitte, ob ein Ordner mit Namen "i" im Verzeichnis 
.. tomcat/WebApps/ROOT 
liegt, ansonsten könnte die Seite (weil die CSS-Dateien nicht geladen werden) defekt aussehen. 
Wenn Sie zusätzlich den Apache als ReverseProxy einsetzen, müssen die Dateien im Apache docRoot Verzeichnis liegen (bei uns z.B. in /var/www/html)

3. Es kommt die Fehlermeldung, dass die Version der Bilder, nicht zur Version von APEX passt.

Da muss einfach der Browser Cache geleert werden. Oder Sie haben die Bilder beim Patchen nicht richtig mit den restlichen Dateien zusammenkopiert 
Hinweis: Für Apex 21.2.6 sollten 16.730 Dateien im Bild-Ordner (i) liegen 
In Version 22.2 sind es 15731 Dateien und 1332 Ordner = 17.063 Dateien

4. Die "ords.war"-Datei funktioniert in Verbindung mit Tomcat einfach nicht:

Prüfen Sie die Konsistenz der ords.war Datei mit:

java -jar ords.war validate 
oder 
java -jar ords.war validate --database o21c

Dann sollte folgende Ausgabe erscheinen:

Name des Datenbankservers eingeben [localhost]: 
Listener-Port der Datenbank eingeben [1521]: 
Datenbankservicename eingeben [o21c]: 
Erfordert SYS AS SYSDBA, um das Oracle REST Data Services-Schema zu verifizieren.
Datenbankkennwort für SYS AS SYSDBA eingeben: 
Kennwort bestätigen:
Informationen werden abgerufen.
Retrieving information.
Oracle REST Data Services will be validated. 
Validating Oracle REST Data Services schema version 21.1.0.r3541002 
... Log file written to /root/ords_validate_core_2021-01-16_133103_00877.log 
Completed validating Oracle REST Data Services version 21.1.0.r3541002.  Elapsed time: 00:00:04.798

Sie können natürlich auch noch die dazugehörige Log-Datei analysieren. Da sollte dann z.B. u.a. folgendes zu finden sein:

 

INFO: 08:27:22 Validating objects for Oracle REST Data Services. 
VALIDATION: 08:27:22 Starting validation for schema: ORDS_METADATA 
VALIDATION: 08:27:22 Validating objects 
VALIDATION: 08:27:23 Validating ORDS Public Synonyms 
VALIDATION: 08:27:24 Total objects: 259, invalid objects: 0 
VALIDATION: 08:27:24     72  INDEX 
VALIDATION: 08:27:24      1  JOB 
VALIDATION: 08:27:24     11  PACKAGE 
VALIDATION: 08:27:24     11  PACKAGE BODY 
VALIDATION: 08:27:24     43  PUBLIC SYNONYM 
VALIDATION: 08:27:24      1  SEQUENCE 
VALIDATION: 08:27:24     14  SYNONYM 
VALIDATION: 08:27:24     27  TABLE 
VALIDATION: 08:27:24     26  TRIGGER 
VALIDATION: 08:27:24     19  TYPE 
VALIDATION: 08:27:24      6  TYPE BODY 
VALIDATION: 08:27:24     28  VIEW 
VALIDATION: 08:27:24 Validation completed. 
INFO: 08:27:24 Completed validating objects for Oracle REST Data Services.

Ein Problem, was mir vier Wochen Suche beschert hat. Wir hatten bei der Installation von ORDS immer das Problem, dass sich die Installation an einer Stelle aufgehängt hatte. Sie hing ca. 15 min und stüzte dann ab mit " IO Error: Connection reset by Peer". 
Das Problem war, dass Java auf unserem System (CentOS 7) mit "/dev/random" nicht genügend viele Zufallszahlen berechnen konnte und stattdessen "/dev/urandom" nehmen musste.

Dazu müssen Sie bei der Installation folgendes zuätzlich angeben:

java -Djava.security.egd=file:///dev/urandom -jar ords.war

Allerdings kann man auch dem Pool der Zufallszahlen von "/dev/random" etwas mehr Entropie verleihen und daher weiterhin "/dev/random" nutzen. Dazu installiert man sich ein entsprechendes Tool:

yum install haveged 
systemctl enable haveged; systemctl start haveged;

 

5. Eine ominöse CSS Datei wird nicht gefunden z.B. 56437564376.css

Hier war eine fehlerhafte ords Installation schuld, es fehlte die Datei apex_rt.xml

Prüfen Sie nach der Installation, ob die folgenden Dateien im angegebenen Config Verzeichnis liegen:

  • apex_al.xml  <= Diese Datei wird vom APEX_LISTENER benötigt !!
  • apex_pu.xml <= Diese Datei wird vom ORDS_PUBLIC_USER benötigt !!
  • apex_rt.xml  <= Diese wird vom APEX_REST_PUBLIC_USER benötigt !!
  • apex.xml       <= Diese Datei wird vom APEX_PUBLIC_USER benötigt !!

Die Dateien sehen wie folgt aus (und können auch manuell erstellt werden):

apex.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>Saved on Sat Oct 22 11:54:56 CEST 2022</comment>
<entry key="db.password">@05939D2C32A74181B5BCBA375C0794A111</entry>
<entry key="db.username">APEX_PUBLIC_USER</entry>
</properties>


apex_al.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>Saved on Sat Oct 22 11:54:56 CEST 2022</comment>
<entry key="db.password">@05B2B32CE300417F3AE4BAD1112826CB84E</entry>
<entry key="db.username">APEX_LISTENER</entry>
</properties>


apex_rt.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>Saved on Sat Oct 22 11:54:56 CEST 2022</comment>
<entry key="db.password">@0577928598D4BAB7423441C0D8DF0855F</entry>
<entry key="db.username">APEX_REST_PUBLIC_USER</entry>
</properties>


apex_pu.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>Saved on Sat Oct 22 11:54:56 CEST 2022</comment>
<entry key="db.password">@05651DD1203D235C56A0585BC871A336A2</entry>
<entry key="db.username">ORDS_PUBLIC_USER</entry>
</properties>
Fehlerhafte / fehlende Dateien weden auch in der log Datei catalina.out angezeigt:
Wenn Sie übrigens das Passwort für einen dieser 4 Bebnutzer geändert haben, sollten Sie das hier in den Dateien auch durchführen. Geben Sie dazu das Passwort im KLARTEXT mit einem führenden ! in die Datei ein.
Also wenn ihr Passwort lautet: Suchmich2023## schreiben Sie in die Datei:
<entry key="db.password">!Suchmich2023##</entry>
<entry key="db.username">APEX_REST_PUBLIC_USER</entry>
 
Wenn Sie dann den TomCat Webserver durchbooten, sollte das Passwort wieder verschlüsselt mit einem führenden @ in der Datei stehen
systemctl stop tomcat && systemctl start tomcat
 
Sollte die Verschlüsselung nicht funktioniert haben, prüfen Sie doch mal bitte ob es das richtige Verzeichnis war in dem Sie die Datei editiert haben und ob TomCat schreibrechte auf dem Ordner/ den Dateien besitzt !
 
Bei uns stand wegen der fehlenden apex_rt.xml Datei im Logfile vom Tomcat (Datei: catalina.out):
Caused by: oracle.dbtools.url.mapping.TargetNotAvailableException: The connection pool named: apex_rt does not exist 
        at oracle.dbtools.url.mapping.db.PoolInjector.inject(PoolInjector.java:60)


Eine CSS Datei des Theme Rollers konnte auf einem Server teilweise nicht mehr gefunden werden. Teilweise ist immer spannend ... 
Ein Blick in die catalina.out brachte etwas Licht ins Dunkel: Einige ORDS_METADATA Views waren invalid- Bei genauerer Betrachtung der Views, stellte sich heraus, dass die dazu passenden Tabellen gar nicht (mehr) da waren. 

Nur wo werden diese angelegt? Nach einiger Suche habe ich beim Auspacken des ords.war Files die Datei ords_database.objects.sql im Ordner scripts/install/core gefunden. 
Nachdem das Skript nochmal installiert wurde (bitte im Schema ORDS_METADATA) lief wieder alles perfekt. 
Sicherheitshalber kann man natürlich einen Zusatzcheck durchführen (hier mir ORDS Version 19.4 (Stand 15.03.2020))

SELECT 
    object_type,    COUNT(valid),    COUNT(invalid) 
FROM 
    ( 
        SELECT object_type, 
            CASE 
                WHEN status = 'VALID' THEN   1 
            END AS valid, 
            CASE 
                WHEN status <> 'VALID' THEN 1 
            END AS invalid 
        FROM 
            dba_objects 
        WHERE 
            owner = 'ORDS_METADATA' 
    ) 
GROUP BY 
    object_type 
ORDER BY    1;


Das Ergebnis sollte in 19.4 (für 21.2 in Klammern) dann so aussehen:

OBJECT_TYPE VALID   INVALID 
INDEX 75 (86) 0 
JOB 1 (1) 0 
LOB 3 (3) 0 
PACKAGE 12 (20)0 
PACKAGE BODY 12 (19)0 
PROCEDURE 1 (1)0 
SEQUENCE1 (1)0 
SYNONYM 14 0 
TABLE 27 (30)0 
TRIGGER 27 (30)0 
TYPE 20 (20)0 
TYPE BODY 6 (6)0 
VIEW28 (34)0


6. Mehrere Webserver belegen den gleichen Port 


Prüfen Sie, ob das Oracle EPG evtl. den gleichen Port, wie Ihr Webserver belegt:

SELECT dbms_xdb.gethttport FROM dual;

Falls es der gleiche Port wie im Webserver ist, können Sie ihn wechseln:

EXEC dbms_xdb.sethttpport(0); -- Ausschalten des Datenbank Ports 
EXEC dbms_xdb.sethttpport(9090);  -- Anderer Port

oder unter Linux auf OS Ebene:

netstat -tulpn | grep 8080



7. Ein oder mehrere Benutzer sind gesperrt oder das Passwort ist falsch bzw. abgelaufen: 


Benutzer APEX_PUBLIC_USER 
Webserver Fehler: 503 Service Unavailable 
Wenn Debugging eingeschalten ist, dann auch noch: 
Der Verbindungspool namens |apex|rt| ist aufgrund der folgenden Fehler nicht korrekt konfiguriert: ORA-28000: Account ist gesperrt. 
Witzigerweise kann die Fehlermeldung auch erscheinen, wenn das Passwort falsch ist! 
Wenn Debugging ausgeschalten ist, bekommen Sie den Fehlertext: 
Benutzer oder Kennwort für den Verbindungspool namens |apex|| ist ungültig oder abgelaufen, oder der Account wurde gesperrt 
Lösung:

ALTER USER apex_public_user [IDENTIFIED BY meinpasswort] ACCOUNT UNLOCK;

Wenn Sie das Passwort auf dem Oracle Server geändert haben, muss es natürlich auch auf dem Oracle Client ( dem Webserver) geändert werden. 
Dass Passwort steht in Datei mit Namen apex.xml (im Ordner den sie bei der ersten Frage der Installation von ords.war angegeben haben) 
In der Datei sind u.a. folgende Zeilen:

<entry key="db.password">@0574B6939D4387C95AD95DA10B99690D65</entry> 
<entry key="db.username">APEX_PUBLIC_USER</entry>


Setzen Sie das geänderte Passwort unverschlüsselt mit vorangestellten ! in die Datei ein (nur bis ords 21.3.4 !!):

<entry key="db.password">!meinpasswort</entry>


Das Passwort wird beim Neustart des Webservers automatisch verschlüsselt. 

Benutzer: APEX_PUBLIC_REST_USER 
Symptome: Static und Workspace Files werden nicht mehr angezeigt 
Webserver Fehler: 503 Service Unavailable 

Wenn Debugging eingeschalten ist, dann auch noch : 
Der Verbindungspool namens |apex|rt| ist aufgrund der folgenden Fehler nicht korrekt konfiguriert: ORA-28000: Account ist gesperrt. 
Witzigerweise kann die Fehlermeldung auch erscheinen, wenn das Passwort falsch ist! 
Wenn Debugging ausgeschalten ist, bekommen Sie den Fehlertext: 
Benutzer oder Kennwort für den Verbindungspool namens |apex|| ist ungültig oder abgelaufen, oder der Account wurde gesperrt 
Lösung:

ALTER USER apex_public_user [IDENTIFIED BY meinpasswort] ACCOUNT UNLOCK;


Dass Passwort steht in Datei mit Namen apex_rt.xml (auch hier im Ordner den sie bei der ersten Frage der Installation von ords.war angegeben haben) 
In der Datei sind u.a. folgende Zeilen:

<entry key="db.password">@0574B6939D4387C95AD95DA10B99690D65</entry> 
<entry key="db.username">APEX_REST_PUBLIC_USER</entry>


Setzen Sie das geänderte Passwort unverschlüsselt mit vorangestellten ! in die Datei ein:

<entry key="db.password">!meinpasswort</entry>


Das Passwort wird beim Neustart des Webservers automatisch verschlüsselt. 

8. defaults.xml Datei nicht lesbar/vorhanden 


Prüfen Sie, ob die Konfigdatei defaults.xml lesbar und für den Webserver (z.B. TomCat) lesbar und auch im richtigen Ordner zur Verfügung steht. 
Fehler: 404 Not Found 
Die Anforderung konnte keiner Datenbank zugeordnet werden. Stellen Sie sicher, dass die Anforderungs-URL richtig ist und dass Zuordnungen zwischen URL und Datenbank korrekt konfiguriert wurden. 

Lösung: 
Stellen Sie sicher, das der Webserver (z.B. TomCat) auf die Datei zugreifen kann. Einfacher Trick: Benennen Sie die Datei um und starten 
Sie den Webserver durch. Er legt selbst eine neue Datei an. Falls nicht, gibt es evtl im Verzeichnis ein Rechteproblem. 

Wenn Sie nicht wissen, in welchen Verzeichnis die Datei liegt: 
im Webserver liegt im ords/WEB-INF Ordner eine Datei mit Namen web.xml. Dort steht u.a.

<param-name>config.dir</param-name> 
<!-- Enter the location where configuration settings should be stored --> 
<param-value>c:\oracle\ords_conf</param-value>


Bei uns hatte sich ein weiterer Fehler in einem Server eingeschlichen: 
Die SQL*Plus Datei pupbld.sql Datei wurde bei der Installation einer neuen Datenbank nicht installiert. Das hatte zur Folge, dass bei jeder Anmeldung eines Benutzers an der Datenbank eine Fehlermeldung:

Kennwort eingeben: 
ERROR: 
ORA-00942: Tabelle oder View nicht vorhanden 


Fehler bei Zugriff auf PRODUCT_USER_PROFILE 
Warnung:  Daten zu der Tabelle Product User Profile sind nicht geladen 
PUPBLD.SQL sollte als SYSTEM gestartet werden 
Letzte erfolgreiche Anmeldezeit: Mi Mrz 25 2020 14:02:32 +01:00 

Verbunden mit: 
Oracle Database 18c Express Edition Release 18.0.0.0.0 - Production 
Version 18.4.0.0.0


Nachdem wir die Datei (@?/sqlplus/admin/pupbld.sql) installiert hatten, funktionierte das Ganze nach einem Neustart des Webservers wieder. 
Sie sollten bei 404 Problemen generell die Hauptverdächtigen Benutzer ( APEX_PUBLIC_USER, ORDS_PUBLIC_USER und APEX_REST_PUBLIC_USER) mal manuell an die Datenbank anmelden. Wenn es da Probleme gibt, sollte diese zuerst gelöst werden! 
 

9. ORDS komplett neu aufsetzen: 


a, Benutzer löschen

SQL> DROP USER apex_listener CASCADE; 
SQL> DROP USER apex_rest_public_user CASCADE;
 

b, Webserver beenden

systemctl stop tomcat


b, ORDS deinstallieren:

java -jar ords.war uninstall

c, ords Configurations Verzeichnis finden und löschen 
Anzeige mittels:

java -jar ords.war configdir

Rückgabe: 
Mar 17, 2020 9:33:17 AM 
INFO: The config.dir value is /u01/software/oracle/ords/config 
d, Löschen des Verzeichnis:

rm -rf /u01/software/oracle/ords/config

Es sollte auch der ords.war und das Verzeichnis ords im Webserver (z.B. in /opt/tomcat/latest/webapps) gelöscht werden 
e, APEX_REST_CONFIG Skript als SYS neu starten

SQL>@apex_rest_config.sql

f, den Oracle ORDS neu konfigurieren: 
Hinweis: Packen Sie die datei ords.war immer neu aus dem Zip-Verzeichnis aus. Es könnten von der letzten Konfiguration sich fehler eingeschlichen haben.

java -jar ords.war
g, ords.war in das Webserver Verzeichnis verschieben
mv ords.war /opt/tomcat/webaps

h, Webserver (z.B. TomCat) wieder starten

systemctl start tomcat

und testen ob es nun funktioniert! 
10.The request could not be mapped to any database 

Der Fehler lautet: URLMappingNotFoundException [statusCode=404, reasons=[The request could not be mapped to any database. Check the request URL is correct] 
Hier war der Rest-Service ausgeschalten. Sie können ihn einschalten mittels:

EXEC apex_instance_admin.set_parameter('RESTFUL_SERVICES_ENABLED','Y'); 
 
 

Der Fehler tritt derzeit in Apex 20.1 bis 22.2 auf. 
Lösung laut Metalink Doc: ID 2685135.1: 

Schalten Sie die Option Friendly URL aus (Shared Components / Application Defintion Attributes) 

[Update vom 6.6.2021) Fehler 404 bei Rest Service 
Diese Mal war das Kennwort des ORDS_PUBLIC_USER abgelaufen.

select username,account_status,lock_date,expiry_date 
from dba_users u 
where username in ('APEX_PUBLIC_USER','ORDS_PUBLIC_USER','APEX_LISTENER');
USERNAME          ACCOUNT_STATUS  LOCK_DATE  EXPIRY_DATE          
----------------- --------------- ---------- -------------------- 
APEX_LISTENER     OPEN                       10.11.2022 11:40:31 
APEX_PUBLIC_USER  OPEN                       10.11.2022 12:12:53 
ORDS_PUBLIC_USER  OPEN                       10.11.2022 12:13:07

12. Fehler 503 Service Unavailable 


Der Datenbankbenutzer für den Verbindungspool |apex|pu| kann das Schema SCOTT nicht als Proxy verwenden. 
Möglicherweise ist eine Einschränkung der maximalen Anzahl an Datenbanksessions konfiguriert, oder ein Autorisierungsfehler liegt vor. 

Die Lösung war bei uns:

alter user scott grant connect through ords_public_user;

Ein ähnlicher Fehler war 
13. 500 Internal Server Error

Ein unerwarteter Fehler mit der folgenden Fehlermeldung ist aufgetreten: 
InternalServerException [statusCode=500, logLevel=SEVERE, reasons=[]] 

Caused by: java.sql.SQLException: ORA-00604: Fehler auf rekursiver SQL-Ebene 1 
ORA-01031: Nicht ausreichende Berechtigungen 
... 
Caused by: Error : 604, Position : 0, Sql = 
select nvl(h.items_per_page,m.items_per_page) items_per_page, t.etag_type, t.etag_query, h.source_type, m.origins_allowed, cursor
(select p.name, p.bind_variable_name, p.source_type,p.access_method, p.param_type from user_ords_parameters p where p.handler_id = h.id) 
parameters, h.source from user_ords_modules m, user_ords_t

APEX Region Display Selector Status auswerten

Bereich:APEX, Version: ab APEX 5.0, Letzte Überarbeitung: 19.12.2019

Keywords:APEX Region Display Selector

In einem meiner letzten APEX Kurse kam die Frage auf, wie kann man ermitteln, welche der Regionen duch den Region Display Selector ausgewählt wurde. Das ist zum Glück sehr leicht:

  • Wir brauchen eine Seite mit mindestens 2 Regionen (Region A und B)
  • Eine Region Display Selector Region
  • Eine Textfeld Item in der Region Display Selector Region (nicht in Region a oder B !) mit Namen P1_REGION_ID
  • und den folgenden Javascript (jQuery) Code im Page Propertie: Javascript / Execute When Page Loads:

$('.apex-rds').data('onRegionChange', function(mode, activeTab) {
apex.item( "P1_REGION_ID" ).setValue( activeTab.href, null, true )
});


Wenn mann nun wissen möchte welche Region ausgewählt wurde, sieht man nach der Auswahl die Nummer im Textfeld. Die kann man sich notieren und ggf eine Aktion damit verbinden.
Bei uns kamen z.B. folgende Werte raus:

  • #R6572207236661919
  • #R1415854210228239
  • #SHOW_ALL

Natürlich können Sie, wenn die Nummern bekannt sind, das Text-Feld in Hidden umändern...
 



Weitere Interessente Artikel zum Thema:


Empfohlene Schulungen zum Thema:


Oracle APEX Variablen im Oracle Trigger auslesen

Bereich:APEX:PL/SQL, Version: ab APEX 18.1, Letzte Überarbeitung: 12.01.2021

Keywords:Oracle Apex Trigger Variablen

Wenn man in seiner Oracle Datenbank Trigger zu Audit-Zwecken verwendet, ist man erstaunt, das als Apex Benutzer nicht der Anmeldebenutzer sondern ANONYMOUS oder APEX_PUBLIC_USER erscheint.

Das Problem kann man natürlich mit ein paar PL/SQL Objekten lösen.:-)
 

GRANT CREATE ANY CONTEXT TO scott;
DROP CONTEXT APEX_ENV;


Etwas unbekannt ist das Oracle Objekt Context, mit dem die Funktion sys_context erweitert werden kann.
Die Funktion sys_context besteht aus zwei Parametern:
Parameter 1: userenv
Parameter 2: ca 60 Stück u.a. OS_OSER, SESSION_USER, ...
Wir können die Funktionen nun erweitern, indem wir den ersten Parameter ändern auf apex_env
 

CREATE OR REPLACE CONTEXT apex_env
USING apex_env
/


Die Context Funktion benötigt zum Auffruf immer ein Package, das wir hiermit anlegen:

CREATE OR REPLACE PACKAGE apex_env
IS
 PROCEDURE set_context(
 p_variable IN VARCHAR2,
 p_value    IN VARCHAR2);
END;
/

CREATE OR REPLACE PACKAGE BODY apex_env IS
  PROCEDURE set_context(
    p_variable IN VARCHAR2,
    p_value    IN VARCHAR2) IS
  BEGIN
    dbms_session.set_context('apex_env',p_variable, p_value);
  END set_context;
END apex_env;
/

 

CREATE PUBLIC SYNONYM apex_env for apex_env;
GRANT EXECUTE ON my_login_package TO scott;


Führen wir einen Testcase durch und setzen den Context manuell:

BEGIN
apex_env.set_context('APP_USER','Marco');
apex_env.set_context('APP_PAGE_ID',123);
apex_env.set_context('APP_ID',100);
apex_env.set_context('APP_SESSION',123454678);
END;
/


Nun können wir den Context wieder auslesen:
 

SELECT
sys_context('apex_env','APP_USER') as APP_USER,
sys_context('apex_env','APP_PAGE_ID') as APP_PAGE_ID,
sys_context('apex_env','APP_ID') as APP_ID,
sys_context('apex_env','APP_SESSION') as APP_SESSION
FROM dual;


Jetzt erstellen wir uns eine Audit-Tabelle, in der stehen soll, welcher APEX Benutzer auf welcher Seite, in welcher APP mit welcher Session ID
die Änderung durchgeführt hat.

CREATE TABLE emp_audit (
empno        INT,
app_user     VARCHAR2(30),
app_page_id  INT,
app_id       INT,
app_session  INT);


und der passende Trigger dazu:

CREATE OR REPLACE TRIGGER EMP_TRG
BEFORE DELETE OR INSERT OR UPDATE ON EMP
FOR EACH ROW
BEGIN
  INSERT INTO emp_audit (empno,app_user,app_page_id,app_id,app_session)
  VALUES (nvl(:new.empno,:old.empno),
    sys_context('apex_env','APP_USER'),
    sys_context('apex_env','APP_PAGE_ID'),
    sys_context('apex_env','APP_ID'),
    sys_context('apex_env','APP_SESSION'));
END;
/


Jetzt brauchen wir nur noch den kleinen Testblock in unsere APEX-App einbauen:
Gehen Sie dazu auf: Edit Application Properties / Security und dort auf Database Session.
Im Bereich "Initialization PL/SQL Code" geben Sie dort ein:

BEGIN
apex_env.set_context('APP_USER',:APP_USER);
apex_env.set_context('APP_PAGE_ID',:APP_PAGE_ID);
apex_env.set_context('APP_ID',:APP_ID);
apex_env.set_context('APP_SESSION',:APP_SESSION);
END;
/


Weitere Tipps und Tricks erfahren Sie in einem unserer APEX oder PL/SQL Kurse (auch als Video-Streaming)



Weitere Interessente Artikel zum Thema:


Empfohlene Schulungen zum Thema:


APEX 23.2 Installation mit minimaler Downtime

Bereich:APEX, Version: ab APEX 23.2:ORDS 23.2, Letzte Überarbeitung: 25.11.2023

Keywords:APEX 23.2 Installation mit minimaler Downtime

Lange haben wir darauf gewartet, nun ist es endlich verfügbar. Seit  November 2023 kann man Oracle APEX 23.2 herunterladen. Im folgenden Tipp beschreiben wir kurz, wie es installiert wird.

Sie können APEX in jede Oracle Personal, Standard, Enterprise oder Express Edition (XE oder FREE) Datenbank installieren ab Version 18c

0. Erstellen Sie ein funktionierendes Backupo des Workspace, der Workspace Files und aller APEX Applikationen.
Das haben wir bereits in einem anderen Tipp thematisiert.

1. Herunterladen des Zip Files
Download Oracle APEX 23.2

2. Auspacken des Zip Files

# unzip apex_23.2.zip


3. Neue Bilderverzeichnisse vorbereiten und evtl an den tomcat Benutzer anpassen (teilweise wird auch www-data verwendet)

# cp -R /u01/software/apex/images/ /var/www/html/i2
# chown -R tomcat:tomcat i2



4. Webserver oder EPG stoppen (als root oder sudo)

# systemctl stop tomcat



5. In den ausgepackten Installationsordner gehen und die Installation via sql*plus starten:

# cd /u01/software/apex/
# sqlplus / as sysdba
SQL> SELECT tablespace_name FROM dba_tablespaces; -- Suchen Sie sich einen passenden aus
SQL> SELECT distinct tablespace_name FROM dba_segments
     WHERE owner like 'APEX%'; -- Da war bisher installiert (wenn es schon eine alte Installation gab )
SQL> @apexins APEX_TBS APEX_TBS TEMP /i/


6. Während das Skript läuft (bei unseren Maschinen ca 30 Min) kann der Bilderordener gewechselt werden

# mv /var/www/html/i /var/www/html/i_231_old
# mv /var/www/html/i2 /var/www/html/i


7. Nachdem das APEX 20.1 Installationsskript fertig ist, die REST Schnittstelle aktualisieren.
Sie sollten dazu die Passwörter der Benutzer APEX_LISTENER und APEX_REST_PUBLIC_USER zu Hand haben :-)

SQL> @apex_rest_config


8. Webserver oder EPG starten (als root oder sudo)

# systemctl start tomcat
oder
SQL> EXEC dbms_xdb.sethttpport(8080); -- oder den Port aus Schritt 4 wieder verwenden


9. Passwort für den Internal Workspace Admin Nutzer ändern

SQL> @apxchpwd


Sie werden die folgenden Parameter gefragt:
Benutzername: [Schlau ist, ihn nicht ADMIN zu nennen !]
Email: [Ihre Email Adresse angeben ]
Passwort: [Nur einmal !, also bitte nicht vertippen :-) ]

Vergessen Sie zum Abschluß nicht, den Browser Cache zu leeren!

Neuerung für die Neuinstallation:
Es gibt ein neues Universalskript mit Namen: apxsilentins.sql
Es übernimmt automatisch die folgenden Schritte:
a, Installation von APEX (Skript apexins.sql)
b, Erstellung oder Upgrade des Instanz-Admin-Accounts (Skript: apxchpwd.sql)
c, APEX_PUBLIC_USER konigurieren
d, Anpassung der Network ACLs
e, Static File Support mittels REST (Skript: apex_rest_config.sql

Aufruf-Syntax:

SQL> @apxsilentins.sql tablespace_apex tablespace_files tablespace_temp images
      password_apex_pub_user password_apex_listener password_apex_rest_pub_user
      password_internal_admin


Parametererklärung:

  • tablespace_apex  Tablespace für die Installation des APEX Benutzers
  • tablespace_files   Tablespace für Uploaded Files
  • tablespace_temp  Sortiertablespace
  • images  Bildordner
  • password_apex_pub_user Passwort für apex_public_user
  • password_apex_listener  Passwort für apex_listener
  • password_apex_rest_pub_user Passwort für apex_rest_public_user
  • password_internal_admin Passwort für den Internal Admin Benutzer


Beispielaufruf:

SQL> @apxsilentins.sql SYSAUX SYSAUX TEMP /i/ Passw0rt!#1 Passw0rt!#2 Passw0rt!#3 Passw0rt!#4


Alternative für Produktiv-Umgebungen (mit absoluter Downtime von unter 1 Minute!):
1-3 siehe oben
4. Webserver nicht beenden !
5. Variablen für die Parameter vorbereiten

SQL> REM Wenn Sie Ihren Tablespace nicht mehr wissen:
SQL> SELECT tablespace_name FROM dba_tablespaces ORDER BY 1;

SQL> DEFINE tablespace_apex=SYSAUX
SQL> DEFINE tablespace_files=SYSAUX
SQL> DEFINE tablespace_temp=TEMP
SQL> DEFINE images=/i/

 

Minimale Downtime, während der Installation (unter 1 Minute )


6. Phase 1: Installation des Full Development (Lief bei uns: 2m 10s)

SQL> @apexins1.sql &tablespace_apex. &tablespace_files. &tablespace_temp. &images.

Wenn nur die Runtime Version installiert werden soll:

SQL> @apxrtins1.sql &tablespace_apex. &tablespace_files. &tablespace_temp. &images.


7. Phase 2: Entwicklung ab jetzt nicht mehr möglich, Endanwender können weiterarbeiten (Lief bei uns: 4m 20s)

SQL> SET define "&"
SQL> @apexins2.sql &tablespace_apex. &tablespace_files. &tablespace_temp. &images.

Wenn nur die Runtime Version installiert werden soll:

SQL> SET define "&"
SQL> @apxrtins2.sql &tablespace_apex. &tablespace_files. &tablespace_temp. &images.

 

In den 4 Minuten, wo das Skript läuft haben Sie Zeit die Bilder/CSS/Javascript Dateien in das passende Webserver Verzeichnis zu kopieren.
Nur überschreiben Sie damit ja das alte Image Verzeichnis und dass muss ja noch 5 Minuten leben

Trick: Kopieren Sie die Bilder in ein Verzeichnis i2

Bei Apache Tomcat wäre das (bei uns): 

/opt/tomcat/latest/webapps

Wenn der Apache Webserver als Reverse Proxy davor geschalten ist: 

/var/www/html

Prüfen Sie ob die Dateien gelesen werden können (Rechte und Eigentümer beachten!)

https://ihr_server/i/apex_version.txt

Sollte zurückliefern:

Application Express Version:  23.2
8. Webserver beenden

# systemctl stop tomcat


9. Phase 3: Endanwender können NICHT mehr weiterarbeiten (lief bei uns 0m 40s)

SQL> SET define "&"
SQL> @apexins3.sql &tablespace_apex. &tablespace_files. &tablespace_temp. &images.

Wenn nur die Runtime Version installiert werden soll:

SQL> SET define "&"
SQL> @apxrtins3.sql &tablespace_apex. &tablespace_files. &tablespace_temp. &images.


Denken Sie nun daran die Bilverzeichnisse zu tauschen, also z.B.

# mv i i_old
# mv i2 i

 

BONUSTIPP:
Prüfen Sie, ob ACLS für die alte APEX Installation vorhanden sind, die gelöscht werden sollten:
Oracle APEX 23.2 migriert sogar die alten ACLS !!! Super !

SQL> select na.host,na.lower_port,na.upper_port,
nap.principal,nap.privilege,nap.end_date
from dba_network_acl_privileges nap, dba_network_acls na
where nap.acl=na.acl
and principal like 'APEX%'
order by principal;


Wenn Sie mit den Tests! erfolgreich durch sind, können Sie den alten Oracle APEX Benutzer löschen

SQL> DROP USER APEX_220200 CASCADE;


Und nun viel Spaß mit der schönen neuen APEX 23.2 Version. 

PS: Wir schulen Seit November 2023 schon mit der neuen Oracle APEX Version 23.2



Weitere Interessente Artikel zum Thema:


Empfohlene Schulungen zum Thema:


Hackerangriffe in APEX

Bereich:APEX, Version: ab APEX 5, Letzte Überarbeitung: 20.04.2020

Keywords:APEX Hackerangriffe

Wenn man seine APEX Anwendung am ersten Tag im Internet frei verfügbar macht, wird man sich gleich über den großen Traffic auf dem Server freuen.
Nur, wenn man nachdenkt, fällt einem beim Betrachten der Logfiles schnell auf, dass die meisten Zugriffe Hackerangriffe sind.
Hier ein paar Auszüge aus unserem Apache Log-File

(1)
POST /wordpress/xmlrpc.php
POST /wp/xmlrpc.php
/blog/xmlrpc.php

/?XDEBUG_SESSION_START=phpstorm
/wp-login.php
/index.php?s=/Index/\\think\\app/invokefunction&function=call_user_func_array&vars[0]=md5&vars[1][]=Hello
/phpMyAdmin/scripts/setup.php

(2)
/oracle/f?p=SCHULUNG:1001::Oracle_ORDS_Installation_f%C3%BCr_APEX:::P1001_TIPPAUSWAHL:563'\"
/vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php
/ords/f?p=SCHULUNG%3A1001%3A%3AOracle_ORDS_Installation_f%C3%BCr_APEX%3A%3A%3AP1001_TIPPAUSWAHL%3A563  400
/ords/f?p=SCHULUNG%3A1001%3A%3AOracle_ORDS_Installation_f%C3%BCr_APEX%3A%3A%3AP1001_TIPPAUSWAHL%3A563%27%20AnD%20sLeep%283%29%20ANd%20%271  400
/ords/f?p=SCHULUNG%3A1001%3A%3AOracle_ORDS_Installation_f%C3%BCr_APEX%3A%3A%3AP1001_TIPPAUSWAHL%3A563%27%26%26sLEEp%283%29%26%26%271  400
/ords/f?p=SCHULUNG%3A1001%3A%3AOracle_ORDS_Installation_f%C3%BCr_APEX%3A%3A%3AP1001_TIPPAUSWAHL%3A563%00%27%7C%7CSLeeP%283%29%26%26%271  400
/ords/f?p=SCHULUNG%3A1001%3A%3AOracle_ORDS_Installation_f%C3%BCr_APEX%3A%3A%3AP1001_TIPPAUSWAHL%3A563%27%20aND%20BeNChMaRK%282999999%2CMd5%28NoW%28%29%29%29%20AnD%20%271  400
/ords/f?p=SCHULUNG%3A1001%3A%3AOracle_ORDS_Installation_f%C3%BCr_APEX%3A%3A%3AP1001_TIPPAUSWAHL%3A563%27%26%26BeNChMaRK%282999999%2CmD5%28NOW%28%29%29%29%26%26%271  400
/ords/f?p=SCHULUNG%3A1001%3A%3AOracle_ORDS_Installation_f%C3%BCr_APEX%3A%3A%3AP1001_TIPPAUSWAHL%3A563%27%20AnD%20sLeep%283%29%20ANd%20%270%27%3D%270  400
/ords/f?p=SCHULUNG:1001::Oracle_ORDS_Installation_f%C3%BCr_APEX:::P1001_TIPPAUSWAHL:563%20and%201%3D1
/ords/f?p=SCHULUNG:1001::Dynamic_Actions_f%C3%BCr_Reportspalten:::P1001_TIPPAUSWAHL:256999999.1 union
/ords/f?p=SCHULUNG%3A61%3A17151203403405%3A%3ANO%3A%3A%3A
/ords/f?p=11000%3A30%3A8476665195031

(3)
/ords/f?p=SCHULUNG:1001::Oracle_ORDS_Installation_f%C3%BCr_APEX:::P1001_TIPPAUSWAHL:563%22%20or%20(1,2)=(select*from(select%20name_const(CHAR(111,108,111,108,111,115,104,101,114),1),name_const(CHAR(111,108,111,108,111,115,104,101,114),1))a)%20--%20%22x%22=%22x HTTP/1.1" 301 493 "-" "-"

(4)
/arx/license.txt
CONNECT ip.ws.126.net:443


Schmunzeln mussten wir schon, wie 90% der Angriffe ablaufen. Ein großer Teil sind versucht php Attacken (1), die bei einer reinen APEX-Installation ins Leere laufen.

Die Angriffsgruppe (2) versucht mit SQL-Injection einen Fuß in die (Datenbank-) Türe zu bekommen.

Beim Angriff (3) waren wir auch verwundert, was die Funktion name_const denn bei Oracle macht. Relativ schnell stellte sich heraus, das ist gar keine Oracle Funktion, sondern gehört zu einer MySQL Datenbank und läuft damit ins leere... :-)

Da sich die Angriffe sehr oft wiederholen (von anderen IP Adressen) gehen wir davon aus, dass es fertige Hacker-Kits gibt, die hier zum Einsatz kommen.

So was können wir tun gegen diese Angriffe?
1. Seine Hausaufgaben machen und alle Variablen/Items immer lieber einaml zu oft prüfen auf Länge, Datentyp und Logic.
2. Prüfsummen in der URL aktivieren
3. Apache/Nginx Logfiles regelmäßig auswerten
4. Apache mod_security installieren
5. Unseren APEX Security Kurs besuchen. Wir haben ihn um die Kapitel Apache und Nginx Security erweitert

Wir haben uns noch eine weitere Abwehrroutine überlegt, ein Shell Script mit Namen blockip.
Es hat die Aufruf-Parameter:

blockip <ip> [-h -d -l -apache -nginx]
-s <ip> [hours] Set IP on Blocked List [for x hours]
-d <ip>|[all]     Drop [all] Blocked IP
-l                Which IP are blocked
-l -history       Which IP were blocked last
-l -apache        Which IP would Blocked from Apache
-l -nginx         Which IP would Blocked from nginx
-apache           Block all Apache hacking IPs for 2 hours
-apache -auto     Look for last 50 new Entries in Log (only Crontab)
-nginx   Block all Nginx hacking IPs for 2 hours
<ip> in aaa.bbb.ccc.ddd for example 185.172.4.126


Es kann IP-Adressen blocken/entblocken manuell oder autmatisch, wenn es im Apache Logfile verdächtige Aktionen bemerkt. Bei uns läuft es via Crontab regelmäßig und sperrt die Hacker für 1 -x Stunden aus.
Alle unsere APEX Schulungteilnehmer erhalten das Shell-Script von uns kostenlos auf Anfrage.

 



Weitere Interessente Artikel zum Thema:


Empfohlene Schulungen zum Thema:


Oracle APEX Kalender Region mit Jahresauswahl

Bereich:APEX, Version: ab APEX 19.2, Letzte Überarbeitung: 22.06.2022

Keywords:Oracle Apex Calender Jahresauswahl nextyear prevyear

Wollten Sie auch schon mal in einer APEX Kalender Region auch das Jahr und den Monat auswählen,
und nicht mit dem Vor und Zurück Buttons 68 Monate wechseln?

Hier werden Sie geholfen :-)

Wir legen uns zwei Select List Items, eines für den Monat (:P1_MONAT) eines für die Jahresauswahl (:P1_JAHR)

:P1_MONAT SQL Query

select
rownum d,
to_char(to_number(rownum),'09') r -- Zahl muss zweistellig sein also z.B 09 !
from dual
connect by level<=12


:P1_JAHR Query für aktuelles Jahr und die letzen 5 Jahre

select
to_char(sysdate +365 - 365*rownum,'YYYY') d,
to_char(sysdate +365 - 365*rownum,'YYYY') r
from dual
connect by level<=6



Unter Kalender Attribute:
Calender Views: [ ] Navigation abwählen
Das ist kein Muss, aber die Benutzer könnten mit den Vor und Zurück Buttons auch Navigieren und dann müsste man auch die Anzeige der beiden Select Listen aktualisieren!


Unter Advanced / JavaScript Initialization Code

function ( pOptions) {
    pOptions.titleFormat      = "[ Mein Kalender ]";                 
    pOptions.weekNumbers      = true;  
    pOptions.weekNumberCalculation = "ISO";                                   
    pOptions.weekNumberTitle  = "KW";    
    pOptions.defaultDate      = $v("P1_JAHR") + "-" + $v("P1_MONAT").trim() + "-01";    // bis APEX 21.1
    pOptions.initialDate      = $v("P1_JAHR") + "-" + $v("P1_MONAT").trim() + "-01";    // ab APEX 21.2  
    pOptions.dayNamesShort         = ["Sonntag", 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag'];              
    return pOptions;
}


 



Weitere Interessente Artikel zum Thema:


Empfohlene Schulungen zum Thema:


Oracle APEX 21.2 in Oracle 21c Pluggable Database installieren

Bereich:APEX:DBA, Version: ab APEX 21.2:RDBMS 21.1, Letzte Überarbeitung: 08.02.2022

Keywords:Oracle APEx Installation

Ich habe mich ja lange Zeit geweigert, die Pluggable Database einzusetzen und wenn es nach mir ginge ....

Trotzdem sollte man sich der Zukunft nicht verschliessen, denn es wird ab 21c (incl) keine NON CDB Datenbanken mehr geben.

Installation einer Apex Version 21.2 in Oracle XE 21c (geht aber auch in einer Enterprise Edition oder Standard Edition):
Gehen wir zuerst mal in den Hauptcontainer und schauen uns um

ALTER SESSION SET CONTAINER=cdb$root;
select con_id,name,open_mode from v$pdbs p;
select name from v$datafile;


Mich stört der Default Container, also löschen ich ihn und lege einen anderen an (ist natürlich optional, und wenn das schon eteas drinliegt, besser vorher migrieren...)

ALTER PLUGGABLE DATABASE XEPDB1 CLOSE;
DROP PLUGGABLE DATABASE XEPDB1 INCLUDING DATAFILES;


Wo liegen denn die Datendateien ?

select name from v$datafile;


Diesen Hauptpfad tragen wir im nächsten Kommando ein (bei uns C:\Oracle\Product\Base21\oradata)

CREATE PLUGGABLE DATABASE apex212 ADMIN USER admin IDENTIFIED BY admin
CREATE_FILE_DEST= 'C:\Oracle\Product\Base21\oradata';


Der Container wird geöffnet, automatisch beim Start der DB mitgestartet und wir gehen in den Container

ALTER PLUGGABLE DATABASE apex212 OPEN;
ALTER PLUGGABLE DATABASE apex212 SAVE STATE;
ALTER SESSION SET container=apex212;


Nun installieren wir in den neu erstellen Container unsere APEX Version.
Das APEX Download haben wir unter c:\temp ausgepackt

cd c:\temp\apex
sqlplus sys/sys@127.0.0.1:1521/apex212 as sysdba
@apexins SYSAUX SYSAUX TEMP /i212/
@apex_rest_config;


Wir entsperren das schema SCOTT und schalten die starke interne Passwort-Prüfung aus (optional) Der Vorteil ist, dass man sich die ganzen Passwort-Parameter wie gewünscht selbst einstellen kann.

EXEC apex_instance_admin.unrestrict_schema('SCOTT');
EXEC apex_instance_admin.set_parameter('STRONG_SITE_ADMIN_PASSWORD','N')


Nun wird das Passwort für den Internal Workspace gesetzt (Sie werden gefragt nach:
Admin-name:
Admin-User Email:
Admin-Passwort:

@apxchpwd


Und weil wir schon hundert Mal vergessen haben, nach spätestens 187 Tagen vom APEX Benutzer und seiner ganzen "Verwandschaft" zu ändern,
erstellen wir ein eigenes Profil für die Truppe:-)
Die Passwörter passen Sie bitte Ihren Wünschen an

CREATE PROFILE web_profil LIMIT
FAILED_LOGIN_ATTEMPTS 10
PASSWORD_LIFE_TIME 1800;
alter user apex_public_user profile web_profil account unlock identified by apex;
alter user APEX_REST_PUBLIC_USER profile web_profil account unlock identified by apex;
alter user ORDS_PUBLIC_USER profile web_profil account unlock identified by ords;
alter user scott profile web_profil account unlock identified by ords;
alter user APEX_LISTENER profile web_profil account unlock identified by apex;


In einem der nächsten Artikel schauen wir uns die dazu passende ORDS Konfiguration an.
Viel Spass bei der Benutzung von APEX und wenn Sie mal eine gute Schulung brauchen, denken Sie an uns ...*zwinker*

 



Weitere Interessente Artikel zum Thema:


Empfohlene Schulungen zum Thema:


JSON Daten extrahieren

Bereich:APEX:PL/SQL, Version: ab RDBMS 18.3, Letzte Überarbeitung: 19.05.2022

Keywords:JSON, Oracle

In unserem heutigen Beitrag wollen wir uns mit dem Thema beschäftigen, wie man aus einem JSON String wieder die Daten extrahieren kann.
Diesen Anwendungsfall hatte ich die letzten 24 Monat sehr häufig, deswegen wurde es mal wieder Zeit sich mit dem Thema JSON in Oracle zu beschäftigen.

Wir fangen mit einer kleinen Test-Tabelle basiernd auf den Emp und Dept Daten des Benutzers SCOTT an:
Die Besonderheit / Schwierigkeit besteht darin, dass die Mitarbeiter in einem Array eingetragen werden (["CLARK","KING","MILLER"]
 

CREATE TABLE dept_json   
( json_text CLOB,   
    CONSTRAINT check_json CHECK ( json_text IS JSON ) );

INSERT INTO dept_json   
VALUES ('{ "DEPT" : {
                       "DEPTNO" : 10,
                       "DNAME" : "ACCOUNTING",   
                       "LOC" : "NEW YORK",  
                       "EMPS"  : ["CLARK","KING","MILLER"] }}');

INSERT INTO dept_json   
VALUES ('{"DEPT" : {
                       "DEPTNO" : 20,
                       "DNAME" : "RESEARCH",   
                       "LOC" : "DALLAS",  
                       "EMPS"  : ["SMITH","JONES","SCOTT","ADAMS","FORD"] }}');


INSERT INTO dept_json   
VALUES ('{"DEPT" : {
                       "DEPTNO" : 30,
                       "DNAME" : "SALES",   
                       "LOC" : "CHICAGO",  
                       "EMPS"  : ["ALLEN","BLAKE","JAMES","MARTIN","TURNER","WARD"] }}');


Als Bonustrack legen wir einen Oracle Text-Index auf die JSON Spalte:


CREATE INDEX dept_json_index   
  ON dept_json(json_text)   
  INDEXTYPE IS CTXSYS.CONTEXT   
  PARAMETERS ('SECTION GROUP CTXSYS.JSON_SECTION_GROUP SYNC (ON COMMIT)');


Wir können dann mit der Funktion JSON_TEXTCONTAINS im JSON String suchen.

SELECT json_text   
  FROM dept_json   
 WHERE JSON_TEXTCONTAINS(json_text, '$', 'KING');


Das Ergebnis sieht dann so aus:


{ "DEPT" : {
                       "DEPTNO" : 10,
                       "DNAME" : "ACCOUNTING",   
                       "LOC" : "NEW YORK",  
                       "EMPS"  : ["CLARK","KING","MILLER"] }}


Wenn man die Daten der JSON Tabelle wieder extrahieren (und weiterverarbeiten) möchte:


SELECT deptno, dname, loc, linenum, arrayval
from dept_json,json_table(json_text, '$.DEPT[*]'
columns ( arraynum for ordinality, DEPTNO,DNAME,LOC,
    nested path '$.EMPS[*]'
        columns ( linenum for ordinality,nested path '$[*]'
                 columns( arrayval varchar2 path '$')
  ) ));


Das Ergebnis sieht dann so aus:
 

DEPTNODNAMELOCLINENUMARRAYVAL
10ACCOUNTINGNEW YORK1CLARK
10ACCOUNTINGNEW YORK2KING
10ACCOUNTINGNEW YORK3MILLER
20RESEARCHDALLAS1SMITH
20RESEARCHDALLAS2JONES
20RESEARCHDALLAS3SCOTT
20RESEARCHDALLAS4ADAMS
20RESEARCHDALLAS5FORD
30SALESCHICAGO1ALLEN
30SALESCHICAGO2BLAKE
30SALESCHICAGO3JAMES
30SALESCHICAGO4MARTIN
30SALESCHICAGO5TURNER
30SALESCHICAGO6WARD


Wenn man mal einen unbekannten JSON String auswerten möchte stellt Oracle dafür auch ein Package zur Verfügung:

SELECT json_dataguide(json_text, DBMS_JSON.FORMAT_HIERARCHICAL, DBMS_JSON.PRETTY)
FROM dept_json;


Die Ausgabe sieht dann so aus:

{
  "type" : "object",
  "o:length" : 128,
  "properties" :
  {
    "DEPT" :
    {
      "type" : "object",
      "o:length" : 128,
      "o:preferred_column_name" : "DEPT",
      "properties" :
      {
        "LOC" :
        {
          "type" : "string",
          "o:length" : 8,
          "o:preferred_column_name" : "LOC"
        },
        "EMPS" :
        {
          "type" : "array",
          "o:length" : 64,
          "o:preferred_column_name" : "EMPS",
          "items" :
          {
            "type" : "string",
            "o:length" : 8,
            "o:preferred_column_name" : "scalar_string"
          }
        },
        "DNAME" :
        {
          "type" : "string",
          "o:length" : 16,
          "o:preferred_column_name" : "DNAME"
        },
        "DEPTNO" :
        {
          "type" : "number",
          "o:length" : 2,
          "o:preferred_column_name" : "DEPTNO"
        }
      }
    }
  }

}

Und nun viel Spaß mit der Auswertung von Daten aus JSON-Ausdrücken. Bei uns wird das Thema ausführlich behandelt in den Kursen Oracle PL/SQL II, Oracle REST und Oracle Dev New Features 12c - 21c.



Weitere Interessente Artikel zum Thema:


Empfohlene Schulungen zum Thema:


JSON Umwandlung in realtionales Format mit JSON_TABLE Beispiele

Bereich:APEX:PL/SQL, Version: ab RDBMS 19.3, Letzte Überarbeitung: 22.07.2022

Keywords:JSON, Array

In vielen unserer Kurse ist JSON ein Thema (z.B. im APEX oder ORDS oder PL/SQL II Kurs). Da die Syntax gewöhnungsbedürftig ist, haben wir mal ein paar Beispiele generiert um die syntax besser zu verstehen.
Ausgangslage ist ein JSON String, der in ein relationales Modell überführt werden soll.

Übersicht der Beispiele:
Beispiel 1, mit 3 Werte
Beispiel 2, Verschiedene Datentypen in JSON
Beispiel 3, mit Geschachtelten Arrays
Beispiel 4, mit 3 Zeilen mit 2 Feldern
Beispiel 5, mit 3 Zeilen mit 2 Feldern und einem Root Eintrag (var)
Beispiel 6, mit 2 Feldern und 3 Zeilen
Beispiel 7, mit Sub-Sub Feldern
Beispiel 8, nur einen Wert extrahieren
Beispiel 9, Wieviele Elemente hat das Array?
Beispiel 10, Sub-Arrays (Darstellungsvariante 1)
Beispiel 11, Sub-Arrays (Darstellungsvariante 2)   
Beispiel 12, Tabelle die von Oracle mit Auto-Rest zurückkommt zerlegen
Beispiel 13: JSON String gefiltert

Beispiel 1, mit 3 Werte

WITH j_son as (SELECT '
{"a":1,
 "b":2,
 "c":3
}' as txt from dual)
SELECT a,b,c
FROM j_son,  
     JSON_TABLE(j_son.txt, '$'
     COLUMNS ( a,b,c )
          ) jt;


Ergebnis:
 

ABC
   
123



Beispiel 2, Verschiedene Datentypen in JSON:

WITH j_son as (SELECT '
{"Zahl":1, "Text": "aBc", "Bool":TRUE,
"Datum1":"2022-07-15", "Datum2":"2019-07-15T14:11:27",
"Datum3":"2022-07-15T14:11:27Z", "Datum4":"2022-07-15T14:11:27+00:00"
}' as txt from dual)
SELECT Zahl,Text,Bool,Datum1,Datum2,Datum3,Datum4
FROM j_son,  JSON_TABLE(j_son.txt, '$' COLUMNS (
       Zahl NUMBER PATH '$."Zahl"',
       Text VARCHAR2(2000) PATH '$."Text"',
       Bool VARCHAR2(10) PATH '$."Bool"',
       Datum1 DATE PATH '$."Datum1"',
       Datum2 DATE PATH '$."Datum2"',
       Datum3 DATE PATH '$."Datum3"',
       Datum4 DATE PATH '$."Datum4"'
          )
     ) jt;


Ergebnis:

ZahlTextBoolDatum1Datum2Datum3Datum4
       
1aBctrue15.07.2022 00:00:0015.07.2022 00:00:0015.07.2022 00:00:0015.07.2022 00:00:00

Hinweis: Die Stunden / Minuten / Sekunden verschwinden hier. Alternative: Datum als Text parsen und mittels to_date in Datum umwandeln.

Beispiel 3, mit Geschachtelten Arrays

WITH j_son as (SELECT '
{"a":"a1",
 "b": [
        {"c": "c1",
         "d": [1,2]}
      ]
}' as txt from dual)
SELECT j_son.txt, "a","c","d"
FROM j_son,  
     JSON_TABLE(j_son.txt, '$' COLUMNS (
       "a" VARCHAR2(5) PATH '$.a',
       NESTED PATH '$.b[*]' COLUMNS (
          "c" VARCHAR2(5) PATH '$.c',
          NESTED PATH '$.d[*]' COLUMNS (
             "d" NUMBER PATH '$[0]'
          )
       )
     )) jt;

    
Ergebnis:

a1cd
   
a1c11
a1c12



Beispiel 4, mit 3 Zeilen mit 2 Feldern

WITH j_son as (SELECT '
[{"A":1,"B":2},
{ "A":3,"B":4},
{ "A":5,"B":6}]' txt from dual)
SELECT A,B
FROM j_son,json_table(j_son.txt,'$[*]'
columns (A,B));

 Ergebnis

AB
12
34
56



Beispiel 5, mit 3 Zeilen mit 2 Feldern und einem Root Eintrag (var)

WITH j_son as (select '
{var:[{"A":1,"B":2},
{ "A":3,"B":4},
{ "A":5,"B":6}]}' txt from dual)
select A,B
FROM j_son,json_table(j_son.txt,'$.var[*]' columns (A,B));

  Ergebnis

AB
12
34
56



Beispiel 6, mit 2 Feldern und 3 Zeilen

WITH j_son as (select '[
{"Vorname":"Marco","Nachname":"Patzwahl"},
{"Vorname":"Hansi","Nachname":"Wurst"},
{"Vorname":"Karin","Nachname":"Sorglos"}
]' txt from dual)
select vorname,nachname
FROM j_son,json_table(j_son.txt,'$[*]'
columns (Vorname,Nachname));

  Ergebnis

VornameNachname
  
MarcoPatzwahl
HansiWurst
KarinSorglos



Beispiel 7, mit Sub-Sub Feldern

SELECT id, var1, sub_id, sub_val
FROM JSON_TABLE (
        to_clob('{ id: 123, var1: "abc",
        subvalues : [
            { id: 1, value: "a", },
            { id: 2, value: "b" } ]} '),
        '$' COLUMNS (
            id NUMBER PATH '$.id',
            var1 VARCHAR PATH '$.var1',
            NESTED PATH '$.subvalues[*]'
            COLUMNS ( sub_id NUMBER PATH '$.id',
            sub_val VARCHAR2(4000) PATH '$.value'
            ) ) );


oder

WITH j_son as (select '{ id: 123, var1: "abc",
        subvalues : [
            { id: 1, value: "a", },
            { id: 2, value: "b" }
            ]}' as txt from dual)
SELECT id, var1, sub_id, sub_val
FROM j_son,JSON_TABLE (j_son.txt,
        '$' COLUMNS (
            id NUMBER PATH '$.id',
            var1 VARCHAR PATH '$.var1',
            NESTED PATH '$.subvalues[*]'
            COLUMNS ( sub_id NUMBER PATH '$.id',
            sub_val VARCHAR2(4000) PATH '$.value'
            ) ) );

  Ergebnis

IDVar2SUB_IDSUB_VAL
123abc1a
123abc2b
    



Beispiel 8, nur einen Wert extrahieren

SELECT json_value ('{"emp":{ "name":"Marco","city":"Bern" } } ','$.emp.name') as name
FROM dual;


Beispiel 9, Wieviele Elemente hat das Array?

SELECT json_value('[1, 2, 3, 4 ]','$.size()') FROM dual;

=>4
oder

SELECT json_query('[1,[2,2,2],3]','$[*].size()' WITH ARRAY WRAPPER)  FROM dual;

=>[1,3,1]

Beispiel 10: Sub-Arrays (Darstellungsvariante 1)

WITH j_son as (select '
{var:[{"A":[1,2],"B":[3,4]},
{ "A":[5,6],"B":[7,8]},
]}' txt from dual)
select A,B
FROM j_son,json_table(j_son.txt,
'$.var' columns (
    nested path '$.A[*]' columns (A number path '$[0]'),
    nested path '$.B[*]' columns (B number path '$[0]') ));

    
Ergebnis:
 

AB
  
1 
2 
 3
 4
5 
6 
 7
 8


   
Beispiel 11: Sub-Arrays (Darstellungsvariante 2   

WITH j_son as (select '
{var:[{"A":[1,2],"B":[3,4]},
{ "A":[5,6],"B":[7,8]},
]}' txt from dual)
select val
FROM j_son,json_table(j_son.txt,
'$.var' columns (
    nested path '$.*[*]' columns (val number path '$[0]' )));

    

VAL
 
1
2
3
4
5
6
7
8


Beispiel 12, Tabelle die von Oracle mit Auto-Rest zurückkommt zerlegen

WITH j_son as (SELECT '
{"items":[
{"deptno":10,"dname":"ACCOUNTING","loc":"NEW YORK",
"links":[{"rel":"self","href":"http://127.0.0.1:8080/ords/scott/dept/10"}]},
{"deptno":20,"dname":"RESEARCH","loc":"DALLAS",
"links":[{"rel":"self","href":"http://127.0.0.1:8080/ords/scott/dept/20"}]},
{"deptno":30,"dname":"SALES","loc":"CHICAGO",
"links":[{"rel":"self","href":"http://127.0.0.1:8080/ords/scott/dept/30"}]},
{"deptno":40,"dname":"OPERATIONS","loc":"BOSTON",
"links":[{"rel":"self","href":"http://127.0.0.1:8080/ords/scott/dept/40"}]}],
"hasMore":false,"limit":25,"offset":0,"count":4,"links":[{"rel":"self","href":"http://127.0.0.1:8080/ords/scott/dept/"},
{"rel":"edit","href":"http://127.0.0.1:8080/ords/scott/dept/"},
{"rel":"describedby","href":"http://127.0.0.1:8080/ords/scott/metadata-catalog/dept/"},
{"rel":"first","href":"http://127.0.0.1:8080/ords/scott/dept/"}]}' as txt from dual)
SELECT deptno,dname,loc,href
FROM  
     j_son,JSON_TABLE(j_son.txt, '$.items[*]'
     COLUMNS ( deptno,dname,loc,
     nested path '$.links[*]' columns (href),
     limit,offset,count)
          ) jt;

Ergebnis:

DEPTNODNAMELOCHREF
    
10ACCOUNTINGNEW YORKhttp://127.0.0.1:8080/ords/scott/dept/10
20RESEARCHDALAShttp://127.0.0.1:8080/ords/scott/dept/20
30SALESCHICAGOhttp://127.0.0.1:8080/ords/scott/dept/30
40OPERATIONSBOSTONhttp://127.0.0.1:8080/ords/scott/dept/40

oder ausführlicher (aber nur für eine Ergebnis-Zeile zur Vereinfachung):


WITH j_son as (SELECT '
{"items":[
{"deptno":10,"dname":"ACCOUNTING","loc":"NEW YORK",
"links":[{"rel":"self","href":"http://127.0.0.1:8080/ords/scott/dept/40"}]}],
"hasMore":false,"limit":25,"offset":0,"count":4,"links":[{"rel":"self",
"href":"http://127.0.0.1:8080/ords/scott/dept1/"},
{"rel":"edit","href":"http://127.0.0.1:8080/ords/scott/dept2/"},
{"rel":"describedby","href":"http://127.0.0.1:8080/ords/scott/metadata-catalog/dept/"},
{"rel":"first","href":"http://127.0.0.1:8080/ords/scott/dept3/"}]}' as txt from dual)
SELECT deptno,dname,loc,href,hasMore,offset,count,href2,href3
FROM  j_son,
     JSON_TABLE(j_son.txt, '$.items[*]'
     COLUMNS ( deptno,dname,loc,
     nested path '$.links[*]' columns (href)) ),
     JSON_TABLE(j_son.txt, '$'
     COLUMNS ( hasMore,limit,offset,count,
     nested path '$.links[0]' columns (href2 varchar2 path '$.href')) ),
     JSON_TABLE(j_son.txt, '$'
     COLUMNS (
     nested path '$.links[1]' columns (href3 varchar2 path '$.href')) )jt;
DEPTNODNAMELOCHREFHASMOREOFFSETCOUNTHREF2HFREF3
         
40OPERATIONSBOSTONhttp://127.0.0.1:8080/ords/scott/dept/40false04http://127.0.0.1:8080/ords/scott/dept1/http://127.0.0.1:8080/ords/scott/dept2/

Beispiel 13: JSON String gefiltert (finde die Werte für B, wenn a=4 , 7, 10 oder 13 ist)

WITH j_son AS (
select '{
  "items": [
    {
      "sub": [
        {
          "a": 1,
          "b": 2,
          "c": 3
        },
        {
   &nb

ORDS 22.x Installation in Verbindung mit Oracle APEX

Bereich:APEX:ORDS, Version: ab APEX 22.1:ORDS 22.2, Letzte Überarbeitung: 26.11.2022

Keywords:ORDS 22.x APEX

Seit Mai 2022 ist eine neue ORDS Version veröffentlicht worden, die eine andere Installation benötigt.
Wir wollen hier die wichtigsten Punkte erklären:

1. Es werden nur hoch die Java Versionen 11 und 17 unterstützt (und KEIN JAVA 8)
Prüfen Sie bitte zuerst welche Java Version sie haben:
Achtung: Bei uns machte auch die OpenJDK Version Probleme und endete mit einem Webserver Fehler 500 und Fehlertext NULL!

Für Windows:

java -version

java -version
java version "17.0.4.1" 2022-08-18 LTS
Java(TM) SE Runtime Environment (build 17.0.4.1+1-LTS-2)
Java HotSpot(TM) 64-Bit Server VM (build 17.0.4.1+1-LTS-2, mixed mode, sharing)
=> So is es gut :-)


Installation unter Windows:

ords.exe --config c:\oracle\ords install

ORDS: Release 22.2 Produktion am Di. Sept. 06 09:49:12 2022

Copyright (c) 2010, 2022, Oracle.

Konfiguration:
  /C:/oracle/ords/

Der Konfigurationsordner C:\oracle\ords enthält keine Konfigurationsdateien.

Oracle REST Data Services - Interaktive Installation

  Geben Sie eine Zahl zur Auswahl des Installationstyps ein
    [1] ORDS nur in der Datenbank installieren oder upgraden
    [2] Datenbankpool erstellen oder aktualisieren und ORDS in der Datenbank installieren/upgraden
    [3] Nur Datenbankpool erstellen oder aktualisieren
  Choose [2]: 2
   Geben Sie eine Zahl zur Auswahl des zu verwendenden Datenbankverbindungstyps ein
    [1] Basis (Hostname, Port, Servicename)
    [2] TNS (TNS-Alias, TNS-Verzeichnis)
    [3] Benutzerdefinierte Datenbank-URL
  Choose [1]: 1
  Geben Sie den Hostnamen der Datenbank ein [localhost]: 127.0.0.1
  Listener-Port der Datenbank eingeben [1521]:
  Datenbankservicename eingeben [orcl]: apex221
  Geben Sie einen Datenbankbenutzernamen mit Administratorberechtigungen an.
    Geben Sie den Administratorbenutzernamen ein: sys
      Datenbankkennwort für SYS AS SYSDBA eingeben:
Verbindung zu Datenbankbenutzer: SYS AS SYSDBA URL: jdbc:oracle:thin:@//127.0.0.1:1521/apex221 wird hergestellt

Informationen werden abgerufen.
Verbindung zu Datenbankbenutzer: ORDS_PUBLIC_USER URL: jdbc:oracle:thin:@//127.0.0.1:1521/apex221 wird hergestellt
  Geben Sie eine Zahl ein, um zusätzliche Features zum Aktivieren auszuwählen:
    [1] Datenbankaktionen (aktiviert alle Features)
    [2] REST-fähige SQL und Datenbank-API
    [3] REST-fähige SQL
    [4] Datenbank-API
    [5] Kein Wert
  Choose [1]: 1
   Geben Sie eine Zahl zum Konfigurieren und Starten von ORDS im Standalone-Modus ein
    [1] ORDS im Standalone-Modus konfigurieren und starten
    [2] Überspringen
  Choose [1]: 2
Die Einstellung db.connectionType wurde auf basic in Konfiguration default gesetzt
Die Einstellung db.hostname wurde auf 127.0.0.1 in Konfiguration default gesetzt
Die Einstellung db.port wurde auf 1521 in Konfiguration default gesetzt
Die Einstellung db.servicename wurde auf apex221 in Konfiguration default gesetzt
Die Einstellung plsql.gateway.mode wurde auf proxied in Konfiguration default gesetzt
Die Einstellung db.username wurde auf ORDS_PUBLIC_USER in Konfiguration default gesetzt
Die Einstellung db.password wurde auf ****** in Konfiguration default gesetzt
Die Einstellung feature.sdw wurde auf true in Konfiguration default gesetzt
Die globale Einstellung database.api.enabled wurde auf true gesetzt
Die Einstellung restEnabledSql.active wurde auf true in Konfiguration default gesetzt
Die Einstellung security.requestValidationFunction wurde auf wwv_flow_epg_include_modules.authorize in Konfiguration default gesetzt

....
INFO: 11:51:30 Validating objects for Oracle REST Data Services.
VALIDATION: 11:51:30 Starting validation for schema: ORDS_METADATA
VALIDATION: 11:51:30 Validating objects
VALIDATION: 11:51:33 Validating roles granted to ORDS_METADATA and
ORDS_PUBLIC_USER
VALIDATION: 11:51:33 Validating ORDS Public Synonyms
VALIDATION: 11:51:34 Total objects: 312, invalid objects: 0, missing objects: 0
VALIDATION: 11:51:34     88  INDEX
VALIDATION: 11:51:34      1  JOB
VALIDATION: 11:51:34      3  LOB
VALIDATION: 11:51:34     20  PACKAGE
VALIDATION: 11:51:34     19  PACKAGE BODY
VALIDATION: 11:51:34      1  PROCEDURE
VALIDATION: 11:51:34     56  PUBLIC SYNONYM
VALIDATION: 11:51:34      1  SEQUENCE
VALIDATION: 11:51:34     31  TABLE
VALIDATION: 11:51:34     31  TRIGGER
VALIDATION: 11:51:34     20  TYPE
VALIDATION: 11:51:34      6  TYPE BODY
VALIDATION: 11:51:34     35  VIEW
VALIDATION: 11:51:34 Validation completed.
INFO: 11:51:34 Completed validating objects for Oracle REST Data Services.

PL/SQL-Prozedur erfolgreich abgeschlossen.
Commit abgeschlossen.
[*** script: ords_alter_session_script.sql]
PL/SQL-Prozedur erfolgreich abgeschlossen.
2022-09-06T09:51:34.159Z INFO        Upgrade f³r Oracle REST Data Services Version 22.2.1.r2021302 wurde abgeschlossen. Verstrichene Zeit: 00:00:22.914

[*** Informationen: Upgrade complete]
[*** Informationen: Upgrade f├╝r Oracle REST Data Services Version 22.2.1.r2021302 wurde abgeschlossen. Verstrichene Zeit: 00:00:22.914
]
------------------------------------------------------------
Containername: APEX221
------------------------------------------------------------

[*** script: ords_configure_gateway.sql]
Configured PL/SQL Gateway user APEX_PUBLIC_USER to be proxiable from
ORDS_PUBLIC_USER

PL/SQL-Prozedur erfolgreich abgeschlossen.
2022-09-06T09:51:34.244Z INFO        Konfiguration von PL/SQL-Gatewaybenutzer f³r Oracle REST Data Services Version 22.2.1.r2021302 wurde abgeschlossen. Verstrichene Zeit: 00:00:00.85

2022-09-06T09:51:34.244Z INFO        Datenbankkennwort f³r ORDS_PUBLIC_USER in APEX221 wird aktualisiert
[*** Informationen: Konfiguration von PL/SQL-Gatewaybenutzer f├╝r Oracle REST Data Services Version 22.2.1.r2021302 wurde abgeschlossen. Verstrichene Zeit: 00:00:00.85
]
[*** script: ords_change_password.sql]
PL/SQL-Prozedur erfolgreich abgeschlossen.
2022-09-06T09:51:34.359Z INFO        Aktualisieren von Datenbankkennwort f³r ORDS_PUBLIC_USER wurde abgeschlossen. Verstrichene Zeit: 00:00:00.100

[*** Informationen: Aktualisieren von Datenbankkennwort f├╝r ORDS_PUBLIC_USER wurde abgeschlossen. Verstrichene Zeit: 00:00:00.100
]
 


Nun wird die ords.war Datei in das TomCat Verzeichnis kopiert/verschoben (z.B. C:\Program Files\Apache Software Foundation\Tomcat 9.0\webapps)
oder unter Linux: /opt/tomcat/latest/webapps
TomCat sollte dann innerhalb von 5 Sekunden einen Ordner ords dort anlegen!

Ein umbenennen des ORDS ist derzeit zu keiner Phase der Installation unterstützt (Stand Nov. 2022)
Denken Sie daran, dass Sie ggf auch in diesen Ordner die APEX Bilder (Ordner images) in den Ordner "i" kopieren !

Nun kommt der spannendste Teil (weil nur zum Teil in der Doku :-) aber dafür gibt es ja Kurse bei Muniqsoft Training ....

Wenn Sie bei TomCat die msi Variante installiert haben, gibt es in er Taskleiste ein TomCat Icon (Feder mit roten oder grünem Punkt)
Rot bedeutet= TomCat nicht gestartet
Grün bedeutet = TomCat gestartet
 

TomCat Properties






Dort tragen Sie im Reiter Java unter Java Options ein:

-Dconfig.url=C:\oracle\ords


Wenn das nicht oder falsch konfiguriert wurde, quittiert Tomcat einen APEX Aufruf mit einem 404 Fehler.

Sollten Sie TomCat lieber über die Kommandozeile starten, sollte bitte zuerst folgender Parameter im DOS Fenster gesetzt worden sein:

_JAVA_OPTIONS=-Dconfig.url=c:\oracle\ords


Sie können das auch unter Systemsteuerungen/System/Erweiterte Systemeigenschaften/Umgebungsvariablen unter SYSTEMVARIABLEN (unten) setzen:

Wichtig. Unter Windows muss der TomCat Dienst in der Lage sein, die Config-Datei (bzw. den ganzen Ordner lesen zu können)
Prüfen Sie bitte auf dem Ordner ob der "Lokale Dienst" Leserechte auf dem Ordner hat. Wenn nicht, vergeben Sie die Rechte durch:
Rechte Maus auf den Ordner / Eigenschaften / Sicherheit : Bearbeiten / Hinzufügen "Lokaler Dienst " eingeben / OK / OK
Auf dem Reiter Sicherheit / Erweitert (ganz unten)  [x] Alle Berechtigungen für untergeordnete Objekte .. anwählen / OK
Warnung ignorieren und Fertig !
Den Fehler sonst zu suchen, macht wirklich [keinen] Spass !
 



Weitere Interessente Artikel zum Thema:


Empfohlene Schulungen zum Thema: