Difference between revisions of "Development Guidelines in German"

From ADempiere
Jump to: navigation, search
This Wiki is read-only for reference purposes to avoid broken links.
Line 414: Line 414:
 
Validierung
 
Validierung
 
Docaction setzen
 
Docaction setzen
 +
 +
=Interface DocAction=
 +
 +
package org.compiere.process
 +
public interface DocAction
 +
 +
WF-Businessobjekte implementieren die in DocAction definierten Methoden, wie in
 +
public class MInvoice extends X_C_Invoice implements DocAction.
 +
Ein BO, das DocAction implementiert, wird “Document” genannt.
 +
Ihre endgültige Fassung hängt vom Objekt ab.
 +
approveIt()
 +
Setzt die Property isApproved auf True
 +
closeIt()
 +
Danach ist keine Action möglich
 +
invalidateIt()
 +
prepareIt()
 +
Logik vor Ausführung
 +
processIt()
 +
Ausführung der Businesslogik
 +
reActivateIt()
 +
nach einem closeIt() kann das Dokument wieder aktiviert werden.
 +
Es häng vom Objekt ab: ein Invoice kann nicht, ein Order schon wieder aktiviert werden.
 +
rejectIt()
 +
reverseAccrualIt()
 +
reverseCorrectIt()
 +
Generiert in Buchhaltung Gegenbuchung. Dafür wird eine Kopie des Originals genommen.
 +
unlockIt()
 +
eine Methode lockIt() gibt es nicht
 +
voidIt()
 +
Definiert static final Properties (String-Konstanten) für die Actions und Stati
 +
ACTION_Complete
 +
ACTION_Close
 +
STATUS_Drafted
 +
STATUS_Completed
 +
etc.
 +
Weitere Methoden
 +
weswegen habe ich sie von den anderen Methoden getrennt? Sind sie Hilfsmethodern?
 +
getApprovalAmt()
 +
getCtx()
 +
ID vom Satz
 +
getDocAction()
 +
getDocStatus()
 +
Liefert einen der als static final Property definierten Stati
 +
getDocumentInfo()
 +
Name des Dokumententyps und Dokument-Nr.
 +
getDocumentNo()
 +
getDoc_User_ID()
 +
Kontrolliert die Sequenz
 +
Z.B. Verkaufs- Kaufs- Zahlungs-Nr.
 +
getProcessMsg ()
 +
Liefert den Wert der Property m_processMsg
 +
get_TrxName()
 +
save()
 +
setDocStatus ()
 +
Setzt  einen des als static final Property definierten Status
 +
u.v.a.m.

Revision as of 13:49, 21 September 2007

Generiert Java Beans

Klasse org.compiere.util.GenerateModel

package org.adempiere.util public class GenerateModel


  • Die Methode main() generiert Java Beans (X_xxxxxx.java-Dateien wie z.B. X_C_Invoice.java).
  • Die Methode main() liest die Tabelle AD_Table und generiert unter anderem für jede Spalte die getter- und setter-Methoden von AD-Tabellen.
  • Es ist möglich, einzelne Beans zu generieren.
  • Siehe weiter im Text.
  • Im Adempiere Sourcecode sind diese Dateien unter org.compiere.model auffindbar.
  • Die compilierte GenerateMdel.class-Datei ist unter .../adempiere_trunk/base/build/org/compiere/util
  • Man kann mithilfe von Aufrufparametern das Ergebnis bestimmen:
    • man selektiert in Eclipse die Methode main(), und mit der rechten Maustaste selektiert man run.
    • Will man Paramenter eingeben, so muss man im run die Parameter eintragen:
      • Parameter 0 : Verzeichnis
      • Wohin die Dateien kopiert werden.
      • Default – wenn kein Parameter: "C:\\Adempiere\\adempiere-all\\extend\\src\\adempiere\\model\\"
      • Im Trunk sind sie in /Adempiere/adempiere_trunk/extend/src/compiere/model//
      • Parameter 1: Package, zu dem die Java-Bean gehören wird
      • Default – wenn kein Parameter: "compiere.model"
      • Parameter2: entity Type
      • (User-Defined, Adempiere, Dictionary, etc).
      • In der Datei sind nur User und Application vorgesehen. Will man andere wie Adempiere, so sollte man das einfügen. Man sollte aber bedenken, dass nur User-defined nicht mit jeder neuen Version gelöscht werden.
      • Default – wenn kein Parameter: "'U','A'"
      • Parameter 3: Tabelle
      • Aus welcher Tabelle die Java Bean generiert wird.
      • Default – wenn kein Parameter: % (alle Tabellen)
  • Man kann auch den Code so ändern, dass die Parameter die gewünschten Einstellungen haben.
  • Jedesmal, wenn die Tabellen des Application Dictionary sich geändert haben, muss man die X_-Dateien generieren, wenn man die Felder im Code ansprechen will.

