1 Themenübersicht
Dieses Dokument beschreibt die prinzipielle Vorgehensweise zum Ziehen von Nummern für Nummernkreise und Unique Counter über den Nummmernkreismanager.
2 Zielgruppe
Anwendungsentwickler
System-Administratoren
Technische Berater
3 Begriffsbestimmung
Nummernkreismanager
Der Nummernkreismanager ist eine Programmierschnittstelle für Entwickler, die Nummernkreise und Unique Counter in ihren Anwendungen verwenden wollen. Er dient zum Ermitteln der nächsten freien Nummer für einen Nummernkreis oder Unique Counter.
Unique Counter
Ein Unique Counter ist ein Zähler, über den eine Anwendung Identifikationsnummern vom Datentyp long erzeugen kann. Die Verwendung von Unique Countern ist anwendungsspezifisch.
Nummernkreisdienst
Der Nummernkreisdienst zieht Nummern für Nummernkreise und Unique Counter. Er wird vom Nummernkreismanager verwendet und läuft auf dem Message-Server.
Eigenschaft „aufsteigend“
Alle vergebenen Nummern eines Nummernkreises oder Unique Counters werden bzgl. ihrer Ordnung persistent gemacht, d.h. keine größere Nummer ist eher persistent als eine Kleinere bzgl. eines bestimmten Zeitpunktes.
Eigenschaft „lückenlos“
Alle in der Datenbank gespeicherten Nummern eines Nummernkreises oder Unique Counters sind fortlaufend, es gibt keine Lücke. Diese Eigenschaft erfüllt implizit die Eigenschaft „aufsteigend“.
4 Ziehen von Nummern
Der Nummernkreismanager dient zum Ziehen von neuen Nummern für Nummernkreise und Unique-Counter. Zum Ziehen der Nummern verwendet der Nummernkreismanager den Nummernkreisdienst des Message-Servers. Eine Anwendung, welche für einen Nummernkreis bzw. Unique-Counter die nächste freie Nummer ermitteln möchte, verwendet dazu normalerweise den Nummernkreismanager. Der Nummernkreisdienst zieht die Nummern blockweise, dadurch benötigt das Ziehen einer Nummer mit dem Nummernkreismanager meist weder einen Datenbankzugriff noch exklusive Persistenzdienstsperren auf dem Zähler des Nummernkreises.
4.1 Zugriff auf den Nummernkreismanager
Eine Anwendung kann über das Environment auf den Nummernkreismanager zugreifen:
com.cisag.pgm.appserver.CisNumberRangeManager nrm= CisEnvironment.getInstance().getNumberRangeManager();
Das Interface com.cisag.pgm.appserver.CisNumberRangeManager bietet die benötigten Methoden zum Ziehen von Nummern für Nummernkreise und Unique-Counter.
4.2 Nummernkreise
Über den Nummernkreismanager können nur Nummern für Nummernkreise gezogen werden, welche die Eigenschaften „lückenlos“ und „aufsteigend“ nicht erfüllen müssen. Man spricht in diesem Fall auch vom expliziten Nummernziehen. Muss ein Nummernkreis die Eigenschaften lückenlos oder aufsteigend erfüllen, so müssen dessen Nummern implizit vom Persistenzdienst beim Speichern der Business-Object-Instanz gezogen werden. Das implizite Ziehen von Nummern ist im Hilfe-Dokument Persistenzdienst beschrieben.
Über die Methode getNextNumber() kann die nächste freie Nummer für den als Argument übergebenen Nummernkreis ermittelt werden.
Über die Methode getNextDetailNumber() kann die nächste freie Positionsnummer ermittelt werden.
4.3 Unique Counter
Über den Nummernkreismanager können nur Nummern für Unique Counter gezogen werden, welche die Eigenschaften „lückenlos“ und „aufsteigend“ nicht erfüllen müssen. Er bietet aber die Möglichkeit, sicherzustellen, dass ein Unique Counter zu einem bestimmten Zeitpunkt, die Eigenschaft „aufsteigend“ erfüllt. Alle bis zu diesem Zeitpunkt gezogenen Nummern sind dann entweder persistent gemacht oder aber verworfen worden.
Über die Methode getNextUniqueCounter() kann die nächste freie Nummer für die als Argument übergebene Unique Counter-ID ermittelt werden.
Über die Methode getNextUniqueCounterBlock() kann die nächsten n freien Nummern für die als Argument übergebene Unique Counter-ID ermittelt werden.
Über die Methode getLastUniqueCounter() kann die letzte gezogene Nummer für die als Argument übergebene Unique Counter-ID ermittelt werden.
4.3.1 Sicherstellen der Eigenschaft „aufsteigend“
Der Nummernkreismanager verwendet beim Nummernziehen Persistenzdienstsperren, um die Eigenschaft „aufsteigend“ zu ermöglichen. Für jeden Unique Counter gibt es ein unterschiedliches Sperrobjekt, für das die Persistenzdienstsperren angefordert werden. Aus diesem Grund muss, um die Eigenschaft „aufsteigend“ zu gewährleisten, der Aufruf zum Ziehen einer neuen Nummer bzw. eines neuen Nummernblocks innerhalb der Transaktion erfolgen, in der auch die Business Object Instanz mit dem Unique-Counter gespeichert wird.
Durch den Aufruf der Methoden getNextUniqueCounter() oder getNextUniqueCounterBlock() wird eine Lesesperre auf dem Sperrobjekt gehalten. Diese Lesesperre wird implizit aufgehoben, wenn die Top-Level-Transaktion, in der der Aufruf erfolgt ist, beendet wurde. Existiert beim Aufruf der Methoden kein Transaktionskontext, so wird die Lesesperre nur während des Methodenaufrufs gehalten.
Über die Methode getLastUniqueCounter() kann die letzte vergebene Nummer abgefragt werden. Innerhalb der Methode wird in einer eigenen Top-Level-Transaktion eine exklusive Sperre auf dem Sperrobjekt angefordert. Diese wird nur gewährt, wenn keine Lesesperren mehr auf dem Sperrobjekt existieren. Das bedeutet, dass alle gezogenen Nummern verarbeitet worden sein müssen. Bis zur zurückgegebenen Nummer ist somit die Eigenschaft „aufsteigend“ erfüllt, alle kleineren Nummern sind entweder persistent oder stellen Lücken dar. Typischerweise wird ein Verarbeitungsauftrag oder eine Reorganisationsanwendung beim Start auf diese Weise ermitteln, bis zu welcher Nummer die Verarbeitung erfolgen soll.
4.3.2 Sperr-Timeouts
Solange Lesesperren gehalten werden, kann keine exklusive Sperre gewährt werden und dadurch auch nicht zeitlich danach angeforderte Lesesperren. Deswegen sollten die Methoden zum Ziehen von neuen Nummern innerhalb der Top-Level-Transaktion so spät wie möglich aufgerufen werden, damit die Lesesperren möglichst kurz bestehen.
Der Entwickler muss auftretende LockExceptions aufgrund von Sperr-Timeouts behandeln. Eine übliche Vorgehensweise ist, den entsprechenden Aufruf der Methode einige Male zu wiederholen.
4.3.3 Hinzufügen eines neuen Unique Counters
Wenn ein neuer Unique Counter-Typ eingeführt werden soll, muss das ValueSet „com.cisag.app.general.CounterType“ erweitert werden. Die Methode „isValidCounterType()“ der Klasse „com.cisag.app.general.log.NumberRangeLogic“ prüft, ob ein angebender Typ eines Unique Counters, für den eine Nummer gezogen werden soll, gültig ist. Damit der neue Unique Counter-Typ als gültig erkannt wird, muss diese Prüfung adaptiert werden.
Gehen sie dazu folgendermaßen vor:
Legen Sie ein neues Entwicklungsobjekt „Java-Klasse“ an. Damit die entsprechende Java-Klasse vom System verwendet wird, tragen Sie die Klasse „com.cisag.app.general.log.NumberRangeLogic“ bei diesem Entwicklungsobjekt im Feld „Ersetze Java-Klasse“ ein. Die neue Java-Klasse muss von der Klasse „com.cisag.app.general.log.NumberRangeLogic“ ableiten, in der Sie die Methode „adaptableIsValidUniqueCounterType()“ überschreiben. Implementieren Sie in dieser Methode die Prüfung auf den hinzugefügten Unique Counter-Typ. Handelt es sich um einen neuen Typ, muss die Methode „true“ zurückgeben ansonsten „false“. Die Methode „adaptableIsValidUniqueCounterType()“ wird von der Methode „isValidCounterType()“ der Basisklasse für die Typ-Prüfung aufgerufen.
Beispiel:
public class NumberRangeLogicAdapted extends
com.cisag.app.general.log.NumberRangeLogic {
public boolean adaptableIsValidUniqueCounterType(short type) {
switch (type) {
case CounterType.NEW_UNIQUE_COUNTER:
return true;
default:
return false;
}
}
Damit die abgeleitete Klasse vom System verwendet wird, muss diese registriert werden. Diese erfolgt in der Klasse „com.cisag.app.Replacements“. In der Methode „register()“ muss angegeben werden, dass die Klasse „com.cisag.app.general.log.NumberRangeLogic“ durch die abgeleitete Klasse ersetzt wird.
Beispiel:
public static void register(Map replacements) {
…
replacements.put(“com.cisag.app.general.log.NumberRangeLogic”,
“com.<Prefix>.app.general.log.NumberRangeLogicAdapted”);
}
4.4 Der Nummernkreisdienst
Auf dem Message-Server läuft der Nummernkreisdienst, der für die Funktion „Nummerierung“ eines Nummernkreises oder für einen Unique Counter die nächste freie Nummer liefert. Der Dienst selbst zieht die Nummern pro Nummernkreis bzw. Unique Counter blockweise, d.h. es wird ein Nummernblock bestimmt und dessen größte Nummer im jeweiligen Zähler persistent gemacht. Die freien Nummern des Blockes werden im Hauptspeicher gehalten. Aus diesem Kontingent wird bei einer Anfrage nach einer neuen Nummer durch den Nummernkreismanager die kleinste nicht vergebene Nummer zurückgegeben. Durch das Vorhalten eines Nummernvorrats im Hauptspeicher kann eine neue Nummer meist ohne Datenbankzugriff ermittelt werden.
Wird der Message-Server abnormal beendet, sind die im Hauptspeicher gehaltenen noch nicht vergebenen Nummern verloren.
Wird der Message-Server normal heruntergefahren, gehen die noch nicht vergebenen Nummern nicht verloren. Es wird die auf der Datenbank persistent gemachte größte Nummer auf die letzte vergebene Nummer des Blocks im Hauptspeicher korrigiert. Wurde der Zähler des Nummernkreises oder Unique Counters durch andere Logiken außerhalb des Nummernkreisdienstes verändert, können die Nummern nicht zurückgelegt werden.