Friday, May 27, 2016

Sitecore EXM: The remote name could not be resolved: 'default-cd-cluster'

While configuring sending EXM messages on Sitecore I faced with problem. Some emails were delivered, others not. Sitecore Email Experience Manager log reported next error:

ERROR Failed to enroll a contact in the engagement plan.
Exception: System.Net.WebException
Message: The remote name could not be resolved: 'default-cd-cluster'
Source: System
   at System.Net.WebClient.DownloadDataInternal(Uri address, WebRequest& request)
   at System.Net.WebClient.DownloadString(Uri address)
   at Sitecore.Modules.EmailCampaign.Core.Gateways.DefaultAnalyticsGateway.EnrollOrUpdateContact(Guid contactId, Guid planId, Guid automationStateId, EcmCustomValues customValues, String[] validStates)
   at Sitecore.Modules.EmailCampaign.Core.Analytics.AutomationStatesManager.EnrollOrUpdateContact(Guid contactId, Guid planId, String stateName, EcmCustomValues customValues, String[] validStates)
   at Sitecore.Modules.EmailCampaign.Core.Dispatch.DispatchManager.EnrollOrUpdateContact(Guid contactId, DispatchQueueItem dispatchQueueItem, Guid planId, String stateName, EcmCustomValues customValues)
   at Sitecore.Modules.EmailCampaign.Core.Dispatch.DispatchTask.OnSendToNextRecipient()

After search this error message I found two articles (first, second) that say the same: you should change Analytics.ClusterName setting. And this solution really helps. This setting is located in Sitecore.Analytics.Tracking.config file and EXM uses it to access to /sitecore/AutomationStates.ashx handler to change contact state in engagement plan.

But, doesn't sound strange? That you should to configure something to start work with Sitecore single instance. How about installation CM/CD/Analytics on one server? Or how about development and testing environments? I know that there are a lot of places where Sitecore as web application requires host name, but everywhere it works automatically. You shouldn't configure something additionally. That's why I decided to customize Sitecore to use 'default-cd-cluster' as key that will be replaced in EXM with current host name. And it was quite easy:

public class CustomAnalyticsGateway : DefaultAnalyticsGateway
{
    public override ContactLockingStatus TryGetContactForUpdate(ID contactId, 
            LeaseOwner leaseOwner, 
            System.TimeSpan leaseDuration, 
            System.TimeSpan timeout, 
            out Sitecore.Analytics.Tracking.Contact contact, 
            out string webClusterName)
    {
       var r = base.TryGetContactForUpdate(contactId, leaseOwner, leaseDuration, timeout, out contact,
           out webClusterName);
       if (webClusterName!= null && webClusterName.Contains("default-cd-cluster"))
       {
           webClusterName = System.Web.Hosting.HostingEnvironment.ApplicationHost.GetSiteName();
       }
       return r;
    }
}

If webClsterName contains 'default-cd-cluster' we change it with current sitename(it also will work if we will replace it with null due to Sitecore EXM later fill it with another value if it is null). And you should let EXM know to use this gateway in your configuration:

<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
  <sitecore>
    <gatewayFactory>
      <analyticsGateway type="YourSolution.CustomAnalyticsGateway, YourSolution"/>
    </gatewayFactory>
  </sitecore>
</configuration>

With this custom class and configuration Email Experience Manager started to work on all machines. And you should not change 'default-cd-cluster' with host name in all your solutions. But don't forget to change this setting when going to live environment.

5 comments:

  1. Another one variant of error in log:

    ERROR Bounce handling failed
    Exception: System.NullReferenceException Message: Object reference not set to an instance of an object. Source: Sitecore.EmailCampaign at Sitecore.Modules.EmailCampaign.Core.Gateways.DefaultAnalyticsGateway.TryGetContactForUpdate(ID contactId, LeaseOwner leaseOwner, TimeSpan leaseDuration, TimeSpan timeout, Contact& contact, String& webClusterName) at Sitecore.Modules.EmailCampaign.Core.Gateways.DefaultAnalyticsGateway.UpdateAutomationState(Guid contactId, Guid planId, Guid automationStateId, EcmCustomValues customValues, String[] validStates) at Sitecore.Modules.EmailCampaign.Core.Analytics.AutomationStatesManager.UpdateAutomationState(Guid contactId, Guid planId, String stateName, EcmCustomValues customValues, String[] validStates) at Sitecore.Modules.EmailCampaign.Core.RecipientStateManager.MoveTo(String statename, String[] validStateNames) at Sitecore.Modules.EmailCampaign.Core.Pipelines.HandleUndeliveredMessage.MoveToBouncedState.Process(HandleUndeliveredMessagePiplelineArgs args) at (Object , Object[] ) at Sitecore.Pipelines.CorePipeline.Run(PipelineArgs args) at Sitecore.Modules.EmailCampaign.Core.MessageTransfer.BounceManager.HandleBouncedMessage(Guid contactId, Guid messageId, Boolean permanentFailure) at Sitecore.Modules.EmailCampaign.Core.MessageTransfer.BounceManager.CheckBouncedMessages(DateTime lastTracked)

    ReplyDelete
  2. Hi,
    I was just looking for such solution, please tell me how to use this CustomAnalyticsGateway class in project?

    When I use:

    var xdbContact = new XdbContactId(contact.ContactId);
    var status = new CustomAnalyticsGateway();
    status.TryGetContactForUpdate(xdbContact.Value, new LeaseOwner("UpdateContact" + Guid.NewGuid().ToString(), LeaseOwnerType.OutOfRequestWorker), TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(5), out TrackingContact, out webClusterName);

    and config:




    I get:
    Tracker.Current is not initialized

    [InvalidOperationException: Tracker.Current is not initialized]
    Sitecore.Analytics.Pipelines.StartAnalytics.StartTracking.Process(PipelineArgs args) +209
    (Object , Object[] ) +59
    Sitecore.Pipelines.PipelineMethod.Invoke(Object[] parameters) +36
    Sitecore.Pipelines.CorePipeline.Run(PipelineArgs args) +365
    Sitecore.Pipelines.CorePipeline.Run(String pipelineName, PipelineArgs args, String pipelineDomain, Boolean failIfNotExists) +158
    Sitecore.Analytics.Pipelines.StartAnalytics.StartAnalyticsPipeline.Run() +170
    Sitecore.Mvc.Analytics.Pipelines.MvcEvents.RequestBegin.StartTracking.Process(RequestBeginArgs args) +112
    (Object , Object[] ) +59
    Sitecore.Pipelines.PipelineMethod.Invoke(Object[] parameters) +36
    Sitecore.Pipelines.CorePipeline.Run(PipelineArgs args) +365
    Sitecore.Pipelines.CorePipeline.Run(String pipelineName, PipelineArgs args, String pipelineDomain, Boolean failIfNotExists) +158
    Sitecore.Mvc.Pipelines.PipelineService.RunPipeline(String pipelineName, TArgs args) +129
    Sitecore.Mvc.Routing.RouteHttpHandler.BeginRequest() +84
    Sitecore.Mvc.Routing.RouteHttpHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData) +46
    System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +103
    System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155

    please help :)

    ReplyDelete
  3. This comment has been removed by the author.

    ReplyDelete
  4. This comment has been removed by the author.

    ReplyDelete
  5. the problem is a config registration
    gatewayFactory
    analyticsGateway type="IGW.CustomAnalyticsGateway, IGW"
    gatewayFactory
    when I remove it - Sitecore works fine

    ReplyDelete