Seit V. 3.3.0 ist /Adempiere/adempiere_trunk/base/src/org/adempiere/util/GenerateModelJPA.java dafür zuständig. Diese Klasse legt die Dateien ohne „X_“-Präfix an, z.B. „C_InvoiceLine.java“. Man muss sie vor dem Deployen umbenennen.

Java-Beans

Besonderheiten der Beans

  • Sind POJOs
  • Pro Businessobjekt gibt es ein Java Bean
  • Sie sind das Bindeglied zwischen dem Java-Code und den Daten der Datenbank.
  • Sie ersparen dem Entwickler, Daten direkt anzusprechen oder Informationen fest zu kodieren. Stattdessen werden Objekte manipuliert, indem die Beans instanziiert werden.
  • Beispiel: bp.getM_PriceList_ID() hier liefert das Objekt BusinessPartner die ID der Preisliste.
  • welchem Package sie angehören: In Adempiere sind im Package org.compiere.model die Java-Bean-Klassen und die Business-Logik-Klassen abgelegt.
  • die Deklaration der Java Bean-Klasse.
  • Zum Beispiel:
  • public class X_C_Invoice extends PO
  • Gewisse Methoden werden in der Klasse PO (Persistence Object in org.compiere.model.PO) implementiert. So rufen zum Beispiel alle Konstruktoren der Java Bean-Klassen PO-Konstruktoren auf ( super (ctx, rs, trxName) bzw. super (ctx, C_Invoice_ID, trxName) ).
  • Die static final Property Table_ID liefert die ID der Tabelle.
  • Beispiel: public static final int Table_ID=MTable.getTable_ID(Table_Name);
  • Man braucht damit die Tabellen-ID nicht im Programm hart zu kodieren.
  • Die protected static Property Model
  • Beispiel: protected static KeyNamePair Model = new KeyNamePair(Table_ID, Table_Name);
  • Die static final Property accessLevel
  • Das sind die Werte, die man bei der Tabellendefinition festglegt hat (Client, Organisation, Client+Organisation, etc).
  • Beispiel: protected BigDecimal accessLevel = BigDecimal.ValueOf(1);
  • AD_ORGTRX_ID_AD_Reference_ID
  • Die ID im Dictionary, die xxxxxx.
  • Methoden
    • initPO
    • wird vom in der Afurufkette zuletzt aufgerufenen PO-Konstruktor ( PO (Properties ctx, int ID, String trxName, ResultSet rs) ) aufgerufen.
    • toString (z.B. Liefert z.B. bei der Klasse C_Invoice: X_C_Invoice[318])
    • Wird bei u.a. bei compare() verwendet oder log.info(toString()
    • getter- und setter-Metoden aller Spalten der Tabelle.
    • Ausnahmen: die Spalten Processing, Processed, Created, CreatedBy, etc. die in der Methode load() der Klasse PO mit dem Aufruf loadDefaults()/SetStandardDefaults() angelegt werden.
    • getDocStatus()
    • setDocStatus()
  • Misc
    • Alle Basisklassen und Beans gehören zum gleichen Package. Dadurch ist das Kreiieren eines Objektes durch den Konstruktor-Aufruf möglich.
    • Datum wird als Timestamp behandelt
    • Boolsche Werte werden als Zeichenketten mit Länge 1 dargestellt (Y=True, N=False). Bei der Abfrage eines booleans wird keine get- sondern eine is-Methode aufgerufen wie isApproved()
    • Es gibt weitere Beans, die anderen Packages zugehören aber zum Model- und Control-eil der Architektur gehören, weil sie zum einen BO darstellen (man kann bei Adempiere eine Activity anlegen) aber auch Abläufe kontrollieren.
    • Sie werden im Laufe der Ausführungen zum Teil behandelt, z.B. MWFActivity, MWFNode, MWFProcess, MDocType, MWorkflow.
Es gibt Java Beans, das nicht eines Business Objekts entstammt:
public class X_AD_WF_Activity extends PO
Diese Klasse ist Hilfsklasse zu  MWFActivity
public class MWFActivity extends X_AD_WF_Activity implements Runnable
  • Beans und PO zusammen realisieren die Persistenz:
    • Beans halten die Daten
    • PO liefert die Mechanismen zur Persistenz

Persistenz-Engine

org.compiere.model.PO

Realisiert die Klassenpersistenz bei Adempiere. PO hat Methodenzum DB-Transfer, ruft Triggers und Modellvalidatoren.

public abstract class PO implements Serializable, Comparator, Evaluatee; Serializable Zum Herausstreamen von Objekten. Comparator Die Methoden compare() und equals() werden von PO implementiert. Evaluatee Implementiert die Methode get_ValueAsString(), die u.a. von org.compiere.util.Evaluator. evaluateLogicTuple() aufgerufen wird. Es werden die Tupel evaluiert, die im Dictionary angegben werden, wie @xxxx@.

Klassenhierarchie: eine Adempiere-Klasse wie MInvoice erbt von X_C_Invoice, das ihrerseits von PO erbt: public class MInvoice extends X_C_Invoice implements DocAction public class X_C_Invoice extends PO


Wichtige Konstruktoren aufgerufen wird immer am Ende der Vater-Konstruktor public PO (Properties ctx, int ID, String trxName, ResultSet rs) um Eine neue Instanz anlegen: wenn man den Parameter ID mit dem Wert 0 belegt. Gibt man als Transaktion null an, so wird eine neue kreiert. org.compiere.util.Trx kontrolliert die Transaktionen mit static Methoden neue Transkaktion anlegen, Trx vergibt einen zufälligen Namen Trx.createTrxName() neue Transkaktion anlegen Trx.createTrxName("Cost") Name der aktuellen Transaktion wird geholt Trx.get(trxName, True) Eine neue Transaktion wird angelegt, wenn es die Transaktion trxName nicht gibt und der zweite Parameter True ist. Trx.get(trxName, True) In Trx.get wird neu angelegt: {

:
retValue = new Trx (trxName)

} Mit der Angabe des Transkationsnamen wird sichergestellt, dass alle DB-Speicherungen mit gleichem Namen als eine Transaktion behandelt werden mit Commit und Rollback.


Der Vater-Konstruktor ruft auf

{

:

load (int ID, String trxName)

}

Wenn man die ID und Transaktion kennt ID > 0 Es werden per SQL die Spalten geholt und die Instanz mit Werten versehen. ID <= 0 neues Objekt. Private Klasse m_createNew bekommt den Wert True, so dass im folgenden das Objekt weiss, dass es sich um eine Neuanlage handelt. Die Spalten Processing, Processed, Created, CreatedBy, etc. werden mit dem Aufruf loadDefaults() angelegt. Verweis auf die Stelle, wo erwähnt wird, dass diese Felder nicht erfasst werden.

loadComplete (boolean success) kann bei Bedarf von den Unterklassen definiert werden. Es wird aber zurzeit nirgends verwendet.

load(ResultSet rs); Auch ein load(ResultSet rs) ruft am Ende load (int ID, String trxName) auf. Hier wird ein ResultSet zum Anlegen eines Objkts herangezogen. Es wird die aktuelle Position des ResultSets genommen; ausserdem wird nicht im ResultSet navigiert.

Konstruktor PO (Properties ctx, int ID, String trxName) MBPartner bp = new MBPartner (line.getCtx(), line.getC_BPartner_ID(), line.get_TrxName()); Konstruktor PO (Properties ctx, ResultSet rs, String trxName)

Weitere Methoden von PO: public final Object get_Value (String columnName) Wird überprüft, ob die Spalte aktiv ist wenn ja, get_Value (int index) aufrufen, das m_newValues[index]zurückliefert. Siehe Properties.

set_ValueNoCheck (String ColumnName, Object Value) Die “Spalte” bekommt ohne Check einen Wert. Unter Umständen wird der Wert abgekürzt. Das ist der Grund dafür, dass man im Programm Werte eingibt und vom Program abgekürzt gespeichert serden: es wird auf die im AD festgelegten Länge abgekürzt.

Die nachfolgenden Methoden werden hier ausgeführt und nicht in den Unterklassen.

delete() Ein Objekt wird gelöscht. Es werden u.a. Events validiert mit ModelValidationEngine. delete_Tree() ID-Bäume werden entfernt save() Die Speicherung der Unkterklassen wird hier vorgenommen. Es werden einige Checks durchgeführt: neues Objekt, Organisation)

