Portlet Modes in Liferay

Portlet modes is a state in which portlet can generate its content.  Portlet can run in different portlet modes which is one of the key difference between portlet and servlet.

Portlet mode represents a task being executed by portlet. The content of the portlet will be different for each portlet mode.

It’s the portal job to instruct portlet in which mode it should run. Portlet modes can be changed on the fly programmatically (in the action phase only). You can define how many modes a portlet can support in its configuration file (portlet.xml).

Portlet Modes in Liferay

 

In this article, I will be showing various portlet modes and how to declare it.

Portlet Modes

To achieve portability, portlet specification (JSR-168) defines the following portlet modes, which are available across all the portal implementations (Liferay, Web Spear, Oracle portal, etc.).

  • View
    • In this mode, the portlet renders the content for its main functionality.
  • Edit
    • This mode is generally used for configuration (setting preferences)
  • Help
    • Portlet can display brief information about it in this mode.

Out of these three, View mode is default and mandatory for all portlets, and that makes sense because portlet executes its main functionality in view mode. Edit and Help are optional.

On top of these, Liferay provides additional modes available to the portlets deployed on the Liferay portal as a blow.

  • About
  • Config
  • Edit default
  • Edit guest
  • Print
  • Preview

All modes provided by Liferay are optional. Portlet modes may be restricted to specific user roles.

For example, View and Help are available to the guest user. However, Edit is only available to users with Portal / Site Administrator role.

The process of defining portlet modes span across the following 4 steps.

Step 1: Declare Portlet Modes

By default, all portlets render in view mode. You no need to declare it explicitly.

If your portlet needs multiple modes, you have to explicitly guide to the portal about it. You can define how many modes a portlet can support in its configuration file called portlet.xml.

Let’s take the example of Liferay MVC Portlet. I gave portlet class as com.opensource.techblog.portlet.ModeDemoPortlet.java. Once created, it looks like the below snapshot.

Project Structure - Portlet Modes in Liferay

Its portlet.xml should look like the below snippet.

<?xml version="1.0"?>

<portlet-app xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd" version="2.0">
    <portlet>
        <portlet-name>modes-demo</portlet-name>
        <display-name>Modes Demo</display-name>
        <portlet-class>com.opensource.techblog.portlet.ModeDemoPortlet</portlet-class>
        <init-param>
            <name>view-template</name>
            <value>/view.jsp</value>
        </init-param>
        <expiration-cache>0</expiration-cache>
        <supports>
            <mime-type>text/html</mime-type>
        </supports>
        <portlet-info>
            <title>Modes Demo</title>
            <short-title>Modes Demo</short-title>
            <keywords>Modes Demo</keywords>
        </portlet-info>
        <security-role-ref>
            <role-name>administrator</role-name>
        </security-role-ref>
        <security-role-ref>
            <role-name>guest</role-name>
        </security-role-ref>
        <security-role-ref>
            <role-name>power-user</role-name>
        </security-role-ref>
        <security-role-ref>
            <role-name>user</role-name>
        </security-role-ref>
    </portlet>
</portlet-app>

Quick observation:

You no need to shout, “Hey, my portlet will render in view mode, so here is the declaration,” because our smart Liferay portal will silently understand it.

You can see, by default, we haven’t defined any modes because the view is a default (understandable) one.

To declare other modes, you need to make a small change in portlet.xml as below.

<?xml version="1.0"?>

<portlet-app xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd" version="2.0">
    <portlet>
        <portlet-name>modes-demo</portlet-name>
        <display-name>Modes Demo</display-name>
        <portlet-class>com.opensource.techblog.portlet.ModeDemoPortlet</portlet-class>
        <init-param>
            <name>view-template</name>
            <value>/view.jsp</value>
        </init-param>
        <expiration-cache>0</expiration-cache>
        <supports>
            <mime-type>text/html</mime-type>
            <portlet-mode>view</portlet-mode>
            <portlet-mode>edit</portlet-mode>
            <portlet-mode>help</portlet-mode>
        </supports>
        <portlet-info>
            <title>Modes Demo</title>
            <short-title>Modes Demo</short-title>
            <keywords>Modes Demo</keywords>
        </portlet-info>
        <security-role-ref>
            <role-name>administrator</role-name>
        </security-role-ref>
        <security-role-ref>
            <role-name>guest</role-name>
        </security-role-ref>
        <security-role-ref>
            <role-name>power-user</role-name>
        </security-role-ref>
        <security-role-ref>
            <role-name>user</role-name>
        </security-role-ref>
    </portlet>
</portlet-app>

Explanation:-

  • Just below mime-type, we defined 3 modes – view, edit, and help.
  • It tells a portal that this portlet can support all those modes.
  • I have declared view as one of the supported modes, but even if you don’t declare it, portlet, by default, supports it.
  • Pay special attention – the portlet-mode element must be below mime-type, or else it will give an error.

