Fehler und Abbruch-Nachrichten in RPG abzufangen und darauf entsprechend zu reagieren, ist nichts Neues. Wie sieht es jedoch damit aus, aus einem Programm direkt eine Nachricht in das Joblog zu schreiben oder gar gewollt einen Abbruch herbeizuführen? So etwas ging bislang nur mit CL-Befehlen oder mit Hilfe von komplexen System-APIs, wie QMHSNDPM (Send Program Messsage). Mit einem der letzten Technology Refreshes wurde für RPG jedoch ein neuer OpCode SND-MSG bereitgestellt, mit dem sowohl Informations- als auch Abbruch-Nachrichten direkt aus RPG verschickt werden können. Wie das genau funktioniert wird in diesem Artikel gezeigt.
Bevor wir uns den Op-Code SND-MSG im Detail anschauen, noch eine Anmerkung:
Anmerkung: Damit der Op-Code SND-PGM ausgeführt werden kann, ist auf jedem System, auf dem das Programm ausgeführt werden soll ein Laufzeit-PTF (Program Temporary Fix) erforderlich!
OpCode SND-MSG – Nachricht senden
Mit Hilfe des Op-Codes SND-MSG können wahlweise Informations- oder Abbruch-Nachrichten verschickt werden. Der Nachrichtentext kann sowohl direkt (hardcodiert) angegeben werden oder aus einer Nachrichten-Datei ermittelt werden. Des Weiteren kann vorgegeben werden, wohin die Nachricht geschickt wird, d. h. an die aktuelle Prozedur, an die rufende Prozedur oder an irgendeine beliebige Prozedur im Aufrufstapel. Damit hat der OpCode SND-MSG annähernd die gleiche Funktionalität wie das System-API QMHSNDPM.
Der neue Op-Code SND-MSG hat die folgende Syntax:
SND-MSG{(E)} {*INFO | *ESCAPE} MessageText or %MSG(MsgId {: MsgFile …})
{%TARGET (*SELF | *CALLER | ProgramOrProcedure
{: OffsetInProgramStack }) };
OPCode 1: SND-MSG Syntax
Das sieht auf den ersten Blick komplizierter aus als es ist. Zu erwähnen wäre noch, dass in der obigen Syntax alle optionalen Angaben in geschwungenen Klammern { } angegeben wurden. Da nicht immer alle Angaben benötigt werden, ist die endgültige Syntax wesentlich unspektakulärer.
- (E)
Die Erweiterung (E) wird nur dann benötigt, wenn der OpCode SND-MSG einen Fehler zurückbringt und dieser Fehler abgefangen werden soll - *INFO / *ESCAPE
Bei der Angabe von *INFO wird eine Informations-Nachricht in das Joblog geschrieben und die Prozedur/Programm danach weiterausgeführt.
Bei der Angabe von *ESCAPE wird eine Abbruch-Nachricht an die rufende Prozedur geschickt und damit die aktuelle Prozedur bzw. das aktuelle Programm abgebrochen. Die Abbruch-Nachricht wird per Default an die rufende Prozedur geschickt, kann jedoch auch an eine andere beliebige Prozedur, die im Aufrufstapel (Callstack) vorgelagert ist, gesendet werden.
Die Angabe von *INFO/*ESCAPE ist optional.
Wird weder *INFO noch *ESCAPE angegeben, so wird eine Informations-Nachricht (*INFO) ins Joblog geschrieben. - MessageText
Der Nachrichten-Text, der angezeigt werden soll.
Der Nachrichten-Text kann hardcodiert werden oder aber auch in einer Variablen hinterlegt angegeben werden.
Mit diesen Angaben sind wir bereits in der Lage mit dem OpCode SND-PGM Nachrichten zu schicken.
In dem folgenden Beispiel werden zwei Informations-Nachrichten verschickt. Bei dem ersten Aufruf wird lediglich die Variable, die den Nachrichten-Text enthält angegeben. Da weder *INFO noch *ESCAPE angegeben ist, wird eine Informations-Nachricht ausgegeben.
Im zweiten Fall ist *INFO explizit angegeben und der Nachrichten-Text wurde hardcodiert hinterlegt.

Im folgenden Beispiel wird 100 durch eine Variable (DIVIDE) dividiert. Das Ergebnis wird als Informations-Nachricht (*INFO) in das Joblog geschrieben. Bei einer Division durch Null oder einem anderen Fehler wird der Fehler-Text aus der Programm-Status-Datenstruktur als Informations-Nachricht in das Joblog geschrieben.

Bei dem folgenden Beispiel handelt es sich um eine Routine über die SQL-Fehler geprüft und ermittelt werden.
Die Prozedur hat einen optionalen Parameter, über den gesteuert werden kann, ob eine Warnung als Fehler behandelt werden soll oder nicht.
In der Prozedur wird das zuletzt ausgeführte SQL Statement analysisert. Über den SQL-Befehl GET DIAGNOSTICS wird zum einen der Nachrichten-Text und zum anderen der SQLCODE des zuletzt ausgeführten SQL-Statements ermittelt.
Sofern das vorherige SQL-Statement fehlerhaft beendet wurde (LocSQLCODE < 100) oder wenn es eine Warnung (LocSQLCODE > 0 jedoch nicht 100) ausgegeben hat und Warnungen als Fehler behandelt werden sollen, wird der zuvor ermittelte Fehlertext als Abbruch-Nachricht an die rufende Prozedur geschickt.
Wenn ein anderer unerwarteter Fehler auftritt, wird dieser durch die MONITOR-GROUP zunächst abgefangen und dann ebenfalls als Abbruch-Nachricht an die rufende Prozedur geschickt.

Bislang wurden die Message-Texte entweder hardcodiert oder aus einer Variablen oder aus der Programm-Status-Datenstruktur ermittelt. Gerade in mehrsprachigen Anwendungen werden die Nachrichtentexte meist nicht hardcodiert im Quell-Code hinterlegt, sondern aus einer Message-File ermittelt, z. B. mit dem CL-Befehl RTVMSG ermittelt und erst danach ausgegeben.
Built-In-Function %MSG() – Ermitteln Nachrichten Texte aus Message-Files
Mit Hilfe der Built-In-Funktion %MSG() kann der Message-Text, der verschickt werden soll, direkt aus einer Nachrichten-Datei/Message-File ermittelt werden. Eine separate Ermittlung des Message-Textes z. B. über den CL-Befehl RTVMSG ist oder aus dem IBM Service MESSAGE_FILE_DATA ist nicht erforderlich.
Die Built-In-Funktion %MSG() bringt keinen Wert zurück und kann auch nur in Verbindung mit dem OpCode SND-MSG verwendet werden.
Die Syntax für die Built-In-Function %MSG() sieht wie folgt aus:
%MSG (MessageId : MessageFile { : ReplacementText } )
Built-In-Function 1: %MSG() für OpCode SND-MSG
- MessageId
Bei dem ersten Parameter handelt es sich um die 7-stellige Nachrichten-Nr. mit der der Fehlertext in der Message-File abgelegt ist. - MessageFile
Nachrichten-Datei, in der die Fehler-Meldung hinterlegt ist.
Die Nachrichten-Datei kann entweder unqualifiziert (z. B. MYMSGF) oder qualifiziert mit der Bibliothek, in der sich die Nachrichten-Datei befindet (z. B. MYLIB/MYMSGF) oder mit *LIBL (z. B. *LIBL/MYMSGF) angegeben werden. - ReplacementText
In den in Message-Files hinterlegten Nachrichten-Texten können Platzhalter (z. B. &1) hinterlegt sein, die zur Laufzeit durch einen entsprechenden Text ersetzt werden können.
In dem dritten optionalen Parameter können die Texte, die anstelle der Platzhalter ausgegeben werden sollen, übergeben werden.
In dem folgenden Beispiel wird zunächst eine Abbruch-Nachricht gesendet. Der Nachrichten-Text wird aus der Nachrichten-Id BST0001 in der Nachrichten-Datei HRMSGFE in der Bibliothek HSRRRPG ermittelt.
Im Anschluss wird dann basierend auf der aktuell verwendeten Sprache die Nachrichten-Datei, die mit dem gleichen Namen in unterschiedlichen Sprach-Bibliotheken vorhanden ist ermittelt. Beim Senden der Abbruch-Nachricht wird dann der Nachrichten-Text für die Message-Id BST0002 aus der Nachrichten-Datei in der entsprechenden Sprachen-Bibliothek ermittelt.
Zum Schluss wird noch eine Informations-Nachricht geschickt. Der Nachrichten-Text wird wiederum aus der sprachenabhängigen Nachrichten-Datei ermittelt. Die in dem Nachrichten-Text hinterlegten Platzhalter werden durch den Inhalt der Variablen LocReplacement ersetzt.

Built-In-Function %TARGET() – Senden Message an Prozedur
Über die Built-In-Function %TARGET() kann gesteuert werden an welche/s Prozedur/Programm (im CallStack) die Nachricht gesendet werden soll.
Wie die Built-In-Function %MSG() kann die Built-In-Function %TARGET() auch nur in Verbindung mit dem OpCode SND-MSG verwendet werden.
Die Syntax für die Built-In-Function sieht wie folgt aus.
%TARGET (*SELF | *CALLER | ProgramOrProcedure {: OffsetInProgramStack} )
Built-In-Function 2 : %TARGET() für OpCode SND-MSG
Die Angabe der Built-In-Funktion ist optional.
Sofern nicht angegeben, werden Informations-Nachrichten an die aktuelle Prozedur (*SELF) und Abbruch-Nachrichten an die rufende Prozedur (*CALLER) geschickt.
Nun kann es jedoch auch sein, dass die Nachricht an eine bestimmte im Aufrufstapel vorgelagerte Prozedur (z. B. beim Senden aus einem Trigger-Programm and QDBPUT oder QDBUDR) oder vielleicht sogar an eine Prozedur, die vor dieser Prozedur im Aufrufstapel liegt (ebenfalls bei einem Trigger-Programm) gesendet werden soll.
In diesem Fall kann der Name der Prozedur, an die die Nachricht gesendet werden soll als Parameter angegeben werden.
Des Weiteren ist es möglich die Nachricht an der Prozedur im Aufrufstapel vorgelagerte Prozeduren zu senden. Dazu muss ein zweiter Parameter angegeben werden. Bei diesem Parameter handelt es sich um eine positive Zahl, die die Anzahl vorgelagerte Prozeduren angibt.
Anmerkung: Sollte es sich bei der aktuellen Prozedur um eine Main-Prozedur handeln, so ist die rufende Prozedur die Programm-Eingangs-Prozedur (PEP). Sofern die Nachricht an die tatsächlich rufende Prozedur/Programm gesendet werden soll, muss %TARGET(*CALLER: 1) angegeben werden.
In dem folgenden Beispiel wird zunächst eine Abbruch-Nachricht ohne Nachrichten-Text gezielt an das Programm/Prozedur DWCGI geschickt.
Im zweiten Fall wird ebenfalls eine Abbruch-Nachricht geschickt. Da der Aufruf aus der Main-Prozedur eines Programmes erfolgt und an die rufende Prozedur bzw. das rufende Programm gesendet werden soll, wird die Nachricht an die der rufenden Prozedur vorgelagerte Prozedur gesendet.

Built-In-Function 3: SND-MSG mit Built-In-Function %TARGET()
Die Built-Infunktionen %MSG() und %TARGET() können auch gleichzeitig innerhalb des gleichen SND-MSG-Statement angegeben werden.
In dem folgenden Beispiel wird wiederumg eine Abbruch-Nachricht an die der rufenden Prozedur im Aufrufstapel vorgelagerten Prozedur geschickt. Der Message-Text wird bei dieser Nachricht jedoch nicht hardociert, sondern aus der Message-Id BST0003 aus der in der Variablen LocMsgF hinterlegten Message-File ermittelt.

Built-In-Function 4: SND-MSG mit den Built-In-Functions %MSG() und %TARGET()
Soweit zum Versenden von Abbruch- und Informations-Nachrichten hardcodiert oder aus Message-Files an beliebige im Aufrufstapel vorgelagerte Prozeduren.
Und nun viel Spaß beim Verschicken von Informations- und Abbruch-Nachrichten direkt aus RPG-Prozeduren!
Birgitta Hauser ist IBM Champion und Spezialistin für SQL- sowie RPG-Programmierung.
Frau Hauser gibt regelmäßig Workshops im Rahmen der MIDRANGE ACADEMY.
Sie schreibt regelmäßig für MIDRANGE und den TechKnowLetter. Hier erhalten Sie brandneue, tiefe Informationen zu SQL, RPG und vielem mehr.
Der TechKnowLetter erscheint monatlich. Sechs Ausgaben erhalten Sie für 88 Euro hier.