Logo Oracle Deutschland   Application Express Community

Automatisierter Export und Import von APEX-Anwendungen per Kommandozeile

Stand APEX-Version Datenbankversion
März 2016 alle alle

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, brauchen 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). In einer Oracle11g-Datenbank ist das ein Java 1.5, Oracle12c bringt Java 6 mit. Sie können natürlich auch das aktuellste Java 8 herunterladen und verwenden. Welche Java-Version Ihnen vorliegt, finden Sie am einfachsten wie folgt heraus:

$ $ORACLE_HOME/jdk/bin/java -version
java version "1.6.0_75"
Java(TM) SE Runtime Environment (build 1.6.0_75-b13)
Java HotSpot(TM) 64-Bit Server VM (build 20.75-b01, mixed mode)

Wenn Sie die in den Skripten referenzierte Dateien ojdbc5.jar, ojdbc6.jar oder ojdbc7.jar in Ihrer Installation nicht finden können, laden Sie sie einfach aus dem OTN herunter und passen Sie die Skripte entsprechend an.

#!/bin/sh
# ORACLE_HOME anpassen ...
ORACLE_HOME=/oracle/u01/app/oracle/product/12.1.0/db_1
# 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/jdbc/lib/ojdbc6.jar
CLASSPATH=$CLASSPATH:$APEX_HOME/utilities
CLASSPATH=$CLASSPATH:.

export APEX_HOME ORACLE_HOME PATH CLASSPATH

java oracle.apex.APEXExport $*

In diesem Beispiel wird die JDBC-Datei ojdbc6.jar angesprochen. Achten Sie hier bitte genau darauf, die richtige zu nehmen. Prüfen Sie zunächst, wie oben bereits erwähnt, mit java -version die Java-Version und nehmen Sie dann ...

  • ojdbc5.jar, wenn Sie ein Java der Version 1.5 verwenden
  • ojdbc6.jar, wenn Sie ein Java der Version 1.6 verwenden
  • ojdbc7.jar, wenn Sie ein Java der Version 1.7 oder höher verwenden

Auf Windows-Systemen sieht das Skript wie folgt aus:

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

set CLASSPATH=%ORACLE_HOME%\jdbc\lib\ojdbc6.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 -expMinimal -expFiles -skipExportDate -expPubReports -expSavedReports -expIRNotif -expTranslations -expTeamdevdata -expFeedback -deploymentSystem -expFeedbackSince -expOriginalIds -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
    -expMinimal:       Only export workspace definition, users, and groups
    -expFiles:         Export all workspace files identified by -workspaceid
    -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
    -expTranslations:  Export the translation mappings and all text from the translation repository
    -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
    -expOriginalIds:   If specified, the application export will emit ids as they were when the application was imported

    Application Example:
       APEXExport -db localhost:1521:ORCL -user scott -password scotts_password -applicationid 31500
    Workspace  Example:
       APEXExport -db localhost:1521:ORCL -user scott -password scotts_password -workspaceid 9999
    Instance Example:
       APEXExport -db localhost:1521:ORCL -user system -password systems_password -instance
    Export All Workspaces Example:
       APEXExport -db localhost:1521:ORCL -user system -password systems_password -expWorkspace
    Export Feedback to development environment:
       APEXExport -db localhost:1521:ORCL -user scott -password scotts_password -workspaceid 9999 -expFeedback
    Export Feedback to deployment environment EA2 since 20100308:
       APEXExport -db localhost:1521:ORCL -user scott -password scotts_password -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 anpassen ...
ORACLE_HOME=/oracle/u01/app/oracle/product/12.1.0/db_1
# APEX_HOME auf das Verzeichnis setzen, in das APEX ausgepackt wurde.
APEX_HOME=$ORACLE_HOME/apex

PATH=$ORACLE_HOME/jdk/bin:$PATH

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
rem ORACLE_HOME anpassen ...
set ORACLE_HOME=C:\oracle\12.1.0\db_1
rem APEX_HOME auf das Verzeichnis setzen, in das APEX ausgepackt wurde.
set APEX_HOME=%ORACLE_HOME%\apex

