Blog

Name is Anant Dubey and the intent to create this blog is to discuss the problems and issues that developer face in the dynamics AX development and to share the new things that come up with the new version of AX.

Monday, November 14, 2016

How to create and debug batch job in AX 2012

There are many scenario where we have to schedule the tasks, so they execute in background. Real world scenarios are
  • Sales order with certain criteria will update status to Invoiced.
  • Scheduled job check the file location to find comma delimited files and after finding create sales order or purchased orders in Ax.
  • Schedule job clear the data in database logging after certain time.
  • Schedule job execute mid night to extract all sales order/ Purchase order and integrated it other system.

In dynamics Ax we can schedule the with help of RunBaseBatch framework.

For current example, I just wrote the batch job which just put its execution time in custom table.
First step for batch process is to enable the Dynamics Ax 2012 as Batch server.
Link


Enable Server
Consider a custom table with only two fields. These fields just dummy text and the time when batch process execute.

Table Structure

Now just create a class, set it run at server.

Class attributes
Extends the class with run batch base class.  The class logic should be same


class ProcessTableIncrement extends RunBaseBatch

{

 

}

 

public container pack()

{

return conNull();

}

 

public void run()

{

 

// The purpose of your job.

TblBatchHit _hit;

 

_hit.HitBy ="BatchJob";

_hit.hitTime= DateTimeUtil ::utcNow();

_hit.insert();

}

 

public boolean unpack(container packedClass)

{

return true;

}

 

Now compile the code and Generate Increment CIL. Incremental CIL generation is required to setup every time you update the code.

Now create ax job which deploy above class as batch Process job.

static void TestBatchHit(Args _args)

{

BatchHeader header;

SysRecurrenceData sysRecurrenceData;

Batch batch;

BatchJob batchJob;

ProcessTableIncrement _ProcessIncrement;

BatchInfo processBatchInfo;

BatchRetries noOfRetriesOnFailure = 4;

;

 

// Create the tutorial_RunBaseBatch job, only if one does not exist

select batch where batch.ClassNumber == classnum(ProcessTableIncrement);

if(!batch)

{

// Setup the tutorial_RunBaseBatch Job

header = BatchHeader::construct();

_ProcessIncrement = new ProcessTableIncrement();

processBatchInfo = _ProcessIncrement.batchInfo();

processBatchInfo.parmRetriesOnFailure(noOfRetriesOnFailure);

processBatchInfo.parmCaption("Table Increment");

 

header.addTask(_ProcessIncrement);

 

// Set the recurrence data

sysRecurrenceData = SysRecurrence::defaultRecurrence();

SysRecurrence::setRecurrenceStartDateTime(sysRecurrenceData, DateTimeUtil::addSeconds(DateTimeUtil::utcNow(), 20));

SysRecurrence::setRecurrenceNoEnd(sysRecurrenceData);

SysRecurrence::setRecurrenceUnit(sysRecurrenceData, SysRecurrenceUnit::Minute);

header.parmRecurrenceData(sysRecurrenceData);

// Set the batch alert configurations

header.parmAlerts(NoYes::No, NoYes::Yes, NoYes::No, NoYes::Yes, NoYes::Yes);

header.save();

 

// Update the frequency to run the job to every two minutes

ttsbegin;

select forupdate batchJob

join batch

where batchJob.RecId == batch.BatchJobId

&& batch.ClassNumber == classnum(ProcessTableIncrement);

 

sysRecurrenceData = batchJob.RecurrenceData;

sysRecurrenceData = conpoke(sysRecurrenceData, 8, [3]);

batchJob.RecurrenceData = sysRecurrenceData;

batchJob.update();

ttscommit;

}

}

 

 
When you execute the X++ job, you will find a new batch job created and waiting state at following link with caption Table Increment

Job Link


From top menu you can check the job execution history.

Batch Job

Job History

If any error occur or you put some info logs, these can be seen from Log from top menu.
For example in some other batch job I used many info boxes at different locations to trace.
11-12-2014 12-58-09 AM

Remove / Delete the batched job.
Delete the existing job is two-step process if job is in waiting step. First we have to convert it into withhold state and then delete it.
Select the required batch job for example if I want to delete Job with caption “Table Increment”. From top menu to select change state to with hold

select

withhold

