Pages

30 April, 2021

Sitecore Marketing Automation Engine failed to start - Workaround for local development

There are several blogposts related to Sitecore Marketing Automation Engine service which is not getting started and Sitecore installation abruptly stops. If it is failing in a production instance, then please do refer the blogpost links at the bottom of this blog to find the root cause and fix it. 

In case, it is for a local development instance and you just want to complete the installation and bring up the Sitecore, you can do the following workaround to install the Sitecore successfully and also bring up the Sitecore Marketing Automation Engine service. 

Installation using SIF:

Edit the xconnect-xp0.json file, go to StartServices task and remove the params to start the marketing automation service. This will allow you to complete the Sitecore installation. Basically we are removing the task to start the service as part of the installation. 

        "StartServices": {
            "Description": "Starts the service.",
            "Type": "ManageService",
            "Params": [
                {
                    "Name": "[variable('Services.IndexWorker.Name')]",
                    "Status": "Running"
                },
                {
                    "Name": "[variable('Services.ProcessingEngine.Name')]",
                    "Status": "Running"
                }
            ]
        }

Installation using sifon or SIM:

Open the compressed installation package using 7-Zip (SIF - \AppData\Roaming\Sitecore\Sitecore Instance Manager\Repository or sifon - c:\Program Files\Sifon\Downloads\), edit the xconnect-xp0.json file directly inside the package, go to StartServices task and remove the params to start the marketing automation service. This will allow you to complete the Sitecore installation.

Start Sitecore Marketing Automation Engine:

Most of the time, this issue happens due to certification. So we can let the xConnection to ignore the certificate validation. Since it is a local development environment, edit xConnect application AppSettings.config, and remove entry with key - validateCertificateThumbprint, save it. Recycle the xConnect application pool and try to start the Sitecore Marketing Automation Engine service and it should work. 

  <!-- Remove this entry and save it. -->
  <add key="validateCertificateThumbprint" value="A24A5C1386846F69A69BD8C0BCC78FA1454872E1" />  

Related blogposts to find the root cause and fix it:

http://www.nehemiahj.com/2021/06/sitecore-marketing-automation-engine.html

installation failure, fails to start marketing automation service - Installation and Upgrading Sitecore - Developers - Sitecore Community

Sitecore 9.1 Failed to start Marketing Automation Service – Sitecore Endeavor (wordpress.com)

xConnect The HTTP response was not successful: Unauthorized - Sitecore Stack Exchange

29 April, 2021

Adding Solr Certificate Store Password with Special Characters in Windows batch file

As part of Sitecore IaaS setup, I had a chance to do On-Premise Solr setup. To enable SSL for Solr, we need a certificate which can be self-signed or CA signed and the store password. In order to enable the SSL for Solr, we need to install the certificate and then we need to edit batch file "\bin\solr.in.cmd" and paste the store password along with the certificate (crt, pfx) file. 

In this example, secret is the password. 

set SOLR_JAVA_HOME="C:\Solr\solr-8.4.0\jdk8u222-b10-jre"
set SOLR_SSL_KEY_STORE=etc/solr-ssl.keystore.jks
set SOLR_SSL_KEY_STORE_PASSWORD=secret
set SOLR_SSL_TRUST_STORE=etc/solr-ssl.keystore.jks
set SOLR_SSL_TRUST_STORE_PASSWORD=secret
set SOLR_HOST="localhost"
set SOLR_Port=8840

Sometimes the provided password for the certificate from the vendor may have some special characters. Since the password with special character has to be entered in the batch file, batch execution will fail and Solr will fail to start with errors like "Keystore was tampered with, or password was incorrect" or "Password verification failed". 

As per Microsoft documentation, there are few limitations when we use SET command in batch file with value string containing special characters like <, >, |, &, and ^. You can escape the special character or you can load the string value from a file without escaping. 

To load the value string with special characters from a file:

  1. Create a file named "key", add the password string with special character and save it in /bin folder. 
  2. Modify the solr.in.cmd file to pick the value string from this file as below.
