Logo Oracle Deutschland   Application Express Community

Automatisierter Export und Import von APEX-Anwendungen per Kommandozeile

Erscheinungsmonat APEX-Version Datenbankversion
Juli 2011 ab 2.2 ab 9.2

Wenn APEX-Installationen im Rechenzentrum betrieben werden, entsteht immer häufiger die Notwendigkeit, Anwendungsexporte nicht mehr über die APEX-Oberfläche, sondern skriptgesteuert durchzuführen. Ein Grund dafür kann bspw. sein, dass das die APEX-Entwicklungsumgebung auf dem Produktivsystem entfernt wurde (Runtime-Only-Install). Neue Anwendungen müssen also auf einem anderen Wege installiert werden. Auch kann es interessant sein, die Anwendungen des Entwicklungssystems (bspw. jeden Abend) automatisiert zu exportieren und (zum Beispiel) in das Versionskontrollsystem einzustellen.

Es ist nicht jedem bekannt, aber APEX bringt die nötigen Werkzeuge bereits mit. Wenn Sie APEX heruntergeladen und das ZIP-Archiv ausgepackt haben, befinden sich die Exportwerkzeuge im Verzeichnis utilities und dort unter oracle und apex. Allerdings liegen die Werkzeuge nur als reine Java-Klassendateien (.class) vor. Damit sie nutzbar werden, sind noch ein paar Vorbereitungen nötig.

Unterverzeichnis "utilities"

Unterverzeichnis "utilities"

Vorbereitungen

Um die Werkzeug benutzen zu können, erzeugen Sie sich am besten zunächst ein Unix-Skript bzw. eine Windows-Batch-Datei. Passen Sie jedoch bei den folgenden Skripten die Umgebungsvariablen ORACLE_HOME und APEX_HOME an Ihre Umgebung an.

Die Werkzeuge sind in Java geschrieben - benötigen also eine Java-Umgebung, um laufen zu können. In diesem Beispiel nehmen wir die Java-Umgebung, die mit der Oracle-Datenbank mitinstalliert wird ($ORACLE_HOME/jdk). Wenn Sie OracleXE verwenden, müssen Sie eine andere schon vorhandene Java-Umgebung nehmen bzw. eine neue herunterladen und installieren. Ebenso dürfte die in den Skripten referenzierte Datei $ORACLE_HOME/oui/jlib/classes12.jar in OracleXE nicht vorhanden sein. Laden Sie sie dann einfach aus dem OTN herunter und passen Sie die Skripte entsprechend an.

#!/bin/sh
ORACLE_HOME=/oracle/u01/app/oracle/product/11.2.0
# APEX HOME auf das Verzeichnis setzen, in das APEX ausgepackt wurde.
APEX_HOME=$ORACLE_HOME/apex

PATH=$ORACLE_HOME/jdk/bin:$PATH

CLASSPATH=$ORACLE_HOME/oui/jlib/classes12.jar
CLASSPATH=$CLASSPATH:$APEX_HOME/utilities
CLASSPATH=$CLASSPATH:.

export APEX_HOME ORACLE_HOME PATH CLASSPATH

java oracle.apex.APEXExport $*

Auf Windows-Systemen sieht das Skript wie folgt aus:

@echo off
set ORACLE_HOME=C:\oracle\11.2.0\db_1
# APEX HOME auf das Verzeichnis setzen, in das APEX ausgepackt wurde.
set APEX_HOME=%ORACLE_HOME%\apex

set CLASSPATH=%ORACLE_HOME%\oui\jlib\classes12.jar
set CLASSPATH=%CLASSPATH%;%APEX_HOME%\utilities
set CLASSPATH=%CLASSPATH%;.

%ORACLE_HOME%\jdk\bin\java.exe oracle.apex.APEXExport %*

Informationen über den Aufruf erhält man, wenn man das Skript ohne Parameter aufruft.

