About the Jahia web layer

November 14, 2023

This section describes the web layer in Jahia. This layer is both flexible and powerful. The section first describes the flow of content and then shows how a page renders.

Content flow

The following diagram shows how site visitors, editors, and developers interact with Jahia. Site visitors request and view pages, editors create content for visitors, and developers create object to provide a better experience for visitors and editors.

image011.png

Developers can create different types of objects, ranging from content definitions to macros used by Jahia to customize the experience for site visitors. Developers can create the following types of objects:

  • Definitions
    Content definitions define the type of objects that are edited in the system as well as their structure. These may range from simple properties to complex sub-tree structures.
  • Rules
    Rules define what to execute (similar to actions) when a certain condition is met. For example, a rule can listen for modifications on content objects, such as a page creation, and trigger execution of code.
  • Actions
    Actions are similar to method calls, except that they are usually called from an AJAX or HTTP POST request. Developers can use existing actions, such as createUser or startWorkflow, or define their own custom actions. You can use actions to perform almost any task in the Jahia back-end from a remote request.
  • Templates
    Templates define the page and content layouts that users use to create pages or display content elements, such as a news entry. You define templates in Jahia Template Studio. Templates can be packaged in template sets and deployed to any web site, or moved from staging to production environments. Template sets can even contain default content, which is useful to create powerful site factory scenarios.
  • Scripts
    Scripts render a specific content object type. The default script type is JSP, and Jahia 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 Jahia.
  • Macros
    Macros modify the final output of a Jahia page. Macros execute even if a page is retrieved from the HTML cache and can be used to quickly customize page output. There are some performance considerations as macros are constantly executed; they must always execute quickly.

Editors log into the system and create sites, pages and other content types that are specified by developers. Editors use Jahia's Edit mode or the simpler Contribute mode to submit content and build sites. Later, rules and actions perform logic actions on content. Templates, scripts and macros output the resulting HTML.

Visitors 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. For example, a dynamic object could be a forum or comment list. The content that visitors contribute is called User Generated Content (UGC). Jahia uses templates, scripts and macros to render the pages for visitors. If visitors have permissions, they enter and modify content in content definitions, and rules and actions are executed on content.

Templates and views

The previous section describes Jahia's editable template system that makes it easy to customize basic and complex layouts without advanced scripting skills. The following image shows how a page is composed.

In this example, a user requests a content object from the Java Content Repository (JCR) located on the home page called "bellini". Jahia uses the URL to find the corresponding content object and then looks for different objects to render the final page.

The example illustrates an advanced use case that directly requests a content object. If Jahia only had a view script for the content object, when requesting the object directly, only an HTML fragment would render instead of a complete page. Object views are designed to be re-used within pages. Instead, Jahia uses a content template. Integrators design a content template specific to one or several content object types that renders content around the object, for example, navigation, headers and footers.

The rendering of a full HTML page for a single content object is similar to the rendering an actual content page. This functionality is also similar to how most CMSs work. A database holds content records and a PHP, ASP or JSP script is called to display the record, which inherits from headers, footers and other features. If you're familiar with Drupal or Joomla, this should be pretty clear for you. The main difference is that the content template is defined directly in the Studio and stored in the JCR, and not as a script on disk.

This example shows how a content object is requested directly. In the simplier case of requesting a page object, you render the page using the following URL: http://www.dogsandcats.com/home.html. Jahia then looks for a page template, scans it to find all the different subitems present on the page, and uses views to render each specific object type.

The Jahia Studio

Templates are defined inside the content repository and you edit them in Jahia Studio. A template is a set of nodes that define the layout of a page and enables users with low scripting or HTML experience to edit or update existing templates. Note that Studio is a development tool that contains advanced features and code editing capabilities. It is not recommended to give access to non-technical users to Studio without training. Advanced users with strong JCR skills could export a template as XML, edit it and import it back into Jahia.

Templates are grouped in template sets, which can be deployed to a site on the same Jahia installation or packaged as a module and exported as a JAR file to either be deployed on another development instance, or to another Jahia installation for staging or production.

Page templates

Page templates define the layout of a page and are the default template type. Editors specify the template to use when they create a new page. Building structured templates targeted to a specific site vertical helps site administrators to ensure that sites have a coherent structure and look, and to make changes later on.

Page templates (and content templates) may also inherit from a parent template. For example, you can have a base template with a free structure, and then inherit from it to build templates that have more rigid structures.

Content templates

