Dev @ Work

A day in the life of a developer

Liferay: Embedding Portlets in your Portlet

July 1st, 2011 by

In this article I will show you how you can embed an existing Liferay portlet into your own plug-in portlet without using Ext. This might be useful in several scenarios, for example: building your own ‘nested portlet’ portlet or include the web form portlet in your own portlet.

The solutions works in Liferay 6.0 EE SP1 and can include portlets from Liferay itself as well as portlets coming from other plug-ins. Other versions of Liferay have not been tested yet.

I hope this snippet is as useful to you as it is to me!

package nl.liones.liferay;
import com.liferay.portal.kernel.exception.SystemException;
import com.liferay.portal.kernel.portlet.PortletBag;
import com.liferay.portal.kernel.portlet.PortletBagPool;
import com.liferay.portal.kernel.util.WebKeys;
import com.liferay.portal.service.PortletLocalServiceUtil;
import com.liferay.portal.theme.PortletDisplay;
import com.liferay.portal.theme.ThemeDisplay;
import com.liferay.portal.util.PortalUtil;
import com.liferay.portal.util.PortletKeys;
import javax.portlet.PortletRequest;
import javax.portlet.PortletResponse;
import javax.portlet.ValidatorException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
/**
 * Portlet embed utility method.
 *
 * @author Stef Busking (Liones), Bert Willems (Liones)
 */
public class RuntimePortletEmbedUtil {
    /**
     * Renders the given portlet as a runtime portlet and returns the portlet's HTML.
     *
     * @param request     The {@link PortletRequest}.
     * @param response    The {@link PortletResponse}.
     * @param portletId   The ID of the portlet to render, includes instance ID for instance portlets.
     * @param queryString The query string to use for the portlet.
     * @return The HTML for the given portlet.
     * @throws SystemException    on error.
     * @throws IOException        on error.
     * @throws ServletException   on error.
     * @throws ValidatorException on error.
     */
    public static String renderPortlet(final PortletRequest request, final PortletResponse response, final String portletId, final String queryString) throws SystemException, IOException, ServletException, ValidatorException {
        // Get servlet request / response
        HttpServletRequest servletRequest = PortalUtil.getOriginalServletRequest(PortalUtil.getHttpServletRequest(request));
        HttpServletResponse servletResponse = PortalUtil.getHttpServletResponse(response);
        // Get theme display
        final ThemeDisplay themeDisplay = (ThemeDisplay) servletRequest.getAttribute(WebKeys.THEME_DISPLAY);
        // Backup current state
        PortletDisplay portletDisplay = themeDisplay.getPortletDisplay();
        PortletDisplay portletDisplayClone = new PortletDisplay();
        portletDisplay.copyTo(portletDisplayClone);
        final Map<String, Object> requestAttributeBackup = new HashMap<String, Object>();
        for (final String key : Collections.list((Enumeration<String>) servletRequest.getAttributeNames())) {
            requestAttributeBackup.put(key, servletRequest.getAttribute(key));
        }
        // Render the portlet as a runtime portlet
        String result;
        try {
            PortletBag implPortletBag = PortletBagPool.get(PortletKeys.JOURNAL);
            com.liferay.portal.model.Portlet portlet = PortletLocalServiceUtil.getPortletById(PortalUtil.getCompanyId(request), portletId);
            servletRequest.setAttribute(WebKeys.RENDER_PORTLET_RESOURCE, Boolean.TRUE);
            result = PortalUtil.renderPortlet(implPortletBag.getServletContext(), servletRequest, servletResponse, portlet, queryString, false);
        } finally {
            // Restore the state
            portletDisplay.copyFrom(portletDisplayClone);
            portletDisplayClone.recycle();
            for (final String key : Collections.list((Enumeration<String>) servletRequest.getAttributeNames())) {
                if (!requestAttributeBackup.containsKey(key)) {
                    servletRequest.removeAttribute(key);
                }
            }
            for (final Map.Entry<String, Object> entry : requestAttributeBackup.entrySet()) {
                servletRequest.setAttribute(entry.getKey(), entry.getValue());
            }
        }
        return result;
    }
}

