Beiträge

Oracle APEX: Custom error messages mit APEX_ERROR

Die Haupt-Anwendungsfälle im Zusammenhang mit der Ausgabe von Fehlermeldungen in APEX-Applikationen dürften die meisten Entwickler nach einer verhältnismäßig kurzen Einarbeitungszeit kennen:

  • Entweder werden Validations ausgeführt, schlagen an und sollen den Endanwender darüber informieren, dass eine entsprechende Bedingung verletzt wurde.
  • Oder während der Ausführung eines Page Processes tritt ein Fehler auf, über den der Endanwender in Kenntnis gesetzt werden soll.

 

Wollten Entwickler in älteren APEX-Versionen eigene Fehlermeldungen ausgeben, geschah dies häufig über die Nutzung der Variable apex_application.g_print_success_message unter zusätzlicher Angabe von Style-Informationen:

apex_application.g_print_success_message := '<span style="color:red;">Achtung: Bei der Aufbereitung der Datei-Inhalte sind insgesamt 23 Fehler aufgetreten, die Daten konnten daher nicht importiert werden.</span>';

Mittlerweile jedoch stellt das APEX-eigene Package APEX_ERROR viel elegantere Möglichkeiten für den Umgang mit eigenen Fehlermeldungen zur Verfügung:

 

Die überladene Prozedur ADD_ERROR bietet verschiedene Varianten an um eigene Fehlermeldungen auf den Error Stack zu legen, die Darstellung übernimmt dabei APEX, so dass die Notwendigkeit zu expliziten Style-Angaben entfallen kann. Ein entsprechender Prozess im Page Processing könnte damit beispielsweise so aussehen:

DECLARE
 -- define some variables
 v_status NUMBER;
 ...
BEGIN
-- do some fancy stuff
...
 v_status := my_schema.my_package.my_function(p_var => '[MY_VALUE]');

IF v_status > 0 THEN
apex_error.add_error(p_display_location => apex_error.c_inline_in_notification,
p_message => 'Achtung: Es ist ein Fehler aufgetreten, so dass…');
 END IF;
EXCEPTION
WHEN OTHERS THEN
-- do some error logging
...
RAISE;
END;

Das eigentliche Potential entfaltet dieses Package aber dann, wenn man auf auftretende Fehler speziell reagieren will, beispielsweise weil gewisse Fehler häufiger auftreten und die Seite speziell für bestimmte Fehlerfälle bestimmte zusätzliche Button-Aktionen oder Auswertungen zur Verfügung stellen soll. Dafür kann man statt der Variable v_status im obigen Code ein Hidden Item P12_STATUS setzen und nach dem Ausführen der Prozesse über einen Branch die Seite neu aufrufen und das Item dabei übergeben. Der Aufruf von APEX_ERROR geschieht nun nicht mehr im Page Processing sondern im Page Rendering und nur dann wenn P12_STATUS einen Wert > 0 enthält

IF :P12_STATUS = '1' THEN
apex_error.add_error(p_display_location => apex_error.c_inline_in_notification,
 p_message => 'Achtung: Das Hochladen der Daten war nicht erfolgreich, so dass…');
ELSIF :P12_STATUS = '2' THEN
 apex_error.add_error(p_display_location => apex_error.c_inline_in_notification,
p_message => 'Achtung: Das Parsen der Daten ist fehlgeschlagen, so dass…');
ELSE
...
END IF;

Zusätzlich besteht nun natürlich die Möglichkeit status-abhängig zusätzliche Items etc. anzubieten – zum Beispiel ein Button um die Daten erneut hochzuladen für P12_STATUS = ‚1‘ oder ein Report mit den Parsing-Fehlern für P12_STATUS = ‚2‘.

Oracle APEX: WWV_FLOW_FND_USER_FK-Verletzung beim Importieren von Workspaces

Ich bin jüngst im Rahmen eines APEX-Projekts auf ein Problem gestoßen, für das ich im Oracle Support Portal keinen einzigen Eintrag finden konnte – nach einigem Überlegen und Testen aber auf eine relativ einfache Lösung gekommen bin.

Ausgangslage

Das erste Arbeitspaket im Rahmen des Projektes ist fertig entwickelt und soll dem Kunden zur Abnahme in der dafür von diesem bereitgestellten Test-Umgebung deployed werden. Da es in dieser Umgebung keine APEX-Entwicklungs-Umgebung gibt, sind die Sourcen per SQLplus, PL/SQL-Developer oder mit ähnlichen Tools zu deployen.

