Thursday, December 31, 2015

AX 2012 - RunBaseBatch Multithreading

Hi All

In AX 2012 Microsoft introduced the new framework (Business Operation Framework service) in order to consume a Batch process especially in Multithread.

But, you can use also the "old" RunBaseBatch class.
About it, take a look to this very interesting POST.

In order to submit a "task" class you can use two methods :

1- "AddRuntimeTask" method.
Adds an instance of a dynamic BatchTask to the BatchHeader.  The BatchTask added exists for only the current run.  It gets copied into the history tables and deleted at the end of the run.  The second parameter, inheritFromTaskId, copies settings such as the batch group and child dependencies from the task specified.

2- "AddTask" method.
Adds an instance of a BatchTask to the BatchHeader.  The BatchTask represents a batch-enabled class that will be scheduled for execution as a task by the BatchHeader.

So, you have to use the first one method otherwise if the process is recursive also the previous child completed tasks will be moved in running state together with the new tasks.

Happy new year!!

 

Tuesday, December 29, 2015

AX 2012 – Export Model Error: The file exists

Hi Guys

Never seen this error? If not, you are lucky!
I faced it during the TFS Build Process. The service is associate to the USER 1.

The strange thing is that the same command run with the User (USER1) works fine. The issue coming running the command in the USER 2 session (RDP Session) and impersonate USER 1.
I didn't understand the reason, so the workaround is been to create a new Active Directory user and associate it to the TFS Build Service.

That's it!

26/06/2017 : I have understood the issue! We need to delete the content of the Temp TFS agent user folder, like C:\Users\TfsAgent\AppData\Local\Temp

AX 2012 - AOS Freeze or Crash during CIL Compilation


Hi All

Today I’d like to share an issue that took a lot of my time!
I'm using AX 2012 R3.
At a certain point, the CIL Compilation failed and the AOS crashed or freeze without any errors that could help me.

For my lucky I use TFS so I try to verify the last check-in, one by one.


Finally I found the problem.

The code below cause the AOS Crash or Freeze during CIL Compilation, Incremental and Full as well.


public void updateRecordsetList()

{

    CustInvoiceTable    custInvoiceTable;

    CustinvoiceJour     CustinvoiceJour;

    CustInvoiceLine     CustInvoiceLine;


    update_recordSet CustinvoiceJour

        setting InvoiceAmount = custInvoiceTable.TotalAmount()

        join *

        from custInvoiceTable

        where custInvoiceTable.InvoiceId == CustinvoiceJour.InvoiceId

        join parentRecId, TaxAmount, AmountCur

        from custInvoiceLine

        where CustInvoiceLine.ParentRecId == custInvoiceTable.RecId;

}
 

The “TotalAmount” custom method of the CustInvoiceTable table contain the following query:


Display amount TotalAmount()

{

    CustInvoiceLine     custInvoiceLine;

   

    select sum(AmountCur) from custInvoiceLine

        where custInvoiceLine.ParentRecId == this.RecId;

 

    return custInvoiceLine.AmountCur;

}

I know that the code isn’t properly written, but, I expect an error.

This issue coming after the last Kernel update.

Before, with AX 2012 RTM Kernel, the CIL Compilation raise an error like below.

Error 1. Class: XXXXX, Method: updateRecordsetList, Exception: System.NullReferenceException: Object reference not set to an instance of an object.

   at Microsoft.Dynamics.Ax.Xpp.ILGenerator.processBytecode(XmlNode childNode)

   at Microsoft.Dynamics.Ax.Xpp.ILGenerator.processBytecodes(TypeBuilder typeBuilder, XmlNode node)

   at Microsoft.Dynamics.Ax.Xpp.ILGenerator.GenerateIL(TypeBuilder typeBuilder, XmlNode node)

   at Microsoft.Dynamics.Ax.Xpp.ILGenerator.TraversePCode(XmlNode node)

   at Microsoft.Dynamics.Ax.Xpp.PCodeTraverser.TraverseMethod(XmlNode methodNode)

   at Microsoft.Dynamics.Ax.Xpp.ILGenerator.GenerateXppModule()


So, with the last Kernel Microsoft introduce something…