Now again go in Functions top menu and select

delete
Now from dialog set status to withhold and click on ok
ddd
This will remove the Batch Job

Debug the Batch Process Job
Now question is how we can debug batch job, for that purpose we have to go in visual studio.

For debugging at AOS server following check box must be check form AOS server configuration.
“Enable breakpoints to debug x++ code running on this server on this machine”
X++



If Client and AOT are in same machine then open the Application explore and locate the file and attach debug there.
Visual studio debug


If files are at AOS is another machine go at XPPIL folder in visual studio and add break point.



From debug menu click on attached process
Attached process
From  Attach to select the manage code.
From top click on select button and select the Managed(v4.0) code
ttss
Check the two check boxes below “Show Processes from All Users and show processes in all sessions and click on refresh.
After refresh select Ax32Serv.exe and click on attach button.

When the job execute after certain time link appear on break point.
sss

Reference taken by:- https://community.dynamics.com/ax/b/alirazatechblog/archive/2014/11/12/exploring-the-batch-job-process-in-dynamics-ax-2012-r3

Wednesday, November 18, 2015

Event Handling in Microsoft Dynamics AX 2012

Today, I am going to talk on the event handling mechanism in Microsoft Dynamics AX 2012. With the event-handling mechanism in Microsoft Dynamics AX 2012 you can lower the cost of doing development and then upgrading these customizations.
Events are a simple and yet powerful concept. In daily life, we encounter with so many events. Events can be used to support these programming paradigms.
  • Observation: Generate alerts to see exceptional behavior.
  • Information dissemination: To convey information to right people at right time.
  • Decoupling: The consumer doesn’t need to know about the producer. Producer and Consumer can be sitting in totally different applications.
  • Terminology: Microsoft Dynamics AX 2012 events are based on .NET eventing concepts.
  •  
  • Producer: Object to trigger the event.
  • Consumer: Object to consume the event and process logic based on the event triggered.
  • Event: An action that needs to be triggered
  • Event Payload: Information that can go along with event.
  • Delegate: Definition that is passed to trigger an event. Basically, communicator between producer and consumer
Things to remember while using Events in AX2012
  • Delegate keyword to use in delegate method.
  • Public or any other accessibility specifier is not allowed in a delegate method.
  • Delegate Method return type must be void.
  • Delegate Method body must be empty.
  • A delegate declaration can have the same type of parameters as a method.
  • Event handlers can run only on the same tier as the publisher class of the delegate runs on.
  • Only static methods are allowed to be event handlers.
  • Delegate method can’t be called outside class. Basically, events can’t be raised outside class in which event is defined.
  • Event handlers for host methods can use one of two parameter signatures:
    • One parameter of the type XppPrePostArgs. Go through all the methods available in XppPrePostArgs.
    • The same parameters that are on the host method that the event handler subscribes to.
Now, let’s talk about how to use events in Microsoft Dynamics AX 2012.
  1. Let’s create a class Consumer to create EventHandler (sendEmailToCustomer). This will be called once order is shipped so that email can be sent to customer to notify. It has to be static method.
  2. Now let’s create Producer class where this event (sendEmailToCustomer) is called using Delegates. Add delegate by right clicking on Producer class > New > Delegate.
  3. Change its name to delegateEmail (you can have any name). Parameter should be same as event handler method (sendEmailToCustomer) i.e. of type Email. Notice it has no body and is a blank method.
  4. Now drag and drop sendEmailToCustomer method from Consumer class to delegateEmail
  5. Look at properties of EventHandler. You will notice it is pointing to Class Consumer and method sendEmailToCustomer
  6. If order is not shipped, I am creating another event handler (errorLog) in Consumer class to log error into error log.
  7. Create another delegate method (delegateErrorLog) in Producer class to call this event handler (errorLog)
  8. Drag and drop event handler (errorLog) in delegate method (delegateErrorLog) similar to step 4.
  9. Now let’s create main method in Producer class to ship order and let’s see how delegates can be used to trigger event handlers.
  10. Suppose shipOrder method returns true. Now, if I run this main method, it should go into delegateEmail method and should trigger method sendEmailToCustomer. Let’s run and see the result.
  11. Here is the result and it is as expected so it did trigger method sendEmailToCustomer.
  12. Let’s suppose shipOrder method returns false. Now, if I run this main method, it should go into delegateErrorLog method and should trigger method errorLog. Let’s run and see the result.
  13. Here is the result and it is as expected so it did trigger method errorLog.
  14. Handlers can also be added or removed
    Add Handler: It uses += sign.
    Remove Handler: It uses -= sign.
  15. Now, let’s use addStaticHandler in main method. If you see the code, it is calling addStaticHandler before calling delegate method. If we run it and see the result, it should send 2 emails.
  16. Here is the result as expected.
  17. Similarly if we use removeStaticHandler method instead of addStaticHandler before calling delegate method then it will remove handler and will not send any email.
