Pages

07 May, 2021

Visual Studio - PowerShell Package Manager Console Reload Profile Script

In case if you are setting up a NuGet PowerShell profile or modifying the profile script for Visual Studio PowerShell Package Manager Console, you will need to close and open the Visual Studio to reload the profile methods. 

To reload the profile scripts without closing and opening the Visual Studio, you can run the below command. This will reload the profile script and the updated method will be available for you to use in Console. 

. $profile

06 May, 2021

Sitecore Upgrade - Sitecore NuGet Package Upgrade using PowerShell

Sitecore enabled package management system for the Sitecore packages from version 9.x. This has helped to avoid unnecessary and complicated reference management. In order to do .NET framework upgrade and Sitecore NuGet package upgrade, there are various ways as follows.
  1. Using NuGet Package Manager 
  2. Using PowerShell Package Manager Console
  3. NuGet CLI
  4. dotnet CLI
Certain Sitecore Helix solution may have 100s of projects so using NuGet Package Manager in Visual Studio may not be productive. As a programmer, you can leverage the PowerShell Package Manager Console to inspect each project and update the packages. 

Gary has written a script to update the Sitecore Packages and as he mentioned, it is easy to extend and tweak it as per our need. One of my requirement is to find the projects which are having Sitecore Packages and update all the packages to the target version in a single shot.  

The below script accepts the old package version and the new package version and finds all the projects having "Sitecore." packages and upgrades the packages to the target version along with dependencies. Save the gist file as nuget_Profile.ps1 in C:\Users\[user]\Documents\WindowsPowerShell folder and restart the Visual Studio for the PowerShell Package Manager console to pick up the profile scripts. 
  1. Finds all the projects with Sitecore packages
  2. Loop through each projects and updates the Sitecore Packages.
  3. If NoReference Package is installed, it finds the alternative package with NoReference and installs it. 
In the PowerShell Package Manager console, execute the method along with old and new package version as below. Please note script is defaulted to version 9.3.0 as old version and version 10.1.0 as the new version. 
UpdateSitecorePackagesForAllProjects -NewVersion 9.0.171219 -OldVersion 10.0.1



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:

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.