We recently came across an issue on Microsoft Dynamics AX 2012 RTM CU-2.  When we try to run the report "Accounts receivable\reports\external\customer account statement", AX ends up hanging. This happens in every environment if I just choose a customer account and leave all else as default.

The reason we found was:

In \Classes\SrsReportRunRdpPreProcessService, executeWithContract method, there are some code shown below, there is a UserConnection ttsBegin and UserConnection ttsCommit pair embedded in global ttsBegin and ttsCommit pair, this makes the database write operation to hang.

// switch company to that user. 
changecompany(companyId)
{

// check if any pre-processing id already exists, if yes, then call cleanup, this will take care of cleaning up left over data.
if(_preProcessedRecId)
{
this.cleanUp(_preProcessedRecId, reportContract.parmRdpName());
}


// starting a default transaction, since some RDP classes do delete as part of their code and they dont have a explicit ttsbegin/ttscommit.
// they were relying on the old behvior of SrsReportRunRdpPreProcessService class starting a default ttsbegin/commit.


ttsBegin;


// We start transaction before calling processReport. By doing so, all data
// inserted by RDP into table will have the same transactionId.
// Always use a UserConnection. The service is currently running on RPC call and hence if outer transaction exists we dont want it to be used.


userConnection = new UserConnection(true);
userConnection.ttsbegin();


// set user connection on RDP class.
rdpInstance.parmUserConnection(userConnection);


// call processReport
rdpInstance.processReport();


// now create a entry in table with report name etc.
// transactionId will be same as the one used in processReport().
preProcessedTable = SrsReportPreProcessedDetails::create(reportContract.parmRdpName(), userConnection, _isPreviewData);


// commit the transaction.
userConnection.ttscommit();
ttsCommit;
}

 

To workaround, the suggestion is to comment out those inner transactions, so that code looks as given in the highlighted sections below:

// switch company to that user. 
changecompany(companyId)
{


// check if any pre-processing id already exists, if yes, then call cleanup, this will take care of cleaning up left over data.
if(_preProcessedRecId)
{
this.cleanUp(_preProcessedRecId, reportContract.parmRdpName());
}


// starting a default transaction, since some RDP classes do delete as part of their code and they dont have a explicit ttsbegin/ttscommit.
// they were relying on the old behvior of SrsReportRunRdpPreProcessService class starting a default ttsbegin/commit.
ttsBegin;


// We start transaction before calling processReport. By doing so, all data
// inserted by RDP into table will have the same transactionId.
// Always use a UserConnection. The service is currently running on RPC call and hence if outer transaction exists
// we dont want it to be used.


userConnection = new UserConnection(true);
//userConnection.ttsbegin();

// set user connection on RDP class.
rdpInstance.parmUserConnection(userConnection);


// call processReport
rdpInstance.processReport();


// now create a entry in table with report name etc.
// transactionId will be same as the one used in processReport().
preProcessedTable = SrsReportPreProcessedDetails::create(reportContract.parmRdpName(), userConnection, _isPreviewData);


// commit the transaction.
//userConnection.ttscommit();
ttsCommit;
}

 

--author: Mansour Yahya Mohamad