Monday, 22 July 2024

Microsoft Dynamics 365 Finance - RunBaseBatch

Background

This is an article I wrote ages ago, originally published on Axaptapedia, which no longer exists. I found the original in my archive and thought it was worth sharing as a blog, as most of it remains relevant for Dynamics 365 Finance and Operations. I've made minor edits and removed deprecated elements from the original, written for Axapta 4.0.

Okay, enough of that. Let's start!

Introduction

The RunBaseBatch class extends the RunBase class and allows creating classes (jobs) that can be added to the batch queue. Once added, the batch server executes the job, a process known as batch processing.

Input Data Parameters

Typically, a class contains logic without a graphical user interface. As RunBaseBatch inherits from RunBase, it uses the dialog framework to prompt users for input parameters interactively. These parameters are class member variables added to the dialog box. The control type depends on the extended data type used. For example, properties like Auto, Combo box, or Radio button can be set on Base enums via the Extended Data Type.

A boolean variable creates a checkbox, an enum a combo box, and a string a text edit control. Each dialog control corresponds to a class variable used to set and retrieve values, persisting them for batch execution. Controls are usually added in code during runtime, requiring a different approach to override methods compared to standard forms. Alternatively, an existing dialog from the AOT can be used for greater control, similar to a standard form.

Parameters enhance job flexibility and reusability, allowing different behaviors based on selections. For instance, a log cleanup job might accept a "days" parameter to delete records older than a user-specified value (e.g., 30 days).

Persistence

Parameters, as class variables, are persisted in the database via the SysLastValue framework. They are packed when the job is queued and unpacked when executed by the batch server. Variables must be listed in a local macro, and the class must override the pack and unpack methods, as RunBaseBatch implements the SysPackable interface.

The pack method is called when a job is queued, and unpack before execution. During batch execution, only new, unpack, and run methods are called, as no user interaction occurs. The run method should contain the core logic.

Query

RunBaseBatch supports queries for data selection. If the queryRun method is overridden, the dialog automatically displays query ranges and values. Users can modify the query via a "Select" button, adding or removing ranges, joining related tables, or changing sort order. For reusable queries, create them in the AOT rather than in code.

Operation Progress

For time-consuming operations, a progress bar is recommended. The RunBase framework's Operation Progress functionality, inherited by RunBaseBatch, can be implemented in the run method to display progress.

Making the Class Runnable

A class is not executable by default. To make it runnable, add a static main method with an Args parameter. The kernel calls this method interactively, passing an Args object containing properties like an active buffer or caller reference. This supports constructor-based object-oriented design and enables access via menu items from the main menu or forms.

Considerations


New Method

As RunBaseBatch classes can run in batch journals, the new method should have no arguments to avoid stack trace errors during batch journal setup.

Version Number

Class variables are listed in a local macro for persistence. A version number tracks changes to the variable list, starting at 1 and incrementing with changes. The unpack method must handle versioning to prevent errors when the persisted variable list size mismatches the macro list.

Methods


new

Creates a new class instance. Called during batch execution.

pack

Persists class variables using a local macro. Called when the dialog is closed with "OK".

unPack

Re-instantiates class variables from the macro. Called before run in batch execution.

dialog

Adds controls to the dialog box, setting values from corresponding class variables.

getFromDialog

Assigns class variable values from dialog controls.

validate

Validates input parameters, displaying an info log for invalid inputs.

run

The central method containing the class's core logic. Called during batch execution.

initParmDefault

Initializes macro list variables when unPack returns false (no usage data found).

queryRun

Returns a queryRun object if the class uses a query.

canGoBatchJournal

Indicates if the class can be included in a batch journal. Default is false.

canGoBatch

Indicates if the class can run in batch. Adds a "Batch" tab to the dialog if true. Default is true.

runsImpersonated

Determines if the job runs under the submitting user’s or batch user’s account. Uses runAs if true. Default is false.

description (static)

Returns the class description, displayed in the batch list and dialog title.

caption

Overrides the base class description for the batch list and dialog title.

Creating a Basic Batch Job Step by Step


Create a Class

From the AOT, create a class extending RunBaseBatch:

public class AV_RunbaseBatchDemo extends RunBaseBatch
{
}

Class Declaration

Add the following to the class declaration:

public class AV_RunbaseBatchDemo extends RunBaseBatch
{
    NoYes displayMessage;
    Description message;

    DialogField fieldDisplayMessage;
    DialogField fieldMessage;

    #define.CurrentVersion(1)

    #localmacro.CurrentList
        displayMessage,
        message
    #endmacro
}

Override the pack Method

public container pack()
{
    return [#CurrentVersion, #CurrentList];
}

Override the unpack Method

public boolean unpack(container _packedClass)
{
    Integer version = RunBase::getVersion(_packedClass);

    switch (version)
    {
        case #CurrentVersion:
            [version, #CurrentList] = _packedClass;
            break;

        default:
            return false;
    }

    return true;
}

Create the description Method

This sets the batch queue description and dialog caption:

public static ClassDescription description()
{
    return 'Runbase batch demo';
}

Create the construct Method

public static AV_RunbaseBatchDemo construct()
{
    return new AV_RunbaseBatchDemo();
}

Override the initParmDefault Method

public void initParmDefault()
{
    super();
    displayMessage = NoYes::Yes;
    message = 'Hello World!';
}

Override the dialog Method

protected Object dialog()
{
    DialogRunbase dlg;

    dlg = super();
    fieldDisplayMessage = dlg.addFieldValue(typeId(NoYes), displayMessage, 'Display message', 'Indicates whether to display a message or not.');
    fieldMessage = dlg.addFieldValue(typeId(Description), message, 'Message', 'The message to display');
    return dlg;
}

Override the getFromDialog Method

public boolean getFromDialog()
{
    boolean ret;

    ret = super();
    
    displayMessage = fieldDisplayMessage.value();
    message = fieldMessage.value();
    
    return ret;
}

Override the run Method

public void run()
{
    if (displayMessage)
    {
        info(message);
    }
}

Create the static main method to make the class runnable.

public static void main(Args _args)
{
    AV_RunbaseBatchDemo rb = AV_RunbaseBatchDemo::construct();

    if (rb.prompt())
    {
        rb.run();
    }
}

No comments:

Post a Comment