So, you can see that with the use of delegates and event handlers, it is so easy to trigger events. Also, it will be easy and less time consuming to upgrade it. Suppose if delegates are called from standard methods while doing customizations then it will be so easy to upgrade if standard methods are changed in next release because only 1 liner code of calling delegate method needs to be rearranged and no changes will be required in event handler methods.
Use of Pre and Post event handlers
In Microsoft Dynamics AX 2012, any event handler method can dropped in other method. If the property "CalledWhen" is set to "Pre" then it becomes pre event handler. If it is set to "Post" then it becomes post event handler. Pre event handler is called before the method under which it is dropped and Post event handler is called after method ends. These are so powerful that event handler method can be created in new class and can be dropped in any standard or any other method without changing a single line of code and can be set as pre or post event handler as per business need. Suppose, before creating a customer in AX, business need is to do some business logic then logic can be written in pre event handler and can be dropped in insert method of CustTable. Similarly, if there is post logic to be written after customer is created then post event handler can be created and dropped in insert method of the Customer Table (CustTable).
Let’s see how pre and post event handler methods can be created and used.
  1. Let’s take same example. I added 2 event handler methods in Consumer class.
  2. Drag and drop both these event handlers in method sendEmailToCustomer
  3. Set property "CalledWhen" to Pre for EventHandler1 and Post for EventHandler2.
  4. Now let’s run main method of Producer class again and see the results. It should call EventHandler1 and then sendEmailToCustomer and then EventHandler2.
  5. Here is the result as expected.
With use of events, it has opened so many doors and possibilities. Model architecture and events can be integrated which can help if multiple vendors are doing customizations in different models so that it doesn’t impact customizations of other models/vendors. Use of pre and post handlers is so powerful that it can be used without changing a single line of code in original method. Pre or Post handlers can be just dropped in the original method and will be called automatically before (pre handler method) or after (post handler method) original method.
Stay tuned for more technical tips on Microsoft Dynamics AX 2012.

Tuesday, November 17, 2015

How to call .exe (executable) file through code in ax 2012

Here I am calling .exe file through AX 2012. What I have done in this is created a Crystal report of AX and make it in .exe format. Now I am calling this through AX 2012 R3.

static void Callingcrystalreport(Args _args)
{
    WinAPI::shellExecute("D:\\BN\\WindowsFormsApplication2.exe");
}

Generate Report through code in ax 2012

In this post I am trying to automatically save report to any format in the shared drive.
report is generating based on parameters, after this we can check in the drive that report is stored in the drive.



static void GenerateReportThroughCode(Args _args)
{
    S3_WHSVariantTable        S3_WHSVariantTable;
    InventItemBarcode         inventItemBarcode;
    ReportRun                 reportRun;
    ;
        select inventItemBarcode where inventItemBarcode.itemBarCode == '4015400548485';
        reportRun = new ReportRun(new Args(ReportStr(S3_DP_RetailLabel_BN)));//where S3_DP_RetailLabel_BN is Morphx Report
        reportRun.args().caller();
        //reportRun.args().parm(itemId);
        reportRun.args().record(inventItemBarcode);
        // reportRun.args().object(List);
        //reportRun.printJobSettings().runServer();
        reportRun.printJobSettings().setTarget(PrintMedium::File);
        reportRun.printJobSettings().format(PrintFormat::PDF);
        reportRun.printJobSettings().fileName(strFmt(@"\\SERVERNAME\FolderName\Barcode\%1.pdf",inventItemBarcode.itemId));
        // reportRun.printJobSettings().outputToClient(true);
        // reportRun.printJobSettings().clientPrintJobSettings();
        reportRun.run();
}

