Jan.24

Connector for Dynamics Crashing When Trying to Open a Map

I was recently trying to use the Connector for Dynamics, which is a tool provided by Microsoft to provide a way to integration the various Dynamics software products. In my situation, I was trying to integrate Dynamics CRM to Dynamics AX 2012 R3.

After installing the Connector and configuring the AX and CRM adapters, I began trying to activate the maps in the recommended order which is (taken from the Connector setup guide):

  1. Map enumerated values
  2. Map employees and ERP system users
  3. Map unit schedules and unit groups
  4. Map currency information
  5. Map items and products
  6. Map customers and accounts
  7. Map contact information
  8. Map sales orders
  9. Map sales invoices

Steps 1-4 ran successfully. However, when I would try to open (not yet run) the map for step 5, the Windows service that sits behind the Connector client would stop responding and crash which would cause the client to shut down.

I tried every debugging process I could think of.

  • Turning on verbose logging for both the client and the service.
  • Examining the resulting entries in the server’s Event log.
  • Attaching WinDBG to the Windows service process and examining the output when recreating the error.
  • Running Fiddler to see if the crash was the result of an error in the network traffic (i.e. the CRM adapter had a problem).
  • Scouring the internet, blogs and Dynamics forums for AX and CRM
    • I even posted to the CRM and AX community forms, but had no answers or even responses.

At a complete standstill, I had to choice to open a MS Support ticket. The engineer mentioned that the Connector does not support self-referencing relationships on CRM entities. In our CRM instance, a self-referencing 1:N relationship on the Product entity.

After performing some testing, against an OOTB/un-customized CRM organization, I found that this was indeed the problem that was causing the Connector’s Windows Service to crash. Basically, the self-referencing relationship was causing the Connector to become stuck in an infinite loop which, in turn, caused a stack-overflow and the subsequent crash.

The recommended course of action was to remove the relationship and it’s related fields. However, due to circumstances beyond my control, I wasn’t able to do that.

I asked if the Microsoft team responsible for the Connector would consider updating the Connector to support a self-referencing relationship. After all, it’s a supported customization in CRM. The reply was since the Connector is deprecated (no longer supported after CRM 2016; versions 8.0 and 8.1), the requested change wasn’t going to happen. (There is a new integration tool being released for Dynamics 365 (version 8.2)).

In the end, I was able to find a solution on my own. I found the XML files that contained the meta-data defining the CRM entities which had been configured in the Connector for integration between AX and CRM. These XML files are located on the server where the Connector is installed: C:\Program Files (x86)\Microsoft Dynamics\Microsoft Dynamics Adapter\Adapters\Microsoft.Dynamics.Integration.Adapters.Crm2011\ObjectConfig\(yourCRMOrgName).

I had to remove two lines from the “ProductObjectProvider” file: the line referencing the relationship and the line referencing the field related to the relationship. Once the XML file was edited, I was able to open the Items to Products map in the Connector and run it as needed.

While this solution works and allows you to get around the deficiency in the Connector, there are some caveats to the solution.

  • Any time you connect the Connector to a new CRM organization (i.e. deploy the integration to test or production), you’ll have to remember to manually edit the XML file.
  • Any time you reconfigure the CRM adapter within the Connector, you’ll need to edit the XML file again.
Dynamics CRM

Jun.10

Scribe Insights Error – Message Processor is unresponsive

I’ve been working on a project where I’ve been using the Scribe Insights tool to move data from a SQL Server database to a Dynamics CRM Online instance. I needed to run this integration each week day so I configured the Scribe Console/Server to manage the integration. I have over 20 different “jobs” (*.dts files) so the process takes well over an hour to run. At first the integration ran well with no major errors.

However, the integration began to fail and when I checked, I found that the error was “The job was terminated because the Message Processor is unresponsive.” As is typical with me, I try to find a solution on my own. So I took to the interwebs and found two primary solutions.

The first solution was to adjust a timeout limit stored in Windows registry. The second solution was to adjust a timeout limit in the Scribe Internal database. I tried both of these but it didn’t help.

I finally contacted Scribe directly (you can’t post on their forum unless they grant you an account) and received a better answer. It turns out that the approach outlined above was on the right track but was not complete. So as of June 2016, you’ll need to follow the below instructions.


If you are using Scribe Insights (this doesn’t pertain to Scribe Online), version 7.6.2 or later, you’ll need to adjust or add two settings to the Scribe Internal database.