Usage APEXExport -db  -user  -password  -applicationid  -workspaceid -instance -expWorkspace -skipExportDate -expPubReports -expSavedReports -expIRNotif -expTeamdevdata -expFeedback -deploymentSystem -expFeedbackSince -debug
    -db:              Database connect url in JDBC format
    -user:            Database username
    -password :       Database password
    -applicationid :  ID for application to be exported
    -workspaceid :    Workspace ID for which all applications to be exported or the workspace to be exported
    -instance :       Export all applications
    -expWorkspace :   Export workspace identified by -workspaceid or all workspaces if -workspaceid not specified
    -skipExportDate : Exclude export date from application export files
    -expPubReports :  Export all user saved public interactive reports
    -expSavedReports: Export all user saved interactive reports
    -expIRNotif :     Export all interactive report notifications
    -expFeedback :    Export team development feedback for all workspaces or identified by -workspaceid to development or deployment
    -expTeamdevdata : Export team development data for all workspaces or identified by -workspaceid
    -deploymentSystem : Deployment system for exported feedback
    -expFeedbackSince :  Export team development feedback since date in the format YYYYMMDD

    Application Example:
       APEXExport -db candy.us.oracle.com:1521:ORCL -user scott -password tiger -applicationid 31500
    Workspace  Example:
       APEXExport -db candy.us.oracle.com:1521:ORCL -user scott -password tiger -workspaceid 9999
    Instance Example:
       APEXExport -db candy.us.oracle.com:1521:ORCL -user system -password manager -instance
    Export All Workspaces Example:
       APEXExport -db candy.us.oracle.com:1521:ORCL -user system -password manager -expWorkspace
    Export Feedback to development environment:
       APEXExport -db candy.us.oracle.com:1521:ORCL -user scott -password tiger -workspaceid 9999 -expFeedback
    Export Feedback to deployment environment EA2 since 20100308:
       APEXExport -db candy.us.oracle.com:1521:ORCL -user scott -password tiger -workspaceid 9999 -expFeedback -deploymentSystem EA2 -expFeedbackSince 20100308

Richten Sie anschließend das Splitter-Werkzeug ein. Damit können Sie die APEX-Exportdatei in ihre Bestandteile zerlegen. Legen Sie die Skripte wie vorhin an, verwenden Sie in der letzten Zeile nur anstelle der Klasse APEXExport die Klasse APEXExportSplitter.

#!/bin/sh
ORACLE_HOME=/oracle/u01/app/oracle/product/11.2.0
# APEX HOME auf das Verzeichnis setzen, in das APEX ausgepackt wurde.
APEX_HOME=$ORACLE_HOME/apex

PATH=$ORACLE_HOME/jdk/bin:$PATH

CLASSPATH=$ORACLE_HOME/oui/jlib/classes12.jar
CLASSPATH=$CLASSPATH:$APEX_HOME/utilities
CLASSPATH=$CLASSPATH:.

export APEX_HOME ORACLE_HOME PATH CLASSPATH

java oracle.apex.APEXExportSplitter $*

Auf Windows-Systemen sieht das Skript wie folgt aus:

@echo off
set ORACLE_HOME=C:\oracle\11.2.0\db_1
# APEX HOME auf das Verzeichnis setzen, in das APEX ausgepackt wurde.
set APEX_HOME=%ORACLE_HOME%\apex

set CLASSPATH=%ORACLE_HOME%\oui\jlib\classes12.jar
set CLASSPATH=%CLASSPATH%;%APEX_HOME%\utilities
set CLASSPATH=%CLASSPATH%;.

%ORACLE_HOME%\jdk\bin\java.exe oracle.apex.APEXExportSplitter %*

Exportieren per Kommandozeile

Wenn Sie die Skripte bzw. Batchdateien fertig haben, kann es losgehen. Das folgende Beispiel exportiert eine Anwendung (in diesem Beispiel wurde das oben beschriebene Unix-Skript export-skript.sh genannt).

$ ./export-skript.sh  -db mydatabaseserver:1521:orcl -user scott -password tiger -applicationid 100
Exporting application 100
  Completed at Thu Jul 14 09:59:27 CEST 2011
$

Die Skriptausgabe ist recht unspektakulär, aber im Betriebssystemverzeichnis befindet sich nun die Datei f100.sql, genauso, als ob Sie den Export über die APEX-Oberfläche gemacht hätten. Wenn es nun daran geht, die Datei in ein Versionskontrollsystem einzustellen, kann es interessant sein, die Datei in ihre Komponenten aufzusplitten. Gegebenenfalls möchte man ja nur eine einzelne Seite auf dem Produktivsystem neu einspielen. Dazu dient der APEXExportSplitter. Und der funktioniert wie folgt.

$ ./splitter-skript.sh f100.sql
Processing:f100.sql
$

Auch hier ist die Ausgabe eher unspektakulär - aber im Hintergrund ist einiges entstanden ...

Die APEX Exportdatei wurde in die einzelnen Komponenten aufgespalten

Abbildung 2: Die APEX Exportdatei wurde in die einzelnen Komponenten aufgespalten