Nach der fehlerfreien Erstellung von Schemas, Tabellen, Packages etc. folgt der Import des APEX-Workspaces; das aus APEX exportierte Script hierfür schaut sinngemäß wie folgt aus:

set define off verify off feedback off
whenever sqlerror exit sql.sqlcode rollback
--------------------------------------------------------------------------------
--
-- ORACLE Application Express (APEX) export file
--
-- You should run the script connected to SQL*Plus as the Oracle user
-- APEX_050100 or as the owner (parsing schema) of the application.
--
-- NOTE: Calls to apex_application_install override the defaults below.
--
--------------------------------------------------------------------------------
begin
wwv_flow_api.import_begin (
p_version_yyyy_mm_dd=>'[DATE]'
,p_default_workspace_id=>276...332
);
end;
/
prompt WORKSPACE 276...332
--
-- Workspace, User Group, User, and Team Development Export:
-- Date and Time: [DATE_AN_TIME]
-- Exported By: ADMIN
-- Export Type: Workspace Export
-- Version: 5.1.2.00.09
-- Instance ID: 714...698
--
-- Import:
-- Using Instance Administration / Manage Workspaces
-- or
-- Using SQL*Plus as the Oracle user APEX_050100

begin
wwv_flow_api.set_security_group_id(p_security_group_id=>276...332);
end;
/
----------------
-- W O R K S P A C E
-- Creating a workspace will not create database schemas or objects.
-- This API creates only the meta data for this APEX workspace
prompt Creating workspace LEHM...
begin
wwv_flow_fnd_user_api.create_company (
p_id => 276...354
,p_provisioning_company_id => 276...332
,p_short_name => '[SHORT_NAME]'
,p_display_name => '[DISPLAY_NAME]'
,p_first_schema_provisioned => '[SCHEMA_NAME]'
,p_company_schemas => '[SCHEMA_NAMES]'
,p_account_status => 'ASSIGNED'
,p_allow_plsql_editing => 'Y'
,p_allow_app_building_yn => 'Y'
,p_allow_packaged_app_ins_yn => 'Y'
,p_allow_sql_workshop_yn => 'Y'
,p_allow_websheet_dev_yn => 'Y'
,p_allow_team_development_yn => 'Y'
,p_allow_to_be_purged_yn => 'Y'
,p_allow_restful_services_yn => 'Y'
,p_source_identifier => '[IDENTIFIER]'
,p_path_prefix => '[PATH_PREFIX]'
,p_files_version => 1
);
end;
/
----------------
-- G R O U P S
--
prompt Creating Groups...
begin
wwv_flow_api.create_user_groups (
p_id => 927...937,
p_GROUP_NAME => 'OAuth2 Client Developer',
p_SECURITY_GROUP_ID => [ID],
p_GROUP_DESC => 'Users authorized to register OAuth2 Client Applications');
end;
/
begin
wwv_flow_api.create_user_groups (
p_id => 927...936,
p_GROUP_NAME => 'RESTful Services',
p_SECURITY_GROUP_ID => [ID],
p_GROUP_DESC => 'Users authorized to use RESTful Services with this workspace');
end;
/
begin
wwv_flow_api.create_user_groups (
p_id => 927...912,
p_GROUP_NAME => 'SQL Developer',
p_SECURITY_GROUP_ID => [ID],
p_GROUP_DESC => 'Users authorized to use SQL Developer with this workspace');
end;
/
prompt Creating group grants...
----------------
-- U S E R S
-- User repository for use with APEX cookie-based authentication.
--
prompt Creating Users...
begin
wwv_flow_fnd_user_api.create_fnd_user (
p_user_id => '276...332',
p_user_name => 'ADMIN',
p_first_name => '',
p_last_name => '',
p_description => '',
p_email_address => '[MAIL_ADDRESS]',
p_web_password => '[PASSWORD_STRING]',
p_web_password_format => '[PASSWORD_FORMAT]',
p_group_ids => '',
p_developer_privs => 'ADMIN:CREATE:DATA_LOADER:EDIT:HELP:MONITOR:SQL',
p_default_schema => '[SCHEMA_NAME]',
p_account_locked => 'N',
p_account_expiry => to_date('[DATE_AND_TIME]','YYYYMMDDHH24MI'),
p_failed_access_attempts => 0,
p_change_password_on_first_use => 'Y',
p_first_password_use_occurred => 'Y',
p_allow_app_building_yn => 'Y',
p_allow_sql_workshop_yn => 'Y',
p_allow_websheet_dev_yn => 'Y',
p_allow_team_development_yn => 'Y',
p_allow_access_to_schemas => '');
end;
/
[MORE_USER_CREATION_STEPS]
prompt Check Compatibility...
begin
-- This date identifies the minimum version required to import this file.
wwv_flow_team_api.check_version(p_version_yyyy_mm_dd=>'[DATE]');
end;
/

