Skip to main content

Enable XPM Session Preview in Web 8 using Microservices

If you implemented the steps in the previous post Implementing Experience Manager in DD4T 2.0 .NET, then at this moment you can run your web application and XPM markup will appear in your HTML output. Also XPM functionality is working.

However, if there are modifications on the Page or any Components on the Page that are not published, the "Update Preview" button will flash in the XPM GUI. Pressing this button will eventually end up in an error and the Update Preview button will keep flashing. This is due to the fact that we have not configured Session Preview yet.

The following sections will guide you through installing and configuring Session Preview and database and services it uses.

Experience Manager Database

This database, aka Session Preview Database, has the same structure as a Tridion Content Data Store database, only that it is used as temporary storage for items that have been modified in XPM and previewed (i.e. rendered with templates), but not yet published.

Consult SDL Documentation portal link Creating the Experience Manager database about steps for creating this database.

Discovery Service

SDL Web 8 introduced several Content Delivery microservices, one of them being the Discovery Service. This service is in charge with showcasing the capabilities a particular server has, such that it is known to other client APIs, which service is installed, which version and under which URL it is accessible.

In my implementation, the Discovery Service runs on port 8082, under URL path: /discovery.svc

For an XPM implementation, a default Discovery Service is used. The service provides an endpoint that issues authorization tokens for clients that provide certain user/password combinations. These tokens are to be used when communicating with the other (discoverable) services. This endpoint is accessible under URL path: /token.svc

Consult SDL Documentation portal link Installing the Discovery Service about steps for installing this service.

Once configured and the discoverable services registered, the Discovery Registration Tool lists the following services in my environment:

[ {
  "Capability" : "com.sdl.web.discovery.datalayer.model.ContentServiceCapability",
  "id" : "DefaultContentService",
  "lastUpdateTime" : 16663565840,
  "uri" : "http://services.tridion.com:8081/content.svc"
}, {
  "Capability" : "com.sdl.web.discovery.datalayer.model.TokenServiceCapability",
  "id" : "DefaultTokenService",
  "lastUpdateTime" : 16663565996,
  "uri" : "http://services.tridion.com:8082/token.svc"
}, {
  "Capability" : "com.sdl.web.discovery.datalayer.model.PreviewWebServiceCapability",
  "id" : "DefaultPreviewWebService",
  "lastUpdateTime" : 16663565934,
  "uri" : "http://services.tridion.com:8083/ws/preview.svc"
} ]

Session Content Service

The Content Service is in charge with serving content and other functionality for your delivery API. In order to use XPM with this service, a different flavour should be installed, namely the Session-enabled Content Service or for short Session Content Service.

This service is not directly used by XPM itself, rather it is used by the web application and the Tridion Content Delivery API when it reads content, metadata, links, etc. from the Content Data Store. In my implementation this service runs on port 8081 under URL path /content.svc

DD4T uses the Content Service by means of pointing to the Discovery Service this service is registered with:

<appSettings>
  <add key="discovery-service-uri"
       value="http://services.tridion.com:8082/discovery.svc/" />
...

Consult SDL Documentation portal link Installing the Session-enabled Content Service about steps for installing the Session Content Service.

By default this service comes with OAuth enabled, which makes it harder to debug or to at least check if it's working. Go ahead and check below the section Disable OAuth for Easier Debugging, in order to disable OAuth for debugging purposes.

Configure Experience Manager Database

Session Content Service must know of the Experience Manager Database in order to read the content from the published data store or the XPM data store. This means we need to configure it in its cd_storage_config.xml. Place for following node and configure its relevant values inside node Configuration / Global / Storages / Wrappers:
<Wrapper Name="SessionWrapper">
  <Storage Type="persistence" Id="sessionDb" dialect="MSSQL" Class="com.tridion.storage.persistence.JPADAOFactory">
    <Pool Type="jdbc" Size="10" MonitorInterval="60" IdleTimeout="120" CheckoutTimeout="120" />
    <DataSource Class="com.microsoft.sqlserver.jdbc.SQLServerDataSource">
      <Property Name="serverName" Value="db.tridion.com" />
      <Property Name="portNumber" Value="1433" />
      <Property Name="databaseName" Value="xpm-db"/>
      <Property Name="user" Value="XPMUser"/>
      <Property Name="password" Value="password"/>
    </DataSource>
  </Storage>