Monday, September 21, 2015

Debugging in Microsoft Dynamics AX 2012 [AX 2012]

In Microsoft Dynamics AX 2012, development can be done in both X++ and .NET managed code. The development environment you use is either the MorphX Integrated Development Environment (IDE) or the Visual Studio IDE depending on the type of development you are doing.
Because X++ and .NET development are integrated, debugging may require that you use the Microsoft Dynamics AX debugger and the Visual Studio debugger depending on your development scenario. This topic provides an overview of common debugging scenarios and information about which debugger to use.
These debugging scenarios include the following:

X++ Code

The process for debugging X++ code varies depending on whether you are debugging standard X++ code or X++ code that is executed in Common Intermediate Language (CIL).

Gg860898.collapse_all(en-us,AX.60).gifStandard X++ Code

To debug X++ code, you use the Microsoft Dynamics AX debugger. This is the full-featured debugger that is part of the MorphX suite of tools. You can use this debugger to debug X++ code that:
  • Runs on the client
  • Runs on the server and is not executed in CIL
To debug X++ code, you set a breakpoint in the MorphX code editor. When you run the code, execution stops at the breakpoint and the Microsoft Dynamics AX debugger opens. You can continue to step through the code in the debugger. For more information, see Microsoft Dynamics AX Debugger.

Gg860898.collapse_all(en-us,AX.60).gifX++ Code that Calls runAs

In X++, you can use the runAs function to call a static method and specify that it is executed in CIL. You can only use this command to run code that runs on the server. Because the method runs in CIL, you must use Visual Studio to debug it.
The high-level process for debugging code called from a runAs function by using the Visual Studio debugger is as follows:
  1. Open your X++ code in the MorphX code editor and set a breakpoint on the line of code that calls the runAsfunction.
  2. Open Visual Studio. Use Application Explorer to open the X++ source code called by the runAs function and then set a breakpoint.
  3. In Visual Studio, attach the debugger to the server process (Ax32Serv.exe).
  4. Run the code in MorphX or step through the code in the Microsoft Dynamics AX debugger.
  5. When the breakpoint is reached in the source code that is running in CIL, context switches to Visual Studio and you can continue to step through the code.
TipTip
When you debug code that is called by the runAs function in Visual Studio, you cannot change the X++ source code in the Visual Studio IDE. You must make the changes in X++, and then do an incremental CIL build to regenerate the .xpp files.

Gg860898.collapse_all(en-us,AX.60).gifCreate the .xpp Source Files

An .xpp file contains the X++ source code for one method of a class or table that is in the AOT. The Visual Studio debugger uses .xpp files when you debug X++ that has been compiled to CIL.
The generated .xpp files are stored in a directory path that might resemble:
 C:\Microsoft Dynamics AX\60\Server\Microsoft\bin\XppIL\source\
You prompt the system to create all the .xpp files by following these steps:
  1. Start the Microsoft Dynamics AX Server Configuration Utility.
  2. On the Application Object Server tab, select the check box that is labeled Enable breakpoints to debug X++ code running on this server.
  3. Restart the Application Object Server (AOS). The XppIL\source\ directory is created and populated.
Thereafter, the .xpp files that correspond to new or modified X++ methods are refreshed on subsequent compiles to CIL.

Managed Code

When you use managed code to develop applications for Microsoft Dynamics AX, you can:
  • Call managed code from X++
  • Call X++ code from managed code
The debugging process varies depending on whether you start debugging from the MorphX IDE or from the Visual Studio IDE.

Gg860898.collapse_all(en-us,AX.60).gifDebugging from MorphX

A common development scenario is calling managed code from X++. In order to do this, you create a managed code assembly in Visual Studio and add the assembly to the model store by using Application Explorer. After you have added the assembly project to the model store, the assembly classes are available from X++ code.
To debug managed code that is called from X++, you use both the Microsoft Dynamics AX debugger and the Visual Studio debugger. The high-level process for debugging from the MorphX IDE is as follows:
  1. Open your managed code in Visual Studio and set the breakpoints.
  2. Attach the Visual Studio debugger to the Microsoft Dynamics AX server (Ax32Serve.exe) or client (Ax32.exe) process.
  3. In the MorphX code editor, set the breakpoints, run your code, and use the Microsoft Dynamics AX debugger as you would typically.
  4. When code execution switches to managed code, context switches to the Visual Studio debugger. When you are finished stepping through managed code, control returns to the Microsoft Dynamics AX debugger.