set /p SOLR_SSL_TRUST_STORE_PASSWORD=<key
set /p SOLR_SSL_KEY_STORE_PASSWORD=<key
Error log from Solr:
2021-04-30 14:30:48.106 ERROR (main) [   ] o.a.s.s.SolrDispatchFilter Could not start Solr. Check solr/home property and the logs
2021-04-30 14:30:48.128 ERROR (main) [   ] o.a.s.c.SolrCore null:org.apache.solr.common.SolrException: Error instantiating shardHandlerFactory class [HttpShardHandlerFactory]: java.io.IOException: Keystore was tampered with, or password was incorrect
	at org.apache.solr.handler.component.ShardHandlerFactory.newInstance(ShardHandlerFactory.java:56)
	at org.apache.solr.core.CoreContainer.load(CoreContainer.java:633)
	at org.apache.solr.servlet.SolrDispatchFilter.createCoreContainer(SolrDispatchFilter.java:262)
	at org.apache.solr.servlet.SolrDispatchFilter.init(SolrDispatchFilter.java:182)
	at org.eclipse.jetty.servlet.FilterHolder.initialize(FilterHolder.java:136)
	at org.eclipse.jetty.servlet.ServletHandler.lambda$initialize$0(ServletHandler.java:750)
	at java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948)
	at java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:742)
	at java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:742)
	at java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:647)
	at org.eclipse.jetty.servlet.ServletHandler.initialize(ServletHandler.java:744)
	at org.eclipse.jetty.servlet.ServletContextHandler.startContext(ServletContextHandler.java:369)
	at org.eclipse.jetty.webapp.WebAppContext.startWebapp(WebAppContext.java:1497)
	at org.eclipse.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1459)
	at org.eclipse.jetty.server.handler.ContextHandler.doStart(ContextHandler.java:854)
	at org.eclipse.jetty.servlet.ServletContextHandler.doStart(ServletContextHandler.java:278)
	at org.eclipse.jetty.webapp.WebAppContext.doStart(WebAppContext.java:545)
	at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
	at org.eclipse.jetty.deploy.bindings.StandardStarter.processBinding(StandardStarter.java:46)
	at org.eclipse.jetty.deploy.AppLifeCycle.runBindings(AppLifeCycle.java:192)
	at org.eclipse.jetty.deploy.DeploymentManager.requestAppGoal(DeploymentManager.java:510)
	at org.eclipse.jetty.deploy.DeploymentManager.addApp(DeploymentManager.java:153)
	at org.eclipse.jetty.deploy.providers.ScanningAppProvider.fileAdded(ScanningAppProvider.java:172)
	at org.eclipse.jetty.deploy.providers.WebAppProvider.fileAdded(WebAppProvider.java:436)
	at org.eclipse.jetty.deploy.providers.ScanningAppProvider$1.fileAdded(ScanningAppProvider.java:65)
	at org.eclipse.jetty.util.Scanner.reportAddition(Scanner.java:610)
	at org.eclipse.jetty.util.Scanner.reportDifferences(Scanner.java:529)
	at org.eclipse.jetty.util.Scanner.scan(Scanner.java:392)
	at org.eclipse.jetty.util.Scanner.doStart(Scanner.java:313)
	at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
	at org.eclipse.jetty.deploy.providers.ScanningAppProvider.doStart(ScanningAppProvider.java:145)
	at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
	at org.eclipse.jetty.deploy.DeploymentManager.startAppProvider(DeploymentManager.java:598)
	at org.eclipse.jetty.deploy.DeploymentManager.doStart(DeploymentManager.java:240)
	at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
	at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:167)
	at org.eclipse.jetty.server.Server.start(Server.java:418)
	at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:119)
	at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:113)
	at org.eclipse.jetty.server.Server.doStart(Server.java:382)
	at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
	at org.eclipse.jetty.xml.XmlConfiguration.lambda$main$0(XmlConfiguration.java:1797)
	at java.security.AccessController.doPrivileged(Native Method)
	at org.eclipse.jetty.xml.XmlConfiguration.main(XmlConfiguration.java:1746)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.eclipse.jetty.start.Main.invokeMain(Main.java:220)
	at org.eclipse.jetty.start.Main.start(Main.java:490)
	at org.eclipse.jetty.start.Main.main(Main.java:77)
