A practical guide to integrating Line of Business systems with BizTalk Server 2010
We are going to assume that we have two companies in our Dynamics AX implementation; one that is Canadian Dollar (CAD) based, and one that is United States Dollar(USD) based. Thus, we need to use the LedgerExchangeRates.create and LedgerExchangeRates.find actions in both companies. For the remainder of this example, we’ll refer to these as daxCADCompany and daxUSDCompany. The complete solution, titled Chapter9-AXExchangeRates, is included in the source code.
Dynamics AX schemas
We’ll start by creating a new BizTalk project, Chapter9-AXExchangeRates, in Visual Studio. After the AIF actions setup is complete, the next step is to generate the required schemas that are needed for our BizTalk application. This is done by right clicking on the BizTalk project in Visual Studio 2010, click Add, highlight and click Add Generated Items. This will bring up the Add Generated Items window, under the Templates section—Visual Studio installed template, select Add Adapter Metadata, and click Add. This will bring up the Add Adapter Wizard window (shown in the following screenshot), so we’ll simply select Microsoft Dynamics AX 2009 and click Next. Now, we’ll need to fill in the AX server instance name (AX 2009-SHARED in our example) under Server name, and the TCP/IP Port number (2712, which is the default port number, but this can differ). Now, click Next from the BizTalk Adapter for Microsoft Dynamics AX Schema Import Wizard window.
Specify the connection information in the next step.
In the next window, you should see all the active AIF services. Note that since the AIF services table is a global table, so you will see all the active services in your Dynamics AX instance. This does not mean that each endpoint, thus each company, is configured to accept the actions that each AIF service listed has available. This is the point where you first verify that your connectivity and AIF setup is correct. An error here using the wizard typically is due to an error in the AIF channel configuration.
In the wizard window above, you can see the AIF services that are enabled. In our case, the ExchangeRatesService is the only service currently enabled in our Dynamics AX instance. Under this service, you will see three possible modes (sync, async request, and async response) to perform these actions. All three will actually produce the same schemas. Which mode and action (create, find, findkeys, or read) we use is actually determined by the metadata in our message we’ll be sending to AX and the logical port configurations in our orchestration. Now, click Finish.
Now in the project solution, we see that the wizard will generate the two artifacts. The first ExchangeRates_ExchangeRates.xsd is the schema for the message type that we need to send when calling the LedgerExchangeRates.create action and it is also the same schema returned in the response message when calling the action LedgerExchangeRates.find. Since we are actually dealing with the same AX table in both actions, Exchange Rates, both actions will in part (one will be the inbound message, the other will be the outbound message) require the same schema.
The second artifact, BizTalk Orchestration.odx, is also generated by default by the wizard. In the orchestration view, we can see that four Multi-part Message Types were also added to the orchestration. Rename the orchestration to something more meaningful such as ProcessExchangeRates.odx.
Now that we have defined our message type that will be returned in our response message, we need to define what the request type will be. Notice from the orchestration view that two messages, ExchangeRatesService_create_Response and ExchangeRatesService_find_Request, have types which Visual Studio has in error ‘does not exist or is invalid’.
For the out-of-the-box find action, we need the message type DynamicsAX5.QueryCriteria. The other message type is return by AX when calling a create action is DynamicsAX5.EntityKey (if we called a createList action, the returned message would be of type DynamicsAX5.EntitiyKeyList).
The schemas for these message types are in the Microsoft.Dynamics.BizTalk.Adapter.Schemas assembly, which can be found in the bin directory of the install location of the BizTalk adapter. Add this reference to the project in Visual Studio. Then, re-select the appropriate message type for each Message Part that is invalid from the Select Artifact Type window as shown.
Next, depending on your organization, typically you may want to either populate the noon exchange rates or closing rates. For our example, we will use the closing USD/CAD exchange rates from the Bank of Canada. This is published at 16:30 EST on the website (http://www.bankofcanada.ca/rss/fx/close/fx-close.xml).
Since this source is already in XML, download and save a sample. We then generate a schema from Visual Studio using the BizTalk Schema Generator (right click the solution, Add Generated Items, Add Generated Schemas, using the Well-Formed XML (Not Loaded) document type. This will generate the schema for the message that we need to receive by our BizTalk application daily. In the example provided, the schema is ClosingFxRates.xsd (the wizard will generate four other .xsd files that are referenced in ClosingFxRates.xsd).
A simple way to schedule the download of this XML data file is to use the Schedule Task Adapter (http://biztalkscheduledtask.codeplex.com/), which can be downloaded and installed at no cost (the source code is also available). Download and install the adapter (requires Microsoft .NET Framework Version 1.1 Redistributable Package), then add using the BizTalk Server Administration Console with the name Schedule. We will use this adapter in our receive location to retrieve the XML via http. There are also RSS adapters available to be purchased from, for example, /nsoftware (http://www.nsoftware.com/). However, for this example, the scheduled task adapter will suffice.
Now, since the source of our exchange rates is a third-party schema, and your specific requirements for the source will most likely differ, we’ll create a canonical schema ExchangeRates.xsd. As you can see in the schema below, we are only interested in a few pieces of information: Base Currency (USD or CAD in our example), Target Currency (again USD or CAD), Rate, and finally, Date. Creating a canonical schema will also simplify the rest of our solution.
Now that we have all the schemas defined for our message types defined or referenced, we can add the messages that we require to the orchestration.
We’ll begin by adding the message msgClosingFxRates. That will be our raw input data from the Bank of Canada with the message type from the generated schema ClosingFxRates.RDF.
For each exchange rate, we’ll need to first query Dynamics AX to see if it exists, thus we’ll need a request message and a response message. Add a message msgAXQueryExchangeRatesRequest, which will be a multi-part message type ExchangeRatesService_find_Request, and msgAXQueryExchangeRatesResponse that will be a multi-part message type ExchangeRatesService_find_Response.
Next, we’ll create the messages for the XML that we’ll send and receive from Dynamics AX to create an exchange rate. Add a message msgAXCreateExchnageRatesRequest, which will be a multi-part message type of ExchangeRatesService_create_Request, and msgAXCreateExchnageRatesResponse that will be a multi-part message type ExchangeRatesService_create_Response.
Finally, we’ll need to create two messages, msgExchangeRatesUSDCAD and msgExchangeRatesCADUSD, which will have the message type of the canonical schema ExchangeRates. These messages will contain the exchange rates for USD to CAD and for CAD to USD respectively. We’ll create these two messages just to simplify our orchestration for this example. In practice, if you’re going to deal with several exchange rates, you will need to add logic to the orchestration to loop through the list rates that you’re interested in and have only one message of type ExchangeRates resent several times.