New Ways of Customization with Application Display Templates (Part II)

 

The first Liferay DevCon has just started in Berlin and we just can't wait to present the world all new features in version 6.2. So I'm writing the second part of my blog about New Ways of Customization with Application Display Templates for those of you (eager like me) who just can't wait to use ADT in your portlets.
 
As you know Liferay is a Developer Friendly platform. We love developing and we love developers using and extending our product. So everytime we add a new framework we make sure it's not only accessible in the portlal, but also in the plugins. Security, Workflow, Asset... are only some examples of powerful features that can be exploded by your plugins. And in 6.2. we've added quite a few more! Let's focus on the ADT framework and see what you need to support this feature in your portlets.
 

Add ADT to your portlets in just 4 steps

In the first part of the blog we explained how ADT was implemented by reusing other existing services and features. We just added a management application to the Site Administration and a mechanism to allow any portlets to have and render their own templates. 
 
This second component is the key to have ADT in your portlets, and we'll describe how to use it in 4 simple steps:
 

1. Custom PortletDisplayTemplateHandler

To join the exclusive ADT club your portlet has to sign a contract committing itself to fulfill all the ADT features. In other words, you have to create a your own PortletDisplayTemplateHandler implementation by extending the BasePortletDisplayTemplateHandler methods. You can check the TemplateHandler interface javadoc to learn what every method is for. Basically:

public class MyAppPortletDisplayTemplateHandler extends BasePortletDisplayTemplateHandler { 
 
public String getClassName() {//Defines the type of entry your portlet is rendering}
   public String getName(Locale locale) {//Declares the name of your ADT type (typically, the name of the portlet)}  
public String getResourceName() {//Here you specify which resource is using the ADT (e.g. a portlet) for permission checking}  

public String getTemplatesHelpPath(String language) {//Adds a custom hint to the top of the ADT in the template editor}
public String[] getRestrictedVariables(String language) {//Provides a list with the restricted variables}   
public Map<String, TemplateVariableGroup> getTemplateVariableGroups(long classPK, String language, Locale locale) throws Exception {//Defines the variables exposed in the template editor}   
 

}

 
Once you've created your handler, you have to declare it in the right section of your liferay-portlet.xml.
<liferay-portlet-app>
 <portlet>
 <portlet-name>MyApp</portlet-name>
 … 
<template-handler>
 org.my.app.template.MyAppPortletDisplayTemplateHandler
 </template-handler>
 … 
</portlet>
 … 
</liferay-portlet-app>
 

2. Permissions

The action of adding ADTs is new to your portlet, so you want to be sure you can grant specific permissions for it. Just add this line to your resource actions file:
<resource-action-mapping>
 <portlet-resource>
 <portlet-name>MyApp</portlet-name>
 <permissions>
 <supports>
 <action-key>ADD_PORTLET_DISPLAY_TEMPLATE</action-key>
 … 
<supports>
 …
 <permissions>
 … 
<portlet-resource>
 … 
<resource-action-mapping>
 

3. Display settings configuration

Let's move to the frontend side of your portlet. Now your portlet officially supports ADT, you'll want to expose this option to your users. Just include the l iferay-ui:ddm-template-selector taglib in your portlet configuration view providing the required information, like this:
 
<aui:form action="<%= configurationURL %>" method="post" name="fm">
 ...
 <aui:fieldset> 
 
<%
 TemplateHandler templateHandler =

TemplateHandlerRegistryUtil.getTemplateHandler(MyType.class.getName());
 %>
  
<liferay-ui:ddm-template-selector
 classNameId="<%= PortalUtil.getClassNameId(templateHandler.getClassName()) %>"
 displayStyle="<%= displayStyle %>"
 displayStyleGroupId="<%= displayStyleGroupId %>"
 refreshURL="<%= PortalUtil.getCurrentURL(request) %>"
 showEmptyOption="<%= true %>"
 /> </aui:fieldset>
 ...
 </aui:form>
 

4. Render templates

Last but not least, you have to extend your view code to render it with the selected ADT. Here is where you decide exactly which part of your view will be rendered by the ADT and what will be available in the template context.
 
<%
 List<MyType> myList = ...;

long ddmTemplateId = PortletDisplayTemplateUtil.getPortletDisplayTemplateDDMTemplateId(
 displayStyleGroupId, displayStyle);
 Map<String, Object> contextObjects = new HashMap<String, Object>();
 contextObjects.put("myExtraObject", someExtraObject);
 %>

<c:choose>

<c:when test="<%= portletDisplayDDMTemplateId > 0 %>">
 <%= PortletDisplayTemplateUtil.renderDDMTemplate(pageContext, ddmTemplateId, myList, contextObjects) %>
 </c:when>

<c:otherwise>
 ...
 </c:otherwise
 </c:choose>
 ...
 
Ok, has it worked for you? Try this:
  1. Add your portlet to a page
  2. Edit configuration
  3. Display Settings selector is displayed (COOL!)
  4. Click Manage Display Settings and create new ADT
  5. The template editor displays your portlet variables (GREAT!)
  6. Save and choose your new ADT
  7. The portlet is rendered with your ADT (NICE!)

 

Demo

In order to show how to integrate 6.2 new frameworks in your plugins, Sergio and Julio have created a very complete sample plugin with several portlets using the Recycle Bin, the new Staging and Search framework features... and also ADT! It's called the jukebox project. This time I decided to use the power of ADT to create a cool iTunes-like coverflow carrousel for the album covers. See the before:
And with a little bit of ADT magic...
 
... this is how it looks at the end:
 
I've shared the code of this example, but remember you'll first need to install the jukebox plugin to make it work (hold on!).
I hope you'll enjoy using ADT as much as we did when developing and testing it. Please let us know about any issue or improvement through our issue tracker and the community tools.
 
I'm running to see the next DevCon talk, see you!

 

Blogs
It seems that the serviceLocator is no longer accessible in 6.2, and the provided overflow template doesn't work anymore. how to solve this problem? thanks
Hi

I have tried implementing application display template for my custom portlet. But when adding new template, I am getting the below exception in the logs


08:10:03,375 ERROR [http-bio-8080-exec-20][ContentUtil:64] java.io.IOException: Unable to open resource in class loader com/liferay/portlet/portletdisplaytemplate/dependencies/portlet_display_template_help.ftl
java.io.IOException: Unable to open resource in class loader com/liferay/portlet/portletdisplaytemplate/dependencies/portlet_display_template_help.ftl
at com.liferay.portal.kernel.util.StringUtil.read(StringUtil.java:2057)
at com.liferay.util.ContentUtil._get(ContentUtil.java:59)
at com.liferay.util.ContentUtil.get(ContentUtil.java:33)
at org.apache.jsp.html.portlet.dynamic_005fdata_005fmapping.edit_005ftemplate_jsp._jspService(edit_005ftemplate_jsp.java:1013)
at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)

I am getting the same exception while adding the new template in the jukebox portlet but template is added. In my custom portlet template is not added and error message (you do not have permission) is displayed on front end as well.

I have added the <action-key>ADD_PORTLET_DISPLAY_TEMPLATE</action-key>.
Great new functionality!
Is there a way of creating adt's automatically from given files in a hook for example?
what is displayStyle and displayStyleGroupId here???

and secondly After following all the steps I am able to get the Display template dropdown with manage display template link but after clicking on manage display template link, I cannot create new ADT as there is no Add button there..