Der Splitter kann übrigens auch mit Exportdateien arbeiten, die aus der Oberfläche heraus exportiert wurden. Jede einzelne der Komponenten kann auch einzeln wieder importiert werden. Wenn Sie den Splitter mit der Option -update aufrufen, vergleicht das Werkzeug die Dateien anhand einer Checksumme und generiert ein Update-Skript, welches nur die veränderten Anwendungsteile neu einspielt. Diese Optionen sind sehr hilfreich, wenn die Komponenten in ein Versionskontrollsystem eingecheckt werden.

Importieren der Dateien - von der Kommandozeile

Wenn Sie sich eine Exportdatei genauer ansehen, dann stellen Sie fest, dass es im Grunde genommen ein SQL-Skript ist - und SQL-Skripte können mit SQL*Plus eingespielt werden. Und genau das ist schon seit dem ersten Release von Application Express möglich - Kommandozeilen-Imports waren prinzipiell also schon immer möglich. Man muss jedoch etwas tun, wenn eine Exportdatei in ein anderes Workspace eingespielt werden soll oder wenn die Applikations-ID auf dem Zielsystem eine andere sein soll (weil die Original-ID vielleicht schon belegt ist). Beginnen wir mit dem Import in einen anderen Workspace. Zunächst loggen Sie sich mit SQL*Plus ins Datenbankschema, welches dem Ziel-Workspace zugeordnet ist, ein ...

$ sqlplus {datenbank-userid}/{datenbank-password}

SQL*Plus: Release 11.2.0.2.0 Production on Thu Jul 14 10:42:27 2011

Copyright (c) 1982, 2010, Oracle.  All rights reserved.


Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - Production
With the Partitioning, Oracle Label Security, OLAP, Data Mining
and Real Application Testing options

SQL>

Danach starten Sie das Skript ...

SQL> @f100
APPLICATION 100 - Interaktive Berichte
Set Credentials...
Illegal security group id value for this schema.
Check Compatibility...
API Last Extended:20100513
Your Current Version:20100513
This import is compatible with version: 20100513
COMPATIBLE (You should be able to run this import without issues.)
Set Application ID...
begin
*
ERROR at line 1:
ORA-20001: Package variable g_security_group_id must be set.
ORA-06512: at "APEX_040000.WWV_FLOW_API", line 51
ORA-06512: at "APEX_040000.WWV_FLOW_API", line 304
ORA-06512: at line 4


Disconnected from Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - Production
With the Partitioning, Oracle Label Security, OLAP, Data Mining
and Real Application Testing options

Sie werden recht schnell feststellen, dass der Import so nicht funktioniert. Die in der Exportdatei hinterlegte Workspace-ID ist eine andere als die des Workspace, in den Sie importieren möchten. Während die APEX-Entwicklungsumgebung damit problemlos umgehen kann, müssen Sie beim Kommandozeilenimport selbst aktiv werden. Und die erste Aktion ist, die Workspace-ID festzustellen - das machen Sie ebenfalls in SQL*Plus.

SQL> select workspace_id, workspace from apex_workspaces

                   WORKSPACE_ID WORKSPACE
------------------------------- ---------------------
               3138423103500405 ZIEL_WORKSPACE

Vor APEX 4.0 hätte man nun die Exportdatei "hacken" müssen - zum Glück ist das nicht mehr nötig. APEX 4.0 führt das PL/SQL Paket APEX_APPLICATION_INSTALL ein, welches aber nur mit Dateien funktioniert, die mit APEX 4.0 exportiert wurden. Im folgenden stellen wir mit APEX_APPLICATION_INSTALL die richtige Workspace-ID ein und stellen darüber hinaus die neue Application-ID auf 999999 ein.

begin
  apex_application_install.set_workspace_id(3138423103500405);
  apex_application_install.set_application_id(999999);
  apex_application_install.set_schema('{<i>DB_SCHEMA</i>}');
end;
/

PL/SQL procedure successfully completed.

Danach starten Sie nochmal das Skript f100.sql. Insbesondere wenn Sie auf der gleichen Datenbank importieren, aus der heraus auch exportiert wurde, werden Sie dann aber wahrscheinlich den folgenden Fehler sehen ...

SQL> @f100
APPLICATION 100 - Interaktive Berichte
:
:
...Application Parent Tabs
...Shared Lists of values
Error creating list of values id="2427807963171347" ORA-00001: unique constraint (APEX_040000.WWV_FLOW_LOV_PK) violated
begin
*
ERROR at line 1:
ORA-00001: unique constraint (APEX_040000.WWV_FLOW_LOV_DATA_PK) violated
ORA-06512: at "APEX_040000.WWV_FLOW_API", line 2844
ORA-06512: at line 3