Step 2: Define JSP corresponds to each Portlet Modes.

Since each portlet mode’s content is different, you must have to provide a separate JSP for each one of them. In the above example, create edit.jsp and help.jsp at the same level of view.jsp.

You can define the content you wish your portlet shows in edit mode in the edit.jsp and help mode in help.jsp. You are free to give any name to these JSPs and stored them in any location under docroot.

The Thumb rule is, you need to define one JSP for each mode.

Step 3: Set one to one mapping of Portlet Modes to JSP

We have defined what modes a portlet can support. We also defined what content (JSP) a portlet should render for each mode. The last thing is to map these JSPs to respective modes.

This mapping can be defined in the portlet configuration file – portlet.xml as below.

<?xml version="1.0"?>

<portlet-app xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd" version="2.0">
    <portlet>
        <portlet-name>modes-demo</portlet-name>
        <display-name>Modes Demo</display-name>
        <portlet-class>com.opensource.techblog.portlet.ModeDemoPortlet</portlet-class>
        <init-param>
            <name>view-template</name>
            <value>/view.jsp</value>
        </init-param>
        <init-param>
            <name>edit-template</name>
            <value>/edit.jsp</value>
        </init-param>
        <init-param>
            <name>help-template</name>
            <value>/help.jsp</value>
        </init-param>
        <expiration-cache>0</expiration-cache>
        <supports>
            <mime-type>text/html</mime-type>
            <portlet-mode>view</portlet-mode>
            <portlet-mode>edit</portlet-mode>
            <portlet-mode>help</portlet-mode>
        </supports>
        <portlet-info>
            <title>Modes Demo</title>
            <short-title>Modes Demo</short-title>
            <keywords>Modes Demo</keywords>
        </portlet-info>
        <security-role-ref>
            <role-name>administrator</role-name>
        </security-role-ref>
        <security-role-ref>
            <role-name>guest</role-name>
        </security-role-ref>
        <security-role-ref>
            <role-name>power-user</role-name>
        </security-role-ref>
        <security-role-ref>
            <role-name>user</role-name>
        </security-role-ref>
    </portlet>
</portlet-app>

Explanation:-

  • Portlet initial parameter (init-param) will do this mapping.
  • This init-param is processed while the portlet is loaded by the portlet container.
  • You can see by default it has a mapping for view.jsp.
  • For view mode, the name of init-param is view-template, and the value is JSP (with relative path).
  • For edit and help modes, the init-param name would be edit-template and help-template, respectively.
  • The value would be corresponding JSP with its relative path from docroot.
  • For simplicity, I kept view.jsp, edit.jsp, and help.jsp directly under docroot. If you wish, you can put them in any path, for example, a folder called html under docroot.
  • In that case you need to define the value of init param as /html/view.jsp, /html/edit.jsp etc.

Step 4: Define the method corresponding to each mode in the Portlet class.

So far, you saw the declaration of portlet modes, their JSPs, and mapping but don’t you feel you should ask a question – hey, who will call these JSP, and where can I put the code before calling these JSP?

And the answer is the methods correspond to each mode in the portlet class, which would fill this gap in this flow.

Open your portlet class and add the following methods to it.

package com.opensource.techblog.portlet;

import com.liferay.util.bridges.mvc.MVCPortlet;

import java.io.IOException;

import javax.portlet.PortletException;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;

public class ModeDemoPortlet extends MVCPortlet {

    @Override
    public void doView(RenderRequest renderRequest,
            RenderResponse renderResponse) throws IOException, PortletException {
        // Code written here would be exucuted before view.jsp is called
        super.doView(renderRequest, renderResponse);
    }

    @Override
    public void doEdit(RenderRequest renderRequest,
            RenderResponse renderResponse) throws IOException, PortletException {
        // Code written here would be exucuted before edit.jsp is called
        super.doEdit(renderRequest, renderResponse);
    }

    @Override
    public void doHelp(RenderRequest renderRequest,
            RenderResponse renderResponse) throws IOException, PortletException {
        // Code written here would be exucuted before help.jsp is called
        super.doHelp(renderRequest, renderResponse);
    }
}

Explanation:-

  • The doView() is a method for view mode. Similarly, doEdit is for edit, and doHelp is for help mode.
  • These methods are originally declared in MVCPortlet class, which is a parent class of your custom portlet.
  • You can override these methods in your custom portlet. If you haven’t override, Liferay will call respective methods from MVCPortlet class.
  • At the end of each method, I did make a super method call. Any guess what the reason is?

Why you need to call a super method at the end of each method that corresponds to portlet modes.

  • I haven’t put a super method call at the end of each method accidentally. It has a specific purpose.
  • I asked a question at the beginning of Step 4 that how the JSP corresponding to each portlet mode is called.
  • You can observe that I haven’t defined any code to redirect to JSP in our custom portlet class then; who will call these JSPs.
  • The answer is – redirection to the corresponding JSP is happening in each super method.

