Einrichtung und Nutzung des PL/SQL Embedded Gateways

Bei Nutzung des PL/SQL Embedded Gateway wird die Aufgabe des Webservers von der Datenbank und dem Listener selbst übernommen - auf dem Datenbankrechner werden also keine weiteren Prozesse benötigt. Insofern ist der Setup sehr einfach und die Administration des Webservers ist mit der normalen Datenbankadministration abgedeckt. Allerdings bietet das Embedded Gateway nicht so viele Webserver-Features wie ein Apache - so gibt es kein URL Rewriting, keine virtuellen Hosts, keine Proxy- und keine speziellen Authentifizierungsmodule. Insofern eignet sich das Embedded Gateway vor allem für Entwicklermaschinen und kleinere Intranet-Umgebungen. Aus Lizenzsicht ist das Embedded Gateway mit der Datenbanklizenz abgedeckt. Für SSL-Zugriff ist allerdings eine Lizenz sowohl der Enterprise Edition der Datenbank als auch der Advanced Security Option erforderlich.

Architektur von Application Express mit dem PL/SQL Embedded Gateway

Abbildung 1: Architektur von Application Express mit dem PL/SQL Embedded Gateway

Die technische Grundlage des Embedded PL/SQL Gateway sind die Protokollserver der XML DB. Der HTTP-Endpoint wird durch den normalen Oracle Listener bereitgestellt, die HTTP-Anfragen der Browser werden durch Shared Server Prozesse der Datenbank bearbeitet. Mehr zur Architektur der XML DB Protokollserver findet sich im XML DB Developers' Guide der Oracle-Dokumentation.

Ein besonderes Merkmal des PL/SQL Embedded Gateway ist, dass alle Inhalte aus der Datenbank kommen - auch die zum APEX-Lieferumfang gehörenden statischen Bild-, CSS- und Javascript-Dateien. Diese werden im sog. XML DB Repository abgelegt - ein virtuelles Dateisystem speziell für die XML DB Protokollserver . Alle Inhalte liegen in einer Systemtabelle - XDB$RESOURCE im Schema XDB. Auf SQL-Ebene können Sie sich diese mit den Views RESOURCE_VIEW und PATH_VIEW ansehen. Mit den PL/SQL-Paket DBMS_XDB können Verzeichnisse und Dateien (Ressourcen) bearbeitet werden. Zur Einrichtung des Embedded Gateways mit APEX sind bereits fertige Konfigurationsskripte vorhanden.

  1. Starten Sie als SYS das Skript $ORACLE_HOME/apex/apxconf.sql. Es fragt Sie nach dem HTTP-Port, den Sie für Application Express verwenden möchten, und führt dann die nötigen Konfigurationsschritte durch.
  2. Starten Sie im APEX-Verzeichnis als SYS das Skript apxldimg.sql. Als Parameter geben Sie das Verzeichnis, in das Sie das heruntergeladene APEX-Archiv ausgepackt haben, an.
  3. Entsperren Sie den Datenbanknutzer ANONYMOUS. Geben Sie dazu als (ebenfalls als SYS) folgendes Kommando ein:
    alter user ANONYMOUS account unlock
    

FTP-Zugang zu den statischen Dateien

Es gibt neben dem XML DB Protokollserver für HTTP auch einen für FTP. Diesen schalten Sie (als DBA) mit einem einfachen PL/SQL-Aufruf wie folgt frei.

begin
  dbms_xdb.setftpport(
    new_port => 2100
  );
end;

Verwenden Sie danach einen "normalen" FTP-Client und verbinden Sie sich mit der Datenbank. Verwenden Sie für die FTP-Verbindung einen DBA-User, aber nicht SYS. Nach dem Login befinden Sie sich im "Root"-Verzeichnis des virtuellen Dateisystems. Der APEX-Pfad /i/ ist auf das Verzeichnis /images abgebildet. Sie können die statischen Dateien also nun auch mit dem FTP-Client bearbeiten, löschen oder neue hochladen. Beachten Sie bitte, dass nur die Dateien unterhalb von /images unter /i/ extern erreichbar sind. Die anderen Verzeichnisse sind zwar für HTTP-Zugriffe erreichbar, Sie müssen sich jedoch vorher wie für FTP mit einem Datenbank-Nutzernamen und -passwort anmelden.

