Development Guidelines in German

From ADempiere
Revision as of 13:47, 21 September 2007 by Vpj-cd (Talk)

Jump to: navigation, search
This Wiki is read-only for reference purposes to avoid broken links.

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