Adding custom Layout type

General Blogs January 12, 2018 By Vitaliy Koshelenko

Liferay has different types of pages. The default one is Layout - it’s standard, empty by default page, which is displayed in navigation menu. Portlets may be added to such page, themes and layouts may be also applied to this type of page. In most cases this page type is used.

But there are different page types, here are they:

  • Link to a Page of This Site - as the name says, this is a link to some page within site. Page of this type doesn’t have it’s own content, it’s used to redirect to some other page within the same site by clicking on this page in navigation menu
  • Link to URL - this is similar to previous type, but may refer to a page of some other site within portal, or even to some external URL
  • Panel - this type of page is used to work with different portlets on one and the same page. When you set page type to Panel in Site Pages menu, you can specify which applications (portlets) will be available on this panel page
  • Embedded - it’s a Liferay page, which contains IFrame, which displays content from specified URL. When you select Embedded page type, you may specify URL to display.

For most cases these page types are quite enogh for portal development. But sometimes there is a need to create a custom type of layout - for example, if you need to create layout as a link to some custom friendly URL, like products category. 

Fortunatelly, Liferay provides great opportunity to extend this funcitonality. See in original Liferay's

# Set the list of layout types. The display text of each of the layout types
# is set in content/ and prefixed with "layout.types.".
# You can create new layout types and specify custom settings for each
# layout type. End users input dynamic values as designed in the edit page.
# End users see the layout as designed in the view page. The generated
# URL can reference properties set in the edit page. Parentable layouts
# can contain child layouts. You can also specify a comma delimited list of
# configuration actions that will be called for your layout when it is
# updated or deleted.

Let's create custom "link_to_category" layout type (similar to Liferay's link_to_layout). For this you need to overwrite 'layout.types' property in the file of the hook module:


and also specify the setting for new layout type:[link_to_category]=/portal/layout/edit/link_to_category.jsp[link_to_category]=/portal/layout/edit/link_to_category.jsp

In the hook set the name and description of created layout type:

layout.types.link_to_category=Link to Category
layout.types.link_to_category.description=Link to Category

In the specified JSP file (link_to_category.jsp) add required content for editing layout functionality. In my case it's the following:

<%@ page import="com.liferay.service.util.CategoryServiceUtils" %>
<%@ page import="com.liferay.service.util.Category" %>
<%@ include file="/html/portal/layout/edit/init.jsp" %>
    Set<Category> categories = CategoryServiceUtils.getCategoryTrees();
    long categoryId = selLayout != null ? GetterUtil.getLong(selLayout.getTypeSettingsProperty("categoryId")) : 0;
<aui:select label="link-to-category" name="TypeSettingsProperties--categoryId--" showEmptyOption="<%= true %>">
    <c:forEach var="category" items="${categories}">
        <aui:option label="${}" value="${category.categoryId}" selected="${category.categoryId eq categoryId}"/>

After deploying hook with the changes above - you'll see the new layout type in Manage Pages section during adding/editing layout.  

After saving such layout custom 'categoryId' field will be saved into layout's typeSettings. Then it can be used within theme for displaying Layout in a different way.

Note 1: the "name" property of field should start with "TypeSettingProperties--" and end with "--" to be saved into Layout's TypeSettings. See in com.liferay.portlet.layoutsadmin.action.EditLayoutsAction#updateLayout:

UnicodeProperties typeSettingsProperties =
      actionRequest, "TypeSettingsProperties--");

Note 2: fields should be with namespaces. Either use AUI components, like in above example (as they generate them automatically), or add them manually to your components name, like:

<select name="_156_TypeSettingsProperties--categoryId--">
    <%-- ... --%>

, where 156 is GRUOP_PAGES portletID, see in com.liferay.portal.util.PortletKeys:

public static final String GROUP_PAGES = "156";

But it's better no not hard-code smiley

Hope, this will be helpful for you.





P.S. Read my Liferay book at

Adding custom classes to Theme Velocity context