Gg860898.collapse_all(en-us,AX.60).gifDebugging from Visual Studio

Before you can call X++ code from managed code, you must first add the managed code project to the model store. After you have done this, you can then use Application Explorer to add elements from the Application Object Tree (AOT) to a Visual Studio project.
To debug X++ code that is called from managed code, you use both the Visual Studio debugger and the Microsoft Dynamics AX debugger. To simplify the debugging process, you can use the debug properties on the .NET project. After you set these properties, the Visual Studio debugger will automatically attach to the correct Microsoft Dynamics AX process (server or client), call the X++ code that you specify, and stop at the breakpoints that you have set.
The high-level process for debugging from Visual Studio is as follows:
  1. In the MorphX code editor, set the breakpoints in X++.
  2. Open your managed code in Visual Studio. Make sure that the debug properties are set correctly on the project.
  3. Press F5 to run the project.
  4. When code execution reaches a breakpoint in X++ code, context switches to the Microsoft Dynamics AX debugger. When you are finished stepping through X++ code, control returns to the Visual Studio debugger.
NoteNote
Instead of setting the debug properties on the .NET project (which causes the Visual Studio debugger to automatically attach to the appropriate Microsoft Dynamics AX process), you can manually attach the debugger to the process.
For more information about how to debug managed code, see Walkthrough: Debugging a Managed Code Event Handler.

Services

A service in Microsoft Dynamics AX is an X++ class that you expose as a service by adding attributes to the class and its methods. Services that you create in Microsoft Dynamics AX are compiled into CIL and run on the server. Therefore, you must use the Visual Studio debugger to debug them.
While you are developing a service class in X++, you can use the Microsoft Dynamics AX debugger to debug the functionality. To debug the code that calls the service, you then use Visual Studio.
The high-level process for debugging a service from Visual Studio is as follows:
  1. In Visual Studio, open the project that calls the Microsoft Dynamics AX service.
  2. In Application Explorer, locate the service operation that you are calling and open the source code.
  3. Set a breakpoint in the service code.
  4. Attach the Visual Studio debugger to the Microsoft Dynamics AX server process (Ax32Serve.exe).
  5. Press F5 to run the project. When the debugger reaches a breakpoint in the service, it will stop and you can then step through the service code.
    TipTip
    When debugging a service in Visual Studio, you cannot change the source code in the Visual Studio IDE. You must make the changes in X++ and then deploy the integration port to regenerate the service .xpp files.
For more information about the Visual Studio debugger, see Debugging in Visual Studio.

Reports

SQL Server Reporting Services is the reporting platform for Microsoft Dynamics AX. The report development environment is integrated into Visual Studio. You can debug reports using the Microsoft Dynamics AX debugger or the Visual Studio debugger, or you can create a job to verify the data that should be generated for the report. For information on how to configure debugging reports, see How to: Configure the Debugger to Debug a Report Data Provider Class. The tool that you use depends on the reporting solution.
Use the Microsoft Dynamics AX debugger for the following scenarios:
  • Debug a report data provider (RDP) class that is bound to a dataset of a report.
  • Debug a custom controller class for a report that runs within code and print management instructions.
  • Debug a custom UI builder class for parameter dialog solutions.
  • Debug a contract class for dataset generation input controllers.
Use the Visual Studio debugger for the following scenarios:
  • An RDP class that requires pre-processing uses services to call the logic. There are two types of pre-process RDP reports:
    • Reports that require print management because it is assumed that the same report will print to various destinations. Process the business logic once and then print the report to each destination.
    • Reports that require lots of processing time.
      For example, the Inventory Closing report.
  • A contract class that implements the Validate interface or the Initialize interface because it is executed using a service call.
  • Batch reports that require a pre-processed RDP class. When reports run in a batch, the reporting framework code is compiled to CIL.
    NoteNote
    If a report in the batch executes an RDP class that does not require pre-processing, Reporting Services will execute the RDP class, and the RDP class can be debugged using the Microsoft Dynamics AX debugger.
  • To debug C# data methods, attach the Visual Studio debugger to a Reporting Services process. Set the target to the .NET 2.0 code type.
