Search code examples
axaptax++dynamics-ax-2009

How to run the class method set with client keyword to run in batch?


The run method shown below is from the class Tutorial_RunbaseBatch to run it in batch.

I made the following changes:

  1. Modified the method constructSecurityKeySet in class SysSecurity to server client static public SecurityKeySet constructSecurityKeySet()

  2. Modified the method runJobStatic in class BatchRun to server client static void runJobStatic(recId batchId)

I am aware of the fact that I should not be playing around with the framework classes but this is just a research. It worked fine until I added the following code sections.

Code change 1:

MenuItemName    menuItemName;
AccessType      act;

Code change 2:

act = securitySet.secureNodeAccessmenuItemName,SysSecurity::accessRecType2UtilElementType(AccessRecordType::MenuItemDisplay)); // Line 24

Now, I get the below error message after adding the above code sections

The server-side impersonated (RunAs) session tried to invoke a method that is available for client-side processing only.
(S)\Classes\Tutorial_RunbaseBatch\run - line 24 
(S)\Classes\BatchRun\runJobStatic - line 62 //which is  batchClass.run();

The SecurityKeySet(SystemClass) has the property RunOn set to calledFrom and is executed wherever the object is called from, which could be client or server. It also has dependencies on Class Batchable and BatchRunable. Both the classes have the property RunOn set to calledFrom

I tried changing the properties to server on the classes but that did not work

Is there anyway to make this code work?

Complete code:

public void run()
{
    SecurityKeySet      securitySet;
    UserGroupId         fromUserGroupId;
    DomainId            domainId;
    MenuItemName        menuItemName;
    AccessType          act;
    ;

    #OCCRetryCount

    fromUserGroupId = "XXXX";
    domainId        = "YYYY";

    if (!this.validate())
        throw error("");

    try
    {
        ttsbegin;
        // this.Update();
        securitySet=SysSecurity::constructSecurityKeySet();//error
        securitySet.loadGroupRights(fromUserGroupId,domainId);
        act = securitySet.secureNodeAccess(menuItemName,SysSecurity::accessRecType2UtilElementType(AccessRecordType::MenuItemDisplay));
        ttscommit;
    }
    catch (Exception::Deadlock)
    {
        retry;
    }
    catch (Exception::UpdateConflict)
    {
        if (appl.ttsLevel() == 0)
        {
            if (xSession::currentRetryCount() >= #RetryNum)
            {
                throw Exception::UpdateConflictNotRecovered;
            }
            else
            {
                retry;
            }
        }
        else
        {
            throw Exception::UpdateConflict;
        }
    }
}

Solution

  • Reason for the issue:

    SysSecurity class is by default set to run on the Client. Changing the method constructSecurityKeySet to server client static will not help to run the code on the server. You can change the RunOn property on the class SysSecurity but there might be a reason why it is set to run on Client. Hence, I would not recommend the option of changing the RunOn mode to Client.

    However, if you still want to try running the code in batch. You can read through the below description about the same error that I faced and how I resolved the issue using a workaround.

    Similar issue:

    I faced the same error message while trying to run SalesInvoice report in Batch to e-mail invoice PDFs.

    The server-side impersonated (RunAs) session tried to invoke a method that is available for client-side processing only.

    The issue with my scenario was the report had an image and embedding logo into the report involved client side processing and the batch process could not handle that while running on the server. Jobs added to the batch process always runs on the Server.

    Perform the following steps in AX to find this information.

    1. Navigate to Basic \ Inquiries \ Batch job
    2. Click the batch job
    3. Click View tasks on the right side to bring the tasks window
    4. On the Tasks window, the column Run location should display Server, where the job executes.

    Caution:

    I would suggest using caution with the below mentioned approach to update the batch job data in the database using T-SQL query.

    Possible fix:

    To run the SalesInvoice job on the client, like it used to do in 4.0, I ended up modifying the value directly in the database using the below query.

    UPDATE dbo.BATCH SET RUNTYPE = 0 WHERE CAPTION = '<Your job caption name...>'
    

    Once the query has been executed to update the batch job data, verify that the Run location column under the Tasks window of the job is set to Client. When the job task is set to run in Client, it will not execute unless the Batch processing is initiated. Batch processing can be started by navigating to Basic \ Periodic \ Batch \ Processing.