Portlets Plugin

  • Tags : jsr-168, portlet, jsr-286
  • Latest : 0.9.2
  • Last Updated: 11 June 2012
  • Grails version : 2.0 > *
  • Authors : Kenji Nakamura, Philip Wu
5 votes
Dependency :
compile ":portlets:0.9.2"



Generate JSR-168 compliant portlet war.


This plugin is designed as an "abstracted" plugin, and shouldn't be installed as a stand-alone. See portlets-liferay and portlets-pluto for the installation.


Portlets plugins source code has migrated from svn repo https://svn.codehaus.org/grails-plugins to github https://github.com/grails-portlets-plugin. If you plan to improve the codebase, please create a JIRA ticket to request github access with your github id. If you join the team, you can update the codebase directly rather than creating a pull request.

Current lead of this project GPPORTLETS no longer actively maintains the plugin. Please create a JIRA ticket and let him know if you're interested in to take over the responsibility. Thank you.

Portlets Plugin

Please create an issue in JIRA under the Grails-Portlets component if you find problems or come up with ideas for enhancements.


This plugin aims to provide a simple (grails) way of developing JSR-168 portlets using well known Grails conventions that can be deployed to compliant Portal servers. Currently Liferay 5.2, Liferay 6, GateIn 3.1 and Pluto 1.1.7 are supported.

Portlets plugin consists of "grails-portlets-plugin" generating JSR-168 compliant configuration files, "grails-portlets-liferay" for Liferay specific configurations, "grails-portlets-gatein" for GateIN specific configurations, "grails-portlets-pluto" for Pluto specific configuration, "grails-pluto", which adds pluto runtime to grails and launch the container with "run-app" command, and "grails-liferay-exploded", allowing a dynamic reloading of classes and GSPs on a stand-alone Liferay server.

"grails-portlets-plugin" doesn't provide a container specific support so it won't work unless implementation specific plugin such as "grails-portlets-liferay" or "grails-portlets-pluto" is installed. "Portlets" plugin is automatically installed by installing those plugins.

You can generate container specific portlet war file by installing "portlets-liferay", "portlets-gatein" or "portlets-pluto". "liferay-exploded" or "pluto" allows to test with those portal container from grails environment.


Portlets plugin should be implicitly installed by installing a container specific portlets plugin.

Liferay portlets

Please see portlets-liferay and liferay-exploded for the details.
For LF6
grails install-plugin portlets-liferay

For LF5 export LIFERAY_HOME=/your_path_to/liferay-portlet-5.2.2 grails install-plugin portlets-liferay grails install-plugin liferay-exploded

Pluto portlets

Please see portlets-pluto and pluto for the details.
grails install-plugin portlets-pluto  
grails install-plugin pluto

GateIn portlets

Please see portlets-gatein for the details.
grails install-plugin portlets-gatein

Create a portlet

grails create-portlet com.company.MyFirst

The command generates a portlet file "grails-app/portlets/com/company/MyFirstPortlet.groovy" as following.

import javax.portlet.*

