As Quirijn already announced eloquently in his post on ViewModels in DD4T 2.0, the idea of making it easier to build a Tridion driven website for developers by introducing the ability to use simple model classes in your MVC application serving Tridion data, is one of the biggest improvements in the DD4T framework. With the public coming-out-of-beta release of DD4T 2.0 for Java, ViewModel functionality has also been fully integrated in the Java version of the framework. This series of posts focus on how ViewModels work in DD4T 2.0 for Java.
DD4T ViewModels in Spring MVC with Tridion data
Before diving into actual creation of ViewModels, it’s good to take a look at how DD4T acts as the middle man between Tridion published content and the Spring MVC web application. Schematically, it looks like this:
Whenever you request a Page, a DCP, a Binary or an item from a Taxonomy, the DD4T Providers access the Tridion Broker database through the Tridion CD API and, if the item exists, gets back a big chunk of Json data. DD4T then attempts to deserialize that Json into objects it knows. The core Tridion model is defined in the dd4t-api and contain all the familiar Tridion item types.
In order to deserialize retrieved data into ViewModels, DD4T 2 for Java’s databind framework hooks into the standard way of deserializing data at the time a retrieved item’s Json data is in the process of being deserialized. This specifically happens when (D)CPs are deserialized, since all normally published Tridion content is contained into (D)CPs.
The databind framework acts as an interceptor in this process, in order to check whether ViewModel definitions apply to the (D)CP currently underway to be deserialized. If this is the case, the appropriate ViewModels are instantiated at that time and filled with the data you require in your ViewModel. The instantiated ViewModels are then added to the Component Presentation model and additionally pushed separately as JavaBeans to the attribute stack of the HttpServletRequest so that Spring MVC can later find the ViewModel when it renders the view associated with the (D)CP.
View Rendering
When all data is deserialized, the instantiated DD4T objects are passed to the Spring MVC controllers, where they are rendered with the appropriate views. DD4T renders views for CPs by first determining the view name from either the Component Template name or by looking at the “view” metadata key if it is set on the Component Template.
If no view metadata key is present in the Component Presentation, DD4T will take the title of the Component Template. In all cases, the following rules apply:
- Both the value of the view metadata field and the title of the component template will be lower cased;
- Spaces in the value will be dashed (‘-‘).
If for example your view name is: ‘generic Content’, the JSP view name should be: generic-content.jsp, which should then be present in the web application as a JSP file. If it is, then a sub Servlet request is fired which outputs the rendered JSP into the parent – usually Page – JSP.
Since the ViewModels were set on the HttpRequest stack as JavaBeans, it means that they are then also available when rendering (D)CPs. So, given we have a ViewModel with the following definition:
@ViewModel (
viewModelNames = {"genericcontent"},
rootElementNames = {"Generic"},
setComponentObject = true,
setRawData = false)
public class Generic extends TridionViewModelBase {
}
The object is available in your JSP by the following bean definitions:
<jsp:useBean id="Generic" type="org.dd4t.test.web.models.Generic" scope="request"/>
<%-- or --%>
<jsp:useBean id="genericcontent" type="org.dd4t.test.web.models.Generic" scope="request"/>
<%-- and / or (in case you need other data in the component object; this you do not normally do!--%>
<jsp:useBean id="component" type="org.dd4t.contentmodel.impl.ComponentImpl" scope="request"/>
…so that further in your JSP you can use the data inside the Bean:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<jsp:useBean id="Generic" type="org.dd4t.test.web.models.Generic" scope="request"/>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
${Generic.heading}
${component.schema.title}
<c:forEach var="embeddedField" items="${Generic.embedded}">
${embeddedField.testfieldOne}
${embeddedField.embeddableTwo.testfieldTwo}
</c:forEach>
… in a clean and easy way.
The next article in this series shows how to start creating and using ViewModels yourself!