Using this code
The snippet below demos how to embed the Liferay Web Form portlet and how to set a preference for this embedded portlet.

final String portletId = "1_WAR_webformportlet_INSTANCE_abcd";
final ThemeDisplay themeDisplay = (ThemeDisplay) request.getAttribute(WebKeys.THEME_DISPLAY);
// get the preferences
final PortletPreferences prefs = PortletPreferencesUtilityLocalServiceUtil.getWrappedPortletPreferences(themeDisplay, portletId);
// set a preference
prefs.setValue("successURL", "some url");
// dont forget to store the preferences
formPrefs.store();
// get the HTML from the portlet
final String portletHtml = RuntimePortletEmbedUtil.renderPortlet(request, response, portletId, "");
Posted in Java | 8 Comments »

Software Complexity – Decomposing an Application

January 14th, 2011 by

Inspired by a talk from Thomas Thwaites about the complexity of creating a simple toaster from scratch, I thought it would be a nice idea to decompose an application I recently build to give you an indication of the complexity.

But first let’s watch Thomas’s talk:

I will use the Kluwer Support portal I recently built as an example. I created a new portlet which was deployed into Liferay, an enterprise portal, which runs on top of the JBoss Application Server which is programmed in Java running on the Java Virtual Machine running on top of the CentOS operating system running on top of an Hardware Abstraction Layer running on top of hardware. Liferay uses Spring to inject services  in my portlet which retrieve data through Hibernate from MySQL.

In order to implement the customer requirements the portlet had to use Spring to separate presentation from business logic which connect to a SOAP web service through HTTP using Axis in order to retrieve data which was index by Solr, a Lucene based search server in order to be able to render a search form using JavaServer Pages and Velocity as HTML which is styled using CSS and made interactively using JavaScript.

If this technological enumeration (a total of 21) makes your head spin you got another thing coming because I only scratched the surface. I estimate it took an army of a million computer scientists over a billion man-hours to make this application work. A small miracle in my opinion!

Solving the Portlet Design Problem

December 22nd, 2010 by

In my previous post I told you about the problem we encountered while implementing the Kluwer Support portal in Liferay. In this post I will explain the solution we came up with.

But first lets have a quick look at the problem again: We needed to support different styles per portlet and ‘read more’ links which needed to work for both custom and out-of-the-box potlets. Let have a look at some of the different ‘web-content display portlet’ styles used in the portal:

Liferay, at least not version 5.2.8 EE, does not support these requirements out of the box (Not entirely true: Liferay does allow you to specify custom CSS rules per portlet instance, but you would need a front-end specialist to maintain the website which IMHO is not acceptable).

To make it even more difficult we were not allowed to use Liferay Ext or place many hooks or have impact on existing communities in the portal instance.

Read the rest of this entry »

Posted in Java | 8 Comments »

Building Kluwer Support Portal – a Developers Perspective

December 17th, 2010 by

In the past two months we (Liones) build a new Liferay based portal for Kluwer (a major Dutch publisher), one of our clients. The purpose of this portal is to help the customers of Kluwer online products to understand and use their products better. This week the Kluwer Support portal was launched with success and I reckoned this was a good moment to share some insight in how we developed that particular portal and what problems we encountered during the development.

But let’s have a look at the result first:

I hope you agree with me when I say that it looks great, I know for a fact a lot of people do. You can find the actual portal at http://www.kluwer.nl/support, although the portal is in Dutch, feel free to look around.

In the next few paragraphs I will share some challenges we faced and the lessons we learned while implementing the Kluwer Support portal.

Read the rest of this entry »

Posted in General, Java | 2 Comments »

Securing your Liferay Service using PermissionChecker

May 3rd, 2010 by

Welcome to 3rd article in this series of articles showing you how you can develop custom Liferay services. In the previous article I showed you how you can implement a custom Liferay service and expose it as a web service. In this article I will show you how you can secure your service using Liferay’s build-in permission model.

