Thursday, March 14, 2019

Event Queue in Sitecore 9.1

Event queue

The event queue is a very useful mechanism in the Sitecore architecture. John Rappel wrote a very nice blogpost on it a while ago (I really do suggest you to read that). But since that day Sitecore came with version 9.1.

In one of our projects we used the event queue to send events to the ContentDelivery servers. The default/system Event Queue was used and it worked fine.  You can find the configuration on these event queues in the <eventing> section in Sitecore.config. The configuration includes a systemDatabase (which is deprecated now) and also a defaultEventQueue.

The configuration and code behind it seem to indicate that Sitecore is slowly refactoring this part and moving towards the <eventqueueprovider>  configuration instead of the <providers>.

Sitecore 9.1

After upgrading to Sitecore 9.1 however, we noticed there is a slight change of plans.. The release notes of 9.1 mention:
The Content Delivery server role does not require the Core database when the Sitecore security membership provider is not used.​​
The documentation on the core database still mentions the ContentDelivery role as one of the roles that refers to the core database, but in this case of the eventQueue you can (should) consider it gone...

Configuration

Let's have a look at the configuration in a Sitecore 9.1:
<eventing defaultProvider="sitecore">
  <providers>
    <clear />
    <!--
      Event provider attributes:
 systemDatabaseName: Deprecated. Name of the database which will hold the system event queue. 
   System event queue receives all the events that are not related to a specific database.
    -->
    <add name="sitecore" type="Sitecore.Eventing.EventProvider, Sitecore.Kernel" systemDatabaseName="core" />
    <add name="sitecore" role:require="ContentDelivery">
   <patch:attribute name="systemDatabaseName">web</patch:attribute>
    </add>
  </providers>
  <!-- EVENT QUEUE -->
  <eventQueueProvider defaultEventQueue="core">
    <eventQueue name="web" type="Sitecore.Data.Eventing.$(database)EventQueue, Sitecore.Kernel">...</eventQueue>
    <eventQueue name="master" role:require="!ContentDelivery" type="Sitecore.Data.Eventing.$(database)EventQueue, Sitecore.Kernel">...</eventQueue>
    <eventQueue name="core" role:require="!ContentDelivery" type="Sitecore.Data.Eventing.$(database)EventQueue, Sitecore.Kernel">...</eventQueue>
  </eventQueueProvider>
  <eventQueueProvider role:require="ContentDelivery">
    <patch:attribute name="defaultEventQueue">web</patch:attribute>
  </eventQueueProvider>
</eventing>

A few things have changed since the previous version here. Note the patches for the ContentDelivery role:

  • systemDatabaseName is set to web instead of core
  • defaultEventQueue is set to web instead of core
  • core and master queues are removed from the eventQueueProvider

As this is only done on the ContentDelivery and not on the other environments, one line in the (still excellent) blog post from John doesn't seem to fit anymore: "Sitecore can no longer assume all web servers in a cluster to have the same database set as the systemDatabase".

Sitecore will handle this nicely (assumption) but in our code we had to make a few small changes.

Coding for a web event queue

Subscribing to the event queue doesn't change as you subscribe to all event queues available with the EventManager.  

Queuing an event however did slightly change as we now push the event to a specific queue. Note that our events are pushed from the ContentManagent role which still has core as the default eventQueue to a ContentDelivery role that has no access to the core queue anymore. So, we need to push to the queue related to the database we want to reach:
var database = Sitecore.Configuration.Factory.GetDatabase(databaseName);
var eventQueue = database.RemoteEvents.EventQueue;
eventQueue.QueueEvent(...);

And we're good to go queue...

Monday, March 11, 2019

Working with external model data in Sitecore SXA variants

SXA and variant definitions

If you are working with SXA, I assume you heard about rendering variants (if not, you're doing it wrong).  There is some documentation on the options you get when creating your own rendering variant: https://doc.sitecore.com/developers/sxa/18/sitecore-experience-accelerator/en/create-a-rendering-variant.html

There is one variant definition option that I would like to highlight here, and that is the "Model".
Model: displays properties from the current Model. The SXA renderings model inherits from Sitecore.XA.Foundation.Mvc.Models.RenderingModelBase. In the Property path field, you can enter the path to the property that you want to display.

 You can use this Model field to display any data you want. I used it to display data from a custom database, but it could also be data from a webservice or any datasource you like. How to do this..

Create your (custom) model

You should start by creating your own component: https://doc.sitecore.com/developers/sxa/18/sitecore-experience-accelerator/en/create-a-new-sxa-module.html  (or copy an existing one and change the data, but that is another topic). What you need is a custom controller, model and probably also a view. Create the necessary items in Sitecore and create your variant definition.

To write the needed code, you can refer to my blog article on custom renderings with variants or to the official docs. The important part here is actually the model class. All (custom) properties you add there will be available in the variants. Fill the data in your repository (called from the controller).
Suppose we have this model:
public class CustomModel: VariantsRenderingModel
{
  public string CustomProperty { get; set; }
  public CustomClass CustomClassProperty { get; set; }
}
and we would like to show the CustomProperty value and a property from the CustomClassProperty as well. Let's create our variant...

Create the variant definition 

In the variant definition that was created for your custom component, you can add a "Model" field.
You can select a tag (just as in other variant fields) and set a css class or other attributes. The Property Path is the really interesting one: here you can define the property from your Model you want to show. As you can see in the screenshots, you just need to add the name of the property as it is in your model class. And you can also get properties from a property..  (like the "Name" property from the CustomClass that was a property of my model).

You will notice that the variant field does not have all properties like a "Field" variant field - e.g. you cannot create a link (which makes sense of course). 

Model data

I am struggling with a few things still..  example: my model has a url and I would like to show that in the variant..  but I can only show the value of the model property - I can't seem to embed this in a "a href..".  I guess there will always be such edge cases that go just that one step further than what is possible ootb. I could go for a quick fix and have my model give me the html for the link..  and if I find a cleaner solution, I'll update the blog :)

Conclusion

Displaying all sorts of external data with variant in SXA was actually easier than expected. Not the first time the product has amazed me in a good way 😃