How? Let’s see by taking an example of super.doView() method.

@Override
public void doView(
        RenderRequest renderRequest, RenderResponse renderResponse)
    throws IOException, PortletException {

    include(viewTemplate, renderRequest, renderResponse);
}

Observation:

  • Internally doView() method makes a call to include() method with viewTemplate, renderRequest and renderResponse as parameters.
  • The viewTemplate is a protected instance variable that is initialized in the init() method of MVCPortlet.
  • The init() method represents the portlet’s initialization phase, and it’s called only once by the portlet container when a portlet is instantiated.
  • Open init() method, and you will find below code in that.
aboutTemplate = _getInitParameter("about-template");
configTemplate = _getInitParameter("config-template");
editTemplate = _getInitParameter("edit-template");
editDefaultsTemplate = _getInitParameter("edit-defaults-template");
editGuestTemplate = _getInitParameter("edit-guest-template");
helpTemplate = _getInitParameter("help-template");
previewTemplate = _getInitParameter("preview-template");
printTemplate = _getInitParameter("print-template");
viewTemplate = _getInitParameter("view-template");

Observation:

  • Apart from viewTemplate various other protected instance variables like aboutTemplate, configTemplate, etc., are assigned a value.
  • _getInitParameter() is used to assigned value to each of them.
  • _getInitParameter() method reads init parameter defined in portlet.xml file.
  • For example _getInitParameter(“view-template”) reads “view-template” init parameter from portlet.xml and assign its value to viewTemplate instance variable.
  • In step 3, we have defined the JSP path for each mode as an init parameter. i.e “view-template” parameter has value “/view.jsp“.
  • It means _getInitParameter(“view-template”) return the path of view.jsp (“/view.jsp in our case) and assigned to viewTemplate variable.
  • In other words, viewTemplate holds the path of JSP (defined in portlet.xml ), which represents the view mode.
  • Similarly, each instance variable holds the path to the corresponding JSP defined in portlet.xml as an init parameter.

Now open include() method which is called from doView() method. You will see one more overloaded method – include() is called which has following code.

protected void include(
        String path, PortletRequest portletRequest,
        PortletResponse portletResponse, String lifecycle)
    throws IOException, PortletException {

    PortletContext portletContext = getPortletContext();

    PortletRequestDispatcher portletRequestDispatcher =
        portletContext.getRequestDispatcher(path);

    if (portletRequestDispatcher == null) {
        _log.error(path + " is not a valid include");
    }
    else {
        checkPath(path);

        portletRequestDispatcher.include(portletRequest, portletResponse);
    }

    if (clearRequestParameters) {
        if (lifecycle.equals(PortletRequest.RENDER_PHASE)) {
            portletResponse.setProperty(
                "clear-request-parameters", Boolean.TRUE.toString());
        }
    }
}

Explanation:

  • Value of viewTemplate from include() method is referred to as the “path” parameter in this method.
  • This “path” is then passed to RequestDispatcher, which will make a call to JSP (referred by path).

I took the example of only 3 methods. If you wish, you can override other methods corresponding to each mode (defined by Liferay), i.e., doAbout, doConfig, doDispatch, doEditDefaults, doEditGuest, doPreview, doPrint, etc., as per the below screenshot.

Other Liferay specific Portlet modes - Portlet modes in Liferay

Let’s put all the building blocks together. Conclusively, the below cheat-sheet gives you a brief about portlet modes.

Portlet-Modes

Summing UP

  • Portlet can have multiple modes. By default, it supports View mode.
  • Defining a portlet mode is 4 step process
    • declare mode (in portlet.xml)
    • Define JSP corresponding to each portlet modes(content)
    • Define mapping of JSP to portlet mode in portlet.xml in the form of init parameter
    • Override method specific to portlet mode and write your custom logic there.
  • While overriding a method in your portlet class, make sure you put a call to its super method at the end, or else it will not find the corresponding JSP.

Recommended For You

About the Author: Nilang

Nilang Patel is a technology evangelist who loves to spread knowledge and helping people in all possible ways. He is an author of two technical books - Java 9 Dependency and Spring 5.0 Projects.

8 Comments to “Portlet Modes in Liferay”

    1. Hello Priyanka,

      Welcome to Techblog and thanks for appreciation. Feel free to ask questions / give suggestions.

      Regards
      Nilang

      1. hey nilang i have a query
        What is the difference between actionRequest.setAttribute(…) and actionResponse.setRenderParameter(…)?

        1. Hey Tanmay,

          Welcome to techblog. Here is the answer of your question.
          actionRequest.setAttribute is similar to httpRequest.setAttribute and you can get the value in JSP like ${variablename}
          actionResponse.setRenderParameter is store the variable as request parameter (which is generally not possible programatically when you work with Java J2ee application). Such parameters can be accessed in render method like renderRequest.getParam(“paramName”).

          Hope this clarify your doubts.

          Regard
          Nilang

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.