I raised a Support Case and Microsoft suggestion is been modify the BP check (around line 222) in the “checkSource” method of the “SysBPCheckMemberFunction” class:


        // Check if setting value from valid function in update_recordset statement

        if ((textBuffer.find('update_recordSet'))

         && (textBuffer.find('setting',textBuffer.matchPos()+textBuffer.matchLen()))

         && (textBuffer.find('=',textBuffer.matchPos()+textBuffer.matchLen()))

         && (textBuffer.find('(+)',textBuffer.matchPos()+textBuffer.matchLen()))

           )

        {

            setMatchPosLineAndColumn();

            if (!isComment())

            {

                this.addSuppressableWarning(#BPErrorMethodUpdateRecordSetCheck, matchPosLine, matchPosColumn, strFmt("Are you setting a value from a supported method in update_recordset?"));

            }

        }

With this modification at least the Developer will not be able to compile the object because will raise a BP error.

 
From my point of view, this issue is time consuming because could take a lot of time.

I hope that Microsoft will improve the Compilation process in order to avoid an AOS crash.
I also create a suggestion in Connect, https://connect.microsoft.com/dynamicssuggestions/feedback/details/2182000

Stay Tuned!

Wednesday, December 23, 2015

TFS – Add or Duplicate a Work Item Type


Hi Guys

In order to add a new Work Item Type you can take a look at https://msdn.microsoft.com/en-us/library/hh409273.aspx

A more easy and fast way is to use the Microsoft Visual Studio Team Foundation Server Power Tools.

For instance, if you have TFS 2013 you can find the tool at the follow link.

Practically, in order to duplicate or create a Work Item Type the steps are:

1-      Install the Tool according the TFS version

2-      Open Visual Studio and go through the menu Tools\Process Editor\Work Item Types\Export WIT

3-      Choose the proper Team Project

4-      Choose the origin Work Item Type

5-      Choose the destination folder

6-      Edit the XML ( i.e. Notepad )

7-      Rename the WORKITEMTYPE and DESCRIPTION Tag

8-      Save the XML

9-     Come back to Visual Studio

10-   Go through the menu Tools\Process Editor\Work Item Types\Import WIT

11-   Choose the XML file

12-   Choose the Team Project

13-   Press OK

That’s it!
 
 

Sunday, December 20, 2015

AX 2012 - Use Paging feature in the AIF Document Service

Hi All
As you know, the Document Service doesn't support the Paging, only Query Service.
Take a look here
 
Below the trick to enable this feature also for the Document Service:
1-      Take a look to the standard class AxdPricelist, prepareForQuery method
2-      Practically, the service use a temporary table that it’s filled every time the service is called
3-      So, the idea is use a temp table and fill it with the proper data coming from a “direct” query to SQL
4-      The Temp Table must have two extra fields, like PageNumber and RowNumber
5-      So, in the prepareForQuery method execute a query directly to SQL using Paging SQL feature like :
a.       Select Field1, Field2, Fieldn from Table\View Order By Field Desc OFFSET ((' + PageNumber + ' - 1) *' + RowsPage + ') ROWS FETCH NEXT ' + RowsPage + ' ROWS ONLY
6-      From my side I used the Statement class and fill the temp table like :
    ResultSet = statement.executeQuery(SQL);
 
    while ( ResultSet.next() )
    {
        TempTable.clear();
 
        TempTable.Field1                = ResultSet.getXX(1);
        TempTable.Field2                = ResultSet.getXX(2);
        …..
 
        TempTable.PageNumber  = PageNumber;
        TempTable.RowsPage    = RowsPage;
 
        TempTable.insert();
    }
 
7-   Before to execute the query you have to retrieve the “range” fields, so PageNumber and RowNumber like :
    Qbr1 = _query.dataSourceNo(1).findRange( fieldNum(TempTable, PageNumber ) );
    Qbr2 = _query.dataSourceNo(1).findRange( fieldNum(TempTable, RowsPage   ) );
 
8-      In a complex queries, we have to create an AX View and use it in the above query.
9-      I have used the OFFSET clause. This feature is available for the SQL Server 2012 and above version. Otherwise you have to use the ROW_NUMBER clause.
Stay Tuned!

Monday, December 7, 2015

AX 2012 Close Open Forms


Hi Guys

About this topics I spent some time and at the end I’m not able to call by code the standard AX 2012 command in order to Close All Forms, see picture below.



 
In order to achieve this goal, I have modified the SysSetupFormRun Class, Run Method and saved the Window handle of all open forms in a List and move it in the Global Cache, like below :

    // Exclude ListPage Forms
    If (this.form().formTemplate() != 1

       )

    {
                …..

classFactory.globalCache().set(...

 

Finally, using the sendMessage WinApi Function I have closed all Forms, like below :

    #WINAPI

    ……
    listIterator ....
    WinApi::sendMessageEx( WindowHandle, #WM_CLOSE, 0, 0);
 
 
 
 
That's it!

Stay Tuned!