Archive

Posts Tagged ‘batch’

Business Operation Framework and multi-threading

February 25th, 2012 1 comment

Some of you will be familiar enough with Ax 2009 and therefore know how to create multiple threads when running batch jobs.
For those of you who aren’t : no worries! Since most of it will be done in the same way as before, you will be up to speed in no time.

The main difference in Ax 2012 is the Business Operation Framework that renders the RunBaseBatch framework kinda obsolete. (Read : It’s MS best practice to use BOF instead of RunBaseBatch). The BOF lets you create services and run these services in CIL. I will spare you the full details about CIL as it out of the scope of this article. You can find all the details about creating these services in some very nice posts of a colleague of mine.

Now that you have seen the basics, let’s get to the point of this article. Today we were wondering if the new BOF would also be able to handle multi-threaded batch processing and escpecially how it would be accomplished. Well here’s how…

In this example I will use a rather useless functionality but it’s done like this to keep things simple. I will have a set with some names in it and instead of running a service to display them all we will create two services :

  • The KeSaeBatchService will be used to run the batch job with and devide the work into smaller threads
  • The KeSaeRunTaskService will act as one of those threads running in batch

Creating the run task service

First thing to do is creating the KeSaeRunTaskService and creating a datacontract for it to contain a name it will be passed as a parameter. So start by creating the data contract.

[DataContractAttribute]
public class KeSaeRunTaskDataContract
{
    Name mName;
}
 
[DataMemberAttribute]
public Name parmName(Name _name = mName)
{
    ;
    mName = _name;
    return mName;
}

Now that we have the contract, let’s create the service class. The service class just contains one method ‘process‘ that will be passed a data contract.

class KeSaeRunTaskService
{
}
 
[SysEntryPointAttribute]
public void process(KeSaeRunTaskDataContract _theContract)
{
    ;
    // Inside the runTimeTask we just print the name passed
    info(strFmt('%1', _theContract.parmName()));
}

Now create a service within the AOT and add the operation as seen below.

Creating the batch operation service

Now let’s do the same thing all over again, but for the service that will be submitted to the batch framework.
The only additional thing here is to create a menu item to that service to be able to run it.

And last but not least we need to put in some code in the batch service to create smaller runTimeTasks when processing in batch so let’s take a look at the process method.

[SysEntryPointAttribute]
public void process()
{
    Set             theNames = new Set(Types::String);
    SetEnumerator   theEnum;
    Name            theName;
    ;
 
    // Add some names to the set to process
    theNames.add('Kenny');
    theNames.add('Klaas');
    theNames.add('Kevin');
    theNames.add('Tom');
    theNames.add('Ronald');
 
    // Create the enumerator
    theEnum = theNames.getEnumerator();
 
    // Loop all the names
    while (theEnum.moveNext())
    {
        // Get the next name
        theName = theEnum.current();
 
        // Create a service controller to run the task for processing one name
        mController = new SysOperationServiceController(classStr(KeSaeRunTaskService), methodStr(KeSaeRunTaskService, process));
 
        // Fetch the data contract from within the controller
        mContract = mController.getDataContractObject('_theContract');
 
        // Put the current name in the controller's data contract
        mContract.parmName(theName);
 
        // Check if we are batch processing or not
        if(this.isExecutingInBatch())
        {
            if(!mBatchHeader)
            {
                mBatchHeader = BatchHeader::getCurrentBatchHeader();
            }
 
            // Create a runTimeTask within the current batch job
            mBatchHeader.addRuntimeTask(mController, this.getCurrentBatchTask().RecId);
        }
        else
        {
            // Just run it immediately
            mController.run();
        }
    }
 
    // If we're processing in batch, then save the batch header
    if(mBatchHeader)
    {
        mBatchHeader.save();
    }
}

This piece of code differs from Ax 2009 by constructing a SysOperationServiceController instead of a RunBaseBatch class to add as a runTimeTask. This works because the SysOperationServiceController extends the SysOperationController which in it’s turn implements Batchable.

class SysOperationServiceController extends SysOperationController
public abstract class SysOperationController extends Object implements Batchable

That’s about it! Do not forget to compile CIL! Then you should be seeing this when your service is being processed in batch.

And when clicking the parameters button on one of the threads, you can see the name that was passed in the data contract to the thread.

All this can be found in an XPO file available here.

Decisions Dynamics Ax Virtual Conference

November 1st, 2010 No comments

This afternoon the virtual conference will take place at 09:00 am EST (3 pm ET).

Decisions technical conference

The session content can be found here but I’m particularly interested in the Performance session (presented by Dick Wenning) and the Batch framework session (presented by Robert Boone).

Please not that registering can still be done and is completely free of charge !
So see you guys at the virtual conference then ! (That is, if I can get to log in to the conference since I haven’t found the login link yet ;-) )