Friday, July 27, 2018

Sitecore Experience Commerce - SitecoreConnectionManager getitemsbypath failures

In the minions commerce engine role of my Experience Commerce 9 environment, I have an import minion which syncs product data into Sitecore. During it's run it ran into errors connecting to Sitecore (via API) to retrieve settings (via content items).
3 11:14:32 ERROR SitecoreConnectionManager: RETRY 1 out of 3 with ERROR Internal Server Error. Failed to logging. /sitecore/api/ssc/auth/login for GET /sitecore/api/ssc/item/?path=%2Fsitecore%2FCommerce%2FCommerce%20Control%20Panel%2FCommerce%20Engine%20Settings%2FCommerce%20Terms%2FBusinessTools%2FViewPropertyNames&database=master&language=en
4 11:14:32 ERROR SitecoreConnectionManager.Error: Message=RETRY FAILED for GET /sitecore/api/ssc/item/?path=%2Fsitecore%2FCommerce%2FCommerce%20Control%20Panel%2FCommerce%20Engine%20Settings%2FCommerce%20Terms%2FBusinessTools%2FViewPropertyNames&database=master&language=en|Trace=   at Sitecore.Commerce.Plugin.Management.SitecoreConnectionManager.<ProcessRequestAsync>d__15.MoveNext()
4 11:14:32 ERROR Management.block.getitemsbypath: Sitecore Item Service Get item failed, Item /sitecore/Commerce/Commerce Control Panel/Commerce Engine Settings/Commerce Terms/BusinessTools/ViewPropertyNames not found.
This error traced back to the PlugIn.Content.PolicySet-1.0.0.json policy set configuration file inside the commerce engine. In this file I had correctly configured the username and password for the Sitecore index, however the Host setting was still set to the default of sxa.storefront.com. As I don't use this domain, it had not been configured with a valid SSL certificate. By changing this host to the correct one (with a valid certificate) the errors no longer occurred.

Sitecore 9 unable to connect to SXA SOLR indexes

