About the DX web layer

  Written by The Jahia Team
   Estimated reading time:

This section details the web layer of a Digital Experience Manager system. This layer is both flexible and powerful; so we will first go over the flow of content, then present how a page is rendered.

Content flow

To understand how Digital Experience Manager works with content, we have illustrated this with the following diagram:

Starting from the bottom up, the developer can create different types of objects, ranging from content definitions to macros that will be used by Digital Experience Manager to customize the experience for other users. We will now briefly detail the different types of objects:

  • Definitions: content definitions define the type of objects that will be edited in the system as well as their structure. These may range from simple properties to complex sub-tree structures
  • Rules: rules define "consequences" (similar to actions) that must be performed when a certain condition is met. They make it possible, for example, to listen to modifications on content objects (such as page creation), to trigger any type of consequence.
  • Actions: actions are similar to method calls, except that they are usually called from an AJAX request or an HTTP POST request. Developer may either use existing actions (such as "createUser" or "startWorkflow") or define their own custom ones to fit their needs. This simple yet powerful extension mechanism makes it possible to perform almost any task in the Digital Experience Manager back-end from a remote request.
  • Templates: templates are defined in the Digital Experience Manager Template Studio, and they make it easy to define page and content layouts that may be used when creating pages or displaying content elements (such as a news entry). Templates may be packaged in Template Sets, and then be deployed to any web site, or moved from staging to production environments. Template Sets may even contain default content, which is useful to create powerful site factory scenarios.
  • Scripts: used to render a specific content object type. The default script type is JSP, but Digital Experience Manager supports any Java Scripting API (http://www.jcp.org/en/jsr/detail?id=223) compatible script language (for example Velocity, Freemarker, or even PHP). Multiple scripts may be provided for a single node type: these are called "views" in Digital Experience Manager.
  • Macros: macros may also be defined to provide quick substitutions on the final output of a Digital Experience Manager page. Macros are executed even if a page is retrieved from the HTML cache, so macros can be very useful to quickly customize page output. There are some performance caveats as macros are constantly executed; they must always be very fast to execute.

Editors will then log into the system and start creating sites, pages and other content types that were specified by the developers. They use Digital Experience Manager's powerful Edit Mode or the simpler Contribute Mode to submit content and build the site bit by bit. As they enter content, rules, actions are used to perform logic actions upon submission; and then templates, scripts and finally macros are used to output the resulting HTML. Visitors will either surf anonymously or log into the system, browse the site and interact with any dynamic object types that the editors and developers have made available to them. An example of such a dynamic object could be a forum, or a comment list. The content they contribute is called "User Generated Content" (or UGC). Again, Digital Experience Manager will use the templates, scripts and macros to render the pages for the visitors, and if they are allowed to enter content, rules, actions and content definitions will again come into play (but not illustrated above to keep the diagram simple).

Templates and views

As presented in the previous section, Digital Experience Manager introduced a new editable template system that makes it easy to customize basic or even complex layouts without advanced scripting skills. To better understand how a page is composed, we will now illustrate this in the following schema:

In the example presented above, we are requesting a content object from the Java Content Repository that is located on the home page called "bellini". Digital Experience Manager will therefore first use the URL to find the corresponding content object, and then starts looking for different objects that will help render the final page. In this specific example, we are not requesting a "page" object, but a content object directly, which is a little more complex. If we had wanted to render the page, we would have used the following URL: http://www.dogsandcats.com/home.html . Digital Experience Manager would have then looked for a page template, scanned it to find all the different sub-items present on the page, and then used views to render each specific object type. In the case of the above example, we have illustrated a more advanced use case, where we directly request a content object directly. If all we had for this content object was a view script, when requesting the object directly, we would probably only get an HTML fragment rendered instead of a complete page (as object views are designed to be re-used within pages). In order to avoid this, Digital Experience Manager has a mechanism called the "content template" that allows integrators to design a template specific to one or several content object types that will be used to "decorate" around the object itself, allowing, for example, to render navigation, headers and footers around the object. The rendering of a full HTML page for a single content object then becomes quite similar to the case of rendering an actual content page. This mechanism if, in fact, very similar to how most CMS work, with a DB holding content records and a PHP, ASP or JSP script that is called to display that record, inheriting from headers, footers and other blocks of features; through includes most of the time. If you're familiar with Drupal or Joomla for instance, this should be pretty clear for you. The main difference here is that the content template is defined directly inside the Studio and stored in the JCR, and not as a script on disk.

The Digital Experience Manager Studio

As templates are not scripts, but defined inside the content repository, Digital Experience Manager introduced a new tool called the Studio to edit them. A template is a set of nodes that will define the layout of a page, allowing users with low scripting or HTML experience to edit or update existing templates. Note that the Studio remains a development tool and has been improved a lot with version 7.0 with advanced features and code editing capabilities. For that reason, it is not recommended to give access to non-technical users to it, at least without a proper training and explanations on what that can / should not do within it. For advanced users with strong JCR skills, you could even export the template as XML, edit it and re-import it back into Digital Experience Manager, should you wish to do so. Templates are grouped in Template Sets, which can then be deployed to a site on the same Digital Experience Manager installation or packaged as a module and exported as a JAR file to either be deployed on another development instance, or to another Digital Experience Manager installation for staging or production.

Page templates

Page templates are the default template type, and are made available to editors when they create a new page. At that point the editor may specify the template he wishes to use that will define the layout of the page. Building structured templates targeted to the specific site vertical makes it a lot easier for site administrators to make sure that the sites have a coherent structure and look, and will also help make changes later on.

Page templates (and content templates) may also inherit from a parent template, so you may, for example, have a "base" template that has a very free structure, and then inherit from it to build templates that have more rigid structures.

Content templates

As explained in the content flow diagram, content templates are used when an URL is requesting a content object that is not a page type, but any other. It is therefore possible to "decorate" a content type by adding navigation, headers, footers, or any other desired page elements around a rendered content object by defining a template and associating it with a list of types (through the Digital Experience Manager Studio UI) for which it should be used. This is very useful for master/detail views, where the master list of objects would be displayed on a page, and the detail view could be a single content object rendered using a content template.

For example, let's say you have news articles in your definitions, and you would like to display a single news article in a full HTML page. You could have a home page that would list the abstract of the last ten news articles, and each of them would have a link to a single news article detail view, with all the details and sub objects attached to it. The home page would be rendered using the page template and the news article detail would be rendered using a content template associated with the news article type.

New REST API

Digital Experience Manager provides a new, modern, REST and HATEOS-compliant API that makes it possible to integrate and discover REST resources easily. This new API was introduced in version 7 and was based on the feedback from the work with the legacy REST API. The legacy REST API is now deprecated but still available, but developers should now use the new API as the old one will be removed in a future version of Digital Experience Manager.

Digital Experience Manager provides a new, modern, RESTful API over JCR content. Based on feedback from users of the legacy REST API, this new API was introduced in version 7 to make it easier to integrate with and discover resources by leveraging the Hypermedia As The Engine Of Application State (HATEOAS) concepts.

We trust that you will find this new API easier to work with and are thus deprecating the legacy REST API, which, while still available, will be removed in a future version of Digital Experience Manager.

Goals

The goals of this new API are as follows:

  • Decouple the API from the rendering pipeline to make it easier to maintain and upgrade
  • Respect REST and HATEOAS principles
  • Provide a simple Create-Read-Update-Delete (CRUD) interface to JCR content, mapped to HTTP methods (PUT/POST, GET, PUT and DELETE, respectively)
  • Focus on JSON representation of resources
  • Optimize for JavaScript client applications
  • Provide full JCR content access

Resources and representations

The REST concepts states that you don't manipulate resources directly, rather you manipulate their state by exchanging representation. In our case, resources are JCR nodes and properties.

We use the following representation for nodes:

{
  "name" : "<the node's unescaped name>",
  "type" : "<the node's node type name>",
  "properties" : <properties representation>,
  "mixins" : <mixins representation>,
  "children" : <children representation>,
  "versions" : <versions representation>,
  "_links" : {
    "self" : { "href" : "<URI for the resource associated with this node>" },
    "type" : { "href" : "<URI for this node's type resource>" },
    "properties" : { "href" : "<URI for this node's properties resource>" },
    "mixins" : { "href" : "<URI for this node's mixins resource>" },
    "children" : { "href" : "<URI for this node's children resource>" },
    "versions" : { "href" : "<URI for this node's versions resource>" }
  }
}

The representation for properties is as follows:

{
  "name" : "<unescaped name>",
  "multiValued" : <boolean indicating whether the property is multi-valued or not>
  "reference": <boolean indicating whether the property value(s) point(s) to a node>
  "value" : "<value>",
  "type" : "<type>",
  "_links" : {
    "self" : { "href" : "<URI this propertys resource>" },
    "type" : { "href" : "<URI for this propertys definition>" }
  }
}

The _links section is currently a simplified version of what is described in the JSON Hypertext Application Language (HAL, http://tools.ietf.org/html/draft-kelly-json-hal-06) and provides links that a client application can, in conformance with HATEOAS principles and along with using the proper HTTP methods, use to navigate and operate on JCR content.
For more details on representations (and the RESTful API in general), please refer to the online documentation: https://www.jahia.com/get-started/for-developers/developers-techwiki/content-manipulation/legacy-rest-api

Entry points

Before being able to retrieve a representation of some JCR content, we need to know which content needs to be accessed. For this reason, each API operation is scoped by both the target workspace (live or default) and the language in which the content is to be manipulated. Therefore, all URIs targeting JCR data will be prefixed as follows: <basecontext>/<workspacename>/<languagecode>/<restof the URI> Once this information is known, we can use one of the API three entry points. Each entry point corresponds to different ways to access the initial representation with which to work and are each assigned to a different URI:

Type of access URI template HTTP methods
By identifier /{workspace}/{language}/nodes/{id}(/(children|mixins|properties|versions)/{subElement})? GET, PUT, DELETE
By path /{workspace}/{language}/paths/{path} GET, POST

By type

/{workspace}/{language}/types/{type}

GET

Security

Access to the REST API is restricted by default, and cannot be used directly by a non authenticated user in live. The exception here are the nodes of types jnt:folder, jnt:page, jnt:portlet, jnt:navMenuText (i.e. pages, folders, portlets and menu labels), located under sites (/sites/.*). If you need to open the API on some nodes, you'll have to provide a configuration file for the security filter module. The configuration should define precisely what you want to open - you can specify the node types and path patterns to what will be allowed :

permission.myApiAccess.api=jcrestapi
permission.myApiAccess.nodeType=nt:myNodeType1,nt:myNodeType2
permission.myApiAccess.pathPattern=/sites/mysites/nodes/.*

Nodes that won't match will not be returned by the API.

The security filter module can add restriction based on user permissions, or the presence of token. In the following example, the user will have access to the API if and only if it has the permission jcr:write :

permission.myApiAccess.api=jcrestapi
permission.myApiAccess.nodeType=nt:myNodeType1,nt:myNodeType2
permission.myApiAccess.pathPattern=/sites/mysites/nodes/.*
permission.myApiAccess.requiredPermission=jcr:write

Here the API will be granted if the user provides a token bearing the "myApp" scope : 

permission.myApiAccess.api=jcrestapi
permission.myApiAccess.nodeType=nt:myNodeType1,nt:myNodeType2
permission.myApiAccess.pathPattern=/sites/mysites/nodes/.*
permission.myApiAccess.scope=myApp

For more details on security filter configuration, check documentation .

Example

Given the following mixin definition:

[jmix:robots] mixin
extends=jnt:virtualsite
 - robots (string, textarea) = 'User-agent: *'

To attach this mixin to an existing `/sites/mySite` node, whose identifier is `foo` , a client would perform the following, creating a new `jmix__robots` resource in the `mixins` collection resource, using a `PUT` request:

PUT /default/en/nodes/foo/mixins/jmix__robots HTTP/1.1
Host: api.example.org
"properties" : {
    "robots" : {
        "value" : "User-agent: Mozilla"
    }
}

Legacy REST API

Digital Experience Manager provides a simple yet powerful REST API that allows CRUD (Create, Retrieve, Update and Delete) operations on content. It also offers more advanced operations such as searches, triggering actions (built-in or custom), as well as authentication. This implementation is now referred to as the "legacy" implementation, and the new REST API should be used for any new projects. Digital Experience Manager also uses this API in various modules to implement their functionality, using AJAX technologies such as JQuery. Access to a content element in the REST API is done through a URL convention that we detail below: o http://(servername:serverport)/(context)/(servlet)/(workspace)/(lang)/(path).(view).(templateType) o Example: http://www.domaine.com/jahia/cms/render/defaut/en/sites/ACME/home.html Where: - servername: is the hostname that is associated with a site, or simply the server's hostname or IP address if no site is associated with a hostname.

  • serverport: is an optional port number if Tomcat is not configured to listen to port 80, or if no Apache server has been setup in front of Tomcat.
  • context: is the context in which Digital Experience Manager is deployed (empty if Digital Experience Manager is deployed as the ROOT application).
  • servlet: the servlet you want to use. Most of the time it will be the "/cms/render" servlet that is the main page render servlet, but you might also need to use /cms/login, /cms/logout or /cms/find 
  • workspace: live or default (=staging).
  • lang: is the language code for the language you wish to render or modify.
  • path: the path to a node (such as /sites/ACME/home.html in the above example).
  • view: an optional view.
  • templateType: the type of render desired. Most of the time it will be .html, but you can just as easily request .csv, .xml or .rss. Of course, this requires the corresponding views to have been defined in the system.

We also provide an URL rewriting system as well as a vanity URL system for SEO compatibility. The above explanation is really targeted towards integrators and developers that want to use the REST API.

Now that we have detailed the URL format, let's look at the possible methods that may be called on an URL. The REST API offers basic CRUD (Create, Retrieve, Update and Delete) methods that are mapped to the HTTP standard methods:

  • GET will render the node.
  • POST will create a new node (or call action).
  • PUT will update the node.
  • DELETE will remove the node.

It is possible to have more methods using actions.

Actions

Actions are an extension point to the default HTTP methods provided in the JCR REST API. Methods may be defined in modules and make it easy to perform additional (and complex) operations on nodes.

Here is an example of an action being called from an URL:

POST http://localhost:8080/cms/render/default/en/sites/ACME/home.startWorkflow.do
 

All actions use the *.do extension at the end. The above example will start a workflow process on the /sites/ACME/home node. Additional parameters may be specified either using the URL query string, although it is recommended to use HTTP body parameters. Here are some additional examples of actions provided by Digital Experience Manager: - NewUser (module: userregistration) - PublishFile (module: docspace) - MailAction (module: formbuilder) - GetFeed (module: feedimporter) - DocumentConverterAction (module: docConverter)

As you can imagine, this makes it easy to use content actions directly from a simple HTML form, without any Javascript (in this example calling the newUser action):

<form method="post" action="<c:url value='${currentNode.path}.newUser.do' context='${url.base}'/>" name="newUser" id="newUser">

Example: native iPhone/iPad application

An interesting example application illustrating the usefulness of the REST API is a prototype of a native iPhone/iPad application that was designed by Digital Experience Manager. The native application connects to Digital Experience Manager on startup, retrieves a configuration file that contains different screen properties, notably queries that will be executed with the REST find servlet. The results are generated using JSON output. The native application can then display the content any way it chooses. Having the content in JSON format makes it easy to adapt to multiple screen sizes, as the native prototype is a dual iPhone and iPad application. The application is also capable of creating new content by using POST HTTP requests to create new content objects. All this is quite optimal and integrated with the authentication as it also uses the login and logout servlets.

As you can see in the above example, the native application displays the ACME demo content, with native device rendering. This makes for a strong mobile user experience while having exactly the same content base. It is also possible to cache the data in the native client for offline browsing.

Mobile rendering

An alternative to the native application rendering is to use user agent matching to change the template type so that the rendering may adapt the size and navigation to the size of mobile devices. Digital Experience Manager makes it possible to configure the user agent matching using regular expression matching and changing the template type dynamically so it becomes possible to switch to alternate scripts to render the content. For example, if we have the following configuration in the WEB-INF/etc/spring/application-renderer.xml file:

<bean class="org.jahia.services.render.filter.UserAgentFilter">
    <property name="priority" value="6" />
    <property name="applyOnModes" value="live,preview" />
    <property name="applyOnConfigurations" value="page" />
    <property name="userAgentMatchingRules">
        <map>
            <entry key=".*iPhone.*" value="iphone" />
            <entry key=".*iPod.*" value="iphone" />
            <entry key=".*iPad.*" value="iphone" />
            <entry key=".*Android.*" value="iphone" />
        </map>
    </property>
</bean>

This means that if an iPhone or Android user agent is detected, it will first look for an "html-iphone" script directory for a view script, and if it does not exist, it will default to an "html" directory. As you can see this simple yet powerful mechanism makes it possible to do all kinds of user agent matching. You could even use it to render for specific desktop user agents (such as legacy ones). It is also possible to use integrate with solutions such as the Apache Mobile Filter (http://www.apachemobilefilter.org) which can expose mobile device capabilities as request attributes if you need more precise control over page rendering. This might also be a good candidate for a filter, or you could integrate WURFL (http://wurfl.sourceforge.net/) as a module.

Macros

As described in the content flow, Digital Experience Manager also has a macro mechanism, which makes it possible to insert markers in pages (even in free text field) that will be dynamically replaced with the corresponding values. This is useful if you want to use a macro to insert a user's name, or anything you might think of. Macros may be defined in modules as JSR-223 script files responding to a specific syntax (such as {getConstant} or {username}), and Digital Experience Manager also offers a few default macros such as:

  • Constants stored in a node property display
  • Form token generation, to prevent multiple submissions of the same form
  • Display the current user name

Filters

Macros actually require a marker to be inserted in the page for the content to be inserted, so there may be some cases where you actually want to filter the output and perform transformations in real time. This can be done through the usage of filters. For example, it might be useful to use a filter to transform all email addresses detected and replace them with an obfuscated version that will avoid detection by spam web spiders. Digital Experience Manager provides different filters out of the box, but you may of course add your own. Here is a non-exhaustive list:

  • Portlet process action filter (for portlet support)
  • Static asset filter (injects JavaScript and CSS in the HTML page header)
  • Metrics logging filter (gathers statistics on object views)
  • User agent dispatcher (for mobile rendering)
  • HTML cache
  • Email obfuscator
  • And a lot more…

As you can see, some filters are quite powerful, while others may be very specific to a certain usage. Filters are an important part of the internal processing of Digital Experience Manager.