Caused by: java.lang.RuntimeException: java.io.IOException: Keystore was tampered with, or password was incorrect
	at org.apache.solr.client.solrj.impl.Http2SolrClient.createHttpClient(Http2SolrClient.java:224)
	at org.apache.solr.client.solrj.impl.Http2SolrClient.&lt;init&gt;(Http2SolrClient.java:154)
	at org.apache.solr.client.solrj.impl.Http2SolrClient$Builder.build(Http2SolrClient.java:833)
	at org.apache.solr.handler.component.HttpShardHandlerFactory.init(HttpShardHandlerFactory.java:321)
	at org.apache.solr.handler.component.ShardHandlerFactory.newInstance(ShardHandlerFactory.java:51)
	... 50 more
Caused by: java.io.IOException: Keystore was tampered with, or password was incorrect
	at sun.security.provider.JavaKeyStore.engineLoad(JavaKeyStore.java:785)
	at sun.security.provider.JavaKeyStore$JKS.engineLoad(JavaKeyStore.java:56)
	at sun.security.provider.KeyStoreDelegator.engineLoad(KeyStoreDelegator.java:224)
	at sun.security.provider.JavaKeyStore$DualFormatJKS.engineLoad(JavaKeyStore.java:70)
	at java.security.KeyStore.load(KeyStore.java:1445)
	at org.eclipse.jetty.util.security.CertificateUtils.getKeyStore(CertificateUtils.java:54)
	at org.eclipse.jetty.util.ssl.SslContextFactory.loadKeyStore(SslContextFactory.java:1194)
	at org.eclipse.jetty.util.ssl.SslContextFactory.load(SslContextFactory.java:334)
	at org.eclipse.jetty.util.ssl.SslContextFactory.doStart(SslContextFactory.java:256)
	at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
	at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:167)
	at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:119)
	at org.eclipse.jetty.client.HttpClient.doStart(HttpClient.java:244)
	at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
	at org.apache.solr.client.solrj.impl.Http2SolrClient.createHttpClient(Http2SolrClient.java:222)
	... 54 more
Caused by: java.security.UnrecoverableKeyException: Password verification failed
	at sun.security.provider.JavaKeyStore.engineLoad(JavaKeyStore.java:783)

13 April, 2021

Sitecore Publishing Service - Recap

This blog is a recap of the Sitecore Publishing Service.

Sitecore introduced Sitecore Publishing Service along with Sitecore v8.2. It is a standalone service which reads the dedicated Publish Queue, create Manifest of items to be changed and process the content movement from source to target.

This standalone service is optional and independent of out of the box Sitecore publishing mechanism in CM. This service helps clients where there is a frequent content changes and multiple content authors. This reduces the load on the CM instance as the entire publishing mechanism will be lifted and handled by Publishing Service. This service also raises the events to clear the cache after the publish. In case if we want to raise custom event, we can patch it and let this service raise the event.

To install this service, there are two steps.

  1. Sitecore Publishing Service which needs .NET core and can be hosted in IIS or any other platform. 
  2. Sitecore Module which needs to be installed in the Content Management server. 
    • This module enabled a Publishing Dashboard which will read the publish job queue and provide a status to the content authors. 
    • It also creates a role by which we can control the full publish to certain users. 
    • It creates a set of tables in the master DB so the connection string user for master DB should have access to create table while this package is installed. 

blockquote { margin: 0; } blockquote p { padding: 15px; background: #eee; border-radius: 5px; } blockquote p::before { content: '\201C'; } blockquote p::after { content: '\201D'; }