Logging independently of transaction scope by using a separate thread in Dynamics AX

Good morning,

Continuing on the topic of good ideas to palliate lazy code designs (ref: previous post on runbuf()), I wanted to discuss a possible way to write to a table from inside a TTS (between a begin and a commit) without being rolled back if an error is thrown or if a ttsabort is called.

Doing this is definitely not best practice, but it was extremely useful for me when I wanted to log information to a table from inside a TTS that would throw errors on occasion where catching was not behaving ideally because of an encompassing TTS (I’ll follow up on that on another post).

So basically, the idea I had is to launch a separate thread only for logging, this would effectively isolate the table insert from the encompassing TTS and would not be rolled back on error in the originating thread. So the logging would always occur regardless of errors.

Here’s a sample of the code:

public class LogThread
{
public server static void logThreadWorker(Thread t)
{
    LogTable log;
    ;

    [log.ParmId,
        log.XmlRequest,
        log.XmlResponse] = t.getInputParm();
    log.insert();
}
}

//Use a separate thread to survive a ttsabort
public server static void logUsingThread(
    str _parmId,
    str _xml1,
    str _xml2)
{
    Thread thread;
    ExecutePermission permission;
    ;

    permission = new ExecutePermission();
    if (!permission)
    {
        return;
    }

    permission.assert();

    // BP deviation documented.
    thread = new Thread();
    if (thread)
    {
        thread.removeOnComplete(true);
        thread.setInputParm([_parmId, _xml1, _xml2]);
        thread.run(classnum(LogThread),
            staticmethodstr(LogThread, logThreadWorker));
    }

    CodeAccessPermission::revertAssert();
}

//This method is the entry point for logging, and is called from a series of transactions and operations that might fail.
//It is called from inside a large TTS encompassing multiple business processes.
protected void log(
    MyWebservice.WebServiceWrapper _webServiceWrapper)
{
    ;

    LogTable::logUsingThread(
        this.parmId(), //I had a parmId for every request to the webService
        _webServiceWrapper.get_LastXmlRequestDoc(),
        _webServiceWrapper.get_LastXmlResponseDoc());
}

This entry was posted in Dynamics Ax 4.0x. Bookmark the permalink.