D:\>ftp -n
ftp> open sccloud033 2100
Connected to sccloud033.de.oracle.com.
220- sccloud033.de.oracle.com
Unauthorised use of this FTP server is prohibited and may be subject to civil an
d criminal prosecution.
220 sccloud033.de.oracle.com FTP Server (Oracle XML DB/Oracle Database) ready.
ftp> user system oracle
331 pass required for SYSTEM
230 SYSTEM logged in
ftp> dir
200 PORT Command successful
150 ASCII Data Connection
drw-r--r--   2 SYS      oracle         0 JAN 14 11:02 OLAP_XDS
drw-r--r--   2 SYS      oracle         0 JAN 14 11:09 home
drw-r--r--   2 SYS      oracle         0 SEP 13 10:45 images
drw-r--r--   2 SYS      oracle         0 JUN 23 15:39 images_201006231639
drw-r--r--   2 SYS      oracle         0 JAN 14 11:02 olap_data_security
drw-r--r--   2 SYS      oracle         0 AUG 10 11:03 public
drw-r--r--   2 SYS      oracle         0 JAN 14 11:09 sys
-rw-r--r--   1 SYS      oracle         0 AUG 10 11:01 xdbconfig.xml
drw-r--r--   2 SYS      oracle         0 JAN 14 11:02 xds
226 ASCII Transfer Complete
ftp: 584 bytes received in 0,13Seconds 4,67Kbytes/sec.
ftp> cd images
250 CWD Command successful
ftp>

Wenn Sie den FTP-Zugang nicht mehr benötigen, sollten Sie ihn abschalten. Das geschieht einfach durch Setzen des Ports auf "0" (Null).

begin
  dbms_xdb.setftpport(
    new_port => 0
  );
end;

Den HTTP Port nachträglich ändern

Um den HTTP Port des Embedded PL/SQL Gateway nachträglich zu ändern, benötigen Sie nur einen PL/SQL Aufruf:

begin
  dbms_xdb.sethttpport(8080);
end;

Wenn Sie auf einem Unix oder Linux-System einen Port unter 1024 nutzen möchten, müssen Sie ein wenig mehr tun - eine Beschreibung der nötigen Schritte finden Sie in der Dokumentation zur Oracle XML DB.

TCP/IP Ports überprüfen

Die Ports werden, wie weiter oben schon erwähnt, vom Oracle Listener bedient. Ein lsnrctl status gibt Ihnen eine Übersicht über die aktuell aktiven Ports.

[oracle@sccloud033 ~]$ lsnrctl status

LSNRCTL for Linux: Version 11.2.0.1.0 - Production on 15-NOV-2010 13:20:43

Copyright (c) 1991, 2009, Oracle.  All rights reserved.

Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=EXTPROC1521)))
STATUS of the LISTENER
------------------------
Alias                     LISTENER
Version                   TNSLSNR for Linux: Version 11.2.0.1.0 - Production
Start Date                02-AUG-2010 17:11:09
Uptime                    104 days 21 hr. 9 min. 34 sec
Trace Level               off
Security                  ON: Local OS Authentication
SNMP                      OFF
Listener Parameter File   /opt/oracle/product/11.2.0/db/network/admin/listener.ora
Listener Log File         /opt/oracle/diag/tnslsnr/sccloud033/listener/alert/log.xml
Listening Endpoints Summary...
  (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC1521)))
  (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=sccloud033.de.oracle.com)(PORT=1521)))
  (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=sccloud033.de.oracle.com)(PORT=8080))(Presentation=HTTP)(Session=RAW))
  (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=sccloud033.de.oracle.com)(PORT=2100))(Presentation=FTP)(Session=RAW))
Services Summary...
Service "orcl" has 1 instance(s).
  Instance "orcl", status READY, has 1 handler(s) for this service...
Service "orclXDB" has 1 instance(s).
  Instance "orcl", status READY, has 1 handler(s) for this service...

Performance-Optimierungen für das Embedded Gateway

Nach einer Standardeinrichtung funktioniert das Embedded Gateway; allerdings lässt die Performance doch massiv zu wünschen übrig. Das liegt aber nicht daran, dass die Protokollserver an sich langsam sind. Vielmehr ist die Default-Konfiguration eher schlecht - und bei APEX merkt man das auch. Es ist aber sehr einfach, die Performance zu verbessern.

  • Setzen Sie (als DBA) die Parameter shared_servers und max_shared_servers so, dass Serverprozesse (Shared Server) in hinreichender Anzahl bereitstehen. Beachten Sie dabei, dass eine APEX-Seite während des Ladens einer Anwendungsseite mehrere HTTP-Anfragen absetzt (Bilder, JavaScript, CSS); ein APEX-Nutzer belegt also für einen Seitenabruf durchaus mehr als einen Server-Prozess. Der Parameter max_shared_servers legt dabei die Obergrenze für die Server-Prozesse fest, während shared_servers eine Art "Zielgröße" darstellt. Mit dem folgenden Beispiel werden beim Start der Datenbank sofort 15 Server-Prozesse gestartet. Bei starker Last können nochmals 10 Prozesse nachgestartet werden, die allerdings auch wieder zerstört werden, wenn die Last zurückgeht. Die 15 Server-Prozesse bleiben jedoch bestehen.
    alter system set shared_servers=15 scope=both
    alter system set max_shared_servers=30 scope=both
    
  • Auch die Anzahl der Dispatcher ist von Bedeutung; diese nehmen die Browser-Anfragen entgegen - auch hier ist es meist sinnvoll, mehr als einen Dispatcher zu starten. Der Parameter dispatchers ist bei Ihnen schon gesetzt, wir ändern nur die Anzahl - es kommt auf den rot markierten Teil an:
    alter system set dispatchers='(PROTOCOL=TCP) (SERVICE=[Hier Datenbank-SID einsetzen]XDB) (DISPATCHERS=3)' scope=both
    
    Wenn die SID Ihrer Datenbank also orcl ist, sieht der Parameter so aus:
    alter system set dispatchers='(PROTOCOL=TCP) (SERVICE=orclXDB) (DISPATCHERS=3)' scope=both
    