begin wwv_flow.g_import_in_progress := true; wwv_flow.g_user := USER; end; 
/
[SOME_EMPTY_ANONYMOUS_BLOCKS]
begin
wwv_flow_api.import_end(p_auto_install_sup_obj => nvl(wwv_flow_application_install.get_auto_install_sup_obj, false));
commit;
end;
/
set verify on feedback on define on
prompt ...done

Das Problem

An der Stelle, wo der erste User-Account erstellt werden soll, schlägt die Script-Ausführung dann fehl:

ORA-02291: Integritäts-Constraint (APEX_050100.WWV_FLOW_FND_USER_FK) verletzt – übergeordneter Schlüssel nicht gefunden

ORA-06512: in „APEX_050100.WWV_FLOW_FND_USER_INT“, Zeile 2010

ORA-06512: in „APEX_050100.WWV_FLOW_FND_USER_API“, Zeile 328

ORA-06512: in Zeile 2

 

Eine Suche im Oracle Support Portal nach WWV_FLOW_FND_USER_FK liefert (heute am 14.01.2020) exakt Null Ergebnisse – es ist also Eigeninitiative gefragt.
Eine Web-Suche offenbart recht schnell, dass der genannte Foreign Key ein Verweis auf den Workspace ist – was einigermaßen überraschend ist, da der Abschnitt der Workspace-Erstellung aus dem Script mit PL/SQL procedure successfully completed erfolgreich durchgelaufen war.

 

Die Lösung

Auf die Lösung bin ich erst gestoßen als ich im PL/SQL-Developer jeden Schritt einzeln ausgeführt habe. Bereits nach dem ersten Block erkannte der Developer eine aktive offene Transaktion – dies ist an entsprechenden Icons zu erkennen.

Die nachfolgenden Schritte verursachten keinerlei Probleme – bis die erste User Group importiert werden sollte. Hier fiel dann auf, dass dem Developer zufolge die Transaktion verschwand. Und der nachfolgende Import von User Accounts schlug daraufhin mit der bereits beschriebenen Fehlermeldung fehl.

Als ich die User-Group-Erstellung ausließ, funktionierte auch der User-Account-Import wieder problemlos. 😊

Da die User Groups im Rahmen des genannten Projekts nicht weiter verwendet werden, ist die Lösung ausreichend: das Entfernen der Erstellung der User Groups aus dem Workspace-Erstellungs-Scripts.

Die Ursache

Die genaue Ursache lässt sich ohne den entschlüsselten Code des Packages WWV_FLOW_API nur schwer ermitteln – höchstwahrscheinlich fehlt in der Procedure CREATE_USER_GROUPS aber ein RAISE um einen auftretenden Fehler weiterzureichen…

 

APEX-Version 19.1 veröffentlicht

Am 29. März 2019 wurde die angekündigte APEX-Version 19.1 von Joel Kallmann offiziell vorgestellt und zum Download freigegeben.

Gegenüber dem letzten Blog-Eintrag ist vor allem ein weiteres Feature erwähnenswert: Die Möglichkeit Daten aus unterschiedlichen Datei-Formaten direkt zu integrieren.

Deklarativ steht diese Möglichkeit vorerst nur über den SQL Workshop im Data Workshop innerhalb der Utilities zur Verfügung.
Wie genau dieser Prozess ausschaut hat Carsten Czarski in seinem Blog-Eintrag Quick and Easy Data Loading with APEX 19.1 vorgestellt.

Der für das Parsen und den Import verwendete Code steht Entwicklern allerdings auch in Form des Packages APEX_DATA_PARSER zur Verfügung – und kann damit beispielsweise in eigene Applikationsteile integriert werden. Auch für die Nutzung dieses Packages gibt es bereits einen entsprechenden Blog-Beitrag.

Außerdem wurde mittlerweile in einem Statement of Direction ein Ausblick auf die in APEX 19.2 zu erwartenden Features gewährt.

Neben der Erweiterung der neuen Daten-Parser- und -Importe werden vor allem verbesserte Popup LOVs und erweiterte Shared LOVs die Usability für Endanwender erhöhen – und auch die angekündigte Überarbeitung der Filtermöglichkeiten von Reports wird vor allem unter all jenen Applikations Usern Freude verursachen, die SQL nicht oder nur eingeschränkt beherrschen und daher mit den aktuellen Möglichkeiten beispielsweise eines Interactive Reports wenig anfangen können.