</Wrapper>

Session Preview Service

This microservice is a key component of the XPM architecture and without it, XPM will not work. The Preview Service is in charge with saving changes to content and metadata back to the Tridion Content Manager. In my implementation this service runs on port 8083 and it is accessible under URL path: /ws/preview.svc

Consult SDL Documentation portal link Installing the Preview Service about steps for installing the Session Preview Service.

By default this service comes with OAuth enabled, which makes it harder to debug or to at least check if it's working. Go ahead and check below the section Disable OAuth for Easier Debugging, in order to disable OAuth for debugging purposes.

Configure Experience Manager Database

Just like its Content Service counterpart, the Preview Service must know of the Experience Manager Database in order to read the content from the published data store or the XPM data store. This means we need to configure it in its cd_storage_config.xml. Place for following node and configure its relevant values inside node Configuration / Global / Storages / Wrappers:

<Wrapper Name="SessionWrapper">
  <Storage Type="persistence" Id="sessionDb" dialect="MSSQL" Class="com.tridion.storage.persistence.JPADAOFactory">
    <Pool Type="jdbc" Size="10" MonitorInterval="60" IdleTimeout="120" CheckoutTimeout="120" />
    <DataSource Class="com.microsoft.sqlserver.jdbc.SQLServerDataSource">
      <Property Name="serverName" Value="db.tridion.com" />
      <Property Name="portNumber" Value="1433" />
      <Property Name="databaseName" Value="xpm-db"/>
      <Property Name="user" Value="XPMUser"/>
      <Property Name="password" Value="password"/>
    </DataSource>
  </Storage>
</Wrapper>

Publication Target

For XPM to work, it must be enabled first in the Publication Target settings. Open your Staging target and select the checkbox Enable for inline editing:
Publication Target enabled for Experience Manager
Once this checkbox is selected, a new tab appears Session Preview:
Session Preview settings

Each line has the following meaning:
  • Content Delivery Endpoint URL: fully qualified URL of the Session Preview Service. E.g. http://my-url:8083/ws/preview.svc
  • OData Access Token URL: in case the services use authentication, this is the fully qualified URL of the Discovery Service token endpoint that performs the check and issues access tokens. E.g. http://my-url:8082/token.svc
  • User Name: user that requests access for the Session Preview Service. This user is defined in file cd_ambient_conf.xml on the Preview Service and must have user role cm
  • Password: password for the user
  • Website URL's: at least one URL that identifies the beginning of an XPM page URL for this staging target

Oh, and Don't Forget...

CIL (REST) Service-Oriented Implementations

Both Content Service and Preview Service require the presence of a cookie named preview-session-token. This cookie identifies the current XPM session and is essential in merging published content from the Content Data Store with not-yet-published content from the Experience Manager Database.

The absence of this cookie has as effect the incorrect functioning of "Update Preview" button in XPM. More precisely, XPM will identify there are modifications to the Page and/or Component on a page that have not been published yet. This triggers the flashing of "Update Preview" button, indicating some new content is available that has not been published yet. Without a valid preview-session-token cookie, the Session Content Service is unable to pull these not-yet-published modifications from Experience Manager Database or from the Content Manager and therefore, Update Preview functionality fails.

The solution is quite straight-forward: install Ambient Data Framework in the web application (where the CIL API is running) so that ADF makes this cookie available in the context when a REST request is built and sent to the Session Content Service.

Alternatively, if using a custom REST client to talk to the Content Service, include the preview-session-token cookie in your custom request.

For more information on architecting XPM solution in service oriented environment, refer to my post Experience Manager in DD4T with Service-Oriented Architecture Providers.

Disable OAuth for Easier Debugging