Embedded Gateway und sichere Verbindungen (SSL)

Das PL/SQL Embedded Gateway kann auch im SSL-Modus betrieben werden. Dabei sind jedoch zwei Voraussetzungen zu beachten:

  • Diese Funktionalität ist Teil der Advanced Security Option
  • Sie benötigen ein Server Zertifikat, mit welchem sich die Datenbank gegenüber dem Webbrowser "ausweist".

Genaue Anweisungen zur Konfiguration des PL/SQL Embedded Gateway mit SSL finden Sie im Handbuch zur Oracle XML DB.

Logging

Verwendet man den Apache, ist alles ganz einfach. Wenn es ein Zugriffsproblem gibt und auf dem Bildschirm nur die berühmte HTTP 404 oder HTTP 500-Meldung erscheint, schaut man am besten in die Datei error_log hinein - dort findet man dann in aller Regel einen ORA-Fehlercode, der beim Analysieren des Problems weiterhilft.

Standardmäßig findet beim PL/SQL Embedded Gateway keinerlei Logging statt. Auch im Fehlerfall sieht man außer der HTTP Fehlermeldung oder einem ggfs. leeren Bildschirm nichts. Bei Problemen sollte also zunächst das Logging aktiviert werden - und zwar wie folgt:

/*
 * Log levels for the global attribute "log-level"
 *
 * LOG_EMERG   CONSTANT PLS_INTEGER := 0;
 * LOG_ALERT   CONSTANT PLS_INTEGER := 1;
 * LOG_CRIT    CONSTANT PLS_INTEGER := 2;
 * LOG_ERR     CONSTANT PLS_INTEGER := 3;
 * LOG_WARNING CONSTANT PLS_INTEGER := 4;
 * LOG_NOTICE  CONSTANT PLS_INTEGER := 5;
 * LOG_INFO    CONSTANT PLS_INTEGER := 6;
 * LOG_DEBUG   CONSTANT PLS_INTEGER := 7;
 */

begin
  dbms_epg.set_global_attribute(
    attr_name  => 'log-level',
    attr_value => dbms_epg.log_debug
  );
end;
/

commit
/

Von nun an werden Debugging-Informationen in die Datenbank-Tracedateien geschrieben (user dump destination). Der Loglevel LOG_DEBUG führt zu recht umfangreichen Informationen. Aus Performancegründen sollten Sie das Logging (wie immer) nur einschalten, wenn Sie es tatsächlich benötigen - es kostet ebenfalls Ressourcen.

Embedded PL/SQL Gateway: (wpdenv.c,681) script_name='/apex' path_info='/apex'script_prefix='' dad_name='apex'
Embedded PL/SQL Gateway: (wpdenv.c,795) User-Agent is Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv ...
Embedded PL/SQL Gateway: (wpdenv.c,1415) dadname = 'apex', path_info = 'apex'
Embedded PL/SQL Gateway: (wpdenv.c,1454) Service will NOT use dynamic auth
Embedded PL/SQL Gateway: (wpx.c,394) Initialized successfully 0
Embedded PL/SQL Gateway: (wpx.c,316) SetRemoteUser : Remote User set to ANONYMOUS for this request.
Embedded PL/SQL Gateway: (wpx.c,480) Auth info from .APP file is being used
Embedded PL/SQL Gateway: (wpd.c,1729) Attempting to logon with '(unknown)'
Embedded PL/SQL Gateway: (wpu.c,1500) DBCharSet=>AMERICAN_AMERICA.AL32UTF8 OWAVersion=10.1.2.0.8 (101208) OWAMatch=>1 (rc=0)
Embedded PL/SQL Gateway: (wpd.c,1763) Logged in as (unknown)
Embedded PL/SQL Gateway: (wpx.c,593) Going to select...
Embedded PL/SQL Gateway: (wpx.c,647) Have been asked to execute a request
:

