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

Community Blogs October 9, 2013 By Eduardo P. Garcia Staff

 

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 liferay-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!

 

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

Community Blogs October 1, 2013 By Eduardo P. Garcia Staff

 

Next week Liferay will hold the first Developer Conference (DevCon) in Berlin. Liferay experts from all around the world will meet up to share their experience and review the latest features of version 6.2.
 
We'll have the chance to introduce Application Display Templates (ADT), a new framework to add custom display options for portlets. Juan Fernández had already given us a glipse of the power of this new tool in one of his blogs last year. This time we'll go deeper into the technical details and even show you how to support ADT in your plugins.
 
In this first part of the blog, we'll focus on how ADT works and how to use it.
 

The ADT concept

Portlet Display Settings are the simpliest way to customize portlet display.  Unlike themes or hooks, they don't require deployment and they affect specific portlet instances. But, they are limited to those that come out of the box... Wouldn’t it be great to have as many of them as we wanted? As a user, this would simplify the task of customizing the portlet display. And as developers, we wouldn’t have to change our portlet configuration code every time a new setting is required.
 
That’s exactly what Application Display Templates  (also known as ADT) provides Adding custom display settigs to our portlets. Actually, this is not a new concept in Liferay. In some portlets such as Web Content, Document and Media or Dynamid Data Lists we can add as many display options (or templates) as we want.
 

Implementation

Since we already had similar features in Liferay, we tried not to reinvent the wheel with ADT. Actually, we aimed to reuse as much logic as possible. Basically, ADT is based on two preexisting Liferay components:
  • For the service layer, we used the Dynamic Data Mapping (DDM) portlet. It manages all the operations for structures and templates in every Liferay applications.
  • We used the existing Template Engine that renders Velocity or Freemarker templates based on a given context.
So we just had to add a new portlet to the Site Administration to manage the display templates, and provide a mechanism such that any portlet can define its own template context and show its custom display settings.
 

Demo

At this point some of you may believe that ADT is too good to be true. During the DevCon we'll do a demo to show how easy it is indeed to customize a portlet display with our new tool. Here you have a preview:
 
1. Adding a new ADT for the Media Gallery
 
2. Introducing the new advanced template editor to write a Freemarker script that displays our pictures in a fancy way using the  Masonry Library
 
3. Apply our new ADT to the Media Gallery...
 
..and check the effect
 
4. Extend our template to display a tooltip with more information about the pictures and include the ratings taglib.
 
You can checkout the complete demo from gihub and try it out yourself. (You will need to install the Resource Importer plugin to get the demo contents installed).
 

Recommendations

As we have seen, ADTs bring a great power. But if there's something we've learnt, is that with great power, comes great responsability!  Let’s go through some good practices  in ADT design:
 

Security

You may want to hide some classes or packages from the template context, to limit the operations that ADTs can perform on your portal. Liferay provides some portal  properties to define the restricted classes, packages and variables:
freemarker.engine.restricted.classes 
freemarker.engine.restricted.packages
freemarker.engine.restricted.variables 
velocity.engine.restricted.classes 
velocity.engine.restricted.packages
velocity.engine.restricted.variables

Performance

ADTs add extra processing task in portlet render. This inevitably has effect in the performance. To reduce this effect, make your ADT as minimal as possible: focus on the presentation and use the existing API for complex operations. Don't forget running performance tests and tuning the template cache options:
 
 
freemarker.engine.resource.modification.check.interval velocity.engine.resource.modification.check.interval

Context

The best way to make great ADTs is to know your template context well and what you can use from it. Now you don’t need to know them by heart thanks to the advanced tempalte editor!
 

Error handling

Finally, you can improve the error handling of your templates by setting these properties:
freemarker.engine.template.exception.handler
 velocity.engine.logger
 velocity.engine.logger.category

Learn more

An this is all for the first part of the introduction to ADT. Soon we'll go through the second part: Supporting ADTs in your plugins. In the meantime you can learn more about ADT in our User Guide or promt your questions in our Forums.
 
See you in Berlin! 

 

Showing 2 results.