Home › Forum › Nuclos Entwicklung › Makros und Regeln › Zugriff auf BusinessObjects mit der neuen API
- Dieses Thema hat 5 Antworten und 2 Teilnehmer, und wurde zuletzt aktualisiert vor 10 Jahre, 5 Monaten von
Matthias Haake.
-
AutorBeiträge
-
17 Dezember 2012 um 18:03 Uhr #6142
Matthias Haake
TeilnehmerHallo.
Im Ticket http://support.nuclos.de/browse/NUCLOS-1430 wurde vom Support angeregt, einen Diskussion-Thread im Forum zu eröffnen.
Thematisch geht es darum, ob und wie es zukünftig möglich sein soll, in einer Regel generisch auf unterschiedliche Entitäten zuzugreifen. Das hieße zum Beispiel, eine Regel berechnet einen Wert und kann das sowohl für Entität X als auch für Entität Y machen.
Wie sind Eure Erfahrungen und Anwendungsfälle zu diesem Thema?
Viele Grüße,
Matthias17 Dezember 2012 um 18:16 Uhr #6143Matthias Haake
TeilnehmerUm selbst mal ein Beispiel zum aktuellen Status Quo zu geben:
Eine Regel berechnet Google-Maps-Links. Dazu werden Adressangaben benötigt. Diese Regel binde ich an mehrere Entitäten (z.B. Mitarbeiter, Kunde, Ansprechpartner, Lieferant, Proband, Institut, Filiale etc) – halt an alle Entitäten, die Adressinformationen besitzen.
Die Felder mit den Adressangaben heißen in allen Entitäten identisch. D.h. die Straße steht immer im Attribut „street“ usw. Jede Entität besitzt ein Feld „streetmap“ vom Typ Text (255). Die Regel ließt nun die Adressangaben aus und generiert einen Text, der im Feld „streetmap“ gespeichert wird.
Mit der neuen API kann man aktuell wie folgt auf BusinessObjects zugreifen:
Mitarbeiter m = context.getBusinessObject(Mitarbeiter.class);
m.setStreetmap(...);
Da bringt es nichts, wenn ich diese Regel auch an die Entität „Kunde“ binde. Der Abruf „getBusinessObject“ wird nicht klappen, da Kunde nicht nach Mitarbeiter gecastet werden kann.
Jetzt kann man
[1] entweder eine Regel pro Entität schreiben
oder
[2] mit Reflections arbeiten
oder
[3] auf ein neues Feature warten, in dem unterschiedliche Eintitäten ein gemeinsames Interface (z.B. IAddressInformation) implementieren könnenViele Grüße,
Matthias17 Dezember 2012 um 18:34 Uhr #6144Matthias Haake
TeilnehmerAbschließend noch ein weiteres Beispiel: Stichwort Adressetiketten
Jeder Adresse kann über eine Klappbox ein Adressformat zugewiesen werden. Dies ist bei uns ein mehrzeiliges Textfeld, was z.B. für einen Ansprechpartner einer deutschen Firma wie folgt aussehen kann:
##company##
##formofaddress####
|appendix##
##street#### |housenumber##
##postalcode#### |city##
##country##
Dieser Ansprechpartner bekommt ein anderes Adressformat zugewiesen als ein ausländischer Lieferant, um sowohl verschiedene Adressfelder zu verwenden als auch um regionale Adressformatierungen zu beherrschen (z.B. DE: Straße + Hausnummer VS US: Hausnummer + Straße).
Die Regel liest beim Update eines Datensatzes die Werte der Adressfelder aus und ersetzt damit die Platzhalter im Adressformat-Template. Das Resultat wird im Feld „addresstext“ der Entität abgelegt. Auch diese Regel wird idealerweise in allen Entitäten mit Adressinformationen wiederverwendet.
Viele Grüße,
Matthias20 Dezember 2012 um 15:01 Uhr #6149Ramin Goettlich
TeilnehmerGenerische getter und setter (getField(String sFieldname) und setField(String sFieldname, Object value) einzubauen, wäre eine Sache von 2 Minuten. Wir versuchen aber, Wege zu finden, die daraus entstehenden Nachteile zu umgehen. Die Nachteile sind:
* Nuclos kann nicht erkennen, dass in Regeln Felder referenziert werden, die nicht oder nicht mehr existieren. Eine Entitätsänderung kann also Regeln zerstören, ohne dass das zunächst auffallen würde.
* Eine automatische Anpassung von Regeln bei Umbenennungen von Feldern wird dann unmöglich.
* Wirklich generische Regeln lassen sich damit auch nicht implementieren. Sie können vielleicht sicherstellen, dass in Ihrem Nuclet alle Adressfelder „strasse,“ „hnr“ o.ä. benannt werden – spätestens wenn Sie das Nuclet aber einem Dritten zur Verfügung stellen möchten, können Sie sich nicht mehr darauf verlassen, dass dieser Dritte derselben Konvention folgt.
Keine Lösung für die ersten beiden Nachteile ist auch die Verwendung voll klassifizierter Strings für Feldnamen, z.B. „..“, da auch dazu ja das BUSINESSOBJEKT bekannt sein muss (und nicht generisch angegeben werden kann). Baut man den String hingegen zusammen, bleiben die Nachteile bestehen, da dann wieder keine automatische Erkennung im Sourcecode der Regel möglich ist.
20 Dezember 2012 um 15:08 Uhr #6150Ramin Goettlich
TeilnehmerWir könnten eine Utils-Klasse („Unsafe“) 😉 zur Verfügung stellen, die einen Workaround bietet und die Inhalte über Reflection holt:
Unsafe.getField(Businessobject bo, String sFieldname)
Unsafe.setField(Businessobject bo, String sFieldname, Object o)Das wäre dann ein Nuclet, nicht Teil von Nuclos, und die Nutzung unterliegt der eigenen Verantwortung.
Aber zumindest hat man einen Workaround für jetzt, auch bevor es einen zukünftig vielleicht besseren Ansatz gibt.
20 Dezember 2012 um 16:15 Uhr #6151Matthias Haake
TeilnehmerVielen Dank für die Antworten. Persönlich finde ich die Interfaces am besten.
Alternativ – aber ein bisschen aufwändiger – könnte man sich ja DTO-Klassen anlegen, die nur die gemeinsamen Felder besitzen. Die Logik-Rules würden dann ausschließlich mit den DTOs arbeiten. Für die entsprechenden Entitäten bräuchte man dann ein Mapping zwischen Entität und DTO. Das wäre in C# über Extension Methods schnell und elegant gelöst, werde in Java aber davon absehen.
Für mich heißt das, ich setze eine statische Utilityklasse ein, die das über Reflections löst und freue mich auf die Interfaces 🙂
Voraussetzung ist aber: Das BusinessObject lässt sich aus dem Kontext abfragen (ohne Class-Parameter). In der aktuellen Version (3.9.4) geht das noch nicht, daher kann man frühestens beim nächsten Update damit starten…
Leider geht auch der versuchte Hack nicht (org.nuclos.server.api.eventsupport ist auch gesperrt) – muss also wirklich warten :dry:
Field field = context.getClass().getField("busiObject");
field.setAccessible(true);
result = (BusinessObject)field.get(context);
-
AutorBeiträge