In save() werden weitere Methoden aufgerufen: beforeSave() Wird meist von den Business-Klassen wie MInvoice, MProduct usw. implementiert. saveNew() Speicherung eines neuen Objektes saveUpdate() Speicherung eines existierenden Objektes.

Änderungsverfolgung eine Session-Variable wird anglegt. MSession session = MSession.get (p_ctx, false) Bei Änderung wird in der Tabelle MChangeLog den Zustand des Objektes vor und nach dem Speichern festgehalten. MChangeLog cLog = session.changeLog Die nötigen Einstellungen muss man im AD vornehmen; dort es ist möglich eine Tabelle zum Log zu melden. Hat man das getan, kann man bei Adempiere am Fenster, wo die Tabelle dargestellt wird, unten rechts mit einem Doppelklick den Änderungslog sehen. Folgendes ist sichtbar: Tabellenname wer/wann den Satz angelegt hat wer/wann den Satz geändert hat änderungslog

saveNew() und saveUpdate() rufen am Ende saveFinish() auf, das seinerseits afterSave() aufruft.

Die Methoden beforeSave() und afterSave() werden meist in den Business-Klassen wie MInvoice, MProduct usw. implementiert.

Properties von PO (u.a.) POInfo p_info (Spalteninfos: Table-ID, Table Name, Access Level, etc). Wird im Vater-Konstruktor geholt mit p_info = initPO(ctx); die Unterklassen implementieren initPO(). Siehe Klasse POInfo. Informationen über Spalten liefert p_info.

