Embedding Dynamic Data Lists in Themes for Liferay 6.2

It is a common practice to embed Web Content Articles in a theme. Once Web Content's were embedded using Web Content Display portlet, nowadays we can use journalContentUtil which is already visible for theme developers:

$journalContentUtil.getContent($groupId, $articleId, $viewMode, $locale, $theme_display)

As usual, there are pros and cons of this approach:

  • It allows us to create editable footers, headers and other technical site elements using WYSIWYG editor via Control Panel's Web Content section. Creating custom structure / template gives even more flexibility and allow developers to implement more specific customer requirements.
  • On the other side, creating new article triggers all the advanced Liferay's WCM actions like creating new asset, indexing content (accurate to fields marked as "Indexable"), processing categories / tags and all the other stuff we don't need when creating an example footer. Sometimes I ended up with several structures, each containing exactly one article. I think this is not what Web Content's were designed for.

Dynamic Data Lists

Since 6.1, Liferay introduced new component - Dynamic Data Lists. As the official documentation says "This is an easy way to create, aggregate, and display new data types. Data Lists are flexible enough to handle all types of data, and you don’t have to write any code".

It sound like perfect solution for all site-embeddable elements which usually are lists of different types of content. Sliding banners in site's bottom section is a simple list of Document Library images, static navigation menu in the top right corner is a list combined with two Text Fields - link and title. All the tabs, accordions and other similar contents are usually lists of Text FieldsHTML Editor and images from Document Library. All these content types are available when creating Dynamic Data List structures.

Embedding DDL in theme

As in the Web Content, we have two possibilities to embed DDL Content in our Theme. First is simply embedding whole DDL Display portlet in a theme (bundled with its preferences), but this is an old and unefficient approach. Second is using DDLUtil (tool similar to journalContentUtil for Web Content).

The second option is far better but does not work out of the box. DDLUtil is not available in velocity / freemarker template context and we have to do few things to make it work:

  1. First we have to put DDLUtil into theme context via hook containig service pre action
  2. Fix NPE error that happens when we run getTemplateContent method with renderRequest set to null (using EXT)

Allow using ddlUtil in Themes

First we need to put ddmUtil into our theme development context. This can be done with a hook that contains portal.properties with servlet.service.events.pre property. There are lots of articles about how to do it (eg. http://www.opensourceforlife.com/2012/06/custom-velocity-variable-in-liferay-61.html) so I won't go into details. The most important part is Action's implementation (in the example, variable will be available for Velocity themes):

    @Override
    public void run(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse)
            throws ActionException {
        Map vars = new HashMap();
        vars.put("ddlUtil", DDLUtil.getDDL());
        httpServletRequest.setAttribute(WebKeys.VM_VARIABLES, vars);
    }

At this point, we should be able to access $ddlUtil variable within theme template. 

Fix DDLImpl error

To retrieve rendered DDL template content, we should use the following DDLUtil's method:

String getTemplateContent(
    long ddmTemplateId, DDLRecordSet recordSet, ThemeDisplay themeDisplay, 
    RenderRequest renderRequest, RenderResponse renderResponse);

It returns rendered HTML content and gets the following parameters:

  • ddmTemplateId - ID of DDL Template we want to use, can be retrieved manually from Control Panel
  • recordSet - Dynamic Data List object, can be retrieved using $ddlRecordSetLocalService using ID which is also available in Control Panel
  • themeDisplay - themeDisplay, available under $theme_display variale for theme developers
  • renderRequest - used internally for obtaining View Mode (which if not present, is automatically set to VIEW)
  • renderResponse - exists in method definiton but is not used in its implementation

First three parameters are obvious and easy to obtain. RenderRequest and RenderResponse however, are not available (The type of $request variable available in theme context, is in fact a descendant of ServletRequest, not PortletRequest - thus we cannot use it in this method).

Although we don't need renderRequest and renderResponse to render the list, setting this parameters to null will cause NullPointerExceptionThis is caused by a small bug that we need to fix using EXT plugin before we can continue. I won't go into details about how to work with EXT, it has been already described very well in official documentation. In short, we should do the following:

  1. Create EXT plugin
  2. Copy DDLImpl.java content to your ext-impl package
  3. Apply these changes
  4. Build, install plugin and restart you server

I created a JIRA task for this issue (LPS-53005) and sent fixing pull request (currently it is waiting for being accepted). 

Rendering Dynamic Data Lists in your theme

Now, we can freely use DDLUtil in our theme (Velocity example):

## Obtain DDLRecordSet
#set($ddlRecordSetLocalService =
    $serviceLocator.findService("com.liferay.portlet.dynamicdatalists.service.DDLRecordSetLocalService"))
#set($rs = $ddlRecordSetLocalService.getDDLRecordSet(23456))

## Get rendered list content
#set($rendered-ddl-content = $ddlUtil.getTemplateContent(12345, $rs, $theme_display, null, null))

## Print it!
<div id="my-ddl">
	$rendered-ddl-content
</div>

There is only one thing to do before we can say our work is finished. Both ID's (ddmTemplateId and recordSetId) are hardcoded, which is not a good practice. Fortunately Liferay allows us to define configurable theme settings which we can use then in the following way:

$getterUtil.getLong($theme_display.getThemeSetting('ddm-template-id'))

Summary

In this article I have shared some of my recent experiences with Dynamic Data Lists in Liferay. I haven't found any materials or even forum discussions about embedding DDLs in themes, so I developed my own solution. I don't know if it is the best way to do it, if not then please post your doubts in comments below the article.

An important note is that all my tests were performed on Liferay 6.2.2 GA3 but I think it will work for all 6.2 versions. I suppose it will not work for 6.1, as the implementation of DDLImpl is completely different.

This is my first blog post on Liferay.com so all the comments referring to its non-technical aspects are also welcome :)

Blogs
Hi Krzysztof,
This is interesting. Will try it out.
But right now, what I am trying to do is to create a custom presentation for the DDL that I have created. The default look shows the fields in the DDL in a not so appealing way. I would like to customize this look with html / css. When I read of form templates, I thought this was what I needed. But all it allows is for rearranging or removing the fields. While this level of customization is useful, it does not serve my purpose. Could you guide me on how this can be done?
Thanks!