class MyFirstPortlet {

def title = 'Portlet Title' def description = ''' Description about the portlet goes here. ''' def displayName = 'Display Name' def supports = ['text/html':['view', 'edit', 'help']]

//uncomment to declare events support //def events = [publish: ["event-1"], process: ["event-2"]]

//uncomment to declare public render parameter support //def public_render_params = ["prp-1","prp-2"]

// Used for liferay // @see http://www.liferay.com/documentation/liferay-portal/6.0/development/-/ai/anatomy-of-a-portlet // def liferay_display_category = "category.sample"

def actionView = { //TODO Define action phase for 'view' portlet mode portletResponse.setRenderParameter("prp-1", "value-1"); }

def eventView = { //TODO Define event phase for 'view' portlet mode. def eventValue = portletRequest.event.value }

def renderView = { //TODO Define render phase for 'view' portlet mode. //Return the map of the variables bound to the view, //in this case view.gsp if it exists or render.gsp if not ['mykey':'myvalue'] }

def resourceView = { //TODO define resource phase for 'view' portlet mode. //Render HTML as response render { html { head() body { "Render me" } } } }

def actionEdit = { //TODO Define action phase for 'edit' portlet mode portletResponse.setEvent("event-1","event-1") portletResponse.setPortletMode(PortletMode.VIEW) }

def renderHelp = { //TODO Define render phase for 'help' portlet mode //Return the map of the variables bound to the view, //in this case help.gsp if it exists or render.gsp if not ['mykey':'myvalue'] }

def doResource = { //TODO Define handling for default resource URL handling method, independent of porlet mode //Return the map of the variables bound to the view, //in this case resource.gsp ['mykey':'myvalue'] }

//invoked by setting 'action' param in resourceURL (as an example) to 'doSomethingAjaxy' def doSomethingAjaxy = { //render JSON render(contentType:"text/json") { example(mykey:"myvalue") } }

//invoked by setting 'action' param in eventURL (as an example) to 'handleThisEvent' def handleThisEvent = { //render thisEvent.gsp render(view:"thisEvent") } }

Portlet Request Action Mapping

For a particular portlet, the plugin delegates to a *Portlet.groovy closure according to the following rules (by order of precedent):

  1. Look for an 'action' parameter on the request and see if the Portlet has a closure with the same name.
  2. Construct a name using the request type (i.e. 'resource', 'event', 'render', 'action') and the portlet mode (i.e. 'view', 'edit', 'help'), e.g. 'renderView', and see if the Portlet has a closure with the same name.
  3. Construct a name using only the request type, e.g. 'doEvent', and see if the Portlet has a closure with the same name.

View Generation

To generate views, run the following command.

grails generate-portlet-views com.company.MyFirst

It generates edit.gsp, help.gsp, and view.gsp under "grails-app/views/myfirst" directory. View.gsp looks like this. Please note portletRequest and portletResponse are bound to the GSP.

<%@ taglib uri="http://java.sun.com/portlet" prefix="portlet" %>
<h1>View Page</h1>
The map returned by renderView is passed in. Value of mykey: ${mykey}
<form action="${portletResponse.createActionURL()}">
    <input type="submit" value="Submit"/>

View Mapping

For those request types that support it ('resource', 'render'), a model can be returned by having the portlet action closure return a map. The model will be passed to a view using the following rules (in order of precedent):
  1. 'XXX/xyz.gsp' where 'XXX' is the name of the portlet (e.g. XXXPortlet.groovy) and 'xyz' is the value of the 'action' parameter on the request
  2. 'XXX/MODE.gsp' where 'XXX' is the name of the portlet (e.g. XXXPortlet.groovy) and 'MODE' is the current portlet mode (e.g. 'view')
  3. 'XXX/render.gsp'

Deploy to container

You can generate portlet war file just same as a servlet war file.

grails war

Please follow the instruction of the portlet container to deploy the portlet war file.


If you install "grails-pluto" plugin, you can run Pluto and deploy the portlet and hot reload the modifications in place. For the details, see Pluto Plugin.

GateIN 3.1

Copy war into Jboss deploy folder or upload it via jboss admin console

Liferay 6

Copy your war to liferay auto-deploy folder or upload it via administration console.

Liferay 5

If you install "grails-liferay-exploded" plugin, you can deploy an exploded war file to Liferay, and dynamically reload and reflect your changes in the grails project.
  1. Run a deployment command. It generates a war, expand, and copy context.xml
file to Liferay's deploy directory. You can run this command when the server is running or stopped.
grails liferay-deploy
  1. Monitor the console output, and confirm the servlet is successfully

(liferay1 is the name of a sample portlet war file)
21:33:16,176 INFO  [PortletHotDeployListener:219] Registering portlets for liferay1
21:33:18,050 INFO  [PortletHotDeployListener:303] 2 portlets for liferay1 are available for use

Once you deploy, you can change the code in the grails projects, and reflect the changes to the running Liferay server by invoking the following command.

grails liferay-update

For the details, please refer to Liferay exploded plugin.

"liferay-exploded" plugin is designed for development purposes only. It utilizes tomcat's hot deployment feature, but due to a memory leak on reloading, you will get OutOfMemoryError after four or five executions of "liferay-update". For production, please deploy the packaged war through Liferay's deploy directory or administration GUI.

Unit Testing

Your portlet groovy classes can be unit tested as per normal Grails controllers.

Functional Testing

The Portlets Plugin includes an embded apache Pluto portlet container (Version 1.1.7) which will be deployed during grails run-app, f you install pluto plugin. Browse to localhost:8080/pluto (login as pluto/pluto). Your portlets will be displayed on the default tab labeled 'Home'. This allows basic functional testing via the WebTest plugin.

Known Issues




Standard property names are used to generate the portlet.xml information for each portlet. They should be defined at the class level and initialized. e.g.
def title = 'HelloWorld'
def displayName = 'Grails Hello World Portlet'
def supports = ['*/*':['view', 'edit']]
def events = [publish: ['event1','event2'],process:['event3']]
def public_render_params = ['prp-1','prp-2']

There are portal container specific properties too. Please consult portlets-liferay and portlets-pluto plugins for the details.

titlethe title of the portlet (normally appears in the title bar when the portlet is displayed)Yes
descriptiona description of the portletNo
displayNamethe name of the portlet when displayed to the userYes
shortTitlea short title for your portletNo
keywordskeywords that describe your portletNo
supportsa map containing mime types and a list containing supported window modes. Standard modes available (According to the spec) are view, edit and helpYes
customModesa map containing custom window modes and their descriptions. Any custom modes referenced in supports need to be declared here.No
supportedPreferencesa map defining the portlet preferences supported by your portlet. The key is the parameter name, the value is the default value for the preference. Multiple values can be supplied as a list and will create a multi-valued portlet preference.No
roleRefsa list or map that specifies the roles required to access this portlet. It is either a list of role names or a map wher the key is the role name and the value is the role link (see the Portlet spec for more details on what how these fields are used). These values are used to generate <security-role-ref> elements.No
customWindowStatesa map containing custom window states used by this portlet and their descriptionsNo
eventsa map containing two keys, 'publish' and 'process', each key is mapped to a list of strings, each string is the name of an event that is either published or processed (or both) by this portlet.
This defines the events supported by this particular portlet, the events also must be declared in the Config.groovy, see below
public_render_paramsA list of supported public render parameters.
This defines the public render parameters supported by this particular portlet, the parameters also must be declared in the Config.groovy, see below

Portlet injected properties

The following properties are provided for use inside actions to access common objects provided by the Portlet API.

portletRequestthe current PortletRequest. It will be of the appropriate request type sub-class.
portletResponsethe current PortletResponse. It will be of the appropriate request type sub-class.
requestIt is an instance of HttpServletRequest of the underlying portlet container. You should use portletRequest instead of request for normal portlet operations. It is available only when you need to something special with the underlying servlet request and use at your own risk.
responseIt is an instance of HttpServletResponse of the underlying portlet container. You should use portletResponse instead of response for normal portlet operations. It is available only when you need to something special with the underlying servlet request and use at your own risk.
sessionthe current PortletSession.
preferencesthe PortletPreferences object for the current user.
windowStatethe current WindowState.
modethe current PortletMode.

Event Declaration

Events are declared in the Config.groovy

liferay {
	events = [
		"event1": [:],
		"event2": [type:"com.mycompany.events.Event2"]

Public Render Parameter Declaration

Public Render Parameters are declared in the Config.groovy

liferay {
	public_render_parameters = [


0.9.2 (12/06/2012)

  • now compatible with grails version > 2.x

0.9.1 (10/24/2011)

  • fixed typo in Portlet example code

0.9 (10/10/2011)

  • added resource URL support
  • added event URL support and syntax for declaring published/processed events
  • added public render parameter syntax for declaring supported parameters

0.8 (6/1/2011)

  • Update to for Grails 1.3+
  • Support for LifeRay 6 and GateIn 3.1
  • JSR-286 is supported as uses spring-mvc-portlet 3.0.5

0.7 (11/4/2009)

  • Got rid of unused Jetty import statements.

0.5 (09/22/2009)

  • Added commons-logging-1.1.1.jar to fix the deployment issue on liferay-5.2.3 with tomcat-6 due to listener registration failure.

0.4 (06/30/2009)

  • Fixed unbalanced curly bracket in gsp template files.

0.3 (05/28/2009)

  • Updated gsp template so that submission works on both pluto and liferay.
  • Added liferay_display_category field to the template so that you can generate
Liferay compatible portlet without any modifications.

0.2 (05/25/2009)

Initial release.