--Timeout Registry Settings
If exists (Select Top 1 * From [SCRIBEINTERNAL].[SCRIBE].[KSYNC] Where Section = 'EVENTMANAGER' And KeyName = 'SETTINGS.PROCHANGTIMEOUT') 
 Update [SCRIBEINTERNAL].[SCRIBE].[KSYNC] Set KeyValue = '180' Where Section = 'EVENTMANAGER' And KeyName = 'SETTINGS.PROCHANGTIMEOUT'
Else
 Insert Into [SCRIBEINTERNAL].[SCRIBE].[KSYNC] Values('EVENTMANAGER','SETTINGS.PROCHANGTIMEOUT','180');

--Memory Registry Settings
-- MAXMEMORYUSAGEMS 
-- For Queue Integration Memory Issues

If exists (Select Top 1 * From [SCRIBEINTERNAL].[SCRIBE].[KSYNC] Where Section = 'MESSAGEPROCESSOR' And KeyName = 'SETTINGS.MAXMEMORYUSAGEMS') 
 Update [SCRIBEINTERNAL].[SCRIBE].[KSYNC] Set KeyValue = '600' Where Section = 'MESSAGEPROCESSOR' And KeyName = 'SETTINGS.MAXMEMORYUSAGEMS'
Else
 Insert Into [SCRIBEINTERNAL].[SCRIBE].[KSYNC] Values('MESSAGEPROCESSOR','SETTINGS.MAXMEMORYUSAGEMS','600');


-- MAXMEMORYUSAGEEM --
-- For File, Timed & Query Integration Memory Issues

If exists (Select Top 1 * From [SCRIBEINTERNAL].[SCRIBE].[KSYNC] Where Section = 'MESSAGEPROCESSOR' And KeyName = 'SETTINGS.MAXMEMORYUSAGEEM') 
 Update [SCRIBEINTERNAL].[SCRIBE].[KSYNC] Set KeyValue = '600' Where Section = 'MESSAGEPROCESSOR' And KeyName = 'SETTINGS.MAXMEMORYUSAGEEM'
Else
 Insert Into [SCRIBEINTERNAL].[SCRIBE].[KSYNC] Values('MESSAGEPROCESSOR','SETTINGS.MAXMEMORYUSAGEEM','600'); 


If you’re using a version of Scribe Insights older than version 7.6.2, you’ll need to edit the Windows registry on the host server.

Registry Locations: 
32-bit     
HKEY_LOCAL_MACHINE\SOFTWARE\Scribe\EventManager\Settings 

64-bit     
HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Scribe\EventManager\Settings

 

Creating the registry entries (the value below is just a starting point and may need to be increased):

  • Right-click on the Settings folder, on the shortcut menu, point to New and then click DWORD Value.
  • Name the new value ProcHangTimeout. Right-click on the new value, on the shortcut menu, click Modify.
  • In the Edit DWORD Value dialog box, in the Value data box, type 180. This is the amount of time, in seconds, to wait before terminating the process.
  • In the Base box, choose the Decimal.

Restart the Scribe services for this setting to take effect. This value may need to be increased depending on your environment.

 

Update: June 2016

I can confirm that after running the Scribe Integration for several days with the settings above, I’ve not had a problem with the Message Processor becoming unresponsive.

Dynamics CRM,Scribe Insights

Apr.06

Using Javascript to Interact with Microsoft Dynamics CRM 2011

One of the ways you can extend Microsoft Dynamics CRM is to perform CRUD (create, read, update and delete) operations via the REST API or the SOAP API. This allows you to interact with the data within CRM with just HTML and Javascript. I recently had a project where I needed to create dialogs for the user to process records but the out-of-the-box CRM dialogs didn’t fit the bill. I was able to build out simple, light-weight and fast dialogs that allowed the user do what they needed to do.

Below are several examples of retrieving data from CRM, changing the Status (statecode) and Status Reason (statusreason) fields and associating Many-To-Many records. These examples are using the version of the Javascript SDK that relies on jQuery. Microsoft provides a version that does not rely on jQuery if you’re unable to use jQuery.  These examples where for Dynamics CRM 2011 but should point you in the right direction if you’re using CRM 2013 or 2014.

Retrieving Data

The following code allows you to retrieve multiple records from a given entity.

SDK.JQuery.retrieveMultipleRecords(
    'entityname',
    'var options = "$select=Name',
    function (values) {
        //OnSuccess callback
    },
    function (error) {
        //OnError callback
    },
    function () {
        //Fires once all data pages have been retrieved.
    });