Disconnected from Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - Production
:

Der Grund hierfür sind die generierten Primärschlüssel für die einzelnen Komponenten; APEX versucht hier, eine ID wiederzuverwenden, was natürlich nicht geht - jede ID darf nur einmal vorhanden sein. Aber auch hierfür bietet APEX_APPLICATION_INSTALL Abhilfe. Machen Sie einen zusätzlichen Aufruf von APEX_APPLICATION_INSTALL.SET_OFFSET. Nehmen Sie irgendeine Zufallszahl als Offset. APEX wird diese beim Erzeugen der Primärschlüssel berücksichtigen und so eindeutige Werte erzeugen.

begin
  apex_application_install.set_workspace_id(3138423103500405);
  apex_application_install.set_application_id(999999);
  apex_application_install.set_schema('{<i>DB_SCHEMA</i>}');
  apex_application_install.set_offset(2763898718743);
end;
/

PL/SQL procedure successfully completed.

Danach läuft das Skript problemlos durch.

SQL> @f100
APPLICATION 100 - Interaktive Berichte
:
:
......scheme 2426409770171307
......scheme 2426505157171307
...plugins
...done
SQL>

Wenn Sie sich in das Workspace einloggen, ist die importiere APEX-Anwendung unter der neuen ID 999999 vorhanden (Abbildung 3).

Die Applikation wurde per Kommandozeile erfolgreich importiert

Abbildung 3: Die Applikation wurde per Kommandozeile erfolgreich importiert

Einzelne Anwendungskomponenten per Kommandozeile importieren

Als nächstes wird gezeigt, wie Sie eine einzelne Komponente in Ihre Anwendung einspielen können. Angenommen, Sie haben die Seite 2 versehentlich gelöscht oder Sie möchten aus einem anderen Grund nur für die Seite 2 auf den Stand der Exportdateien zurückgehen. Im besten Fall liegen die Exportdateien im Versionskontrollsystem, so dass Sie sich die gewünschte Version einfach aus diesem herausziehen können. Zum Ausprobieren löschen Sie einfach die Seite 2.

Navigieren Sie dann in das Verzeichnis application, welches das Splitter-Werkzeug angelegt hat. Starten Sie darin SQL*Plus und setzen Sie wiederum die Umgebung mit APEX_APPLICATION_INSTALL.

begin
  apex_application_install.set_workspace_id(3138423103500405);
  apex_application_install.set_application_id(999999);
  apex_application_install.set_schema('{<i>DB_SCHEMA</i>}');
  apex_application_install.set_offset(2763898718743);
end;
/

PL/SQL procedure successfully completed.

Das Skript, welches nur die Seite 2 neu einspielt, befindet sich im Verzeichnis pages unterhalb von application und trägt den namen page_00002.sql. Warten Sie aber noch mit dem direkten Aufruf, denn zunächst muss die SQL*Plus-Datenbanksitzung noch für den Import einer APEX-Komponente vorbereitet werden (beim Import einer Gesamt-Applikation wird dies automatisch gemacht). Rufen Sie zuerst das Skript init.sql und dann set_environment.sql auf - beide liegen direkt im Verzeichnis application. Achten Sie darauf, dass Sie die gleiche Datenbanksitzung verwenden wie beim Aufruf von APEX_APPLICATION_INSTALL (SQL*Plus also nicht zwischendurch verlassen).

SQL> @init
SQL> @set_environment.sql
APPLICATION 100 - Interaktive Berichte
Set Credentials...
Illegal security group id value for this schema.
Check Compatibility...
API Last Extended:20100513
Your Current Version:20100513
This import is compatible with version: 20100513
COMPATIBLE (You should be able to run this import without issues.)
Set Application ID...
SQL>

Und jetzt ist es soweit. Stellen Sie nur die Seite 2 wieder her.

SQL> @pages/page_00002
...PAGE 2: Interaktive Berichte
SQL> commit;

Commit complete.

Und das war es auch schon - die Seite 2 ist wieder da. Genauso können Sie auch die anderen Komponenten einzeln wieder einspielen. Man sieht sehr schön, dass Ihnen mit diesen beiden unscheinbaren Java-Klassendateien zwei sehr mächtige Werkzeuge an die Hand gegeben werden. Nimmt man SQL*Plus als Importwerkzeug dazu, lassen sich mit APEX genauso mächtige Deployment-Prozesse aufsetzen, wie man es von anderen Entwicklungsumgebungen her kennt.

Zurück zur Community-Seite