General Blogs January 11, 2018 By Vitaliy Koshelenko

To make some custom class available inside a theme velocity template, you need to put it's instance into com.liferay.portal.kernel.util.WebKeys#VM_VARIABLES request attribute. And it will be populated to the velocity context automatically (in com.liferay.portal.velocity.VelocityTemplateContextHelper#prepare method), see:

// Insert custom vm variables

Map<String, Object> vmVariables =
   (Map<String, Object>)request.getAttribute(WebKeys.VM_VARIABLES);

if (vmVariables != null) {
   for (Map.Entry<String, Object> entry : vmVariables.entrySet()) {
      String key = entry.getKey();
      Object value = entry.getValue();

      if (Validator.isNotNull(key)) {
         template.put(key, value);

To achieve this, you can use custom service pre action:

Inside this action you can put required objects into WebKeys#VM_VARIABLES request attribute map:

public class VMPopulateServicePreAction extends Action {

    public void run(HttpServletRequest request, HttpServletResponse response) {
        Map vmVariablesMap = (Map) request.getAttribute(WebKeys.VM_VARIABLES);
        if (vmVariablesMap == null) {
            vmVariablesMap = new HashMap<String, Object>();
        vmVariablesMap.put("categoryService", new CategoryServiceImpl());
        request.setAttribute(WebKeys.VM_VARIABLES, vmVariablesMap);


And now you can use those object in your theme, like:

#set ($categoryNav=$categoryService.getCategoryNav($categoryId))

Hope, this will help smiley


Liferay Migration from 5.2.3. to 6.2 (step-by-step instructions)

General Blogs May 21, 2015 By Vitaliy Koshelenko

Step 1. Liferay Migration to 6.0.6

1. Create 5.2.3 DB dump (db.sql).
2. Create database for LR 6.0.6 (db606).
3. Load 5.2.3 dump into 6.0.6 database:
mysql -uroot -p1 db606 < db.sql;

Delete all database views (if any).
4. Unzip clean Liferay 6.0.6.
5. Delete all folders from 'webapps' (except 'ROOT' and 'tunnel-web'); delete jre from tomcat folder.

6. Copy 'data' folder from Liferay 5.2.3 to Liferay 6.0.6.
7. Startup Liferay 6.0.6 (with default Hypersonic database settings).
8. Shutdown Liferay 6.0.6.
9. Create file:
10. Startup Liferay 6.0.6. Wait until Liferay's upgrade process has upgraded database to 6.0.6.
11. Check if there is no " ' " symbol in DB field.
Go to Control Panel → Server Administration → Data Migration. Click 'Execute' under 'Convert legacy permission algorithm'.
12. Once permission algorithm is upgraded, remove permissions.user.check.algorithm property
from file and restart server.
13. Go to Control Panel → Server Administration → Data Migration. Select 'FileSystemHook' inside Migrate images section, and click 'Execute' button.
14. Change image.hook.impl to com.liferay.portal.image.FileSystemHook in file and restart server.

Step 2. Liferay  Migration to 6.2.

1. Create 6.1 DB dump (db61.sql).
2. Create database for LR 6.2 (db62).
3. Load 6.1 dump into 6.2 database:
mysql -uroot -p1 db62 < db61.sql;

Check if there is no " ' " symbol in DB field.
4. Unzip clean Liferay 6.2.
5. Startup Liferay 6.2 (with default Hypersonic database settings).
6. Shutdown Liferay 6.2.
7. Copy 'data' folder from Liferay 6.1 to Liferay 6.2.
8. Modify file, add db configuration:
9. Startup Liferay 6.2. Wait until Liferay's upgrade process has upgraded database to 6.2.

Step 3. Portlets and Themes Migration.

3.1. Migrate portlets from 5.2.3 to 6.2 version.

3.2. Migrate themes from 5.2.3 to 6.2 version. Make sure, that themeId is the same in 5.2.3 and 6.2 versions, otherwise themes will be not applied for pages.

Showing 3 results.