Home › Forum › Nuclos Entwicklung › Makros und Regeln › BusinessObject is not in a modified state
- Dieses Thema hat 6 Antworten und 2 Teilnehmer, und wurde zuletzt aktualisiert vor 8 Jahren, 11 Monaten von
Ramin Goettlich.
-
AutorBeiträge
-
3 Januar 2015 um 11:48 Uhr #8067
Josef Hopfgartner
TeilnehmerHallo Forum!
Ich habe im Wiki das Beispiel zur InsertFinalRule gefunden und es für meine Anwendung herangezogen.
Jedoch mache ich hier etwas falsch.Fehler:
Caused by: org.nuclos.api.exception.BusinessException: BusinessObject is not in a modified state and cannot be updated.
at org.nuclos.server.nbo.BusinessObjectServiceProvider.update(BusinessObjectServiceProvider.java:119)
at org.nuclos.api.provider.BusinessObjectProvider.update(BusinessObjectProvider.java:81)
at at.netzagentur.versuch.BuchungAusFahrzeugkosten_IFR.insertFinal(BuchungAusFahrzeugkosten_IFR.java:26)
at org.nuclos.server.eventsupport.ejb3.EventSupportFacadeBean.executeInsertSupportEvent(EventSupportFacadeBean.java:1003)
… 96 moreDas Attribut BuchungId ist in diesem Fall NULL.
Das Businessobjekt wird also geändert.
Daher verstehe ich den Fehler nicht…package at.netzagentur.versuch;
import org.nuclos.api.rule.InsertFinalRule;
import org.nuclos.api.context.InsertContext;
import org.nuclos.api.annotation.Rule;
import org.nuclos.api.exception.BusinessException;
import org.nuclos.api.provider.BusinessObjectProvider;@Rule(name="BuchungAusFahrzeugkosten_IFR", description="BuchungAusFahrzeugkosten")
public class BuchungAusFahrzeugkosten_IFR implements InsertFinalRule {public void insertFinal(InsertContext context) throws BusinessException {
Fahrzeugkosten fahrzKo = context.getBusinessObject(Fahrzeugkosten.class);if (fahrzKo.getBuchung() == null ) {
java.lang.Long kto=40008172L;
Buchung bu = new Buchung();
bu.setKontoId(kto);
bu.setDatum(fahrzKo.getDatum());
bu.setReferenz(fahrzKo.getPartner() + bu.getDatum().toString());
bu.setReferenznummer(fahrzKo.getId().intValue());
bu.setSoll(fahrzKo.getSummegroovy());
BusinessObjectProvider.insert(bu);
fahrzKo.setBuchungId(bu.getId());
}
BusinessObjectProvider.update(fahrzKo);
}
}3 Januar 2015 um 12:41 Uhr #8068Ramin Goettlich
TeilnehmerHallo,
das BO ist nicht geändert, siehe auch http://support.nuclos.de/browse/NUCLOS-3895
Mit einer kleinen Änderung funktionierts:
Long id = BusinessObjectProvider.insert(bu);
fahrzKo.setBuchungId(id);Das BusinessObjectProvider.update(fahrzKo); sollte auch in den IF-Teil, sonst knallts auch sobald fahrzKo.getBuchung() != null.
Grüsse,
nuclosian4 Januar 2015 um 04:17 Uhr #8071Josef Hopfgartner
TeilnehmerDanke für den Hinweis. Der Fehler blieb jedoch.
Ich arbeite mit Nuclos 4.3.2Beta.Irgendwie will das BO „Fahrzeugkosten“ einfach nicht den Status auf „isUpdate“ geändert bekommen…
Ich habe die Regel entsprechend umgeschrieben.
Eigentlich war die Änderung bzgl. der update-Methode ja lediglich die Einführung einer zusätzlichen Long „id“.
Zuvor hatte ich halt statt dessen den Funktionsaufruf mit getId() im Einsatz.Hier der abgeänderte Code, der immer noch den selben Fehler wirft:
public void insertFinal(InsertContext context) throws BusinessException {
Fahrzeugkosten fahrzKo = context.getBusinessObject(Fahrzeugkosten.class);if (fahrzKo.getBuchung() == null ) {
java.lang.Long kto=40008172L;
Buchung bu = new Buchung();
bu.setKontoId(kto);
bu.setDatum(fahrzKo.getDatum());
bu.setReferenz(fahrzKo.getPartner() + bu.getDatum().toString());
bu.setReferenznummer(fahrzKo.getId().intValue());
bu.setSoll(fahrzKo.getSummegroovy());
Long id = BusinessObjectProvider.insert(bu);
System.out.println("DEBUG bu.id " + id);
fahrzKo.setBuchungId(id);
BusinessObjectProvider.update(fahrzKo);
}
}DEBUG bu.id 40009215
4 Januar 2015 um 20:14 Uhr #8072Ramin Goettlich
TeilnehmerSorry, das geht so tatsächlich nicht. In einer insert/insertFinal-Regel befindet sich das Objekt im Status „inserted“ und kann sich daher nicht im Status „modified“ befinden. Folgender Workaround funktioniert:
Nicht das Objekt aus dem Kontext ändern, sondern sich das FahrzeugKo nochmal explizit per QueryProvider.getById() holen und darauf dann den Update machen.
Dass ein Feld „Referenznummer“ in der Buchung existiert, lässt darauf schliessen, dass es sich hier eigentlich um eine 1:1-Verknüpfung zwischen Fahrzeugko und Buchung handelt. Vielleicht genügt der Verweis von der Buchung aus ja schon und man muss nicht zwingend gegenseitig verweisen?
4 Januar 2015 um 23:12 Uhr #8075Josef Hopfgartner
TeilnehmerDanke für die Lösung – mit dem Nachladen des BOs funktioniert das Update.
Demnach war der Wiki-Beispiel-Eintrag zu IFR nicht (mehr) aktuell. Eigentlich schade, dass in der IFR das Objekt vorhanden ist und nicht mehr verändert werden kann.
Zu meinen Absichten:
Ich bilde tatsächlich eine 1:1 Beziehung ab.
Ich beabsichtige, eine Kostenrechnung zu führen.
Als erstes BO habe ich das Fahrtenbuch eingeführt.
Weitere BO sind in Ausarbeitung.
Jedes BO soll eine oder mehrere Buchungen anlegen können – und zwar nach den Regeln der doppelten Buchhaltung.Eine Referenz von Buchung auf Fahrtenbuch ist daher nicht möglich, weil es noch andere BOs gibt, die ebenfalls als Referenz gelten können.
Ich evaluiere gerade „virtuelle BO“, weil diese ja eine solche Anwendung ermöglichen könnten. Demnach wäre es ein DB-VIEW auf alle in zu Betracht kommenden BOs (UNION ALL Klausel).
5 Januar 2015 um 00:41 Uhr #8076Ramin Goettlich
Teilnehmer„Buchungen“ klingt nach vielen Datensätzen. Da würde ich von UNION ALL aus Performancegründen eher abraten, insbesondere wenn es viele buchungsauslösende BOs gibt.
Ausserdem ist ein Referenzfeld auf eine virtuelle Entität (View) kein echter Constraint, d.h. referentielle Integrität wäre dann nicht mehr gesichert und man könnte einen Datensatz aus dem buchungsauslösenden BO löschen, die Buchung würde als Datenleiche bestehen bleiben (wenn man sich nicht selbst zuverlässig um die Löschung kümmert).
Wie wärs mit einem Referenzfeld je buchungsauslösendem BO in der Buchung? Macht natürlich nur Sinn, wenn überschaubar viele.
Warum FahrzeugKo auf Buchung verweisen muss, ist mir immer noch nicht klar, aber das funktioniert ja nun. Kann das denn auf Dauer richtig sein, was wenn man z.B. einen FahrzeugKo-Satz stornieren möchte, dann resultiert ggf. eine zweite Buchung daraus – dann klappt damit der 1:1-Beziehung nicht mehr.
5 Januar 2015 um 00:41 Uhr #8077Ramin Goettlich
Teilnehmer„Buchungen“ klingt nach vielen Datensätzen. Da würde ich von UNION ALL aus Performancegründen eher abraten, insbesondere wenn es viele buchungsauslösende BOs gibt.
Ausserdem ist ein Referenzfeld auf eine virtuelle Entität (View) kein echter Constraint, d.h. referentielle Integrität wäre dann nicht mehr gesichert und man könnte einen Datensatz aus dem buchungsauslösenden BO löschen, die Buchung würde als Datenleiche bestehen bleiben (wenn man sich nicht selbst zuverlässig um die Löschung kümmert).
Wie wärs mit einem Referenzfeld je buchungsauslösendem BO in der Buchung? Macht natürlich nur Sinn, wenn überschaubar viele.
Warum FahrzeugKo auf Buchung verweisen muss, ist mir immer noch nicht klar, aber das funktioniert ja nun. Kann das denn auf Dauer richtig sein, was wenn man z.B. einen FahrzeugKo-Satz stornieren möchte, dann resultiert ggf. eine zweite Buchung daraus – dann klappt das mit der 1:1-Beziehung nicht mehr.
-
AutorBeiträge