set 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 my12cserver:1521/servicename 
                      -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 - mit 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 - Kalender Community
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_050000.WWV_FLOW_API", line 51
ORA-06512: at "APEX_050000.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

Die in der Exportdatei verwendete Workspace-ID muss also durch diese ersezt werden. Es ist aber nicht nötig, die Exportdatei zu "hacken" - APEX bringt dafür das PL/SQL Paket APEX_APPLICATION_INSTALL mit. Mit diesem Paket können Workspace- und Applikations-ID, aber auch andere Einstellungen, die in der Zielumgebung anders sein könnten (bspw. Parsing Schema oder Applikations-Alias), gesetzt werden. 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_application_alias('NEWALIAS');
  apex_application_install.set_schema('{DB_SCHEMA}');
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 - Kalender Community
:
:
--application/ui_types
--application/create_application
--application/shared_components/navigation/lists
begin
*
ERROR at line 1:
ORA-00001: unique constraint (APEX_050000.WWV_FLOW_LISTS_PK) violated
ORA-06512: at "APEX_050000.WWV_FLOW_API", line 13503
ORA-06512: at line 2

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 oder, wenn Sie sich eine solche nicht ausdenken wollen, nehmen Sie GENERATE_OFFSET. APEX wird diesen Offset dann beim Erzeugen der Primärschlüssel berücksichtigen und so auf eindeutige Werte kommen.

begin
  apex_application_install.set_workspace_id(3138423103500405);
  apex_application_install.set_application_id(999999);
  apex_application_install.set_application_alias('NEWALIAS');
  apex_application_install.set_schema('{DB_SCHEMA}');
  apex_application_install.generate_offset;
  -- mit SET_OFFSET kann man die den OFFSET auch selbst bestimmen
  -- apex_application_install.set_offset(2763898718743);
end;
/

PL/SQL procedure successfully completed.

Danach läuft das Skript problemlos durch.

SQL> @f100
APPLICATION 100 - Kalender Community
:
:
......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 zurückspielen

Als nächstes wird gezeigt, wie Sie eine einzelne Komponente in Ihre Anwendung zurückspielen 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 aus diesem herausziehen und zurückspielen können.

Vorab sei gesagt, dass das Einspielen einzelner Dateien, die durch den Splitter erzeugt wurden, nicht zu empfehlen ist. Es wird sehr häufig zu Fehlern führen, da nahezu jede Seite Gemeinsame Komponenten referenziert. Insbesondere wenn die Exportdatei aus einem anderen Workspace oder einer anderen Applikation stammt, werden die APEX-internen Primär- und Fremdschlüssel nicht mehr zusammenpassen und der Import wird mit Fehlern abgebrochen.

Einfacher ist es, die ganze Applikation als neue Anwendung zu importieren (das kann im Application Builder oder per Kommandozeile erfolgen) und die fragliche Komponente dann als Kopie aus dieser Anwendung neu zu generieren. Abbildung 4 zeigt dies am Beispiel einer neuen Seite, die als Kopie einer Seite aus einer anderen Anwendung erstellt wird.

Neue Seite als Kopie einer anderen Anwendung erstellen

Abbildung 4: Neue Seite als Kopie einer anderen Anwendung erstellen

Diese Vorgehensweise ist auch mit vielen Gemeinsamen Komponenten möglich: Nahezu überall können diese als Kopie einer anderen Komponente, aus einer anderen Anwendung, erzeugt werden.

Wie man sieht, können die beiden unscheinbaren Java-Dateien APEXExport.class und APEXExportSplitter.class die Grundlage für ein mächtiges und ausgefeiltes APEX-Versionsmanagement sein. Ein Export per Kommandozeile lässt sich als Job aufsetzen und so ist das tägliche, automatisierte Exportieren aller Anwendungen ein Kinderspiel. Auch das automatische Einspielen in ein anderes System (bspw. ein Testsystem) lässt sich gut realisieren. Schließlich finden Entwickler im Versionskontrollsystem auch ältere Versionen, die sie zurückspielen und so u.U. versehentlich gelöschte oder veränderte Komponenten wiederherstellen können. So wird mit APEX eine ebenso professionelle Entwicklung möglich wie mit anderen Umgebungen.

Zurück zur Community-Seite