The filter can be tweaked to match how you are trying to retrieve values. For example, the following filter is matching the School ID value, the Student Name ID value, the Degree optionset value and the Status (statecode) value. This filter would just replace ‘var options = “$select=Name’ in the above example. You can test your filter strings by hitting the OData service over a browser and examining the results.

"$filter=pt_School/Id eq (Guid'" + schoolId + "') and pt_StudentName/Id eq (Guid'" + studentId + "') and pt_Degree/Value eq " + degreeValue + " and statecode/Value eq 0"

 

Creating Records

The process to create a record looks somewhat similar to retrieving records. However, we create a simple Javascript object to contain the field values for the new record and pass that into the createRecord call.

There are a couple things to note here:

  1. Make sure that the names of the object’s properties match the schema names of the fields you’re populated on the entity.
  2. If you’re trying to set the value of an Optionset field, use the numerical value that CRM assigned to the option.
var myNewRecord= {};
historyRecord.name = 'John';
historyRecord.description = 'This is my description';
historyRecord.fieldA = 'Contents for FieldA';
historyRecord.fieldB = 'Contents for FieldB';

SDK.JQuery.createRecord(
    historyRecord,
    'entityname',
    function (record) {
        //OnSuccess Callback
    },
    function (error) {
        //OnError Callback
    });

Updating Records

To update an existing record, you’ll need the GUID value of the record and you’ll need to create a Javascript object just like when you create a new record. However, you only need to add the fields you’re changing to the Javascript object. Make sure that the object’s property names match the schema names of the fields.

var updatedRecord = {};
updatedRecord .FieldA = 'New value for FieldA';
updatedRecord .FieldB = 'New value for FieldB';

SDK.JQuery.updateRecord(
    currectRecordId,
    updatedRecord,
    'entityname',
    function () {
        //OnSuccess Callback
    },
    function () {
        //OnError Callback
    });

Associating Records

You can also associate records via the REST/OData API.

SDK.JQuery.associateRecords(
    "parentId",
    "parentEntityName",
    "relationshipName",
    "childId",
    "childEntityName",
    function () {
        //OnSuccess Callback
    },
    function (error) {
        //OnError Callback
});

Changing the Status and Status Reason

It is possible to change the Status (statecode) and Status Reason (statuscode) from Javascript. However, it can’t be done via the Rest/OData API. You have to build a SOAP envelope and submit it to the service at “/XRMServices/2011/Organization.svc/web”.

SDK.JQuery.SetStateRequest(
    1, //Status (statecode)
    206300005, //Status Reason (statuscode)
    'entityName', 
    currentRecordId, 
    function () {
        //OnSuccess Callback
    }
);

//Building the SOAP envelope
SetStateRequest: function (newStateCode, newStatusCode, entityName, entityId, successCallback) {
     
var requestMain = ""
requestMain += "";
requestMain += "  ";
requestMain += "    ";
requestMain += "      ";
requestMain += "        ";
requestMain += "          ";
requestMain += "            EntityMoniker";
requestMain += "            ";
//Setting Record Id Guid
requestMain += "              " + entityId + "";
//Setting Entity Name
requestMain += "              " + entityName + "";
requestMain += "              ";
requestMain += "            ";
requestMain += "          ";
requestMain += "          ";
//Setting StateCode (Status)
requestMain += "            State";
requestMain += "            ";
requestMain += "              " + newStateCode + "";
requestMain += "            ";
requestMain += "          ";
requestMain += "          ";
//Setting StatusCode (Status Reason)
requestMain += "            Status";
requestMain += "            ";
requestMain += "              " + newStatusCode + "";
requestMain += "            ";
requestMain += "          ";
requestMain += "        ";
requestMain += "        ";
requestMain += "        SetState";
requestMain += "      ";
requestMain += "    ";
requestMain += "  ";
requestMain += "";
     
var req = new XMLHttpRequest();
    
req.open("POST", "http://adm-v-dcrm01/PokagonDev/XRMServices/2011/Organization.svc/web", true)
// Responses will return XML. It isn't possible to return JSON.
req.setRequestHeader("Accept", "application/xml, text/xml, */*");
req.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
req.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/Execute");
//var successCallback = null;
var errorCallback = null;
req.onreadystatechange = function () { SDK.JQuery.SetStateResponse(req, successCallback, errorCallback); };
req.send(requestMain);
Dynamics CRM