1 Themenübersicht
Hooks sind eine Schnittstellentechnologie in Comarch ERP Enterprise, mit denen vorhandener Programmcode releasesicher und konfliktfrei erweitert werden kann. Hooks werden beispielsweise verwendet, wenn in einer Anpassung oder App, die den Standardcode erweitert, für eine Business-Object-Erweiterung zusätzliche fachliche Prüfungen durchgeführt werden müssen, die die im Standard vorhandenen Prüfungen ergänzen.
Im Gegensatz zu den Replacements kann vorhandener Programmcode durch Hooks mehrmals voneinander unabhängig erweitert werden.
Dieses Dokument beschreibt die Funktionsweise von Hooks und die Nutzung von Hooks im Java-Code.
2 Zielgruppe
- Entwickler
3 Beschreibung
3.1 Funktionsweise von Hooks
Hooks sind Schnittstellen zwischen einem Hook-Anbieter und Hook-Verwendern. Der Hook-Anbieter definiert Methoden in einem Java-Interface (Hook), die er in bestimmten Situationen aufruft. Ein Hook-Verwender implementiert die benötigten Hooks.
Beispiel:
Um eine fachliche Prüfung mittels Hooks erweiterbar zu machen, definiert der Hook-Anbieter eine Methode
void validateUpdate(…)
und ruft diese Hook-Methode zusätzlich zu der vorhandenen fachlichen Prüfung auf.
Der Hook-Verwender stellt eine Methodenimplementierung bereit. In der Methodenimplementierung führt der Hook-Verwender die Prüfungen durch und sendet im Fehlerfall Meldungen an die Programm-Message-Queue.
Über Parameter der Hook-Methode stellt der Hook-Anbieter Daten als Teil der Schnittstelle der Implementierung zur Verfügung.
Durch die Aufrufrichtung vom Hook-Anbieter zum Hook-Verwender verbleibt die Ablaufsteuerung beim Hook-Anbieter. Hook-Implementierungen können nur im Rahmen der definierten Schnittstelle Einfluss auf den Hook-Anbieter nehmen.
Beispiel:
Wenn der Hook-Verwender in der Methode validateUpdate() eine Fehlermeldung an die Programm-Message-Queue sendet, wird dies das Speichern des Objekts verhindern. Der Hook-Verwender kann jedoch nicht andere Prüfungen unterdrücken oder andere Aktionen für das Business Entity ausführen, weil der Hook hierzu keine Möglichkeit bietet.
Ein Hook kann mehrfach implementiert werden, so dass im Beispiel in einer weiteren App ebenfalls eine Prüfung für das Business Entity erstellt werden kann.
Die verfügbaren Hooks und die Hook-Implementierungen sind in eigenen Entwicklungsobjekten hinterlegt: Eine Hook-Contract-Definition enthält angebotene Hooks, während in einer Hook-Contract-Implementierung die implementierten Hooks aufgeführt sind.
3.2 Entwicklungsobjekte der Hook-Infrastruktur
3.2.1 Hook-Contract-Definitionen und Hook-Contract-Implementierungen
3.2.1.1 Hook-Contract-Definitionen
Eine Hook-Contract-Definition enthält zusammengehörige Hooks, z.B. alle Hooks auf Business-Entity-Ebene eines bestimmten Business Entitys. Hooks aus der Logik- und der Dialogschicht für dasselbe Business Entity sollten jedoch in getrennten Hook-Contract-Definitionen enthalten sein.
Erst durch eine Hook-Contract-Definition sind die Hooks zur Implementierung freigegeben.
Hook-Contract-Definitionen sind Entwicklungsobjekte des Typs „Hook Contract“, Subtyp „Hook-Contract-Definition“ (XML: HOOK_DEFINITION). Es handelt sich um einen XML-Entwicklungsobjekttypen. Die genaue Beschreibung der XML-Elemente ist in der Dokumentation „Entwicklungsobjekte“ enthalten.
Beispiel einer Hook-Contract-Definition, die einen zustandsbehafteten Hook (HookState) und einen zustandslosen Hook frei gibt:
<?xml version=”1.0″ encoding=”UTF-8″?>
<HookContract xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:noNamespaceSchemaLocation=”HookXMLSchema.xsd”>
<HOOK_DEFINITION>
<contextClass>com.cisag.app.general.log.CountryEntity
</contextClass>
<hookState>
<interface>com.cisag.app.general.hook.log.SingleObjectEntityState
</interface>
</hookState>
<hook>
<interface>com.cisag.app.general.hook.log.SingleObjectValidateUpdateHook
</interface>
</hook>
</HOOK_DEFINITION>
</HookContract>
Die Kontextklasse (contextClass) dient der Identifikation der Hook-Contract-Definition aus dem Java-Code des Hook-Anbieters heraus. Es sollte diejenige Klasse verwendet werden, deren Verhalten durch den Hook erweiterbar ist.
Ein Hook kann auch in mehreren Hook-Contract-Definitionen freigegeben werden. Eine Implementierung des Hooks bezieht sich immer auf eine Hook-Contract-Definition. Beispielsweise werden für die Logik-Ebene von SingleObjectEntitys häufig dieselben Hooks verwendet. Eine Hook-Contract-Definition gilt jedoch jeweils für ein SingleObjectEntity.
3.2.1.2 Hook-Contract-Implementierungen
Um einen Hook zu implementieren, ist neben der Hook-Implementierung (Java-Klasse) auch eine Hook-Contract-Implementierung nötig. In der Hook-Contract-Implementierung werden alle zu implementierenden Hooks und die jeweilige Implementierungsklasse angegeben.
Für eine Hook-Contract-Implementierung kann eine beliebige Untermenge der angebotenen Hooks implementiert werden. Es ist also nicht erforderlich, alle Hooks zu implementieren.
Eine Hook-Contract-Implementierung ist ein Entwicklungsobjekt vom Typ „Hook Contract“, Subtyp „Hook-Contract-Implementierung“ (XML: „HOOK_IMPLEMENTATION“). Folgendes Beispiel implementiert beide Hooks aus obiger Hook-Contract-Definition:
<?xml version=”1.0″ encoding=”UTF-8″?>
<HookContract xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:noNamespaceSchemaLocation=”HookXMLSchema.xsd”>
<HOOK_IMPLEMENTATION>
<contract>com.cisag.app.general.hook.log.Country</contract>
<hookState>
<interface>com.cisag.app.general.hook.log.SingleObjectEntityState
</interface>
<implementation>com.ado.ext.app.example.general.log.CountryHookState
</implementation>
</hookState>
<hook>
<interface>
com.cisag.app.general.hook.log.SingleObjectValidateUpdateHook
</interface>
<implementation>
com.ado.ext.app.example.general.log.CountryHookImplementation
</implementation>
</hook>
</HOOK_IMPLEMENTATION>
</HookContract>
Eine Hook-Contract-Implementierung implementiert immer genau eine Hook-Contract-Definition. Müssen für eine Aufgabenstellung verschiedene Hook-Contract-Definitionen implementiert werden, ist hierzu jeweils eine eigene Hook-Contract-Implementierung erforderlich.
Für mehrfache Implementierungen gibt es folgende Regeln:
- In einer Hook-Contract-Implementierung kann derselbe Hook mehrmals implementiert werden. Dies ist jedoch nur in speziellen Fällen sinnvoll, beispielsweise wenn verschiedene Hook-Einschränkungen benötigt werden.
- In einer Adaptierung oder App ist es möglich, mehrere Hook-Contract-Implementierungen zur selben Hook-Contract-Definition zu erfassen. Sinnvoll ist dies jedoch nur, um die Entwicklungsobjekte innerhalb einer größeren Adaptierung bzw. App zu untergliedern.
- Ein zustandsbehafteter Hook aus einer Hook-Contract-Definition kann in einer Adaptierung (ein Entwicklungspräfix) oder einer App jedoch nur einmal implementiert werden. Falls es weitere Hook-Contract-Implementierungen der Hook-Contract-Definition gibt, steht die Implementierung des zustandsbehafteten Hooks auch dort zur Verfügung (entsprechender Methodenparameter vorausgesetzt).
3.2.1.3 Erweiterbarkeit von Hook-Contract-Definitionen
Eine veröffentlichte Hook-Contract-Definition kann nur dadurch erweitert werden, dass neue Hooks eingeführt werden. Bestehende Hooks dürfen nicht nachträglich verändert werden, d.h. es dürfen weder Methoden verändert, gelöscht oder neu hinzugefügt werden.
Hinweis:
Ein Hook darf auch dann nicht aus Hook-Contract-Definitionen entfernt werden, wenn sich seine Schnittstelle als unvollständig oder fehlerhaft erwiesen hat. Alle vorhandenen Aufrufstellen müssen erhalten bleiben (Ausnahmen siehe Deprecated unten).
Hook-Contract-Definitionen sollten in diesem Fall durch einen neuen Hook ergänzt werden. Das Java-Interface des neuen Hooks darf dabei jedoch nicht vom alten Hook erben, noch darf er Methoden des alten Hooks duplizieren. Falls notwendig, können Hook-Implementierungen gleichzeitig Methoden des alten und des neuen Hooks verwenden.
Deprecated-Markierungen sind an Hook-Contract-Definitionen („Abgelehnt“-Markierung am Entwicklungsobjekt) und Hooks (@Deprecated-Annotation im Javacode) möglich. Die Entwicklungsobjekte können dann im übernächsten Release gelöscht werden. Deprecated-Markierungen sollten für Hook-Contract-Definitionen, Hooks und HookStates jedoch die Ausnahme bleiben, da sie die Release-Sicherheit beeinträchtigen.
3.2.2 Hooks
Hooks sind Java-Interfaces in Namensräumen des Hook-Anbieters. Es gibt zustandslose und zustandsbehaftete Hooks.
Ein Hook wird in einer Java-Klasse implementiert, die selbst das Hook-Interface implementiert. Jede Hook-Implementierung muss in einer Hook-Contract-Implementierung aufgeführt sein.
3.2.2.1 Zustandslose Hooks
Zustandslose Hooks enthalten die Hook-Methoden, die durch den Hook-Anbieter in bestimmten Situationen aufgerufen werden. Zustandslose Hooks erweitern das Interface com.cisag.pgm.base.Hook.
Implementierungen müssen CisFactory-Singletons sein und einen Default-Konstruktor besitzen. Ihre Lebensdauer ist in der Regel kurz. Sie werden durch die System-Engine erzeugt, sobald der Hook-Anbieter entsprechende Methoden am CisHookManager aufruft.
Es ist möglich, mehrere Hooks in derselben Java-Klasse zu implementieren.
Aufrufreihenfolge
Ein Hook kann mehrfach implementiert werden. Hook-Methoden werden in der Regel auf allen Implementierungen nacheinander aufgerufen, es sei denn, dies ist beim Hook anders vorgesehen.
Die Aufrufreihenfolge wird durch die System Engine bestimmt, und kann durch die Hook-Implementierungen nicht beeinflusst werden. Es ist keine Aufrufreihenfolge für die Hook-Implementierungen definiert. Aus diesem Grund dürfen verschiedene Implementierungen derselben Hook-Methode nicht voneinander abhängig sein.
Methodenparameter
Die Parameter von Hook-Methoden sind Teil der Schnittstelle. Daten des Hook-Anbieters, auf die die Hook-Implementierung Zugriff erhalten sollen, werden als Parameter übergeben.
Folgende zwei Parameter werden von sehr vielen Hook-Methoden bereitgestellt:
- Eine Objektsicht kapselt die Daten des Business Entitys. Bestimmte interne Daten sind in einer Objektsicht möglicherweise nicht enthalten. Objektsichten sind entweder nur lesbar, eingeschränkt schreibbar, oder uneingeschränkt schreibbar. In einer eingeschränkt schreibbaren Objektsicht sind nur die Attribute aus Business Entity Extensions mit dem eigenen Entwicklungspräfix schreibbar.
- Eine Instanz eines zustandsbehafteten Hooks
Isolierung der Programm-Message-Queue
Jede Hook-Implementierung wird innerhalb eines Methodenaufrufs von Meldungen anderer Implementierungen desselben Hooks isoliert. Das bedeutet, dass Meldungen anderer Hooks, und auch des Hook-Anbieters selbst, innerhalb der Hook-Implementierung nicht sichtbar sind. Diese Isolierung erfolgt automatisch durch die System Engine.
Exceptions in Hook-Methoden
Hook-Methoden dürfen keine Exceptions in ihrer Schnittstelle vorsehen. Exceptions dürfen nur im Falle von Programmierfehlern die Hook-Implementierung verlassen. Im Falle einer Exception wird der Aufruf aller Hook-Implementierungen für denselben Hook-Aufruf abgebrochen.
Hook-Einschränkungen
Zustandslose Hooks können mit einer Hook-Einschränkung versehen werden. Durch die Hook-Einschränkung wird der Aufruf einer Hook-Implementierung an zusätzliche Bedingungen geknüpft. Beim Aufruf eines Hooks gibt der Hook-Anbieter bestimmte Entwicklungsobjekte als Hook-Einschränkung an, und die Hook-Infrastruktur wählt nur diejenigen Hook-Implementierungen zum Aufruf aus, die dieselben Entwicklungsobjekte als Hook-Einschränkung verwenden. Als Entwicklungsobjekte können Java-Klassen, Business Objects, logische Datentypen, Objektsichten und Anwendungen verwendet werden.
Die Hook-Einschränkung wird im XML der Hook-Contract-Definition und der Hook-Contract-Implementierung am einzuschränkenden Hook angegeben. In der Hook-Contract-Definition werden für jedes Entwicklungsobjekt der Typ und eine ID angegeben:
<hook>
…
<interface>…</interface>
<restriction>
<businessObject id=”objectClass”/>
</restriction>
In der Hook-Contract-Implementierung muss nun das Business Object selbst angegeben werden:
<hook>
…
<interface>…</interface>
<restriction>
<businessObject id=”objectClass”>
com.cisag.app.production.obj.ProductionItem
</businessObject>
</restriction>
<implementation>…</implementation>
Die so ausgezeichnete Hook-Implementierung wird nur aufgerufen, wenn der Hook-Anbieter beim Aufruf dasselbe Business Object angibt.
Hook-Einschränkungen sind besonders in Hook-Contract-Definitionen nützlich, die für mehrere Business Entitys gelten. Ein Beispiel hierfür sind die BIS-Hooks.
Weitere Informationen zur Überprüfung von Restriktionen finden Sie im Kapitel „Hinweise zur Entwicklung“.
XML-Syntax:
Definition einer Einzel-Restriktion in der Hook-Contract-Definition:
<Restriktionstyp id=“Bezeichner“ [optional=“boolean“]/>
Als Restriktionstypen sind zulässig:
- javaClass für Java-Klassen
- dataView für Objektsichten
- businessObject für Business Objekte
- logicalDatatype für logische Datentypen
- application für Anwendungen
Der Bezeichner muss innerhalb des Restriktionsblocks eindeutig sein.
Das Attribut optional ist ab Release 5.2 verfügbar und kennzeichnet, ob diese Restriktion optional ist (true) oder nicht (false). Wird es nicht angegeben, ist die Restriktion als Default erforderlich.
Definition einer Einzel-Restriktion in der Hook-Contract-Implementierung:
<Restriktionstyp id=“Bezeichner“>
Name des Entwicklungsobjekts
</Restriktionstyp>
Statt eines konkreten Entwicklungsobjekts kann auch die Wildcard „*“ verwendet werden, weitere Informationen dazu im Kapitel „Hinweise zur Entwicklung“.
Implementierungen
Folgendes Beispiel zeigt eine Implementierung eines Hooks mit Zugriff auf einen zustandsbehafteten Hook, den die Objektsicht bereitstellt.
Die Implementierungen des zustandslosen Hooks, HookImpl, und des zustandsbehafteten Hooks, StateImpl, sind in derselben Adaptierung bzw. in derselben App implementiert. Durch die Hilfsmethode getState() erhält die Hook-Implementierung „ihre“ Implementierung des zustandsbehafteten Hook.
public class HookImpl implements SingleObjectValidateUpdateHook {
private final CisHookManager hm = CisEnvironment.
getInstance().getHookManager();
@Override
public void validateUpdate( CountryView view) {
CountryHookStateImpl hookState = hm.getState(
view.getHookState(), CountryHookStateImpl.class);
// method implementation
}
}
Generics
Hooks, die in mehreren Hook-Contract-Definitionen verwendet werden, geben oft Objektsichten als Generic-Parameter an, um vom konkreten Business Entity einer Hook-Contract-Definition abstrahieren zu können. In einer Implementierung dieses Hooks sollten diese Generics-Parameter auf die der Hook-Contract-Definition entsprechende Objektsicht instanziiert werden.
Beispiel: Von der Hook-Contract-Definition „Country“ wird folgender Hook angeboten:
interface SingleObjectValidateUpdateHook<V extends DataView<?>>
Da der Hook auch in anderen Hook-Contract-Definitionen verwendet wird, ist statt CountryView nur DataView<?> angegeben. In einer Hook-Contract_Implementierung für die Hook-Contract-Definition „Country” sollte nun „CountryView“ angegeben werden.
public class CountryHookImplementation implements
SingleObjectValidateUpdateHook<CountryView>
3.2.2.2 Zustandsbehaftete Hooks
Zustandsbehaftete Hooks (HookState) geben Hook-Verwendern die Möglichkeit, einen Zustand zwischen mehreren Hook-Aufrufen zu halten. Beispielsweise können Daten eines Dependent, oder ein sonstiger Anwendungszustand im HookState gehalten werden. Zustandsbehaftete Hooks erweitern das Interface com.cisag.pgm.base.HookState.
Meist haben zustandsbehaftete Hooks keine Methoden, sondern sie stehen in den Methoden von zustandslosen Hooks, in der dies vorgesehen ist, zur Verfügung. Dafür ist der zustandsbehaftete Hook in der Regel in einer Objektsicht enthalten.
Zustandsbehaftete Hooks haben einen definierten Lebenszyklus. Die Implementierungen werden durch die System-Engine erzeugt und vom Hook-Anbieter verwaltet. Ebenso hängt vom Hook-Anbieter ab, wie viele Objekte einer Implementierungsklasse tatsächlich erzeugt werden. Für eine Dialog-Anwendung wird je Anwendungsinstanz ein eigenes HookState-Objekt erzeugt.
Falls ein zustandsbehafteter Hook Methoden deklariert, gilt für sie dasselbe wie für Hook-Methoden. Wenn die Methode
void clone()
deklariert ist, muss ihre Implementierung eine Kopie des HookState erzeugen.
Implementierungen
HookStates müssen aufgrund ihres Lebenszyklus immer in einer eigenen Java-Klasse implementiert werden. Das HookState-Interface enthält üblicherweise keine Attribute und Methoden, und der Hook-Verwender kann beliebig Attribute und Methoden definieren, wie im folgenden Beispiel:
public class StateImpl implements AHookState {
private String s;
public StateImpl() {
// may initialize attributes
}
public String someMethod() {
// …
}
}
Jede HookState-Implementierung muss einen Default-Konstruktor besitzen.
3.2.2.3 Zentrale Hook-Interfaces
Hook-Interfaces, die von vielen Hook-Contract-Definitionen verwendet werden, z.B. von Business Entitys, die die SingleObjectEntity-Infrastruktur nutzen, sind in folgenden Namensräumen enthalten:
com.cisag.app.general.hook.log (für Logik-Hooks)
com.cisag.app.general.hook.ui (für Hooks der Dialogoberfläche)
3.2.2.4 Hook-Basisklassen
Ein Hook kann zusätzlich zu seinem Java-Interface eine abstrakte Basisklasse enthalten. Hook-Implementierungen können dann nach eigener Wahl auch von der Basisklasse ableiten, anstatt das Java-Interface direkt zu implementieren. Die Basisklasse ermöglicht Hook-Implementierungen nur einen Teil der Hook-Methoden implementieren zu müssen.
Wenn eine Basisklasse existiert, ist sie im Java-Interface als innere Klasse mit dem Namen „Base“ definiert.
3.3 CisHookManager
Der Aufruf von Hooks erfolgt im Java-Code des Hook-Anbieters durch die PGM-Schnittstelle CisHookManager.
Der CisHookManager verwendet Hook-Container, um den Hook-Anbieter von der Anzahl der konkret vorhandenen Hook-Implementierungen zu entkoppeln. Ein Zugriff auf einzelne Hook-Implementierungen ist jedoch auch möglich.
3.3.1 Aufruf von Hook-Methoden
Hook-Methoden können entweder am Hook-Container oder direkt auf den Hook-Implementierungen aufgerufen werden. Der Hook-Container ist ein Java-Proxy und implementiert auf diese Weise das jeweilige Hook-Interface.
Ein Aufruf am Hook-Container führt automatisch zum Aufruf aller Implementierungen. Der Aufruf am Hook-Container ist nur möglich, wenn die Hook-Methode den Rückgabetyp void verwendet.
Folgendes Beispiel zeigt den Container-Aufruf, wobei hm der CisHookManager, contextClass die Kontextklasse der aufzurufenden Hook-Contract-Definition ist, und als Hook-Parameter dataView (Objektsicht) verwendet wird.
SingleObjectValidateUpdateHook hook =hm.getHookContainer(
contextClass, SingleObjectValidateUpdateHook.class);
hook.validateUpdate(dataView);
Derselbe Hook-Aufruf als Aufruf aller Implementierungen sieht wie folgt aus:
for (SingleObjectValidateUpdateHook hook :
hm.getHookImplementations(contextClass,
SingleObjectValidateUpdateHook.class)) {
hook.validateUpdate(dataView);
}
Für Hook-Methoden mit anderen Rückgabetypen als void muss das untere Beispiel um eine Kombination der Rückgabewerte ergänzt werden.
Erfordert der Hook Restriktionen, so sind diese als zusätzlicher Parameter in den Methoden hm.getHookContainer bzw. hm.getHookImplementations anzugeben:
HookRestriction res = HookRestriction.create
(HookRestriction.restrictBusinessObject(“object”,
com.cisag.app.general.obj.Partner.class),
HookRestriction.restrictDataView(“view”,
PurchaseContractDetailView.class));
SingleObjectValidateUpdateHook hook =hm.getHookContainer(
contextClass, res, SingleObjectValidateUpdateHook.class);
Es gibt spezielle Hooks (Strategien, ActionHooks), für die Hook-Methoden nur auf bestimmten, aber nicht allen Implementierungen aufgerufen werden müssen. In diesem Fall ist nur der Aufruf der Implementierung möglich. Der HookContainer kann nicht verwendet werden.
3.3.2 Verwalten zustandsbehafteter Hooks
HookState-Implementierungen werden in HookState-Containern verwaltet. Ein HookState-Container wird durch den Hook-Anbieter über die folgende Methode erzeugt:
CisHookManager.createStateContainer(contextClass,hookStateClass)
Das Containerobjekt enthält alle HookState-Implementierungen, die für die angefragte Hook-Contract-Definition (contextClass) und zustandsbehafteten Hook (hookStateClass) existieren.
Der Hook-Anbieter hat keinen Zugriff auf einzelne HookState-Implementierungen. Stattdessen muss er den Container bei der Erzeugung einer Objektsicht übergeben, damit die Implementierungen in den Hooks zur Verfügung stehen.
3.3.3 Hooks in Vererbungshierarchien
Sind mehrere Hook-Anbieter in eine Vererbungsstruktur wie SingleObjectEntity eingebunden, und sollen dieselben Hooks angeboten werden, ist es sinnvoll, alle Gemeinsamkeiten zwischen den Hook-Anbietern in die Basisklassen der Vererbungsstruktur auszulagern.
Gleichartige Hook-Contract-Definitionen unterscheiden sich oft nur in der Kontextklasse und dem konkreten Typ der Objektsicht. Dieses sind die einzigen Aspekte, die in den Unterklassen der Vererbungshierarchien festgelegt werden müssen.
Die Hook-Infrastruktur ermöglicht auch, dass einzelne Unterklassen gar keine Hook-Contract-Definition haben, obwohl die Oberklasse Hook-Methoden aufruft. Zu diesem Zweck liefert der CisHookManager immer einen leeren Hook-Container, wenn als Kontextklasse null übergeben wird. Der Aufruf von Hook-Methoden hat dann keinen Effekt.
3.3.4 Bestimmung der Kontextklasse
Die Kontextklasse sollte niemals mittels dynamisch (z.B. this.getClass()) bestimmt werden, sondern immer als Konstante (com.cisag.app…X.class) angegeben werden. Im Falle einer Klassenersetzung des Hook-Anbieters (Replacement) würde sonst die falsche Kontextklasse verwendet werden.
3.4 Hinweise zur Entwicklung
Damit eine in einer Entwicklungsaufgabe gesperrte Version eines Hook-Contract-Entwicklungsobjekts (Hook-Contract-Definition, Hook-Contract-Implementierung) von einem ERP-System-Application-Server (SAS) zur Laufzeit verwendet wird, müssen die Verzeichnisse der Entwicklungsaufgabe (für Sperre in Aufgabe bzw. lokale Sperre) im Klassenpfad vorhanden sein. Insbesondere gilt dies für die kompilierten Java-Klassen im classes-Verzeichnis der Entwicklungsaufgabe. Anderenfalls verwendet der SAS die aktive Version des Entwicklungsobjekts.
Nach der Neuanlage eines Hook-Contract-Entwicklungsobjekts muss das Entwicklungsobjekt mindestens einmal gespeichert worden sein, damit ein SAS das Entwicklungsobjekt zur Laufzeit verwenden kann.
Achten Sie beim Start eines SAS auf Fehler- und Warnmeldungen der Hook-Infrastruktur in der Logdatei bzw. auf der Konsole. Die Meldungen weisen darauf hin, ob bestimmte Hook-Contract-Definitionen oder Hook-Contract-Implementierungen nicht konsistent sind.
Nicht konsistente Hook-Contract-Implementierungen werden von der Hook-Infrastruktur zur Laufzeit des SAS nicht berücksichtigt, d.h. Hook-States werden nicht erzeugt, und die Hook-Methoden aus dieser Hook-Contract-Implementierung werden nicht aufgerufen.
Nicht konsistente Hook-Contract-Definitionen werden von der Hook-Infrastruktur nicht berücksichtigt, ebenso wie alle Hook-Contract-Implementierungen für diese Hook-Contract-Definition.
3.4.1 Restriktionsüberprüfung
Bei der Konsistenzprüfung der vorhandenen Hook-Implementierungen (beim Starten des Application-Servers) müssen folgende Bedingungen erfüllt sein, damit die Implementierung gültig ist:
- Zu jeder in der Hook-Implementierung deklarierten Restriktion muss eine Restriktion in der Definition deklariert sein.
- Zu jeder in der Hook-Definition als nicht-optional deklarierten Restriktion muss eine Restriktion in der Implementierung deklariert sein.
Diese Bedingung wird erst ab Release 5.2. überprüft.
Eine Restriktions-Definition passt zu einer Implementierungs-Deklaration, wenn der Bezeichner und der Typ jeweils identisch sind.
Bei der Ermittlung der passenden Implementierungen zur Laufzeit gibt es zwei Möglichkeiten:
- Die zweistelligen Methoden getHookImplementations (Context-Klasse, Hook-Interface) und getHookContainer (.,.) verwenden keine Runtime-Restriktionen und ermitteln daher alle Implementierungen des Interfaces, ohne auf Übereinstimmungen mit evtl. vorhandenen Restriktionsdefinitionen der Implementierung zu prüfen.
- Die dreistelligen Methoden getHookImplementations (Context-Klasse, Restriktion, Hook-Interface) und getHookContainer (.,.,.) bekommen eine Liste von Restriktionen übergeben. Sie beeinflussen wie folgt, welche Implementierungen berücksichtigt werden: In der Liste müssen nicht alle von der Implementierung deklarierten Restriktionen enthalten sein. Jede übergebene Runtime-Restriktion muss aber zu einer in der Hook-Implementierung deklarierten Restriktion passen. Also: nur die tatsächlich übergebenen Runtime-Restriktionen schränken die Auswahl ein, fehlende Restriktionen dagegen nicht.
Eine Runtime-Restriktion passt zur Implementierungsdeklaration, wenn der Bezeichner, der Typ und der Wert des Entwicklungsobjekts identisch sind. Ist statt eines konkreten Entwicklungsobjekts in der Implementierungsdeklaration die Wildcard „*“ angegeben, so sind alle Werte des Entwicklungsobjekts erlaubt, nur Bezeichner und Typ müssen weiterhin übereinstimmen.
Bei der Ermittlung der passenden Implementierungen hat die Deklaration einer Restriktion als „optional“ (in der Hook-Definition) keinerlei Einfluss.
3.4.2 Installationsabhängigkeit
Durch die Angabe einer Interface- und Implementierungsklasse in einer Hook-Contract-Implementierung entsteht eine Installationsabhängigkeit zwischen der Provider-App, die das Interface zur Verfügung stellt, und der User-App mit ihrer Hook-Contract-Implementierung. Das Dokument „App-Kommunikation ohne Installationsabhängigkeit“ beschreibt Möglichkeiten, diese Abhängigkeit zu vermeiden.