Content templates are used when a URL requests a content object other than a page type. A content template enhances a content type by adding navigation, headers, footers, or other page elements around the rendered content object. In a content template, you associate the template with a list of types for which it should be used in Jahia Studio. You can use content templates with master/detail views, where the master list of objects display on a page, and the detail view is a single content object rendered using a content template.

For example, assume you have news articles in your definitions and want to display a single news article in an HTML page. You could create a home page that lists the last ten news articles, with links to a news article detail view for each article and the details and subobjects 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.

REST API

Jahia’s REST and HATEOS-compliant API that makes it possible to integrate and discover REST resources easily.

Note: Jahia’s legacy REST API is deprecated. Developers should use the new API as the legacy API will be removed in a future version of Jahia.

The API:

  • Decouples the API from the rendering pipeline to make it easier to maintain and upgrade
  • Respects REST and HATEOAS principles
  • Provides a simple CRUD interface to JCR content, mapped to HTTP methods (PUT/POST, GET, PUT and DELETE)
  • Focuses on JSON representation of resources
  • Is optimized for JavaScript client applications
  • Provides full JCR content access

Resources and representations

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

Jahia uses 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) 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 Legacy REST API documentation here.

Entry points

To retrieve a representation of JCR content, you need to know which content to access. Each API operation defines the target workspace (live or default) and language in which to manipulate the content. All URIs targeting JCR data have the following prefix: <basecontext>/<workspacename>/<languagecode>/<rest of the URI>. Once you know this information, you 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 mode. The exception is the nodes of types jnt:folder, jnt:page, jnt:portlet, jnt:navMenuText (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 file 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 are not returned by the API.

The security filter module can add restrictions based on user permissions or the presence of token. In the following example, the user will have access to the API 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 access to the API will be granted if the user provides a token with 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 the 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, you would create 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

Jahia provides a legacy 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. Jahia also uses the legacy API in various modules to implement their functionality, using AJAX technologies such as JQuery.

You access a content element in the REST API in a URL that uses the following syntax:

http://(servername:serverport)/(context)/(servlet)/(workspace)/(lang)/(path).(view).(templateType)

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 Jahia is deployed. The context is empty if Jahia is deployed as the ROOT application.
  • servlet
    Is the servlet you want to use. Usually this is the /cms/render servlet that is the main page render servlet. Otherwise, you might use /cms/login, /cms/logout or /cms/find.
  • workspace
    Is live or default (=staging).
  • lang 
    Is the language code for the language you wish to render or modify.
  • path
    Is the path to a node, such as /sites/ACME/home.html in the above example.
  • view
    Is an optional view.
  • templateType
    Is the type of render desired. Usually this is .html, but you can just as easily request .csv, .xml or .rss. Of course, the corresponding views must have been defined in the system.

For example:

http://www.domain.com/jahia/cms/render/defaut/en/sites/ACME/home.html

Jahia also provides a URL rewriting system and a vanity URL system for SEO compatibility. The above explanation is targeted towards integrators and developers that want to use the REST API.

You can call the following methods on a URL. The REST API offers basic CRUD (Create, Retrieve, Update and Delete) methods that map to HTTP standard methods:

  • GET 
    Renders the node
  • POST 
    Creates a new node or call action
  • PUT 
    Updates the node
  • DELETE 
    Removes the node

You can 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 starts a workflow process on the /sites/ACME/home node. You can specify additional parameters using the URL query string, although it is recommended to use HTTP body parameters. Here are some additional examples of actions provided by Jahia:

  • 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

In this example, a prototype of a native iPhone/iPad application designed in Jahia uses the REST API. The native application connects to Jahia on startup, retrieves a configuration file that contains different screen properties, including queries that execute with the REST find servlet. The results are generated using JSON output.

The native application can display content anyway it chooses. Having 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 can also use 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 shown in the following image, the native application displays 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

You can use user agent matching to change the template type so that your site adapts to the size and navigation of mobile devices, instead of using native application rendering. You can configure user agent matching with regular expression matching and change the template type dynamically and apply alternate scripts to render the content. For example, if you 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, Jahia will first look for an "html-iphone" script directory for a view script.  If it does not exist, Jahia will default to an "html" directory. This 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

Jahia macros replace markers that you add to pages (even in a free text field) with corresponding values. For example, you can use a macro to insert a user's name into a page. You can define macros in modules as JSR-223 script files responding to a specific syntax, such as {getConstant} or {username}. Jahia 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 replace a marker in a page with content specified by the macro. Instead, you may want to filter the output and perform transformations in real time. You can do so with filters. For example, you can use a filter to transform all email addresses detected on a page and replace them with obfuscated versions that avoid detection by spam web spiders. Jahia provides 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 Jahia.