By default, all microservices in Web 8 have OAuth token based authentication/authorization enabled. This makes it harder to debug or at least inspect by means of simply accessing their endpoint URL in a browser. Attempting to do so, will result in the following JSON being displayed in the browser:

{"error":"invalid_grant"}

Although this message alone is a good indication there is a service listening at that address, port and URL path, it is still very cryptic and does not provide a clear picture what the status of that service is.

This is why, for the duration of configuring, setting up the services, I choose to disable OAuth on the Web 8 microservices. The moment when I have my services up and running, I immediately turn OAuth back on. Note that all services must have the same state of OAuth. You cannot have some services use OAuth and some not. It is either on for all services in an environment or off for all.

There are other methods of debugging / inspecting these services and I won't go into details on those. This is what I prefer doing for a short period of time while getting all functionality running.

To disable OAuth, edit each service cd_ambient_conf.xml file. Locate node RequestValidator and comment it out:

<RequestValidator>com.sdl.web.oauth.validator.OAuth2RequestValidator</RequestValidator>

<!--RequestValidator>com.sdl.web.oauth.validator.OAuth2RequestValidator</RequestValidator-->

Next, locate node Rules and set its Enabled attribute to false:

<Rules Enabled="false"/>

Restart each service.

To enable OAuth, remove comment from RequestValidator node and set Rules to Enabled true.



Comments

Popular posts from this blog

Scaling Policies

This post is part of a bigger topic Autoscaling Publishers in AWS . In a previous post we talked about the Auto Scaling Groups , but we didn't go into details on the Scaling Policies. This is the purpose of this blog post. As defined earlier, the Scaling Policies define the rules according to which the group size is increased or decreased. These rules are based on instance metrics (e.g. CPU), CloudWatch custom metrics, or even CloudWatch alarms and their states and values. We defined a Scaling Policy with Steps, called 'increase_group_size', which is triggered first by the CloudWatch Alarm 'Publish_Alarm' defined earlier. Also depending on the size of the monitored CloudWatch custom metric 'Waiting for Publish', the Scaling Policy with Steps can add a difference number of instances to the group. The scaling policy sets the number of instances in group to 1 if there are between 1000 and 2000 items Waiting for Publish in the queue. It also sets the

Toolkit - Dynamic Content Queries

This post if part of a series about the  File System Toolkit  - a custom content delivery API for SDL Tridion. This post presents the Dynamic Content Query capability. The requirements for the Toolkit API are that it should be able to provide CustomMeta queries, pagination, and sorting -- all on the file system, without the use third party tools (database, search engines, indexers, etc). Therefore I had to implement a simple database engine and indexer -- which is described in more detail in post Writing My Own Database Engine . The querying logic does not make use of cache. This means the query logic is executed every time. When models are requested, the models are however retrieved using the ModelFactory and those are cached. Query Class This is the main class for dynamic content queries. It is the entry point into the execution logic of a query. The class takes as parameter a Criterion (presented below) which triggers the execution of query in all sub-criteria of a Criterio

Running sp_updatestats on AWS RDS database

Part of the maintenance tasks that I perform on a MSSQL Content Manager database is to run stored procedure sp_updatestats . exec sp_updatestats However, that is not supported on an AWS RDS instance. The error message below indicates that only the sa  account can perform this: Msg 15247 , Level 16 , State 1 , Procedure sp_updatestats, Line 15 [Batch Start Line 0 ] User does not have permission to perform this action. Instead there are several posts that suggest using UPDATE STATISTICS instead: https://dba.stackexchange.com/questions/145982/sp-updatestats-vs-update-statistics I stumbled upon the following post from 2008 (!!!), https://social.msdn.microsoft.com/Forums/sqlserver/en-US/186e3db0-fe37-4c31-b017-8e7c24d19697/spupdatestats-fails-to-run-with-permission-error-under-dbopriveleged-user , which describes a way to wrap the call to sp_updatestats and execute it under a different user: create procedure dbo.sp_updstats with execute as 'dbo' as