Verify a report dataset by using an X++ job:
  • Create a job to verify the report dataset for an RDP class based report. Pass a data contract to the job, call theprocessReport method, and then verify the results.
  • Create a job to execute a query that is used in a report and then verify the data.
For more information about debugging and troubleshooting report issues, see Troubleshooting reporting.

Enterprise Portal

Both managed code and X++ code are used for Enterprise Portal. The C# managed code is used in User Controls that appear on Enterprise Portal pages. The X++ code is used in data sets, tables, and classes that are accessed by Enterprise Portal pages. You can use Visual Studio to debug the C# managed code. You can use the Microsoft Dynamics AX debugger to debug X++ code for Enterprise Portal.

Gg860898.collapse_all(en-us,AX.60).gifManaged code in Enterprise Portal

The high-level process for debugging managed code in Enterprise Portal is as follows:
  1. Configure the Enterprise Portal site to enable debugging.
  2. In Visual Studio, attach the Visual Studio debugger to the Enterprise Portal process.
  3. Add breakpoints to the User Control code that you want to debug.
  4. Display the page in Enterprise Portal that contains the managed code that you want to debug.
For more information about how to debug managed code in Enterprise Portal, see How to: Debug User Controls.

Gg860898.collapse_all(en-us,AX.60).gifX++ code in Enterprise Portal

The high-level process for debugging X++ code in Enterprise Portal is as follows:
  1. Configure the Microsoft Dynamics AX installation to enable debugging of X++ code in Enterprise Portal.
  2. In the Development Workspace, add breakpoints to the X++ code that you want to debug.
  3. Open the Microsoft Dynamics AX debugger.
  4. Display the page in Enterprise Portal that uses the X++ code that you want to debug.
For more information about how to debug X++ code in Enterprise Portal, see How to: Debug X++ Code on EP Pages.

Batch Jobs

Like services that you create in Microsoft Dynamics AX, batch jobs are compiled into CIL and run on the server. Therefore, you must use Visual Studio to debug batch jobs.
Batch jobs are used when you have code that you want to schedule to run at a specific time or in regular intervals. One example is if you have code that performs lots of processing that you want to run when the system is not heavily used. Code that runs as a batch job must be contained in a class that extends the RunBaseBatch class. For more information, see RunBase Framework.
The process for debugging a batch job is similar to debugging a service. When you create your class in X++, you can use the standard Microsoft Dynamics AX debugger. To debug a class that is running as a batch job, you then use the Visual Studio debugger.
The high-level process for debugging a batch job from Visual Studio is as follows:
  1. Open Visual Studio. In Application Explorer, locate the batch job class and open the source code.
  2. Set a breakpoint in the code.
  3. Attach the Visual Studio debugger to the Microsoft Dynamics AX server process (Ax32Serv.exe).
  4. In Microsoft Dynamics AX, schedule the batch job that calls your class to run.
  5. When code execution hits the breakpoint that you set, the context switches to Visual Studio and you can continue to step through the code.

How to debug batch jobs and service operations?

All the batch jobs and service operations now run in the managed code (IL) and therefore breakpoints set in x++ do not get hit as expected! Instead you should be setting breakpoints in the IL code in Visual Studio. Here are the steps you would be following to do so:
1. Open Visual Studio as an Administrator and go to Tools > Options > Debugging > General. Make sure “Enable Just My Code (Managed Only)” is unchecked.
Image
2. Go to Debug > Attach to Process. Click “Select…” and check the appropriate version of the managed code in your case.
Image
3. Check both options at the bottom of “Attach to Process” form. Select Ax32Serv.exe from the list of processes.
Image
4. Load the XppIL source file in Visual Studio now. Make sure you have enabled breakpoints to debug x++ code in the AX Server Configuration Utility. You can find these files under a location similar to the following:
C:\Program Files\Microsoft Dynamics AX\6.3\Server\AxaptaDev\bin\XppIL\source
5. Now set the breakpoint at any of the desired statement.
Image
6. Finally, trigger the batch job or service operation to debug in the AX Client. The breakpoint set in Visual Studio should be hitting now! Make sure to generate IL to reflect the changes in the XppIL source files after updating the x++ code.