For creating a batch class in Dynamics AX we can start from the Tutorial_RunbaseBatch class,
but here is the explanation for understanding all its methods:
In the classDeclaration, we declare any variable that contains user’s selection or preferences
(for example, the customer account for launch a customer report). Also, we declare other
variables like dialog fields, auxiliar variables, etc. But, the most important feature here, is the #localmacro.CurrentList declaration. This macro helps you to define which variables you want
to save for running the class in batch mode (when not user interaction is available).
class Tutorial_RunbaseBatch extends RunBaseBatch { // Packed variables TransDate transDate; CustAccount custAccount; // Dialog fields DialogField dlgCustAccount; DialogField dlgTransDate; // Current version // We can have different versions for different purposes #define.CurrentVersion(1) #define.Version1(1) #localmacro.CurrentList // Our current variable list for save user's selected values transDate, custAccount #endmacro }
The macro #define.CurrentVersion(1) and #define.Version1(1) are useful for scaling our class
when we need to change/upgrade it preserving compatibility.
Now two methods: pack and unpack. These methods are used for store and retrieve user’s
preferences and perform the batch operation when none user are available (in batch mode).
Here is the point where we use the macro defined previously:
public container pack() { return [#CurrentVersion,#CurrentList]; } public boolean unpack(container packedClass) { Version version = RunBase::getVersion(packedClass); ; switch (version) { case #CurrentVersion: [version,#CurrentList] = packedClass; break; //case #otherVersion: //[version,#CurrentList, #otherList] = packedClass; //break; default: return false; } return true; }
public Object dialog() { DialogRunbase dialog = super(); ; // Creation of our custom dialog fields/controls to ask user for preferences dlgTransDate = dialog.addFieldValue(typeid(TransDate),transDate); dlgCustAccount = dialog.addFieldValue(typeid(CustAccount),custAccount); return dialog; } public void dialogPostRun(DialogRunbase dialog) { ; super(dialog); } public boolean getFromDialog() { ; // Retrieving user's preferences transDate = dlgTransDate.value(); custAccount = dlgCustAccount.value(); return super(); } public boolean validate() { // We can perform some validations here if (false) return checkFailed(""); return true; }
server static Tutorial_RunbaseBatch construct() { return new Tutorial_RunbaseBatch(); } public void run() { try { // Obviously, this code is silly, why show something to nobody? // remember, this code is running in batch without user interaction info(strfmt("Parameters: %1 for %2", transDate, custAccount)); } catch(Exception::Deadlock) { retry; } catch(Exception::UpdateConflict) { throw Exception::UpdateConflict; } catch { throw Exception::Error; } } static void main(Args args) { Tutorial_RunbaseBatch tutorial_RunBase; ; // Instanciating this batch class tutorial_RunBase = Tutorial_RunbaseBatch::construct(); // Prompting user and run if all is ok if (tutorial_RunBase.prompt()) tutorial_RunBase.run(); }