Last updated by prkn8tr 3 months ago
Portlets Plugin
Please create an issue in JIRA under the Grails-Portlets component if you find problems or come up with ideas for enhancements.
Overview
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.
Installation
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-liferayFor 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.
com.mycompany
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):
- Look for an 'action' parameter on the request and see if the Portlet has a closure with the same name.
- 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.
- 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" %>
<div>
<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"/>
</form>
</div>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):
- '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
- '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')
- 'XXX/render.gsp'
Deploy to container
You can generate portlet war file just same as a servlet war file.
Please follow the instruction of the portlet container to deploy the portlet
war file.
Pluto
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.
- 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.
- Monitor the console output, and confirm the servlet is successfully
registered.
(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.
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
TODO
Reference
Configuration
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.
| property | description | required |
|---|
|
| title | the title of the portlet (normally appears in the title bar when the portlet is displayed) | Yes |
|
| description | a description of the portlet | No |
|
| displayName | the name of the portlet when displayed to the user | Yes |
|
| shortTitle | a short title for your portlet | No |
|
| keywords | keywords that describe your portlet | No |
|
| supports | a map containing mime types and a list containing supported window modes. Standard modes available (According to the spec) are view, edit and help | Yes |
|
| customModes | a map containing custom window modes and their descriptions. Any custom modes referenced in supports need to be declared here. | No |
|
| supportedPreferences | a 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 |
|
| roleRefs | a 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 |
|
| customWindowStates | a map containing custom window states used by this portlet and their descriptions | No |
|
| events | a 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 | No |
|
| public_render_params | A 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 | No |
Portlet injected properties
The following properties are provided for use inside actions to access common objects provided by the Portlet API.
| property | description |
|---|
| portletRequest | the current PortletRequest. It will be of the appropriate request type sub-class. |
|
| portletResponse | the current PortletResponse. It will be of the appropriate request type sub-class. |
|
| request | It 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. |
|
| response | It 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. |
|
| session | the current PortletSession. |
|
| preferences | the PortletPreferences object for the current user. |
|
| windowState | the current WindowState. |
|
| mode | the 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 = [
"param-1":"com.mycompany.public-param-1"
]
}History
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.