Informationen der Spalten: ein Aufruf get_Value("Spaltenname") bewirkt am Ende ein Aufruf get_Value (int index); dort wird m_newValues[index] zurückgeliefert (oder m_oldValues[index], wenn m_newValues==null) protected transient CLogger log = CLogger.getCLogger (getClass()) Zur Anzeige der Unterklassen-Ausgaben der Konsole private static Clogger s_log = CLogger.getCLogger (PO.class);

Zur Anzeige de PO-Ausgaben in der Konsole

private Doc m_doc private Object[] m_IDs = new Object[] {I_ZERO} // Ids der sätze private Object[] m_oldValues = null; // alte Werte private Object[] m_newValues = null; // neue Werte private Mattachment m_attachment = null; etc.


Klasse POInfo

package org.compiere.model public class POInfo implements Serializable

Diese Klasse ist der Zugang zu POInfoColumn-Instanzen

Enthält Informationen über die Spalten des Businessobjektes ist serialisierbar (zum übertragen ausserhalb des Programms) Properties u.a. m_AD_Table_ID m_TableName m_AccessLevel POInfoColumn[] m_columns private Properties m_ctx = null Methoden u.a. Beziehen sich meist über den Index auf Properties von m_columns Der Konstruktor POInfo (Properties ctx, int AD_Table_ID, boolean baseLanguageOnly) ruft loadInfo() auf, das in einem SQL, das die Tabellen AD_Table t AD_Column c

AD_Val_Rule vr  und 