Mit Hilfe des Loggings können Sie auch eine weitere Eigenheit des Embedded Gateways ergründen - dazu der nächste Abschnitt.

Eigene PL/SQL Prozeduren direkt per URL aufrufen

Im Gegensatz zum Apache erlaubt das Embedded Gateway den direkten Aufruf von eigenen PL/SQL-Prozeduren nicht. Wenn Sie also als Beispiel im Parsing Schema Ihrer APEX-Anwendung die folgende Prozedur erzeugen und die Ausführungsprivilegien an alle vergeben ...

create or replace procedure testhtp 
is 
begin 
  htp.p('TEST'); 
end;
/

grant execute on testhtp to public
/

... und diese Prozedur dann im Browser aufrufen ...

1. Versuch: Direkter Aufruf einer eigenen PL/SQL Prozedur mit dem Embedded Gateway

Abbildung 4: 1. Versuch: Direkter Aufruf einer eigenen PL/SQL Prozedur mit dem Embedded Gateway"

... stellen Sie fest, dass dies offensichtlich nicht erlaubt ist. Verwendet man den Apache, funktioniert es ohne Probleme. Woran liegt das? Ein Blick in die Logging-Informationen gibt Auskunft:

Embedded PL/SQL Gateway: (wpd.c,2536) attempt to call forbidden procedure!
Embedded PL/SQL Gateway: /apex/PARTNER.TESTHTP HTTP-403 It is forbidden to call this procedure directly from the browser!
Embedded PL/SQL Gateway: (wpu.c,626) longjumping back to the beginning
Embedded PL/SQL Gateway: (wpu.c,488) cleaning up before longjmp
Embedded PL/SQL Gateway: (wpu.c,492) doing a rollback
Embedded PL/SQL Gateway: (wpcs.c, 76) Executed 'rollback' (rc=0)
Embedded PL/SQL Gateway: (wpcs.c, 76) Executed 'begin dbms_session.reset_package; end;' (rc=0)
Embedded PL/SQL Gateway: (wpd.c,1818) Going to close cursor

Das PL/SQL Embedded Gateway erlaubt das direkte Aufrufen nur für die Prozeduren der APEX-Engine. Möchte man (wie im Beispiel) auch andere Prozeduren aufrufen, müssen diese freigeschaltet werden. Dir Prüfung erfolgt, indem das Embedded Gateway die Prozedur wwv_flow_epg_include_mod_local im Schema der APEX-Engine (hier: APEX_040000) aufruft. Standardmäßig liefert diese stets false zurück. Spielen Sie also als SYS folgende Prozedur ein.

alter session set current_schema=APEX_040000
/

CREATE OR REPLACE function wwv_flow_epg_include_mod_local(
  procedure_name in varchar2
) return boolean
is
begin
  --
  -- Administrator note: the procedure_name input parameter may be in the format:
  --
  --    procedure
  --    schema.procedure
  --    package.procedure
  --    schema.package.procedure
  --
  -- If the expected input parameter is a procedure name only, the IN list code shown below
  -- can be modified to itemize the expected procedure names. Otherwise you must parse the
  -- procedure_name parameter and replace the simple code below with code that will evaluate
  -- all of the cases listed above.
  --
  if upper(procedure_name) in ('PARTNER.TESTHTP') then
      return TRUE;
  else
      return FALSE;
  end if;
end wwv_flow_epg_include_mod_local;
/

Ein neuer Versuch mit dem Browser funktioniert nun. Natürlich können Sie die Namen der Prozeduren auch in einer Tabelle speichern und im PL/SQL Code anhand dieser Tabelle prüfen, ob das Aufrufen der Prozedur erlaubt ist. Das einfachste denkbare Beispiel wäre, stets true zurückzugeben - damit würde sich das Embedded Gateway genauso wie der Apache verhalten.

Direkter Aufruf einer eigenen PL/SQL Prozedur mit dem Embedded Gateway nach Freischaltung

Abbildung 5: Direkter Aufruf einer eigenen PL/SQL Prozedur mit dem Embedded Gateway nach Freischaltung

Wie schon weiter oben erwähnt, bietet das PL/SQL Gateway bei weitem nicht die Funktionsfülle wie der Apache Webserver mit seinen vielen Modulen. Die sehr populäre Funktion des URL Rewritings, also das Umschreiben einer APEX-URL (f?p=129:1) in eine leicht zu merkende /myapplication, kann jedoch auch mit dem Embedded Gateway nachgebildet werden. Wie das geht, ist in diesem Community-Tipp beschrieben.

Zurück zur Community-Seite