After installing a clean Sitecore 9 (update 2) instance I noticed some errors in the Sitecore log files around web and master indexes for SXA:
ERROR Unable to connect to [https://localhost:8983/solr], Core: [sitecore_sxa_master_index] 
 ERROR Unable to connect to [https://localhost:8983/solr], Core: [sitecore_sxa_web_index]
This was not an error connecting to SOLR, but the fact that these two cores did not exist. Hence the following log line:
Message: The remote server returned an error: (404) Not Found.
To resolve these error, you will need to log into your SOLR application and create the two cores.
SOLR add a core
This will stop the above errors from appearing in the logs.

Thursday, July 26, 2018

Sitecore Experience Commerce - InvalidShopCurrency error on site publish

When attempting to perform a site publish (to the web database) on a Sitecore instance containing Experience Commerce, the following error occurred part way through the publish:
Job started: Publish to 'web'|#Exception: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> Microsoft.OData.Client.DataServiceQueryException: An error occurred while processing this request. ---> Microsoft.OData.Client.DataServiceClientException: { "@odata.context":"https://localhost:5000/Api/$metadata#Sitecore.Commerce.Core.CommandMessage","MessageDate":"2018-07-25T20:38:11.802773Z","Code":"Error","Text":"Currency 'NZD' for Shop 'MyShop' was not found.","CommerceTermKey":"InvalidShopCurrency"}
This issue relates to the fact that that environment was configured (via the configuration in the commerce engine) to be using NZD (New Zealand dollars) as a currency. The issue then relates to the commerce engine being able to retrieve the currency settings from the Sitecore instance.

This traces back to the shared default currency setting in Sitecore (/sitecore/Commerce/Commerce Control Panel/Shared Settings/Currency Settings/Currency Sets/Default) which OOTB is not set to NZD and does not have NZD configured at all. Updating this and then restarting the commerce engine environment (due to caching) resolved the error.

Sitecore Experience Commerce - Default currency settings

Sitecore Experience Commerce - Site publish to web fails with 401 error

When trying to perform a site publish (to the web database) on a Sitecore instance with Experience Commerce installed, the following error occurred part way through the publishing process.

Sitecore Experience Commerce - 401 on site publish
Job started: Publish to 'web'|#Exception: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> Microsoft.OData.Client.DataServiceQueryException: An error occurred while processing this request. ---> Microsoft.OData.Client.DataServiceClientException: Status Code: 401; Unauthorized    at Microsoft.OData.Client.BaseAsyncResult.EndExecute[T](Object source, String method, IAsyncResult asyncResult)   at Microsoft.OData.Client.QueryResult.EndExecuteQuery[TElement](Object source, String method, IAsyncResult asyncResult)
Looking in the commerce engine showed:
51 08:17:14 ERROR ClientCertificateValidationMiddleware: Certificate with thumbprint 1D59F02B4279CB000588E905D7162499599632E3 does not have a matching Thumbprint.51 08:17:14 INFO ClientCertificateValidationMiddleware: Certificate with thumbprint 1D59F02B4279CB000588E905D7162499599632E3 is not valid.
This one comes back to our old friend the certificate thumbprint. This is sewt by default in the App_Config/Include/Y.Commerce.Engine/Sitecore.Commerce.Engine.Connect.config configuration file (but of course should be patched). Setting this value to the thumbprint used on the certificate assigned to the commerce engine should allow the publish to proceed.

Sitecore Experience Commerce - Engine is not generating any log files

After an upgrade from Experience Commerce 9 update 1 to update 2, all 4 of my commerce engine roles were not generating any log files and in fact the logs folder did not exist at all. The engines were running as expected and bootstraps were successful, the issue came down to configuration.

Inside the config.json configuration file, there was an incorrect Serilog configuration.
"Serilog": {
 "Using": [ "Serilog.Sinks.Literate", "Serilog.Sinks.File" ],
 "MinimumLevel": {
  "Default": "Information",
  "Override": {
   "Microsoft": "Information",
   "System": "Information"
  }
 },
 "WriteTo": [
  {
   "Name": "Async",
   "Args": {
    "configure": [
     {
      "Name": "LiterateConsole"
     }
    ]
   }
  }
 ],
 "FileSizeLimitBytes": 100000000
},
The snipped from the configuration file above, incorrectly had the WriteTo section. By removing this section and restarting the IIS website, the commerce engine began to generate log files as expected.

Wednesday, July 25, 2018

Sitecore install error - Cannot retrieve the dynamic parameters

When attempting to install an instance of Sitecore 9 (update 2) I was getting the following errors from the SIF installation in PowerShell.
Install-SitecoreConfiguration : Cannot retrieve the dynamic parameters for the cmdlet. Retrieving the COM class factory for component with CLSID {688EEEE5-6A7E-422F-B2E1-6AF00DC944A6} failed due to the following error: 80040154 Classnot registered (Exception from HRESULT: 0x80040154 (REGDB_E_CLASSNOTREG)).
In my case I had accidentally opened the x86 version of PowerShell as opposed to the standard. Re-opening the correct version and running the install again, allowed the installation to complete as expected.

Sitecore Experience Commerce - Engine could not load type

During an upgrade of Sitecore Experience Commerce (from update 1 to update 2), I was getting the following error message on a failed bootstrap of the commerce engine:
Could not load type 'Sitecore.Commerce.Plugin.Workflow.Workflow' from assembly 'Sitecore.Commerce.ServiceProxy, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null'.
As I had customized the commerce engine, I had to upgrade the project from the latest SDK manually (as opposed to simply deploying the pre-compiled version). This involved update plugin references, merging environment JSON configuration files and adding new DLL references. In this case, I had missed adding the new reference to Sitecore.Commerce.Plugin.Workflow and it caused the bootstrap to fail.

Adding a reference to the Sitecore.Commerce.Plugin.Workflow inside the Sitecore.Commerce.Engine project, re-deploying then allowed the bootstrap to complete.

Friday, July 20, 2018

Sitecore Experience Commerce - Errors generating the Sitecore Service Proxy

As I had created a custom API in the Experience Commerce engine, I was required to rebuild the Sitecore Commerce Service proxy (Sitecore.Commerce.ServiceProxy). This led to a couple of issues on rebuild:
CS0756 A partial method may not have multiple defining declarations
This can be resolved by opening the ConnectedService.json file for the affected engine environment (ops or shops) and editing the GeneratedFileNamePrefix setting. In my case this had incorrectly changed itself to Reference when it should have been CommerceOps (or CommerceShops). You should also delete the the reference.cs file which was generated.

Another error may also occur:
The namespace 'Sitecore.Commerce.Plugin.CacheWatcher' already contains a definition for 'ExtensionMethods'
Again this points back to the ConnectedService.json file for CommerceOps. The UseNameSpacePrefix should be set to true and NamespacePrefix set to "CommerceOps".


This should now generate the ServiceProxy DLL as expected with no errors.

Sitecore Experience Commerce - InvalidPolicySetJson on boostrap

When attempting to bootstrap the commerce engine, after upgrading the instance from update 1 to update 2, the following error occurred:
"@odata.context": "https://localhost:5015/CommerceOps/$metadata#Commands/$entity",
"@odata.type": "#Sitecore.Commerce.Core.Commands.BootstrapCommand",
"Id": "3f98d6d62af54509904abc8b9cc7cf37",
"ResponseCode": "Error",
"Messages": [
{
"MessageDate": "2018-07-19T22:24:26.5227643Z",
"Code": "Error",
"Text": "PolicySet json is not valid.",
"CommerceTermKey": "InvalidPolicySetJson"
}
]
This is a generic, error and the next step is to check the logs of the commerce engine instance you are calling (in this case the ops environment). This gave the following more detailed error:
ERROR Error resolving type specified in JSON 'Sitecore.Commerce.Plugin.Workflow.WorkflowPolicy, Sitecore.Commerce.Plugin.Workflow'. Path 'Policies.$values[0].$type', line 12, position 102.Newtonsoft.Json.JsonSerializationException: Error resolving type specified in JSON 'Sitecore.Commerce.Plugin.Workflow.WorkflowPolicy, Sitecore.Commerce.Plugin.Workflow'. Path 'Policies.$values[0].$type', line 12, position 102. ---> Newtonsoft.Json.JsonSerializationException: Could not load assembly 'Sitecore.Commerce.Plugin.Workflow'.
In my case I had missed the Sitecore.Commerce.Plugin.Workflow.dll file in my upgrade of the commerce engine (SDK) project.

Sitecore Identity Server - CryptographicException Keyset does not exist

During an upgrade of  a Sitecore Experience Commerce instance from update 1 to update 2, the identity server started to display the following error when attempting to get a token via Postman.
Unhandled exception: "System.Security.Cryptography.CryptographicException: Keyset does not exist
This is a permissions issue in relation to the certificate used on the identity server. To resolve this issue:

  1. Open a Command Prompt window.
  2. Type mmc and press the enter key. 
  3. On the File menu, click Add/Remove Snap In.
  4. Click Add.
  5. In the Add Standalone Snap-in dialog box, select Certificates.
  6. Click Add.
  7. In the Certificates snap-in dialog box, select Computer account and click Next. Optionally, you can select My User account or Service account. If you are not an administrator of the computer, you can manage certificates only for your user account.
  8. In the Select Computer dialog box, click Finish.
  9. In the Add Standalone Snap-in dialog box, click Close.
  10. On the Add/Remove Snap-in dialog box, click OK.
  11. In the Console Root window, click Certificates (Local Computer) to view the certificate stores for the computer.
  12. Locate the certificate used on the identity server site
  13. Right click the certificate
  14. Select All Tasks
  15. Select Manage Private Keys
  16. Add the identity of the application pool of the identity server and select Ok
The error should no longer occur.

Apply permissions to a certificate

Thursday, July 19, 2018

Sitecore Experience Commerce - Identity Server No signing credential is configured

After upgrading Sitecore Identity Server as part of a migration from update 1 to update 2 of Experience Commerce, the following error appeared after attempting to authenticate in postman:
Unhandled exception: "System.InvalidOperationException: No signing credential is configured. Can't create JWT token
   at IdentityServer4.Services.DefaultTokenCreationService.<CreateHeaderAsync>d__5.MoveNext()
I was able to resolve this error by setting the correct thumbprint in the appsettings.json file of the identity server.

Sitecore Experience Commerce - Upgrade Analytics Core package installation fails

When running the upgrade of Sitecore Experience Commerce from update 1 to update 2, the package installation of Sitecore Commerce ExperienceAnalytics Core 11.2.83.zip was failing due to an item:saved event.

I was able to get this package to install correctly by disabling the Sitecore.ExperienceAnalytics.Client.config configuration file.

Tuesday, July 10, 2018

Sitecore Experience Commerce - Management.GetCommerceTerms and related methods in logs

Looking at the logs for a long running Sitecore Experience Commerce minion, I noticed large chunks of the following logs:
INFO Management.GetCommerceTerms./sitecore/Commerce/Commerce Control Panel/Commerce Engine Settings/Commerce Terms/BusinessTools/ViewPropertyNames|en
INFO Management.block.getitemsbypath./sitecore/Commerce/Commerce Control Panel/Commerce Engine Settings/Commerce Terms/BusinessTools/ViewPropertyNames|en
INFO Management.block.getitembyid.7f475f9d-341e-4a21-bec2-0f5f74987a3b: Language=en
It turns out that my minions environment (and the Habitat example) did not enable caching for queries related to management. For example the OOTB Habitat minions experience commerce environment (defined in PlugIn.Habitat.CommerceMinions-1.0.0.json) references a PolicySetId of Entity-PolicySet-MinionsMemoryCachePolicySet which in turn is defined in PlugIn.MinionsMemoryCache.PolicySet-1.0.0.json.

To allow caching of these management related queries, the following can be added to the PlugIn.MinionsMemoryCache.PolicySet-1.0.0.json file (or your own custom version).
{
  "@odata.type": "Sitecore.Commerce.Plugin.Management.ManagementCachePolicy, Sitecore.Commerce.Plugin.Management",
  "AllowCaching": true,
  "Expiration": 3600000
},
It may appear more cut-down than other caching examples, but worked in my environment.

Extract of a caching policy for a Sitecore Experience Commerce engine environment

Monday, July 9, 2018

Sitecore SOLR - unknown field MyFieldName

After adding a new computed index field to my SOLR web index, I was getting the following error on rebuild:
Job started: Index_Update_IndexName=sitecore_web_index|#Exception: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> SolrNet.Exceptions.SolrConnectionException: <?xml version="1.0" encoding="UTF-8"?>
<response>
<lst name="responseHeader"><int name="status">400</int><int name="QTime">1</int></lst><lst name="error"><lst name="metadata"><str name="error-class">org.apache.solr.common.SolrException</str><str name="root-error-class">org.apache.solr.common.SolrException</str></lst><str name="msg">ERROR: [doc=sitecore://web/{57606db8-1237-463b-a934-01f3854a2909}?lang=en&amp;ver=0&amp;ndx=sitecore_web_index] unknown field 'MyFieldName'</str><int name="code">400</int></lst>
</response>
 ---> System.Net.WebException: The remote server returned an error: (400) Bad Request.
This is due to the fact that when I added the field to the index, the returnType was set as:
returnType="System.Double"
Where it should have been set as:
returnType="double"
This data return type is mapped on the SOLR field map:
Sitecore SOLR Field Map

Wednesday, July 4, 2018

Sitecore Experience Commerce - ERROR Site Disabled. Failed to logging

In a Sitecore Experience Commerce environment running the minions role, the following set of errors would occur when attempting to access an item in Sitecore.
17 19:13:17 INFO Management.block.getitembyid.0F65742E-317F-44B0-A4DE-EBF06209E8EE: Language=en
17 19:13:17 ERROR SitecoreConnectionManager: RETRY 1 out of 3 with ERROR Site Disabled. Failed to logging. /sitecore/api/ssc/auth/login for GET /sitecore/api/ssc/item/0F65742E-317F-44B0-A4DE-EBF06209E8EE?database=master&language=en
17 19:13:17 ERROR SitecoreConnectionManager: RETRY 2 out of 3 with ERROR Site Disabled. Failed to logging. /sitecore/api/ssc/auth/login for GET /sitecore/api/ssc/item/0F65742E-317F-44B0-A4DE-EBF06209E8EE?database=master&language=en
17 19:13:17 ERROR SitecoreConnectionManager: RETRY 3 out of 3 with ERROR Site Disabled. Failed to logging. /sitecore/api/ssc/auth/login for GET /sitecore/api/ssc/item/0F65742E-317F-44B0-A4DE-EBF06209E8EE?database=master&language=en
17 19:13:17 ERROR SitecoreConnectionManager.Error: Message=RETRY FAILED for GET /sitecore/api/ssc/item/0F65742E-317F-44B0-A4DE-EBF06209E8EE?database=master&language=en|Trace=   at Sitecore.Commerce.Plugin.Management.SitecoreConnectionManager.ProcessRequest(CommerceContext commerceContext, String action, String method, ItemModel itemModel)
System.Exception: RETRY FAILED for GET /sitecore/api/ssc/item/0F65742E-317F-44B0-A4DE-EBF06209E8EE?database=master&language=en
   at Sitecore.Commerce.Plugin.Management.SitecoreConnectionManager.ProcessRequest(CommerceContext commerceContext, String action, String method, ItemModel itemModel)
17 19:13:17 ERROR Management.block.getitembyid: Sitecore Item Service Get item failed, Item 0F65742E-317F-44B0-A4DE-EBF06209E8EE not found.
I had checked the configuration file along with the content set policy (PlugIn.Content.PolicySet-1.0.0.json) and all connection details and user accounts were correct for the Sitecore instance.\\

It turned out that this error was occurring because the minion experience commerce engine role was blocked from accessing the Sitecore content management instance due to an IP white listing rule.

Tuesday, July 3, 2018

Sitecore Experience Commerce - Facets are limited to 100 results

I was debugging a Sitecore Experience Commerce product list locally (using SOLR as a search provider) and noticed that a category with a large number of brands to facet on, would always limit out at 100 results. This was not ideal as that 100 would include facets with 0 aggregate count (matches for a given search) which meant actual brands that were in the results would not appear as a valid facet.

This turned out to be a default setting with SOLR whereby the maximum number of facets to return for a given query was 100. This can be increased to a valid number as required or to unlimited with a setting of -1.

To increase the number of facets to return with a SOLR index in Sitecore, you will need to do the following.

  1. In the SOLR directory locate the index you wish to target.
    1. In my case this was the web index - which is located in C:\solr\server\solr\sc_web_index
  2. Inside the conf child director is a solrconfig.xml configuration file.
  3. The facet.limit setting needs to be edited - in my case this setting was not present
    1. A valid number to set a hard limit of facets to return or -1 for unlimited.
  4. Add or edit the setting in the following location.
  5. Restart the SOLR service.
<requestHandler name="/select" class="solr.SearchHandler">
<!-- default values for query parameters can be specified, these
  will be overridden by parameters in the request
  -->
<lst name="defaults">
  <str name="echoParams">explicit</str>
  <int name="rows">10</int>
  <str name="facet.limit">-1</str>

Note: the snippet has been cut-down, however there is enough here to see where to add the setting.

After making this change, I was now seeing all of the brand facet data that I was expecting.