AD_Element e umfasst (Parameter des SQL:m_AD_Table_ID), pro Spalte eine Instanz von POInfoColumn anlegt und mit den Daten des SQL belegt t.TableName c.ColumnName c.AD_Reference_ID c.IsMandatory c.IsUpdateable c.DefaultValue e.Name,e.Description c.AD_Column_ID c.IsKey c.IsParent c.AD_Reference_Value_ID vr.Code c.FieldLength c.ValueMin c.ValueMax c.IsTranslated t.AccessLevel c.ColumnSQL c.IsEncrypted Die Infos aller Spalten werden nach m_columns gebracht. Bei Übersetzungen wird die Tabelle AD_Element_TRL eingesetzt und die Sprache selektiert public static POInfo getPOInfo (Properties ctx, int AD_Table_ID) ruft den Konstruktor auf. getPOInfo() wird ihrerseits jeweils in initPO() der Java Beans für die entsprechende Tabellen-ID aufgerufen.initPO() wird beim PO-Konstruktor aufgerufen. getColumnName (int index) isColumnMandatory (int index) String getColumnDescription (int index) getColumnCount() Class getColumnClass (int index)


Klasse POInfoColumn

package org.compiere.model public class POInfoColumn implements Serializable

Enthält Informationen über eine Spalte des Businessobjektes Properties (alle public) AD_Column_ID ColumnName ColumnSQL DisplayType ColumnClass IsMandatory DefaultLogic IsUpdateable ColumnLabel ColumnDescription AD_Reference_Value_ID ValidationCode FieldLength ValueMin ValueMax ValueMin_BD ValueMax_BD Methoden IsKey IsParent IsTranslated isUpdateable toString IsEncrypted

Zusammenhang zwischen POInfoColumn, PO und Beans (X_-Klassen) POInfoColumn-Instanzen halten Information über die Properties der Businessobjekten (=Spalten) Beans halten die Daten PO kümmert sich um Speichern und Lesen


Business Objekt-Klassen

package org.compiere.model

Es gibt zwei Arten von Business-Objekten Workflow-Business-Objekten Sie werden innerhalb eines Workflows aufgerufen. Sie müssen deswegen den Anforderungen des WF genügen zusätzlich zu ihren BO-Pflichten. z.B: Minvoice, MOrder Klassendefinition public class MInvoice extends X_C_Invoice implements DocAction Mit DocAction wird diese Klasse dieMethoden implementieren, die zur Realisierung eines WF erforderlich sind. Diese Methoden werden von Buttons aufgerufen, die im Application Dictionary bei Table&Columns definiert werden können. Abhängig vom Status und nächster DocAction wird dann die entsprechende Methode aufgerufen.

Zum weiteren Verständnis sieheKapitel über WF.

Diese Methoden fragen Stati ab und setzen Actions. prepareIt() Es werden u.a. Events validiert mit ModelValidationEngine. Die Klasse ModelValidationEngine kann eingesetzt werden, um eigene Business-Logik zu realisieren. Hier werden Events aufgefangen und davon abhängig Dokumenten-Stati und -Typen festgelgt und Methoden aufgerufen. Eine eigene -Klasse definiert man in Client-Fenster, Feld Validierungsklasse. Ein Beispiel eine eigene Validierungsklasse findet man bei Libero. completeIt() Es werden u.a. Events validiert mit ModelValidationEngine approveIt() etc. Document Workflow-Klassen definieren die Property private String m_processMsg, die Meldungen unten links an den Fenstern anzeigen wie "PeriodClosed".

Methoden, deren Zusammespiel die eigentliche Business-Logik realisieren. Z.B. bei Minvoice validatePaySchedule() testAllocation() getOpenAmt() etc.

Stammdaten-Business-Objekten z.B: MProduct public class MProduct extends X_M_Product kein implement-Teil Methoden, deren Zusammespiel die eigentliche Business-Logik realisieren. Z.B. bei MProduct isProductStocked() isOneAssetPerUOM() getAttributeSet() etc.

Die Properties hängen vom Zweck der Klasse ab.

Alle BO implementieren Trigger-Methoden beforeSave() Logik, bevor die Daten gespeichert werden. afterSave() Logik, nachdem die Daten gespeichert worden sind. beforeDelete() Logik, bevor die Daten gelöscht werden afterDelete()

