Comparison of the SysOperation and RunBase frameworks in Ax 2012

Description:- SysOperation is a framework in Microsoft Dynamics® AX 2012 that allows application logic to be written in a way that supports running operations interactively or via the Microsoft Dynamics AX batch server. The framework provides capabilities that are very similar to the RunBase framework that came before it. The batch framework has very specific requirements for defining operations:

1.       The operation must support parameter serialization so that its parameters can be saved to the batch table.
2.       The operation must have a way to display a user interface that can be launched from the batch job configuration user interface.
3.       The operation must implement the interfaces needed for integration with the batch server runtime.

The RunBase framework defines coding patterns that implement these requirements. The SysOperation framework provides base implementations for many of the patterns defined by the RunBase framework.

SysOperation and RunBase are frameworks geared toward building operations that can run via the batch server or interactively. In order for an operation to run via the batch server, it must meet these requirements:

1.       It must support parameter serialization via the SysPackable interface.
2.       It must support the standard run () method defined in the BatchRunable interface.
3.       It must support the batch server integration methods found in the Batchable interface.
4.       It must provide a mechanism to show input parameters with a user interface.

Currently in Microsoft Dynamics AX, all operations that must run via the batch server must derive from either the SysOperationController or the RunBaseBatch base class.
The following two samples illustrate the basic capabilities provided by the two frameworks:

1.       SysOpSampleBasicRunbaseBatch
2.       SysOpSampleBasicController

The simplest operation based on the RunBaseBatch base class has to implement 12 overrides. The purpose of this sample is simply to compare the RunBase and SysOperation frameworks. For full details of the RunBase framework, see the following article on MSDN: RunBaseBatch FrameWork

Create Class in Ax Classes node and Name itSysOpSampleBasicRunbaseBatch”. 
ClassDeclaration
  1. Derives from RunBaseBatch.
  2. Declares variables for operation input parameters.
  3. Declares variables for dialog box controls.
  4. Declares a macro defining a list of variables that need to be serialized.
class SysOpSampleBasicRunbaseBatch extends RunBaseBatch
{
    str text;
    int number;
    DialogRunbase       dialog;

    DialogField numberField;
    DialogField textField;

    #define.CurrentVersion(1)

    #LOCALMACRO.CurrentList
        text,
        number
    #ENDMACRO
}

Dialog

Populates the dialog box created by the base class with controls needed to get user input. The initial values from the class member variables are used to initialize the controls. The type of each control is determined by the EDT identifier name.

protected Object dialog()

{

dialog = super();

textField = dialog.addFieldValue(IdentifierStr(Description255),

text,

'Text Property',

'Type some text here');

numberField = dialog.addFieldValue(IdentifierStr(Counter),

number,

'Number Property',

'Type some number here');

return dialog;

}

getFromDialog

Transfers the contents of dialog box controls to operation input parameters.

public boolean getFromDialog()

