Freitag, 8. Dezember 2017

Forms 12c, Reports und Weblogic in Docker - nun wirklich lauffähig

Heute möchte ich beschreiben, wie man Forms 12c, Reports und Weblogic in Docker zum Laufen bringt. Das war schon länger ein Wunsch von mir und Dirk Nachbar (http://dirknachbar.blogspot.de) hat dafür großartige Vorarbeit geleistet, unterstützt von Robert Crames (http://robertcrames.blogspot.ch) und Jan-Peter Timmermann (https://jan-peter.me).

Warum denn Docker wird man sich vielleicht fragen? Die einfache Antwort lautet: weil Docker toll ist und man nicht immer wieder eine neue VM mit Forms aufzusetzen braucht. Außerdem sind automatisierte Builds und das Bereitstellen einer Umgebung ohne viele manuelle Aktivitäten einfach besser.

Mein Setup sieht so aus:
  • Laptop mit Windows 7
  • darauf eine VM mit Ubuntu 17.10
  • und in Ubuntu läuft Docker
Die Ubuntu-Maschine und der WLS-Docker Container teilen sich Verzeichnisse, in denen die erstelle WLS-Domäne liegt. So kann direkt von Ubuntu aus die Domäne verändert und konfiguriert werden. Ein paar weitere Vorarbeiten sind noch zu leisten, wie z.B. User oracle und Gruppe oinstall anzulegen. Auf meinem Ubuntu mußten noch die Versionen von docker und docker-compose upgegradet werden, denn die aktuellen Versionen aus dem Software-Repository waren nicht mehr ganz aktuell.


Die Installationsschritte sind im Prinzip genau wie bei einer Installation von Forms/Weblogic auf einem Host. Man braucht im Einzelnen:
  • eine Datenbank für das Repository (entweder Docker oder Host)
  • einen Weblogic im Docker
  • eine Repository Installation
  • eine Forms/Reports Weblogic Domäne

Hier für dieses Beispiel habe ich alles in 2 Docker-Images installiert und bin der Anleitung von Dirk aus seinem Github gefolgt.

1. Aufbau des Datenbank Images (gefordert wird eine Standard oder eine Enterprise Installation für das Repository)
Hierfür habe ich einen Git Clone des offiziellen Oracle Docker Githubs gemacht und mittels ./buildDockerImage.sh -v 12.2.0.1 -e ein Image der Enterprise Edition gebaut.


Nach dem erfolgreichen Erstellen wird dieses Image z.B. hiermit gestartet:
docker run --name oracle12-ee -p 1521:1521 -p 5500:5500 -p 8080:8080 -e ORACLE_PWD=neuesPasswort -v /opt/oracle/oradata:/u01/app/oracle/oradata oracle/database:12.2.0.1-ee

2. Aufbau des Weblogic Images
Dieser Teil beginnt mit dem Git Clone von Dirks Github Repository und hat mehrere Schritte.
Zuerst erfolgt der Build des OracleLinux:latest mit dem Oracle JDK 8u151. Dafür muss man das JDK 8u151 tar.gz in den Ordner OracleJava/java-8 legen und ein
./buildDockerImage.sh machen.

Danach gibt es ein oracle/serverjdk Image. Anschauen kann man sich die vorhandenen Images mit dem Command: docker images


Nun wechselt man ins Verzeichnis OracleFMWInfrastructure/dockerfiles und erstellt ein Weblogic Abbild. Dafür muss man vorher noch bei Oracle die entsprechende Weblogic-Zip-Datei fmw_12.2.1.3.0_infrastructure_Disk1_1of1.zip herunterladen und in OracleFMWInfrastructure/dockerfiles/12.2.1.3 ablegen.
Mit ./buildDockerImage.sh -v 12.2.1.3 wird der Build gestartet und am Ende kommt ein Oracle WebLogic Server Infrastructure 12.2.1.3.0 heraus.


Letzter Abschnitt ist das Erweitern des WLS-Infrastructure Images mit den Forms und Reports Sourcen (Wechsel ins Verzeichnis OracleFormsReports/dockerfiles und Ablage der Installations-Dateien fmw_12.2.1.3.0_fr_linux64.bin und fmw_12.2.1.3.0_fr_linux64-2.zip im Unterordner OracleFormsReports/dockerfiles/12.2.1.3. Mit ./buildDockerImage.sh -v 12.2.1.3 wird der Image-Build gestartet.


Am Ende hat man dann ein Image localhost/oracle/formsreports TAG: 12.2.1.3

3. Jetzt geht es ans Konfigurieren der Domain. Dafür hat Dirk im Verzeichnis OracleFormsReports/samples eine Konfigurationsdatei setenv.sh vorbereitet, die die nötigen Umgebungsvariablen setzt (hier ein Auszug).

Diese Datei muss entsprechend angepasst werden; sehr wichtig sind die Eintragungen im #Repository Connect für den Connect des RCU gegen diese Datenbank. Da bin ich zuerst in eine Falle gelaufen und habe für DC_DB_HOST die falsche IP angegeben, dann hat die Erstellung der Domain nicht funktioniert.
Mit ifconfig auf dem Docker Host gibt es ein Netzwerk namens docker0 und unter der inet stehen sollte eine IP stehen. Diese ist die richtige für den DB Container.

Nun kann mit dem Erzeugen der WLS-Domäne und Start des Admin-Servers begonnen werden (vorher sollte die DB aber gestartet sein). Die Variablen aus setenv.sh werden gemerkt, exportiert und vom docker-compose genutzt.

source ../setenv.sh
docker-compose up -d frfmw; docker logs frfmw -f

Wenn man Ende ein <BEA-000365> <Server state changed to RUNNING.>
steht, ist alles gut verlaufen.

Nun kann im Browser der Enterprise Manager mit der URL http://localhost:7001/em aufgerufen werden.

Hierin können nun die Managed Server MS_FORMS und MS_REPORTS gestartet werden.


Wenn man dann auch noch von der Ubuntu-VM die Ports entsprechend forwarded, kann man im Client im Browser auch die Forms-Testseite aufrufen:
http://localhost:9001/forms/frmservlet


Was kann man noch machen?

Einen zuvor erstellten Reports-Server starten

Da die Konfigurationsdateien der Domain alle in einem Verzeichnis auf dem Docker Host zugänglich sind, kann man sie dort auch bequem bearbeiten und die Änderungen sind persistiert (z.B. default.env, formsweb.cfg, rwserver.conf, httpd.conf und andere).

Man kann auch das neue FADS mit dem Forms 12.2.1.3.0 nutzen, siehe dazu auch ins readme-File von Dirk.

Tja was soll ich sagen, ich bin erstmal sehr begeistert von dieser Variante. Denn nach einem Neustart des Ubuntus kann man die Datenbank und den WLS Admin Server mit 2 einzelnen docker Befehlen wieder starten und die Umgebung ist wieder da. Hier ist es auch von Vorteil, dass die o.g. Herren die ganze Domänen-Erstellung gescriptet haben und man ohne GUI auskommt. Von Oracle gibt es dafür bislang keinen Support, was nicht heißt, dass man es nicht trotzdem machen und versuchen soll.

Viele Grüße
Holger

Donnerstag, 30. November 2017

einen Forms Datenblock mit einer Pipelined Table Function erstellen

Heute wurde ich im Daily Standup im aktuellen Projekt gefragt, ob ich oder einer der Kollegen schon mal einen Forms Datenblock mit einer Pipelined Table Function erstellt habe. Dies habe ich abgefragt und verneint. Und vor kurzem tauchte diese Frage auch schon im Oracle Support Forum auf.

Also habe ich das einfach ausprobiert und kann sagen, es funktioniert. Dieses Vorgehen will ich hier einmal exemplarisch beschreiben. Als Datenquelle dient das gute DB-Schema HR mit den Tabellen Employees und Department.

Zuerst erstelle ich auf der Datenbank ein Package mit einer Pipelined Table Function.


Nach dem Erstellen schaue ich mir einmal das Ergebnis als SQL im SQLDeveloper an für Department 50.


Das funktioniert ja bisher alles ohne Probleme, das Erstellen einer einfachen Forms-Maske dafür ist auch nicht schwer. Erst erstelle ich mir mit dem Wizard basierend auf einer View den Datenblock und das Layout und nachher schalte ich das Ganze auf die Pipelined Table Function in einer Select-From Query um.


Am Ende dann die fertige Maske, die übrigens mit Forms 10g erstell wurde. Es geht also recht einfach, auch neue Features der Datenbank in Forms zu nutzen.


Übrigens kann ich das o.g. Package nicht in Forms erstellen, es muß auf der Datenbank sein. Auch in Forms 12c geht das nicht, da wird die Pipelined Table Function noch nicht von der Engine verstanden. Aber das gehört ja auch eher als API in die Datenbank finde ich.

Ob ich den konstanten Parameter 50 auch noch auf ein referenziertes Item beispielsweise eines anderen Forms-Blocks umbauen kann, habe ich noch nicht probiert. Es scheint aber nicht zu funktionieren, siehe Thread im Forum.

Dort wird als Lösung die Nutzung einer Package-Variable bzw. eines Sys-Kontextes vorgeschlagen:
AND d.deptno = SYS_CONTEXT ('from_clause_context', 'deptno')

Was aber auch geht, ist die Benutzung fester Werte mit Variablen in der Zuweisung.

asQuery_V := 'TABLE(Package.TableFunction('||Variable_1_V||',' ||Variable_2_V||'))';
set_block_property('BLOCK', QUERY_DATA_SOURCE_NAME, asQuery_V);

Viele Grüße
Holger

Samstag, 25. November 2017

Mein persönlicher Rückblick auf die #DOAG2017

Nach 5 jähriger Abstinenz von der DOAG Hauptkonferenz hatte ich endlich wieder das Vergnügen, dieses Jahr vom 20-23.11.2017 dorthin zu können. Die Anreise am Montag verlief leider dank der deutschen Bahn alles andere als glücklich (es gab 90 Minuten Verspätung) und so verpasste ich leider das #ACE Dinner, das Martin Klier angesetzt hatte.


Im Vorfeld schon grob das Veranstaltungsprogramm mit den möglichen Sessions zusammengesucht, war ich ganz gut vorbereitet für den ganzen Marathon an Vorträgen. Dafür aber auch noch ein paar persönliche Gespräche angesetzt, mit ehemaligen Kollegen, mit Forms Gleichgesinnten und besonders mit Michael Ferrante, dem Oracle Forms Product Manager. Mein persönlicher Fokus bestand natürlich hauptsächlich auf Forms, SQL, PL/SQL, APEX, Weblogic und Docker Sessions und meine Erwartungen daran wurden auch erfüllt. Dazu später aber noch mehr.

Der Dienstag stand ganz unter dem Zeichen von Forms Vorträgen, die Kollegen haben mich später gefragt, wo ich denn den ganzen Tag lang war. Meine Antwort: von einer Session zur nächsten. :-) Die Referenten für Forms waren u.a. Mia Urman, Michael Ferrante, Jürgen Menge, Gerd Volberg. Am Abend gab es dann das Forms Community Meeting, das sehr gut besucht war. Dort konnten wir M. Ferrante alle Fragen stellen, die uns run um Oracle Forms beschäftigen. Teilweise sehr interessante Dinge, die hoffentlich noch kommen werden. Eins scheint unumstößlich: selbst Oracle Forms soll es angeblich in die Cloud schaffen.







Das war also der erste Tag, im Rückblick der spannendste für mich von den 3 Veranstaltungstagen. Abends ging es dann mit der DOAG DB Community in der Nürnberger Altstadt zum gemütlichen Ausklang.

Am 2. Tag war ein Tag ohne Forms Vorträge, dafür gibt es ja genug andere Themen. Ganz oft gab es zumindest für mich viele interessante parallele Sessions, da war entscheiden angesagt. Wie immer ein ganz großes Angebot auf der DOAG. Ich meine gehört zu haben, dass die Hälfte aller Einreichungen an Vorträgen abgesagt werden musste.
  • Ausfallsicherheit für den Weblogic Admin Server
  • Goldene Regeln für schlechte Programmierung
  • intelligente Chatbots
  • SQL Magic
  • APEX REST Services in 5.2
  • PL/SQL API 
  • Docker for Dummies
Und schon war der letzte Tag da, der Donnerstag. Das war ein gemischter Tag, den ich mit ein paar Vorträgen und vielen Gesprächen verbracht habe. Highlight des Tages waren u.a. der persönliche Talk mit einem umkomplizierten Michael Ferrante und einem Vortrag von Adam Lukaszewski zum Thema Boost your Forms Development with GIT and Forms API Master. Dabei wurde schon gezeigt, wie man mit Hilfe von Git, dem Forms API Master und dem Mergetool parallel an Forms Objekten entwickeln kann, auch mit mehreren Branches. Das kannte ich so bisher auch noch nicht, denn sonst hieß es ja immer, Mergen von binären Objekten geht nicht.



Was soll ich sagen? Es waren tolle informative Tage in Nürnberg, mit gutem Austausch und neuen Erfahrungen. Neue Türen geöffnet und viele bekannte Gesichter gesehen und gesprochen. Wenn mich jemand fragt, würde ich sagen: es hat sich total gelohnt. Vielen Dank natürlich an die DOAG für die tolle Vorbereitung und Planung und an meinen Arbeitgeber, der mir das ermöglichte. Nächstes Jahr bin ich hoffentlich auch selber wieder mit einem Vortrag dabei. Ganz persönlich fand ich auch die Leute von Oracle sehr angenehm und menschlich. Ein paar Bilder für diesen Beitrag habe ich von anderen Twitteren genommen, ich hoffe das ist ok.

Viele Grüße
Holger

Montag, 3. Juli 2017

Eine kleine aber feine Falle bei boot.properties im Weblogic Server

Diesmal möchte ich über eine kleine aber feine Falle bei der Datei boot.properties im Weblogic Server berichten. Wenn man das Verhalten kennt, wird man darüber sicher schmunzeln.

Im Rahmen der Vorbereitung einer Schulung installieren wir den Weblogic Server inkl. Forms und Reports. Und um den Start zu vereinfachen, gibt es Methoden, eine Datei namens boot.properties zu haben, um ohne Eingabe der Credentials die entsprechenden Managed und Admin Server zu starten.

Das Template für die Datei boot.properties sah so bei uns aus:
Username=weblogic
Password=welcome1 


Sieht doch eigentlich ganz gut aus denkt man. Trotzdem kommt beim Start eines Server das folgende Fenster:


Merkwürdig, genau das wollten wir doch aber vermeiden und uns das Leben erleichtern. Ok, eine Ahnung macht sich im Kopf breit und mal flugs bei Oracle geschaut. Selbst dort ist die Schreibweise lowercase.

Also neuer Versuch mit kleiner Schreibweise:
username=weblogic
password=welcome1



Noch als Zusatzinfo: wir arbeiten auf Windows, da hätte ich nicht mit so einer Eigenart gerechnet. Und wir fragten uns schon, wieso wird die Datei nicht berücksichtigt. Jetzt sind wir wieder etwas schlauer und ich habe direkt zu dem Kollegen gesagt, da wird ein Blog draus.

Viele Grüße
Holger

Dienstag, 27. Juni 2017

Wie verändere ich das Icon meiner Applikation in Forms 12c ?

Heute habe ich die Frage im Oracle Forum gesehen, wie man das Icon einer Applikation in Forms 12c verändert ? Das nehme ich zum Anlass, das Vorgehen etwas genauer zu beschreiben.

 Das es mit Webutil realisiert ist, wird es auch sicher schon in vorherigen Versionen funktionieren. Ich möchte also das Standard-Icon von Java gegen ein rotes Kreuz bei mir austauschen.


Wichtigstes Stück Programmcode ist folgender Aufruf aus der Webutil-Bibliothek:
   WebUtil_SeparateFrame.SetIcon('provision_delete.gif'); 

Das Icon habe ich der Einfachheit halber in einen Ordner kopiert, der von Forms aus direkt erreichbar ist: %MIDDLEWARE_HOME/forms/java%

Damit der ganze Spass auch funktioniert, muß in der Konfiguration separateFrame=true gesetzt sein,
sonst passiert über den obigen Aufruf gar nichts.

Hier der Screenshot ohne Änderung:




Hier der Screenshot mit Änderung:

Sogar in der Taskleiste sieht man die Applikation mit dem geänderten Icon:


Und hier noch die Konfiguration aus der formsweb.cfg für den Standalone Launcher:
[my_webutiltstandalone]
form=my_webutil_demo.fmx
separateFrame=true
WebUtilArchive=frmwebutil.jar,jacob.jar
WebUtilLogging=off
WebUtilLoggingDetail=normal
WebUtilErrorMode=Alert
WebUtilDispatchMonitorInterval=5
WebUtilTrustInternal=true
WebUtilMaxTransferSize=16384
baseSAAfile=webutilsaa.txt
fsalcheck=true
baseSAAfile=basesaa.txt 

So viel für heute, viel Spass beim Ausprobieren wünscht
Holger

Freitag, 28. April 2017

Forms 12c und FRM-91135 auf Linux - wenn der Forms Builder nicht aufgeht

Hallo zusammen,

heute möchte ich über die Lösung des Incidents FRM-91135 auf Linux berichten. Die komplette Weblogic Suite inkl. Forms und Reports ist installiert und läuft. Nur der Forms Builder geht nicht auf und sagt frech:

FRM-91135: fatal error: message file FMC <language> .msb not found

Das Thema hatte ein Kollege auch neulich von mir, aber auch noch nichts gefunden. Und was ist der einfache Grund? Das Oracle Home ist nicht richtig gesetzt. Das kommt daher, dass auf der gleichen VM noch die Datenbank für das Repository installiert ist.

Vorher ist das ORACLE_HOME: ORACLE_HOME=/u01/app/oracle/product/12.2/db_1

Also setzen wir das ORACLE_HOME doch mal richtig:
export ORACLE_HOME=/home/oracle/Oracle/Middleware/Oracle_Home

und dann rufen wir den Forms Builder auf im Ordner: /home/oracle/user_projects/domains/forms_domain/config/fmwconfig/components/FORMS/instances/forms1/bin

./frmbld.sh &



Ja prima und dann funktioniert es endlich, wie schön.

Viele Grüße
Holger

Montag, 20. März 2017

Forms - mit PL/SQL alle Datensätze eines Blocks in eine PL/SQL-Tabelle laden

Während meines jetzigen Projektes hatte ich schon öfter folgende Aufgabe zu lösen: wie bekomme ich denn alle Records eines Datenblocks in eine PL/SQL-Tabelle ? Um damit z.B. andere Berechnungen durchzuführen, Plausibilitäten darüber laufen zu lassen oder andere Listen zu füllen.

Nachdem ich das ein paar Mal gemacht habe, wollte ich mein Vorgehen dabei zum Besten geben.
Wenn man den gesamten Code noch in ein Forms-Package steckt, ist die PL/SQL-Tabelle auch von anderen Codestellen anzusprechen und zu benutzen.

Dafür bastel ich mehr zu allererst einen Record, mit allen Feldern, die ich brauche und darauf basierend eine PL/SQL-Tabelle und eine konkrete Instanz der entsprechenden Speicherstruktur:

   TYPE mein_Record_T IS RECORD (
    Feld1         VARCHAR2(250),
    Feld2         NUMBER := 0,
    Feld3         VARCHAR2(5)
    );

TYPE meine_PLSQLTabelle_T IS TABLE OF mein_Record_T INDEX BY PLS_INTEGER;

meineKonkrete_PLSQLTabelle meine_PLSQLTabelle_T;

Und nun kann ich alle Datensätze des Blocks durchlaufen und in der Objekt-Struktur abspeichern:

  PROCEDURE Fuelle_meine_PLSQLTabelle(meinBlock_I IN VARCHAR2) IS
    meinIndex_V              NUMBER;
  BEGIN
    GO_BLOCK(meinBlock_I);
    FIRST_RECORD;
    LOOP
      meinIndex_V := meineKonkrete_PLSQLTabelle.COUNT;
    
      IF TRIM(NAME_IN(meinBlock_I || '.Feld1')) IS NOT NULL THEN
        meineKonkrete_PLSQLTabelle(meinIndex_V).Feld1 := NAME_IN(meinBlock_I || '.Feld1');
        meineKonkrete_PLSQLTabelle(meinIndex_V).Feld2 := NAME_IN(meinBlock_I || '.Feld2');
        meineKonkrete_PLSQLTabelle(meinIndex_V).Feld3 := NAME_IN(meinBlock_I || '.Feld3');
      END IF;
      
      EXIT WHEN :SYSTEM.LAST_RECORD = 'TRUE';
      NEXT_RECORD;
    END LOOP;     
  END Fuelle_meine_PLSQLTabelle;

Dieses Konstrukt konnte ich nun schon ein paar Mal gebrauchen, um mir das Leben mit Daten aus den Datenblöcken zu vereinfachen. Denn ich musste immer alle Daten haben, um damit z.B. andere Daten bewerten zu können. Wenn natürlich die Datenblöcke viele Daten enthalten, dauert der ganze Fetch entsprechend länger. Davon ist meine Maske aber nicht betroffen, und so helfen diese paar Zeilen Code mir ungemein.

Schöne Grüße
Holger