Alle RPG Programme lassen sich am einfachsten mit meinem Pre-Compiler erstellen, den Sie ebenfalls auf dieser Seite finden.
Dieser Prototyp wird für weitere Programme benötigt und muss in einer Datei QRPGLEH zu finden sein. Alle Prototypen und andere Copystrecken sind in einer eigenen Quelldatei QRPGLEH abgelegt, dies ist an C Konventionen angelehnt und ermöglicht, dass zusammengehörende Quelldateien gleiche Membernamen haben dürfen; die häufiger anzutreffende Variante die Copystrecken dann mit einem H als Suffix zu versehen ist ein Fall für eine Büttenrede auf der Informatiker Fassenacht, insbesondere wenn von den kanppen 10 Buchstaben noch weiter für Prefixe und andere Suffixe vergeudet werden, hier versucht wohl mancher aus der 10 Buchstaben Not eine 5 Buchstaben Tugend zu machen. Ein weiterer gewünschter Nebeneffekt davon ist, dass alle Quellen, die nach Programmquellen aussehen auch wandelbar sind, was die Automatisierung von Compiles vereinfacht.
Eine kurzgefasste Blackbox Beschreibung der Programme und Serviceprogramme
befindet sich oft in den Headerdateien bei den Prototypen. Die
Compileanweisungen befinden sich als Kommentar in den Quellen der
Implementierung und können zur automatischen Erstellung mit dem
Precompiler verwendet werden. Alle Erstellungsbefehle sind in sich
abgeschlossen, es werden keine Binderverzeichnisse und keine Binderquellen
benötigt, alle Objekte werden in die Curlib des umwandelnden Jobs
generiert. Als erstes installiert man sich am Besten den Precompiler und
danach reicht es dann zur Installation einer der Komponenten aus sich die
Quellen komplett per FTP auf seine Maschine zu transferieren, die
Bibliothek mit den Quellen in der Libl und dem PreCompiler nach vorne zu
platzieren, die Installationsbibliothek als Curlib festzulegen und alle
wandelbaren Quellen (alles außer QRPGLEH) über den Precompiler zu
jagen. Auf meiner AS400 (und auf einigen Kundenmaschinen) habe
ich eine PDM Option angelegt, die die Quellen an den PreCompiler übergibt;
wenn man das dann per SBMJOB macht und als Jobnamen den Namen der Quelldatei
vergibt, dann kommt man auch aus dem SEU wie gewohnt an die Wandlungsliste dran.
Folgendes Utilitie stellt einen kleinen Preprozessor dar, der universell
Erstellungsbefehle aus Kommentaren von Quelldateien herauszieht und über C
API system() ausführt. Siehe auch die Erstellungsbefehle in dieser Quelle
selber.
Dieses Tool hat sich bisher eher nach Art eines Virus verbreitet; wenn ich
für einen Kunden Programme schreibe, installiere ich mir mein
kleines Tool und werde meist gebeten es dann nicht zu löschen und es wird
dann weiter verwendet, wechselt einer der Programmierer
den Arbeitsplatz, wandert das Tool dann oft mir zum neuen Arbeitgeber.
Header für ILE Programmerstellungs Utility
Prototyp für API QMHSNDPM zum senden Programm Message
Prototyp für C API system()
ILE Programmerstellungs Utility
Dieses Utility erzeugt aus den Parametern (siehe Header Datei) ein FTP Skript
und führt es im Batch aus. Geschreiben habe ich das mal
als Fingerübung zu Beginn meiner CL ist überflüssig Phase. Wenn
man das Resultat mit den zahlreichen Alternativen vergleicht,
sieht man wie einfach das sein kann. Wenn ich dieses Geschäft ernsthaft zu
betreiben hätte, würde ich die Java Variante vorziehen,
wegen des wesentlich komfortableren Errorhandlings.
Header für Batch FTP Utility
Batch FTP Utility
Dieses Tool dient zur formatierten Anzeige von Journaleinträgen. Per Parameter gibt man die Datei, das Journal und 2 Timestamps zur zeitlichen Auswahl der Journaleinträge, sowie den gewünschten Namen der Ausgabedatei an. Per Programm wird dann eine passende Ausgabedatei erstellt und gefüllt, die die relevanten Felder der Journal Informationen und alle Felder der journalisierten Datei enthält, diese kann dann als Basis zur weiteren Auswertung mit SQL dient. Früher habe ich mir das alles per Hand zurecht gefummelt, aber irgendwann hat es mir gereicht und ich habe mir da was kleines, nettes geschrieben.
Für meine Praxis ist das ein echtes Arbeitspferd, überall wo das
möglich ist - seltsamerweise gibt es immer noch AS400 Installationen
mit echter Journalisierungs Allergie - setze ich (fast) alle produktiv
genutzten Dateien und alle Objekte meiner Testumgebung flächendeckend
unter Journalisierung, bei Fehler Abklärungen und bei Integrationstests
extrahiere ich mir dann alle Journaleinträge nach Dateien getrennt
und kann dann per SQL auswerten was genau von wem geschrieben wurde, welche
Felder wie fortgeschrieben wurden und einiges mehr.
Dieses Tool verbreitet sich meist mit größerer Verzögerung,
zunächst wird mehr oder weniger Kopf schüttelnd verfolgt
was ich da so treibe, dann kommt hin und wieder die Frage könntest Du mal da suchen, vielleicht findest du ja was im Journal und irgendwann hat das Tool dann wieder einen Rechner erobert.
Header für ANZJRN
Header für API system
Header für QMHSNDPM
Quelle ANZJRN
Break Message Handler sind ein kleines Zaubertool für Test und Debug
Zwecke. Hiermit kann man aus einem interaktiven Job eine Auswertung im Batch
erstellen und automatisch wieder interaktiv anzeigen, wenn der Batch fertig
ist, oder sich aus einem Batch Job zur Laufzeit dessen QTEMP geben lassen, oder
sich den LDA in einen Spool drucken lassen und das ganze interaktiv initiiert,
oder sich in einem beliebigen interaktiven Programm zu beliebiger Zeit eine
Command Line innerhalb des Jobs holen, oder auch nur einfach Kollegen damit
ärgern ihren Job fern zu steuern. Gebrauchsanleitung folgt später
einmal, für die, die diese Spielereien nicht kennen.
Break Message Handler
Command für Break Message Handler
In Java kennt man den Begriff Reflection, damit meint man das dynamische
Erzeugen von Objekten deren Klasse man erst zur Laufzeit kennt - also zum
Beispiel aus einer Datei liest. Relative Java Anfänger verwenden diese
Technik häufig beim registrieren des JDBC Treibers mit Class.forName()
ohne sich was dabei zu denken.
Beim gebundenen Aufruf von Prozeduren in ILE, hat man ein ähnliches
Problem zu bewältigen, wie Java: alle Prozeduren müssen zur
Übersetzungszeit bekannt sein. Es sei denn, man kennt die richtigen APIs.
Header für Errorhandling APIs
Header Konstanten Berechtigung
Header für Hilfsfunktion zur Konvertierung Objekttyp
Header für MI Aufruf zum Holen SysPointer auf Objekt
Header für APIs zum dynamischen laden und aufrufen von Prozeduren
Header für Serviceprogramm zum Holen von Procedure Pointer
ServiceProgramm, tauscht Namen gegen Procedure Pointer
Beispiel dynamischer Aufruf gebundener Prozedur aus RPG
Für die Übertragung von Datenbankdaten zwischen der AS/400 und
anderen Datenbanksystemen werden zumeist Workarounds wie Client Access oder RPG
Programme im Verbund mit FTP eingesetzt. Diese Lösungen sind dann instabil
und erfordern zumeist ständigen manuellen Aufwand. Seltener werden
automatische Lösungen eingesetzt, die oft teure Middleware erfordern.
Warum verwendet hierfür eigentlich kaum jemand Java??? Das ist einfach und
schnell programmiert, funktioniert vollautomatisch, alles was man braucht
kostet nichts (oder sagen wir lieber fast nichts), kann jede Datenbank mit
jeder verknoten (oder sagen wir lieber fast jede) und läuft auf jedem
Rechner (oder sagen wir lieber auf fast jedem).
Basisobjekt für Datentransfer, repräsentiert Datei, voll parametrisiert
Einstieg in die Anwendung, wird mit Parameter der Properties aufgerufen
Beispiel Properties für Quelldatei AS/400 mit Toolbox Treiber
Beispiel Properties für Zieldatei AS/400 mit native Treiber
Beispiel CL Programm zum Submit des Java Aufrufs
Prototypen von VECTOR ala Java in RPG
ILE Exit Handler
User Heaps, dynamische Speicherverwaltung ala ILE
Speicher Verarbeitung mit C in RPG
throw Exception mit Escape Message
VECTOR a la Java in ILE RPG implementiert
Diesen kleinen Generator zum erzeugen der /free /end-free Einträge habe
ich als
kleine Fingerübung und als Studie
für einen "richtigen" Generator geschrieben, der mal in meinem Model View
Controller Framework Verwendung finden soll.
Und ausserdem hatte ich keine Lust mehr zum 76. Mal /end-free auf die 17. Art
falsch zu schreiben. Wenn es Ihnen genauso geht...
Header für Main Prototyp von GENFREE
Prototyp für API QMHSNDPM zum senden Programm Message
Prototyp für C API system()
Generator GENFREE zum erzeugen der /free /end-free Eintr�e
Momentan handelt es sich noch um eine Betaversion, die an meine Arbeitsweise
angepasst ist.
Bei mir kommt vor der Programmierung das Design, das heißt, dass ich
zuerst die Exporte eines Moduls festlege, also mit dem
schreiben der Prototypen eines Moduls anfange. Für die Prototypen habe ich
eine eigene Quelldatei, die bei mir QRPGLEH heißt.
Für die Copystrecke mit den Prototypen, die Quelle für das Modul
(und die Copystrecke für die Initialisierung, bei late bind zur
Laufzeit) haben alle denselben Namen.
Nach den Prototypen schreibe ich dann ein Programm, das alle Prozedurexporte als Dummy Implementierung ohne Funktionalität enthält. Und genau das macht nun mein Generator, er generiert mir aus der Copystrecke mit den Prototypen eine Compile fertige Implementierung.
In dem kleinen Beispiel steckt mehr Substanz, als man auf den ersten Blick vermuten mag, zumal mancher sagen mag, das macht V5R2 ja automatisch, da kann man sich Schlüssel vom System generieren lassen.
Voraussetzung für den Einsatz dieses SQL Programms ist, wie für den Einsatz von SQL generell zu empfehlen, die Verwendung von Commit Steuerung. Am einfachsten erreicht man das dadurch, dass man seine Bibliothek mit CREATE SCHEMA erstellt und sich anschließend um Commit nicht mehr kümmert, außer in der Anwendung nach Abschluß einer Transaktion Commit zu sagen oder eben Rollback, falls man es nicht ernst gemeint hat. Um den Rest kümmern sich dann die entsprechenden Voreinstellungen des SQL Umfeldes, die allesamt in Richtung der Verwendung von Transaktionskontrolle gedreht sind.
Zu beachten ist in der Quelle auch, dass sofort ohne lesen geschrieben wird; dieser kleine Trick sorgt dafür, dass keine Sperrprobleme auftreten können, denn DB2 geht mit Satzsperren etwas lax um, was zuweilen zu Verklemmungen führen kann. Mittlerweile wird es die Besucher meiner Web Seite nicht mehr überraschen, daß zur Erstellung der UDF mein kleiner Pre Prozessor CRTCPP verwendet wird.
Verwenden lässt sich der Mechanismus zum generieren der Schlüssel
direkt innerhalb von SQL Anweisungen, also mit:
INSERT INTO KUNDE VALUES(GET_KEY('KUNDE', 'KUNDE_ID'), 'Hugo',
'Hühnerkopf',
....)
SQL User Defined Function
SQL Script für Schlüssel Datei
Seit V4R2 kann die AS400 Java und damit auch komprimieren und dekomprimieren im Standard ZIP Format und immer noch wird Geld verdient - mit unnötigen Tools. Da kann sich unsereins im Midrange Magazin die Finger wund schreiben, dass man für Zip Utilities kein Geld mehr ausgeben muss und immer wieder wird gefragt, wie man komprimieren kann. Java beinhaltet ein kleines Programm jar, mit dem man Zip Files verarbeiten kann und das ist auf allen AS400 fix und fertig installiert.
Falls die Qshell das Hindernis sein sollte, wofür gibt es meine Freeware Seite. Ich habe mich mal hingesetzt und einen kleinen Command geschrieben, der ein kleines CL bedient, das dann den Java Archiver per Qshell bedient und zum Download auf meine Seite gestellt. Den Command wandelt man sich am Besten mit meinem CRTCPP um, ansonsten muss man aufpassen, dass man als Command verarbeitendes Programm ZIPCPP angibt, sonst geht es zwar unheimlich flott, macht aber nichts.
Als aktuelles Verzeichnis wird immer das Benutzer Verzeichnis angenommen, das beim Benutzerprofil eingetragen ist. Beim Zippen kann man ein verzeichnis angeben, dann wird nach Java Art rekursiv nach unten alles gezippt; alternativ kann man auch eine einzelne Datei oder eine Gruppe mit der Wildcard * angeben. Beim Entzippen wird in das aktuelle Verzeichnis alles entpackt. Wer auf den Geschmack kommt und mehr Komfort mag, kann den Command und das CL aufbohren - selbstredend freue ich mich über Feedback und stelle verbesserte Versionen gerne auf meine Freeware Seite.
Ach ja, wenn Ihr Browser nicht so will, wie Sie wollen, weil die Datei für
den Command QCMDSRC.ZIP heißt, mit rechter Maustaste
und speichern unter gehts trotzdem.
Command ZIP zum packen/entpacken
CL als Command Processing Programm für ZIP
Ich hätte eigentlich gedacht, dass das mit den Triggerprogrammen jedem bekannt ist, wie das geht. Es tauchen jedoch immer wieder einmal Fragen zu Triggerprogrammen in Mailinglisten und Newsgroups auf, die einen anderen Eindruck bei mir hinterlassen.
Nun habe ich momentan nicht die Muße und auch andere Schwerpunkte, um einen Artikel (gab es schonmal von mir, 1997 im Midrange Magazin) oder gar ein Tutorial über Triggerprogrammierung zu schreiben und so will ich wenigstens ein Beispiel dazu auf meine Freewareseite stellen. Mein Trigger Generator, den ich mal für eine Datenübernahme geschrieben habe, ist schon ein wenig in die Jahre gekommen und den möchte ich in dieser Form nicht veröffentlichen, aber ich habe wenigstens noch ein vorzeigbares Beispielprogramm gefunden.
Header für ILE RPG Trigger
Beispiel Trigger in ILE RPG
RPG auf der AS400 ist die einzige Programmiersprache der Welt bei der Lese- und Schreibanweisungen mit der Datenbank arbeiten (ja, ich weiss COBOL auch, aber das ist noch so eine Geschichte...); in allen anderen Umgebungen kann man nur mit SQL auf die Datenbank und die elementaren Anweisungen richten sich immer an sequentielle Haufen, die mancher auch Streamfiles nennt. Vor ILE Zeiten kam man nun an diese Dinger aus RPG garnicht ran, seit ILE geht das immerhin mit C APIs. Wer hätte denn bei dem Elan des Silverlake Projektes, seinerzeit bei der Entwicklung der /38 an einen Rckfall ins Zeitalter der sequentiellen Haufen gedacht. Heute ist das natürlich alles ganz anders, da heißt das dann XML, Webservice, Property-File oder heterogene Datenschnittstelle, aber wie auch immer, man muss ran an diese Dinger und wer kann schon C und RPG.
In Java käme keiner auf die Idee derartig komplizierte Schnittstellen anzubieten, wie in C, aber mit der Koexistenz von Java und RPG ist es nicht weit her, auch wenn da die Marketing Jungs und Mädels was anderes erzählen, ich habe jedenfalls in meinem kleinen Open Source Programm versucht ein wenig von der Eleganz von Java in RPG einzubringen, wohl wissend, dass das nur begrenzt gelingen kann, implementiert unter der Verwendung der C APIs. Eine ausführliche Beschreibung des Programmes findet sich im Midrange Magazin.
Header für C function access
Header für Streamfile APIs
Header für ILE RPG OUTSTREAM
Outstream a la Java in ILE RPG
Ich hatte früher mal einen Lehrer, der meine Einwände gegen Hausaufgaben nicht gelten lassen wollte, 'wenn man sie bewältigen kann, sind sie zu leicht', 'wenn sie schwerer sind, bringt sie keiner hin und alle schreiben ab von einem, für den sie zu leicht waren'; sein Hauptargument war, dass man ja beim abschreiben auch was lernt. Habe ich ihm damals nicht geglaubt, glaube ich heute auch noch nicht. Deshalb habe ich auch Beispiele aus meinen aktuelleren Artikeln in Midrange Magazin hier reingestellt.
Wo es einen Outstream gibt, da ist hoffentlich auch ein Instream, sonst hätte man die Daten eigentlich garnicht schreiben brauchen. Wenn der Outstream sich an Java anlehnt, dann wird es nicht überraschen, dass sich der Instream auch an Java anlehnt. Wobei ich an dieser Stelle auch mal schreiben muss, dass RPG bei weitem nicht an Java ranreicht; am meisten nervt mich, dass es die RPG Pseudo Objekte immer nur einmal gibt und wenn ich mir die Klimmzüge anschaue, die manche schlauen Leute da veranstalten - zum Abgewöhnen, oder positiv formuliert: zum Angewöhnen (von Java versteht sich). Eine ausführliche Beschreibung des Programmes findet sich im Midrange Magazin.
Header für Streamfile APIs
Header für ILE RPG INSTREAM
Instream a la Java in ILE RPG
In Java ist es allgemeiner Brauch alles Mögliche an Programmen
konfigurierbar zu machen.
Die Konfigurationen legt man dann einfach in Streamfiles ab, die man mit jedem
Editor pflegen kann.
Es gibt eine allgemein verwendete Syntx für solche Dateien, die aus
wenigen Elementen besteht.
Verwendung von Namens Parametern
qualified names mit Punkt als Trenner
Knast Zeichen als Kommentar
Meine Properties verwenden selbstredend meine Streamfile Service Programme zum verarbeiten der Streamfiles.
Header für Properties
Properties a la Java in ILE RPG
Was sich auf der AS/400 API nennt, nutzt meistens einen UserSpace für die
Ausgabe, was die Handhabung eher verkompliziert als
vereinfacht. RPG Programmierer kopieren dann immer wieder Codestrecken zur
Modifizierung von einer Quelle in die andere, oder programmieren
das extrahieren der Einträge aus dem Userspace immer wieder aufs Neue,
jedesmal ein wenig anders, manchmal richtig, manchmal eben nur
fast. Mir war das alles zu kompliziert und auch lästig, also habe ich
versucht das einmal ordentlich zu machen.
Header für APILIST
Quelle APILIST ServiceProgramm
Header CEE4RAGE
Header QMHSNDPM
Header UserSpace
Am einfachsten sieht man immer an einem Beispiel wie ein ServiceProgramm
verwendet wird. Dieses Beispiel verwendet das API QEZLSGNU, das
interaktive Jobs ausliest.
Quelle TSTAPILIST kleines Testprogramm
Header System
Header für API QEZLSGNU
Hin und wieder braucht man sogenannte Listener, Programme die auf ankommende Events warten. AppServer4RPG braucht das und mich hat es schon immer gestört, dass man das über Workmanagement sicherstellen muss. Einfacher geht das mit einem Unkaputtbaren, der einfach als letzte Aktion ein neues Exemplar von sich selber ins Leben setzt. Technisch geht das über einen sogenannten Exithandler (CEE4RAGE lässt grüßen). Fix und fertig habe ich das in ein kleines Programm (STRNEP) rauszentralisiert.
Selbiges hat dann 4 Parameter: Name des aufzurufenden Programms, Bibliothek des Programms, Name der JOBQ, Bibliothek der JOBQ. Jetzt muss man nur noch eine JOBQ haben, die die Jobs reinlässt. Ich bevorzuge ein eigenes Subsystem für die NEPs mit einer JOBQ, die unbegrenzt reinlässt. Zum schlafen legen fährt man das Subsystem runter und alle NEPs setzen sich beim Ende wieder in die JOBQ rein, sodass sie nach STRSBS bin schon da rufen, deswegen fiel mir da immer der Wettlauf zwischen Hase und Igel ein. Überleben tut das Ganze dann selber PWRDWNSYS *immed, falls das Subsystem aus QSTRUP gestartet wird - und finden tut man das ganze hier:
QRPGLEH.CEE4RAGE
QRPGLEH.SYSTEM
QRPGLEH.QMHSNDPM
QRPGLESRC.STRNEP
Bequem umwandeln kann man sich das dann wieder mit CRTCPP, ebenfalls zu finden in diesem Theater.
Hier sollen später weitere Open Source Programme und Teile enthalten sein!