Nuclos generic implementation tutorial: GenericBusinessObject, generic BO, replace instanceof, rule, number range, sum calculation, mapping. |
Language: Deutsch · English
Hands-on tutorial for generic implementation – one abstract BO and one rule for many concrete BOs (number ranges, sum calculation).
Auf dieser Seite |
Goal: create a generic business object and implement a generic rule. |
The generic implementation replaces repeated rule code branched by instanceof with one abstract BO serving several concrete BOs.
Several BOs (quote, order, delivery note, purchase order) receive an automatic number on creation. Previously solved via instanceof:
public void insert(InsertContext context) throws BusinessException {
final Modifiable<?> businessObject = context.getBusinessObject(Modifiable.class);
if (businessObject instanceof Angebot) {
((Angebot) businessObject).setAngebotsnr(NummernkreiseLogik.getNextValue(Angebot.class));
} else if (businessObject instanceof Auftrag) {
((Auftrag) businessObject).setAuftragsnr(NummernkreiseLogik.getNextValue(Auftrag.class));
} else if (businessObject instanceof Lieferschein) {
((Lieferschein) businessObject).setLieferscheinnr(NummernkreiseLogik.getNextValue(Lieferschein.class));
} else if (businessObject instanceof Bestellung) {
((Bestellung) businessObject).setBestellnr(NummernkreiseLogik.getNextValue(Bestellung.class));
}
} |
Create a new generic BO Nummerierbar in the business object wizard with exactly one attribute Nummer (no layout/permissions) and assign it to a nuclet.
The data type of the generic attribute must match that of the fields in the implementing BOs. |
For each implementing BO create a record with the attribute mapping (e.g. Nummer → order number). Nuclos generates the class Nummerierbar.java with generic getters/setters:
import org.nuclos.businessentity.*;
import org.nuclos.api.businessobject.Dependent;
import org.nuclos.api.businessobject.Flag;
import org.nuclos.api.UID;
import org.nuclos.api.businessobject.GenericBusinessObject;
import java.util.List;
import java.util.ArrayList;
import java.util.HashSet;
/**
* BusinessObject: Nummerierbar
*<br>
*<br>Nuclet: org.nuclet.tulteclico
*<br>DB-Name: [generic]
*<br>Editable: true
*<br>Localized: false
*<br>Statemodel: false
**/
public class Nummerierbar implements GenericBusinessObject<Long> {
private org.nuclos.api.businessobject.BusinessObject<Long> businessObject;
public Nummerierbar(org.nuclet.tulteclico.Lieferschein businessObject) {
this.businessObject = businessObject;
}
public Nummerierbar(org.nuclet.tulteclico.Bestellung businessObject) {
this.businessObject = businessObject;
}
public Nummerierbar(org.nuclet.tulteclico.Auftrag businessObject) {
this.businessObject = businessObject;
}
public Nummerierbar(org.nuclet.tulteclico.Angebot businessObject) {
this.businessObject = businessObject;
}
public org.nuclos.api.UID getEntityUid() {
return businessObject.getEntityUid();
}
public org.nuclos.api.businessobject.BusinessObject<Long> getBusinessObject() {
return businessObject;
}
public java.lang.String getEntity() {
return businessObject.getEntity();
}
public java.lang.Long getId() {
return businessObject.getId();
}
public java.lang.Integer getVersion() {
return businessObject.getVersion();
}
public boolean isInsert() {
return businessObject.isInsert();
}
public boolean isUpdate() {
return businessObject.isUpdate();
}
public boolean isDelete() {
return businessObject.isDelete();
}
/**
* Getter-Method for attribute: changedAt
*<br>
*<br>Entity: Nummerierbar
*<br>DB-Name: DATCHANGED
*<br>Data type: org.nuclos.common2.InternalTimestamp
*<br>Localized: false
*<br>Output format: null
*<br>Scale: null
*<br>Precision: null
**/
public java.util.Date getChangedAt() {
// all implemented BOs:
if (this.businessObject instanceof org.nuclet.tulteclico.Lieferschein) {
return ((org.nuclet.tulteclico.Lieferschein) this.businessObject).getChangedAt();
}
if (this.businessObject instanceof org.nuclet.tulteclico.Bestellung) {
return ((org.nuclet.tulteclico.Bestellung) this.businessObject).getChangedAt();
}
if (this.businessObject instanceof org.nuclet.tulteclico.Auftrag) {
return ((org.nuclet.tulteclico.Auftrag) this.businessObject).getChangedAt();
}
if (this.businessObject instanceof org.nuclet.tulteclico.Angebot) {
return ((org.nuclet.tulteclico.Angebot) this.businessObject).getChangedAt();
}
// not implemented attribute:
return null;
}
/**
* Getter-Method for attribute: changedBy
*<br>
*<br>Entity: Nummerierbar
*<br>DB-Name: STRCHANGED
*<br>Data type: java.lang.String
*<br>Localized: false
*<br>Output format: null
*<br>Scale: 255
*<br>Precision: null
**/
public java.lang.String getChangedBy() {
// all implemented BOs:
if (this.businessObject instanceof org.nuclet.tulteclico.Lieferschein) {
return ((org.nuclet.tulteclico.Lieferschein) this.businessObject).getChangedBy();
}
if (this.businessObject instanceof org.nuclet.tulteclico.Bestellung) {
return ((org.nuclet.tulteclico.Bestellung) this.businessObject).getChangedBy();
}
if (this.businessObject instanceof org.nuclet.tulteclico.Auftrag) {
return ((org.nuclet.tulteclico.Auftrag) this.businessObject).getChangedBy();
}
if (this.businessObject instanceof org.nuclet.tulteclico.Angebot) {
return ((org.nuclet.tulteclico.Angebot) this.businessObject).getChangedBy();
}
// not implemented attribute:
return null;
}
/**
* Getter-Method for attribute: createdAt
*<br>
*<br>Entity: Nummerierbar
*<br>DB-Name: DATCREATED
*<br>Data type: org.nuclos.common2.InternalTimestamp
*<br>Localized: false
*<br>Output format: null
*<br>Scale: null
*<br>Precision: null
**/
public java.util.Date getCreatedAt() {
// all implemented BOs:
if (this.businessObject instanceof org.nuclet.tulteclico.Lieferschein) {
return ((org.nuclet.tulteclico.Lieferschein) this.businessObject).getCreatedAt();
}
if (this.businessObject instanceof org.nuclet.tulteclico.Bestellung) {
return ((org.nuclet.tulteclico.Bestellung) this.businessObject).getCreatedAt();
}
if (this.businessObject instanceof org.nuclet.tulteclico.Auftrag) {
return ((org.nuclet.tulteclico.Auftrag) this.businessObject).getCreatedAt();
}
if (this.businessObject instanceof org.nuclet.tulteclico.Angebot) {
return ((org.nuclet.tulteclico.Angebot) this.businessObject).getCreatedAt();
}
// not implemented attribute:
return null;
}
/**
* Getter-Method for attribute: createdBy
*<br>
*<br>Entity: Nummerierbar
*<br>DB-Name: STRCREATED
*<br>Data type: java.lang.String
*<br>Localized: false
*<br>Output format: null
*<br>Scale: 255
*<br>Precision: null
**/
public java.lang.String getCreatedBy() {
// all implemented BOs:
if (this.businessObject instanceof org.nuclet.tulteclico.Lieferschein) {
return ((org.nuclet.tulteclico.Lieferschein) this.businessObject).getCreatedBy();
}
if (this.businessObject instanceof org.nuclet.tulteclico.Bestellung) {
return ((org.nuclet.tulteclico.Bestellung) this.businessObject).getCreatedBy();
}
if (this.businessObject instanceof org.nuclet.tulteclico.Auftrag) {
return ((org.nuclet.tulteclico.Auftrag) this.businessObject).getCreatedBy();
}
if (this.businessObject instanceof org.nuclet.tulteclico.Angebot) {
return ((org.nuclet.tulteclico.Angebot) this.businessObject).getCreatedBy();
}
// not implemented attribute:
return null;
}
/**
* Getter-Method for attribute: nummer
*<br>
*<br>Attribute Information:<br>
*<br>
*<br>Entity: Nummerierbar
*<br>DB-Name: [generic]
*<br>Data type: java.lang.String
*<br>Localized: false
*<br>Output format: null
*<br>Scale: 255
*<br>Precision: null
**/
public java.lang.String getNummer() {
// all implemented BOs:
if (this.businessObject instanceof org.nuclet.tulteclico.Lieferschein) {
return ((org.nuclet.tulteclico.Lieferschein) this.businessObject).getLieferscheinnr();
}
if (this.businessObject instanceof org.nuclet.tulteclico.Bestellung) {
return ((org.nuclet.tulteclico.Bestellung) this.businessObject).getBestellnr();
}
if (this.businessObject instanceof org.nuclet.tulteclico.Auftrag) {
return ((org.nuclet.tulteclico.Auftrag) this.businessObject).getAuftragsnr();
}
if (this.businessObject instanceof org.nuclet.tulteclico.Angebot) {
return ((org.nuclet.tulteclico.Angebot) this.businessObject).getAngebotsnr();
}
// not implemented attribute:
return null;
}
/**
* Setter-Method for attribute: nummer
*<br>
*<br>Attribute Information:<br>
*<br>
*<br>Entity: Nummerierbar
*<br>DB-Name: [generic]
*<br>Data type: java.lang.String
*<br>Localized: false
*<br>Output format: null
*<br>Scale: 255
*<br>Precision: null
**/
public void setNummer(java.lang.String pNummer) {
// all implemented BOs:
if (this.businessObject instanceof org.nuclet.tulteclico.Lieferschein) {
((org.nuclet.tulteclico.Lieferschein) this.businessObject).setLieferscheinnr(pNummer);
}
if (this.businessObject instanceof org.nuclet.tulteclico.Bestellung) {
((org.nuclet.tulteclico.Bestellung) this.businessObject).setBestellnr(pNummer);
}
if (this.businessObject instanceof org.nuclet.tulteclico.Auftrag) {
((org.nuclet.tulteclico.Auftrag) this.businessObject).setAuftragsnr(pNummer);
}
if (this.businessObject instanceof org.nuclet.tulteclico.Angebot) {
((org.nuclet.tulteclico.Angebot) this.businessObject).setAngebotsnr(pNummer);
}
}
} |
In the server rule manager create a rule on creation, assign it to all implementing BOs (order/conditions as usual) and, instead of instanceof, fetch the generic BO from the context:
public void insert(InsertContext context) throws BusinessException {
Nummerierbar n = context.getBusinessObject(Nummerierbar.class);
n.setNummer(NummernkreiseLogik.getNextValue(n.getEntityUid()));
} |
Quote, order and invoice each have a subform with positions and the rule total = unit price × quantity. Instead of doing this per BO, it is solved generically.
After mapping, Nuclos generates Beleg.java and Belegposition.java. The latter maps e.g. getMenge() to getPos() of the respective concrete BO and provides getBelegposition() as a list.
public void save(SaveContext context) throws BusinessException {
Belegposition pos = context.getBusinessObject(Belegposition.class);
BigDecimal einzel = pos.getEinzelpreis();
Integer menge = pos.getMenge();
if (einzel != null && menge != null) {
pos.setGesamtpreis(einzel.multiply(new BigDecimal(menge)));
}
} |
The rule is assigned to all relevant position BOs – one implementation covers all document types. |