{

text = textField.value();

number = numberField.value();

return super();


putToDialog

Transfers the contents of operation input parameters to dialog box controls.

protected void putToDialog()

{

super();

textField.value(text);

numberField.value(number);


pack

Serializes operation input parameters.

public container pack()

{

return [#CurrentVersion, #CurrentList];


unpack

Deserializes operation input parameters.

public boolean unpack(container packedClass)

{

Integer version = conPeek(packedClass,1);

switch (version)

{

case #CurrentVersion:

[version,#CurrentList] = packedClass;

break;

default:

return false;

}

return true;


run

Runs the operation. This sample prints the input parameters via the Infolog. It also prints the tier that the operation is running on and the runtime that is used for execution.

public void run()
{
    if (xSession::isCLRSession())
    {
        info('Running in a CLR session.');
    }
    else
    {
        info('Running in an interpreter session.');
        if (isRunningOnServer())
        {
            info('Running on the AOS.');
        }
        else
        {
            info('Running on the Client.');
        }
    }
    info(strFmt('SysOpSampleBasicRunbaseBatch: %1, %2', this.parmNumber(), this.parmText()));
}

description

A static description for the operation. This description is used as the default value for the caption shown in batch and the operation user interface.

public static ClassDescription description()
{
    return 'Basic RunBaseBatch Sample';
}

main

The main interaction code for the operation. This code prompts the user for input, and then runs the operation or adds it to the batch queue.

public static void main(Args args)
{
    SysOpSampleBasicRunbaseBatch operation;

    operation = new SysOpSampleBasicRunbaseBatch();
    if (operation.prompt())
    {
        operation.run();
    }
}

parmNumber

Optional. It is a Microsoft Dynamics AX best practice to expose operation parameters with the property pattern for better testability and for access to class member variables outside the class.

public int parmNumber(int _number = number)
{
    number = _number;

    return number;
}

parmText

Optional. It is a best practice to expose operation parameters with the property pattern.

public str parmText(str _text = text)
{
    text = _text;

    return text;
}
After it is implemented, the operation can be run by using the Go button on the code editor toolbar.
 If an X++ class implements the main operation, it is automatically called by the code editor. The sample’s main operation will prompt the user for input for the operation when operation.prompt () is called. If the prompt returns true, main calls operation.run () directly. If the prompt returns false, the user either cancelled the operation or scheduled it via batch.
To run the operation interactively, enter data on the General tab of the operation user interface.


Make sure that the Batch processing check box is cleared on the Batch tab.


Clicking OK will run the operation and print the following output to the Infolog window.

The Infolog messages show that the operation ran on the server, because the sample class is marked to run on the server. The operation ran via the X++ interpreter, which is the default for X++ code. 

If you repeat the previous steps but select the Batch processing check box on the Batch tab, the operation will to run via the batch server. When the Batch processing check box is selected, the following Infolog message is shown, indicating that the operation has been added to the batch queue.

The operation may take up to a minute to get scheduled. After waiting for about a minute, open the Batch job form from the Application Object Tree (AOT).
 Repeatedly update the form by pressing the F5 key, until the job entry shows that the job has ended. Sorting by the Scheduled start date/time column may help you find the operation if there are many job entries in the grid. After you find the correct job, select it, and then click Log on the toolbar.

Clicking Log opens an Infolog window indicating that the operation ran in a CLR session, which is the batch server execution environment.



In summary, this sample shows the minimum overrides needed to create an operation that can run either interactively or via the batch server by using the RunBaseBatch base class. 

SysOpSampleBasicController 
The purpose of the SysOperation framework is to provide the same capabilities as the RunBase framework but with base implementations for common overrides. The SysOperation framework handles basic user interface creation, parameter serialization, and routing to the CLR execution environment. The following table of overrides shows the code needed to match the functionality demonstrated for the RunBase-based sample in the previous section.

The SysOperation sample contains two classes: a controller class named SysOpSampleBasicController and a data contract class named SysOpSampleBasicDataContract.



SysOpSampleBasicController should derive from SysOperationServiceController, which provides all the base functionality for building operations; however, there are a few issues with that class as it is shipped with Microsoft Dynamics AX 2012, and these will be addressed in a future service pack. In the meantime, to work around the issues, a new common class, SysOperationSampleBaseController, is provided. Details of the issues worked around will be discussed at the end of this paper. 
Create Class in Classes node and Name it SysOperationSampleBaseController.
classDeclaration

Derives from the framework base class SysOpSampleBaseController.
Normally the operation should derive from the SysOperationServiceController class. The sample base class provides a few fixes for issues in that class.

class SysOpSampleBasicController extends SysOpSampleBaseController
{
}

new

Identifies the class and method for the operation. In the sample, this points to a method on the controller class; however, in general, it can be any class method.
The framework will reflect on this class/method to automatically provide the user interface and parameter serialization.

void new()
{
    super();

    this.parmClassName(classStr(SysOpSampleBasicController));
    this.parmMethodName(methodStr(SysOpSampleBasicController, showTextInInfolog));
    this.parmDialogCaption('Basic SysOperation Sample');
}

showTextInInfolog

Prints the input parameters via the Infolog. Also prints the tier that the operation is running on and the runtime that is used for execution.

public void showTextInInfolog(SysOpSampleBasicDataContract data)
{
    if (xSession::isCLRSession())
    {
        info('Running in a CLR session.');
    }
    else
    {
        info('Running in an interpreter session.');
        if (isRunningOnServer())
        {
            info('Running on the AOS.');
        }
        else
        {
            info('Running on the Client.');
        }
    }
    info(strFmt('SysOpSampleBasicController: %1, %2', data.parmNumber(), data.parmText()));
}

caption

A description for the operation. This description is used as the default value for the caption shown in batch and the operation user interface.

public ClassDescription caption()
{
return 'Basic SysOperation Sample';
}

main

The main interaction code for the operation. This code prompts the user for input, and then runs the operation or adds it to the batch queue.

public static void main(Args args)
{
    SysOpSampleBasicController operation;

    operation = new SysOpSampleBasicController();
    operation.startOperation();
}

Now Create a Class from Classes node and name it “SysOpSampleBasicDataContract”.

classDeclaration

The data contract attribute is used by the base framework to reflect on the operation.

[DataContractAttribute]
class SysOpSampleBasicDataContract
{
    str text;
    int number;
}

parmNumber

The data member attribute identifies this property method as part of the data contract. The label, help text, and display order attributes provide hints for user interface creation.

[DataMemberAttribute,
SysOperationLabelAttribute('Number Property'),
SysOperationHelpTextAttribute('Type some number >= 0'),
SysOperationDisplayOrderAttribute('2')]
public int parmNumber(int _number = number)
{
    number = _number;

    return number;
}

parmText

The data member attribute identifies this property method as part of the data contract. The label, help text, and display order attributes provide hints for user interface creation.

[DataMemberAttribute,
SysOperationLabelAttribute('Text Property'),
SysOperationHelpTextAttribute('Type some text'),
SysOperationDisplayOrderAttribute('1')]
public Description255 parmText(str _text = text)
{
    text = _text;

    return text;
}

As in the RunBase sample, the operation can be run by using the Go button on the code editor toolbar.
The main class calls operation.startOperation(), which handles running the operation synchronously or adding it to the batch queue. Although operation.run() can also be called, this should be done only if the data contract has been programmatically filled out. The startOperation method invokes the user interface for the operation, and then calls run.
To run the operation interactively, enter data on the General tab of the operation user interface. The user interface created by the framework is very similar to the one created in the RunBase sample.
Make sure that the Batch processing check box is cleared on the Batch tab.
Clicking OK will run the operation and print the following output to the Infolog window.
The Infolog messages show that, unlike in the RunBase sample, the operation ran in a CLR session on the server. If you repeat the previous steps but select the Batch processing check box on the Batch tab, the operation will run via batch, just as in the RunBase sample.
The operation may take up to a minute to get scheduled. After waiting for about a minute, open the Batch job form from the AOT, as in the RunBase sample.
Repeatedly update the form by pressing the F5 key, until the job entry shows that the job has ended. Sorting by the Scheduled start date/time column may help you find the operation if there are many jobs entries in the grid. After you find the correct job, select it, and then click Log on the toolbar.
Clicking Log opens an Infolog window indicating that the operation ran in a CLR session, which is the batch server execution environment.
This sample showed that the SysOperation framework can provide the same basic functionality as the RunBase framework. In addition, it provides implementation for common RunBase overrides, such as parameter serialization and user interface creation. It also provides the capability to route synchronous operations to a CLR session.

Related Posts

Previous
Next Post »

Thanks for comments.....