Logik, nachdem die Daten gelöscht worden sind

Business-Klassen implementieren unterschiedliche Konstruktoren entsprechend ihrem Zweck.

Beispiele:

Standard-Konstruktor MInvoiceLine (Properties ctx, int C_InvoiceLine_ID, String trxName) MInvoice to = new MInvoice (from.getCtx(), 0, null); public MProduct (X_I_Product impP) Konstruktor der MProdct-Klasse für den Produkt-Import. Properties eines instanziierten Produktes werden mit den Werten des Objektes impP belegt. Man kann beispielsweise das Verhalten des Imports mit der Klasse ImportProduct und X_I_Product beeinflussen oder mit ValidateModel.


Business-Klassen implementieren des öfteren die static-Methode get(), die ein Array von Objekten dieser Klasse liefern. Besipiel: public static MProduct[] get(Properties ctx, String whereClause, String trxName) Zweck?

Business-Klassen implementieren eine Property zum Loggen von Ereignissen in der Konsole private static Clogger s_log = CLogger.getCLogger (Mproduct.class);

Business-Klassen implementieren einen Objektcache private static CCache<Integer,MInvoice> s_cache= new CCache<Integer,MInvoice>("C_Invoice", 20, 2); // 2 minutes die Anzahl Objekte im Cache (hier 20) und die Verweildaür (hier 2 Minuten) sind je nach Objekt unterschiedlich. org.compiere.util.CacheMgt managt den Cache über den Application Server.


Businesslogik Ich muss zuerst die Methode beschreiben, die alle anderen aufruft, oder wenigstens darauf verweist. Funktionsweise anhand von Minvoice.prepareIt() Model Validation (wenn es eine gibt) Siehe Kapitel über ModelValidation. Holt sich eine Instanz von DocumentType anhand von "C_DocTypeTarget_ID" Prüfung, ob Periode geöffnet ist anhand des DocBaseTyp Zeilenvalidierung überprüfung des Cashbooks Doctype checken oder setzen BOM expandieren Steürberechnung Landed Costs pro Zeile Zürst werden alle Kosten aufsummiert und dann den Zeilen verteilt Bei einer Zeile werden alle Kosten dem Produkt zugewiesen MinvoiceLine allocateLandedCosts() ruft auf MinvoiceLine getBase() Hier ist die Berechnung nach LANDEDCOSTDISTRIBUTION_Costs nicht implementiert. Validierung Docaction setzen

Interface DocAction

package org.compiere.process public interface DocAction

WF-Businessobjekte implementieren die in DocAction definierten Methoden, wie in public class MInvoice extends X_C_Invoice implements DocAction. Ein BO, das DocAction implementiert, wird “Document” genannt. Ihre endgültige Fassung hängt vom Objekt ab. approveIt() Setzt die Property isApproved auf True closeIt() Danach ist keine Action möglich invalidateIt() prepareIt() Logik vor Ausführung processIt() Ausführung der Businesslogik reActivateIt() nach einem closeIt() kann das Dokument wieder aktiviert werden. Es häng vom Objekt ab: ein Invoice kann nicht, ein Order schon wieder aktiviert werden. rejectIt() reverseAccrualIt() reverseCorrectIt() Generiert in Buchhaltung Gegenbuchung. Dafür wird eine Kopie des Originals genommen. unlockIt() eine Methode lockIt() gibt es nicht voidIt() Definiert static final Properties (String-Konstanten) für die Actions und Stati ACTION_Complete ACTION_Close STATUS_Drafted STATUS_Completed etc. Weitere Methoden weswegen habe ich sie von den anderen Methoden getrennt? Sind sie Hilfsmethodern? getApprovalAmt() getCtx() ID vom Satz getDocAction() getDocStatus() Liefert einen der als static final Property definierten Stati getDocumentInfo() Name des Dokumententyps und Dokument-Nr. getDocumentNo() getDoc_User_ID() Kontrolliert die Sequenz Z.B. Verkaufs- Kaufs- Zahlungs-Nr. getProcessMsg () Liefert den Wert der Property m_processMsg get_TrxName() save() setDocStatus () Setzt einen des als static final Property definierten Status u.v.a.m.