The permission system in Liferay is pretty powerful: you configure permissions on roles or teams. Next you apply roles to either groups (communities, organizations) or individual users. In this article we will define a new permission: the permission to access our “very exiting business logic” sayHello. After all, we have invested countless hours in developing it; we don’t want everybody to use it without us knowing ;) .

I hope this article is useful to you. Please let me know if you have any questions or comments; just drop me a message and I will get back to you as soon as I can.
Read the rest of this entry »

Posted in Java | 7 Comments »

Expose a Liferay Service as a Web Service

April 26th, 2010 by

In my previous article I showed you how you can implement a reusable Liferay Service without using Ext or  the Service Builder utility. In this article we will take it one step further and expose the service we have created as web service again without using Ext or the Service Builder.

Liferay exposes the services based on Axis using a separate web application called tunnel-web. We will hook into tunnel-web so our service will be exposed in exactly the same way Liferay services are externalized. Let’s get started.
Read the rest of this entry »

Posted in Java | 12 Comments »

Implementing a reusable Liferay Service Without Ext or Service Builder

April 19th, 2010 by

In Liferay you can split your application logic vertically exposing each component as a separate independent service. This service can be consumed by your portlet applications and any other applications. Liferay itself exposes several services to you: GroupService (for managing communities) and UserService (for managing users) for example. In this article I will show you how you can create a reusable service yourself and host it in Liferay.

In this article we will build a simple hello world service, nothing to fancy (I want to leave something for you to do yourself ;) ). We will code the service from scratch without using tools like service builder.

The project will contain 3 modules:

  1. A library containing the service contract
  2. A web application implementing the service contract
  3. A web application consuming the service

I hope you like this article, please let me know if you have any questions or comments. Lets get started. I assume you have read my previous article about using Maven to build Liferay applications. If not please read it first.
Read the rest of this entry »

Posted in Java | 29 Comments »

Setting up Maven for Liferay Development

April 17th, 2010 by

Welcome to the third article in these series about Liferay usage, maintenance and development. In this post I will show you how to set up your Liferay development enviroment using Apaches Maven2 build tool. We will develop a really simple JSR-168 portlet which can be deployed into Liferay. I assume you have read my previous articles and that you are using Liferay 5.2.3 on JBoss 5.1. I hope you like this post as much as the previous ones, if you have any feedback feel free to contact me or post a response.

The next version of Liferay, release date end Q1 begin Q2, will have complete support for maven including custom archetypes. Some of the steps described in this article will be obsolete then, but lets get started. Read the rest of this entry »

Posted in Java | 4 Comments »

SEO Friendly URLs for Liferay Portlets

April 4th, 2010 by

In my previous article I showed you how you can optimize SEO from within a portlet. Today we will take it one step further: I will show you how you can optimize portlet URLs. By default the URLs generate by Liferay are quite messy; it contains the portlet ID, the state and several other options. This doesn’t really look nice for Google.

However, Liferay has a nice method of controlling the URL the portal generates for a portlet, the ‘FriendlyURLMapper‘. You can implement this interface, registerd it in the liferay-portlet.xml and you will have nice URLs. In the following example I will show how to implement it and what each individual method does.

Read the rest of this entry »

Posted in Java | 12 Comments »

Liferay Training @ Frankfurt, part 4

March 31st, 2010 by

Today is the last day of the Liferay development training in Frankfurt, which is too bad because there is so much more to discover about Liferay.

A quick summary of what we have learned during this course:

  • Setting up Liferay, the plugin SDK and the Ext environment (allows you to customize the Liferay core)
  • Setting up MySQL for Liferay
  • Setting up a basic portlet
  • Setting up a Liferay entity & service, a portlet which consumes it and hook those two up including validation and localization
  • Creating a hook
  • Creating a theme
  • And a lot more…

I think this will be the last update regarding the Frankfurt training.

Posted in General | No Comments »