AX 2012: Beispiel für die Verwendung des SysOperation-Frameworks
04.11.2012Microsoft Dynamics AX (Axapta)
|
Dieser Beitrag bezieht sich auf die Version:
Dynamics AX 2012
Dynamics AX 2012
Super Beitrag, herzlichen Dank! Eine Frage bezüglich der gespeicherten Datei. In einer 3-Tier Architektur wird das File auf dem AOS Server abgelegt. Wie öffnet der User die Datei wenn er nur Zugriff auf AX über Remote App oder RDS Server hat? |
Wenn man nur Zugriff auf AX über Remote App hat, befürchte ich hat man schlechte Karten. Mein Beispiel geht davon aus, daß der Benutzer die Datei an einer Stelle ablegt auf die er auch Zugriff hat. |
|
|
|
|
|
|
Das SysOperation-Framework ist eine Neuerung in Dynamics AX 2012 und soll das RunBasebatch-Framework ersetzen. In der MSDN sind zahlreiche Dokumentationen und Whitepaper über dieses Framework zu finden, welche ich unbedingt empfehle zu lesen.
Der folgende Beitrag enthält ein bewusst einfach gehaltenes Beispiel, wie man in AX 2012 Programmlogik auf Basis dieses Framework einsetzen kann.
Das Beispiel besteht dabei aus insgesamt vier Klassen:
Data Contract Class
Eine Data Contract Class besteht im Grunde genommen lediglich aus Accessor-Methoden (parm...-Methoden) und ist dadurch gekennzeichnet, daß in der classDeclaration() das Attribute DataContractAttribute verwendet wird.
Für alle Accessor-Methoden des Data Contracts werden vom SysOperation-Framework beim Aufruf entsprechende Dialogfelder generiert.
DIe weiteren im Beispiel verwendeten Attribute SysOperationContractProcessingAttribute bzw. SysOperationGroupAttribute verknüpfen zum Einen den Data Contract mit einem UI Builder und zum Anderen wird - neben der standardmässig immer generierten Feldgruppe namens Parameter - eine weitere Feldgruppe mit dem internen Namen DemoGroup.
Accessor-Methoden eines Data Contracts müssen immer über das Attribute DataMemberAttribute gekennzeichnet werden. Das Attribute SysOperationDisplayOrderAttribute legt die Reihenfolge der Felder im Dialog fest und mit Hilfe des Attributes SysOperationGroupMemberAttribute wird gesteuert, daß das Feld innerhalb der in der classDeclaration() definierten Feldgruppe eingeordnet wird.
Die Accessor-Methode für das Datum unterscheidet sich im groben nur durch ein weiteres verwendetes Attribute SysOperationLabelAttribute mit Hilfe dessen das Label des Dialogfeldes festgelegt wird.
Das hier anzugebende Datum ist im übrigen lediglich zu Demonstrationszwecken implementiert und hat keinen erwähnenswerten Einfluss auf die Programmlogik.
In der Accessor-Methode für den Dateinamen wird über das Attribute SysOperationDisplayOrderAttribute festgelegt, daß das Feld das Erste im Dialog sein soll.
Eine Besonderheit unter den im Beispiel verwendeten parm-Methoden stellt die folgende Methode dar. Weil innerhalb von Accessor-Methoden nicht jeder in AX zur Verfügung stehender Datentyp verwendet werden kann, muss ein Query beispielsweise in einen String umgewandelt und übergeben werden. Das SysOperation-Framework stellt dafür eigene Methoden zur Verfügung.
Die Methode validate() steht nur zur Verfügung, wenn in der classDeclaration() des Data Contracts die Klasse SysOperationValidatable eingebunden wurde. Dann funktioniert sie ähnlich, wie im RunBaseBatch-Framework.
Die Methode initialize() steht nur zur Verfügung, wenn in der classDeclaration() des Data Contracts die Klasse SysOperationInitalize eingebunden wurde. Diese Methode wird nur aufgerufen, wenn keine Nutzungsdaten vorhanden oder verwendet werden.
Service Class
Diese - von SysOperationServicebase abgeleitete - Klasse, enthält die eigentliche Logik des Beispiels.
Genauergesagt ist die Logik in der Methode runService() enthalten. Die Besonderheit dieser Methode ist, daß sie als einzigen Parameter den Data Contract erhält und daß das Attribute SysEntryPointAttribute gesetzt ist. Der Name der Methode hingegen bleibt dem Entwickler überlassen, die Methode wird über den Namen in der Methode newFromArgs() des Service Controllers referenziert.
Die im Beispiel enthaltene Methode enthält keine aufregende Logik, sie erstellt ledigich eine einfache Text-Datei und schreibt in diese einige Werte aus den über den Query übergebenen Ausgangsrechnungen.
Controller Class
Eine Controller Class muss von SysOperationServiceController abgeleitet sein.
Die Methode newFromArgs() ist eine selbst erstellte Methode, die dazu dient, die Klasse zu instanziieren. Dabei wird die Klasse und die als Service aufzurufende Methode festgelegt. Gleichzeitig wird über die Methode parmArgs() des Frameworks der Aufrufer für einen evtl. späteren notwendigen Zugriff gespeichert.
Die initQuery() dient dazu, den Query für den Dialog zu initalisieren. Diese Methode wird später von der Methode initializeServiceParameter() aufgerufen.
Erwähnenswert ist in Verbindung mit dem Query die Klasse SysOperationHelper, die u.a. Methoden zur Verfügung stellt, um einen Query in einen String zu konvertieren und umgekehrt. Dies ist notwendig, da der Data Contract nur mit "einfachen" Datentypen arbeiten kann.
Wie zuvor angekündigt, verwende ich die Methode initializeServiceParameter() um den Query des Dialoges über die Methode initQuery() zu initalisieren. Weiters wird an dieser Stelle ein weiterer Parameter mit Werten befüllt.
Die main()-Methode ist bereits aus dem RunBaseBatch-Framework hinreichend bekannt. Sie wird immer dann aufgerufen, wenn die Controller Class über ein MenuItem aufgerufen wird.
In dieser Methode wird - über die oben erwähnte Methode newFromArgs() - die Klasse instanziiert. Weiters wird über parmExecutionMode() der Ausführungsmodus festgelegt und schließlich über startOperation() der eigentliche Aufruf des Service gestartet.
Diese Methode retouniert übrigens einen Enum-Wert vom Typ SysOperationStartResult mit Hilfe dessen man abfragen kann, ob das Service beispielsweise sofort oder im Stapel gestartet wurde oder ob der Dialog vom Benutzer abgebrochen wurde.
UI Builder Class
Eine User Interface Builder Class ist dadurch gekennzeichnet, daß sie von SysOperationAutomaticUIBuilder abgeleitet ist. Eine solche Klasse kann dazu verwendet werden, den vom Framework automatisch generierten Dialog um eigene Logik zu erweitern.
Die Verknüpfung zwischen Data Contract und UI Builder erfolgt dabei über das Attribute SysOperationContractProcessingAttribute in der classDeclaration() des Data Contracts.
Ein Ziel unserer UI Builder Class ist, das Lookup-Formular des Feldes für das Debitorenkonto zu übersteuern. Dazu erstellen wird eine neue Methode beliebigen Namens - im Beispiel custAccount_lookup() - und befüllen diese mit dem gewünschten Programmcode. Im Grunde genommen unterscheidet sich die Methode nicht von anderen, ähnlichen Lookup-Methoden. Das einzige worauf man achten muß ist, daß die Methode die gleichen Parameter enthält, wie die gleichwertige Methode eines Formulares.
Die Methode postBuild() ist ein idealer Platz, um die in der classDeclaration() deklarierte Variable vom Typ DialogField über bindInfo().getDialogField() mit Leben zu befüllen.
Auch ist die Methode gut dazu geeignet, die Eigenschaften von Dialogfelder abhängig vom Aufrufer zu übersteuern. Im Beispiel wird dazu die Methode parmArgs() des Service Controllers abgefragt.
In der Methode postRun() kann man nun das Dialogfeld mit der oben beschriebenen Lookup-Methode verbinden.
Menu Item
Als letzten Schrittt gilt es nun ein MenuItem für die Service Controller Class zu erstellen. Ruft man dieses MenuItem auf, so sollte sich das oben beschriebene Beispiel wie folgt im Client darstellen: