Rendering contents: Views
Content items are typically used in two contexts:
- Accessed via APIs in a headless application
- Rendered on a website
This tutorial focuses on rendering the Content entries in a website, with the concept of views.
Before you begin
Jahia modules rely on Java and Maven. The key requirements are as follows:
- Access to a local Jahia system or the free cloud trial from Jahia
- Oracle JDK 11 or OpenJDK 11
- Maven 3.3+
- Completion of the Module Management & Content Type Definition Tutorials
- The IDE of your choice
What you will learn
By following the steps in this tuturial, you will learn about using views to render custom content types in Jahia.
- Create a view and define its structure
- Display dynamic content in multiple ways
- Manage your content rendering files
About Views
A view determines how a content item will be displayed. A view is:
- defined in a JSP file,
- embedded in a Jahia module
- bound to a content type.
Several views can be attached to the same content type, and made available to content authors. Views are dynamic and can display content from various sources, and include other views to optimize code reusability. Views are cached by default.
For this tutorial, we are going to rely on the following content type definition and the module defined in the module management tutorial:
[jnt:introBlock] > jnt:content, jmix:structuredContent
- title (string) i18n
- description (string) i18n
- creationDate (date)
Create a view
Views can be created in two ways:
- Use the Jahia Studio
- Use your favourite IDE and create the file manually
Views are stored in Jahia modules, under the path src/main/resources
. An example of a view path would be src/main/resources/
jnt_introBlock
/html/
introBlock
.jsp
Where:
- jnt_introBlock is the aggregation of
<nodetypePrefix>_<nodetypeName>
- introBlock (filename) is the
<nodetypeName>
Create this directory structure and an empty View file for your content definition.
View structure
The base content of a view is as follows, and can be copied and pasted to the view file you created.
<%@ page language="java" contentType="text/html;charset=UTF-8" %>
<%@ taglib prefix="template" uri="http://www.jahia.org/tags/templateLib" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="jcr" uri="http://www.jahia.org/tags/jcr" %>
<%@ taglib prefix="ui" uri="http://www.jahia.org/tags/uiComponentsLib" %>
<%@ taglib prefix="functions" uri="http://www.jahia.org/tags/functions" %>
<%@ taglib prefix="query" uri="http://www.jahia.org/tags/queryLib" %>
<%@ taglib prefix="utility" uri="http://www.jahia.org/tags/utilityLib" %>
<%@ taglib prefix="s" uri="http://www.jahia.org/tags/search" %>
<%--@elvariable id="currentNode" type="org.jahia.services.content.JCRNodeWrapper"--%>
<%--@elvariable id="out" type="java.io.PrintWriter"--%>
<%--@elvariable id="script" type="org.jahia.services.render.scripting.Script"--%>
<%--@elvariable id="scriptInfo" type="java.lang.String"--%>
<%--@elvariable id="workspace" type="java.lang.String"--%>
<%--@elvariable id="renderContext" type="org.jahia.services.render.RenderContext"--%>
<%--@elvariable id="currentResource" type="org.jahia.services.render.Resource"--%>
<%--@elvariable id="url" type="org.jahia.services.render.URLGenerator"--%>
Understanding the elements:
- The
<%@
taglib
is a list of available taglibs (functions) available to the view builders - The
<%--@elvariable
are comments used by some IDEs (Intellij…) for automatic resolution of variables implicitly declared in the JSP. They will enable auto completion within the IDE for any variables declared like this. - The rest of the file is used for the rendering of the content type.
Hardcode Hello world!
into your view.
<%@ page language="java" contentType="text/html;charset=UTF-8" %>
<%@ taglib prefix="template" uri="http://www.jahia.org/tags/templateLib" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="jcr" uri="http://www.jahia.org/tags/jcr" %>
<%@ taglib prefix="ui" uri="http://www.jahia.org/tags/uiComponentsLib" %>
<%@ taglib prefix="functions" uri="http://www.jahia.org/tags/functions" %>
<%@ taglib prefix="query" uri="http://www.jahia.org/tags/queryLib" %>
<%@ taglib prefix="utility" uri="http://www.jahia.org/tags/utilityLib" %>
<%@ taglib prefix="s" uri="http://www.jahia.org/tags/search" %>
<%--@elvariable id="currentNode" type="org.jahia.services.content.JCRNodeWrapper"--%>
<%--@elvariable id="out" type="java.io.PrintWriter"--%>
<%--@elvariable id="script" type="org.jahia.services.render.scripting.Script"--%>
<%--@elvariable id="scriptInfo" type="java.lang.String"--%>
<%--@elvariable id="workspace" type="java.lang.String"--%>
<%--@elvariable id="renderContext" type="org.jahia.services.render.RenderContext"--%>
<%--@elvariable id="currentResource" type="org.jahia.services.render.Resource"--%>
<%--@elvariable id="url" type="org.jahia.services.render.URLGenerator"--%>
Hello world!
Display a view
From the Jahia UI, deploy your module and activate it on your test site. To refer to instructions check the module management tutorial.
In the Jahia contributor interface, from page composer, click +Add Conent. Select your content type and preview. It should display Hello world! For detailed instructions visit the Adding a page tutorial or Test your content type in the Content Definition tutorial
Display dynamic content
Dynamic content is aggregated along with the HTML on the server-side, and fetches data from the database. Jahia uses the Apache Jackrabbit framework to structure the data. The hierarchy and properties of the data structure are important to understand before displaying dynamic content. Please refer to the content type definition tutorial.
Content can be displayed in a View by using the Java Expression Language (EL). EL is simple. In order to display the property title
of the current node, you would add the following to your view HTML:
${currentNode.properties['title'].string}
Note the .string
at the end of the EL code. It indicates the format in which you want to render the content. Other formats exist, such as long
, date
, time
.
Now, as an exercise, using the above notation, edit your view such that it displays all the properties of your custom nodetype definition.
Use JSTL and functions
JSTL, or Java Standard Tag Library is used to call functions of any sort, including conditional structures, String and Date manipulation. They can also be used to call one of the many APIs exposed by Jahia, such as the query API or the search API.
This tutorial will focus on the conditional structures and date rendering for the sake of demonstration.
JSTL tags are imported at the beginning of a JSP file, assigned to a prefix, and can then be used anywhere in the rest of the file.
<%@ page language="java" contentType="text/html;charset=UTF-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:if test="${currentNode.properties['title'] != null}">
<h2>${currentNode.properties['title'].string}</h2>
</c:if>
In the previous example, the taglib http://java.sun.com/jsp/jstl/core
is associated with the prefix c
, and the function if
is used.
Another common use case of JSTLs is for date formatting using the formatDate function:
<%@ page language="java" contentType="text/html;charset=UTF-8" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<fmt:formatDate value="${creationDate.time}" pattern="MMMM" var="startDateMonth"/>
<fmt:formatDate value="${creationDate.time}" pattern="d" var="startDateDay"/>
<fmt:formatDate value="${creationDate.time}" pattern="yyyy" var="startDateYear"/>
<div class="date">Publication date: ${startDateYearyyyy}-${startDateMonthMMMM}-${startDateDayd}</div>
With conditional and formatting JSTL functions, you should be able to render any piece of content in a better way:
- Only display fields that are not null or not empty
- Format dates appropriately
Going further with JSTL
There is much more to JSTL than what is shown in this tutorial. Please refer to the appropriate documentation of JSTL library descriptions (.tld files) to learn more about the various available libraries.
Code factorization and keeping things simple
It is possible to split a content type rendering into multiple files in order to keep things simple, and optimize re-usability of the code.
Additional views for the same content type can be created by following this convention: src/main/resources/jnt_introBlock
/html/
introBlock
.
viewName
.jsp
For instance, if we created the view:src/main/resources/jnt_introBlock/html/introBlock.title.jsp
. This could display the title of your view, as well as its HTML rendering. You could then include it from the main view of the content type with the following JSTL syntax:
<template:include node="${currentNode}" view="title" />
There are multiple ways to include code in a JSP, some have caching implications. Caching is essential to making sure Jahia can handle thousands of concurrent visitors. Views are cached by default, and it is essential to understand the various features associated with caching in Jahia. Please read the Caching tutorial for more information.
XSS vulnerabilities
When developing custom JSP views, especially those requiring user interaction, the following rule of thumb can reduce the risk of simple cross-site scripting XSS attacks, such as JavaScript code injection. When using values of request parameters in view markup, they need to be escaped, for example:
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
...
<label for="username"><fmt:message key="label.username"/></label>
<input type="text" name="username" id="username" value="${fn:escapeXml(param.username)}" />
Expect that values that come from request parameters can be not well-formed or malicious. For example, if your view expects a JCR node path as a request parameter path, you should take care of checking if the path value really corresponds to a node, for example:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<%@ taglib prefix="jcr" uri="http://www.jahia.org/tags/jcr" %>
...
<jcr:node path="${param.path}" var="myNode"/>
<c:if test="${not empty myNode}">
do something
</c:if>
<c:if test="${empty myNode}">
unknown node path
</c:if>