Auf der DOAG 2010 hielt Stephan Engel einen Vortrag zum Thema "ApEx effektiv" und zeigt Lösungen für Standardanforderungen mit Köpfchen auf. Application Express (kurz ApEx) ist eine Entwicklungsumgebung für Oracle Datenbanken.
Effiziente Betriebsoptimierung durch Cloud Nutzung
ApEx effektiv - DOAG 2010 - OPITZ CONSULTING - Stephan Engel
1. Stephan Engel OPITZ CONSULTING Bad Homburg GmbH Lösungen für Standard-anforderungen mit Köpfchen DOAG Konferenz 2010, Nürnberg, 17.11.2010 ApEx effektiv
14. Fachliche Fehlermeldungen aus Prozessen Löschen nur mit Sicherheitsabfrage Rückfrage „Daten wurden geändert“ Navigation mit „Zurück“-Buttons Vorgestellte Lösungen
15. Geschäftslogik liegt in PL/SQL vor In dieser Geschäftslogik finden auch Validierungen statt. Schlägt eine Validierung fehl wird typischerweise eine Exceptiongeworfen Ziel: Diese Validierungen soll nur einmal aufgerufen werden und fachliche Meldungen in der Oberfläche angezeigt werden Fachliche Fehlermeldungen aus Prozessen
16. Szenario: Eingabeformular für Projekte Projektname muss eindeutig sein Gesichert durch einen Unique Constraint Default Verhalten: Fachliche Fehlermeldungen aus Prozessen
18. Nachteil der Validierungslösung Performance Code-Redundanzen Aufwand bei der Entwicklung Vorteil Sieht gut aus Ziel: Entwicklung einer Lösung, die Nachteile kompensiert UND gut aussieht Fachliche Fehlermeldungen aus Prozessen
19. Lösungsansatz Fehlermeldungen in Collectionschreiben Bericht auf Seite 0, der aussieht wie Validierungsmeldungen Fachliche Fehlermeldungen aus Prozessen
20. Vorgehen: 1. Neue Collection beim Anmelden an die Anwendung anlegen: Fachliche Fehlermeldungen aus Prozessen
21. 2. Methode zum Schreiben der Fehlermeldungen in die Collectionanlegen: Fachliche Fehlermeldungen aus Prozessen
22. 3. Bericht auf Seite 0 anlegen: Fachliche Fehlermeldungen aus Prozessen
23. 4. Globale Prozesse und Items definieren: Item F101_SHOW_ERRROS Branch definieren, der im Fehlerfall auf der Seite bleibt Prozess anlegen, der die Collection aufräumt Fachliche Fehlermeldungen aus Prozessen
24. 5. Fehler in PL/SQL fangen und loggen: Fachliche Fehlermeldungen aus Prozessen
25. Anforderung: Alle Löschaktionen in der Anwendung sollen mit einer Sicherheitsabfrage bestätigt werden Häufige Umsetzung: javascript:apex.confirm(htmldb_delete_message,'DELETE'); Nachteil: Muss bei jedem Button implementiert werden Löschen mit Sicherheitsabfrage
26. Idee: Einhängen in den Submit-Prozess Generisch auf allen Seiten automatisch eine Delete-Meldung anzeigen, wenn der Request bestimmten Werten entspricht Löschen mit Sicherheitsabfrage
28. Dieser Code kann z. B. auf Seite 0 oder im Template platziert werden Vorteil Seite 0: Verhalten kann z. B. gezielt für bestimmte Seiten mit ApEx-Mitteln ausgeschaltet werden Code ist unabhängig vom gewählten Seitentemplate vorhanden Löschen mit Sicherheitsabfrage
29. Anstelle der Standard JavaScript Dialoge sind in ApEx 4 auch jQueryUI Dialoge functionsubmitOverride(event) { if(apex.jQuery('#pRequest').val().indexOf('DELETE')>-1) { apex.jQuery('#ConfirmDeleteMessage').dialog('open'); } else { this._submit(); } } Löschen mit Sicherheitsabfrage
31. Der hier vorgestellte Mechanismus kann auch für andere Themen benutzt werden z. B.: Änderungen finden nur nach Rückfrage statt, wenn Datensatz bestimmten Status hat Rückfrage kann z. B. lauten:„Daten wurden geändert“ Rückfrage „Daten wurden geändert“
32. Implementierung mit dem Gedanken „Checksumme“ Beim Laden der Seite den Inhalt aller Items in einen String packen Beim Submit prüfen, ob der alte String != Neue String und Request z.B. = „Back“ Wenn ja, dann Meldung anzeigen Vorteil: Funktioniert immer, z. B. auch bei tabellarischen Formularen Rückfrage „Daten wurden geändert“
33. Methode zum Bauen des Strings Item auf Seite 0 anlegen und z.B. mithilfe einer Dynamic Action das Item beim Laden der Seite füllen Rückfrage „Daten wurden geändert“ functioncalculatePageItemsChecksum() { returnapex.jQuery(":input").map(function(){ return (apex.jQuery(this).attr("id")=='pRequest' ||apex.jQuery(this).attr("id")=='P0_PAGE_INPUT_TYPE_CHECKSUM' || apex.jQuery(this).attr("id")==null || apex.jQuery(this).attr("id")=='' )?null:apex.jQuery(this).val(); } ).get().join(","); }; $s('P0_PAGE_INPUT_TYPE_CHECKSUM',calculatePageItemsChecksum());
34. Beim Submit prüfen, ob eine Meldung angezeigt wird Rückfrage „Daten wurden geändert“ if(!(apex.jQuery('#pRequest').val().indexOf('CANCEL')>-1 || apex.jQuery('#pRequest').val().indexOf('SAVE')>-1 || apex.jQuery('#pRequest').val().indexOf('DELETE')>-1) && (apex.jQuery('#P0_PAGE_INPUT_TYPE_CHECKSUM').val() != calculatePageItemsChecksum())) { apex.jQuery('#ConfirmUnsavedChangeMessage').dialog('open'); }
35. In ApEx-Anwendungen wird häufig mit Buttons navigiert Deshalb soll auch der Anwendungsfall „Zurück“ über Buttons implementiert werden Navigation mit „Zurück“-Buttons
36. Lösungsansätze: Javascript: Über die History kann auf die vorherige Seite zurücknavigiert werden. Nachteil: Funktioniert nicht, wenn zweimal auf der gleichen Seiten geblieben wird Mit einem speziellen Item auf den Seiten wird über die Funktion „Branchto Page Identifiedby Item“ auf die Ursprungsseite zurückgesprungen. Nachteil: Komplexere Navigationen sind sehr aufwendig Idee: Mit einer Collection einen Navigationsstack implementieren, bei „Back“ automatisch auf die letze Seite des Stacksnavigieren Navigation mit „Zurück“-Buttons
37. Collection anlegen Prozess anlegen, der die aktuelle Seite auf den Stack legt Muss auf jeder Seite bis auf die Login Seite ausgeführt werden Wenn die oberste Seite auf dem Stack schon die aktuelle Seite ist, dann nichts tun Navigation mit „Zurück“-Buttons APEX_COLLECTION.CREATE_COLLECTION(p_collection_name => 'NAVIGATION_COLLECTION');
38. Navigation mit „Zurück“-Buttons DECLARE v_last_page PLS_INTEGER; BEGIN SELECT c001 INTO v_last_page FROM (SELECT seq_id, c001 FROM apex_collections WHERE collection_name = 'NAVIGATION_COLLECTION' ORDER BY seq_id DESC) WHERE ROWNUM < 2; IF v_last_page != :app_page_id THEN apex_collection.add_member (p_collection_name => 'NAVIGATION_COLLECTION', p_c001 => :app_page_id ); END IF; EXCEPTION WHEN NO_DATA_FOUND THEN apex_collection.add_member (p_collection_name => 'NAVIGATION_COLLECTION', p_c001 => :app_page_id ); END;
39. 3. Prozess anlegen, der auf den „Zurück“-Button reagiert Navigation mit „Zurück“-Buttons DECLARE v_last_page PLS_INTEGER; v_seq_id PLS_INTEGER; BEGIN -- Vorherige Seite vom Stack ermitteln SELECT c001 INTO v_last_page FROM (SELECT seq_id, c001, ROW_NUMBER () OVER (ORDER BY seq_id DESC) seq FROM apex_collections WHERE collection_name = 'NAVIGATION_COLLECTION') WHERE seq = 2; -- Aktuelle Seite vom Stack ermitteln, damit sie gelöscht werden kann SELECT seq_id INTO v_seq_id FROM (SELECT seq_id, c001, ROW_NUMBER () OVER (ORDER BY seq_id DESC) seq FROM apex_collections WHERE collection_name = 'NAVIGATION_COLLECTION') WHERE seq = 1; …
40. Navigation mit „Zurück“-Buttons -- Aktuelle Seite löschen apex_collection.delete_member (p_collection_name => 'NAVIGATION_COLLECTION', p_seq => v_seq_id ); -- Redirect OWA_UTIL.redirect_url ( 'f?p=' || :app_id || ':' || v_last_page || ':' || :app_session ); -- Verarbeitung abbrechen apex_application.g_unrecoverable_error := TRUE; EXCEPTION -- Keine Daten auf dem Stack, kein Redirect. WHEN NO_DATA_FOUND THEN NULL; END;
42. Fazit Die hier vorgestellten Lösungen entlasten den Entwickler von Standardaufgaben, sind generisch im Ansatz und somit wiederverwendbar und erhöhen den Komfort für den Endbenutzer. Daher sollten sie in Erwägung gezogen werden, wenn eine Neuentwicklung mit ApEx begonnen wird!