Sei sulla pagina 1di 75

Portlet Development Best Practices

Misagh Moayyed
Software Developer
Unicon, Inc.

June 10, 2012

Copyright Unicon, Inc., 2008. Some rights reserved. This work is licensed under a
Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License.
To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/3.0/us/
Unicon

2
Agenda
1. Portlet Overview
a) JSR168
b) JSR286: Events, Resources
2. Spring Portlet MVC Framework
a) Framework overview
b) Controllers, View Resolvers, Annotations
c) Exceptions, Internationalization
3. Getting started with Portlet Development
a) Development Environment
b) Plugins, Libraries and Tips
4) Q&A 3
Portlet Overview

4
Definitions

What is a portlet?
A portlet is an application that provides a specific
piece of content (information or service) to be
included as part of a portal page.

What is a portal?
A portal container runs portlets and provides
them with the required runtime environment.

5
Diagram from Java Portlet Specification, Version 2.0 Public Draft
6
uPortal Content Management Portlet

7
Java Portlet Standards

Java Portlet 1.0 Specification (JSR 168)


Started: 29 January 2002
Released: 27 October 2003
Reference Implementation: Apache Pluto
Linked to WSRP 1.0 Specification

Java Portlet 2.0 Specification (JSR 286)


Started: 29 November 2005
Final Approval Ballot: 3 March 2008 (Passed)
Reference Implementation (Pluto 2.0)
Linked to WSRP 2.0 Specification
8
Portlets and Servlets

Portlets and Servlets closely related,


but no direct connection

Portlets run in Portlet Container

Portlet Container is an extension


of a Servlet Container

Portlet Application is an extension


of a Web Application
web.xml & portlet.xml Deployment Descriptors

Can have Portlets and Servlets together in


the same Web App
9
JSR 168 Features
Lifecycle (init, action, render, destroy)
Portlet URLs (Render URL, Action URL)
Portlet Mode (View, Edit, Help)
Window States (Normal, Maximize, Minimize)
Render Parameters
Portlet Preferences
Portlet Info and Security
Portlet Deployment Descriptor (portlet.xml)

expiration-cache

10
Multiple Request Phases

Action Requests
Executed only once
Used to change system state (e.g. form post)
No markup produced

Render Requests
Executed at least once
May be executed repeated
Produces the fragment markup
Results can be cached

Portlet 2.0 adds Event Requests and


Resource Requests (now we have four!)
11
Portlet Modes

Control state of portlet from


portal-provided navigation controls

Three standard modes:


VIEW: Normal display of Portlet
EDIT: Configure the Portlet (e.g. Preferences)
HELP: Show documentation about Portlet

Portals can have additional custom modes


(several suggested modes in the specs)

Portlets can change their own mode

12
Portlet.xml
<portlet>
<description xml:lang="en">A Content Management Portlet</description>
<portlet-name>ContentManagementPortlet</portlet-name>
<display-name xml:lang="en">Content Management System</display-name>
<portlet-class>org.springframework.web.portlet.DispatcherPortlet
</portlet-class>
<init-param>
<name>contextConfigLocation</name>
<value>/WEB-INF/context/ContentManagementPortlet-context.xml</value>
</init-param>
<expiration-cache>0</expiration-cache>
<supports>
<mime-type>*/*</mime-type>
<portlet-mode>VIEW</portlet-mode>
<portlet-mode>EDIT</portlet-mode>
<portlet-mode>HELP</portlet-mode>
<portlet-mode>CONFIG</portlet-mode>
</supports>
13
</portlet>
Portlet URL Handling

Portals are in control of actual URLs

Portlets must use specific APIs for generating


URLs and setting parameters

Multiple types of URLs corresponding to


request types (Action and Render)

No concept of path for the portlet must


use Portlet Mode, Window State, and Request
Parameters for navigation

14
JSR 286 Features

Portlet Events

Resource Serving

Public Render Parameters

Portlet Filters

Caching Changes

15
Portlet Events

16
Portlet Events

New Lifecycle Phase: Event Processing

For each overall portal page request:


Action Phase called on at most one portlet
window
Event Phase called on as many portlet windows
as necessary
Render Phase called on up to as many portlet
windows that are displayed on current page

Events may be generated during Action Phase


or Event Phase not during Render Phase

17
EventPortlet Interface

javax.portlet.EventPortlet Interface
May be implemented by a Portlet
Contains one method:
void processEvent(EventRequest, EventResponse)
EventRequest object provides event payload and
other typical portlet info (mode, window state,
etc)
processEvent is similar to processAction for
copying renderParameters

18
Publishing Events

Events may be published using methods on


ActionResponse or EventResponse
setEvent or setEvents
Multiple calls to setEvent and setEvents are
allowed

Event delivery and processing order


is not guaranteed

19
Event Definitions

Events must be defined in portlet.xml

After event definition, each portlet must


declare what events it will publish or receive

Portal-defined events do not have to be


defined in portlet.xml

Event naming:
Must use the W3C QName standard
Receiving events can end with a * wildcard
Can declare default-event-namespace in
portlet.xml and just use local names
20
Supported Events in Portlet.xml
<portlet>
<supported-processing-event>
<qname xmlns:x="https://source.jasig.org/schemas/uportal/search">
x:SearchRequest
</qname>
</supported-processing-event>

<supported-publishing-event>
<qname xmlns:x="https://source.jasig.org/schemas/uportal/search">
x:SearchResults
</qname>
</supported-publishing-event>
</portlet>

21
Event Definitions in Portlet.xml
<portlet-app>
<event-definition>
<qname xmlns:x="https://source.jasig.org/schemas/uportal/search">
x:SearchRequest
</qname>
<value-type>org.jasig.portal.search.SearchRequest</value-type>
</event-definition>
</portlet-app>

22
Resource Serving

23
Resource Serving

Portlets can create two types of Resource


Links
Direct Links (not new)
Resource URL Links (new!)

Direct Links
More efficient
Not guaranteed to go through Portal
Will not have portal context available
No portal access control

Resource URL Links


Will go through the ResourceServingPortlet
interface 24
ResourceServingPortlet

ResourceServingPortlet Interface
void serveResource
(ResourceRequest, ResourceResponse)

Portlet can produce content with


ResourceResponseWriter
OutputStream
Delegate with a RequestDispatcher call

Portal is not allowed to modify content

Portlet should not use HTTP GET for state


change use HTTP POST/PUT/DELETE instead
25
The Spring Portlet MVC
Framework

26
Using A Framework

Frameworks take care of infrastructure and


let you focus on your unique functionality

Coding Portlets from scratch is of course an


option, but let's go to the frameworks...

27
Spring MVC

Flexible and Lightweight

Request-Oriented Web Framework

Implements Classic MVC Pattern


Model

Information to be presented

Contract between Controller and View
View

User interface definition

Used to render the Model for display
Controller

Handles the request and assembles the Model

Delegates to service layer for business logic
28
Handler
Select
Mapping Controller

Lookup Generate

ModelAndView
Request Dispatcher Map (Model)
Return
(Servlet/Portlet)
Response
viewName

Render
Lookup

Select View
View Resolver
29
Spring Controllers

Basic interfaces handle requests and


potentially return a ModelAndView

Many useful abstract classes for common


Controller patterns

All easily extensible for your custom handling

Support for annotation-based controllers

30
Spring Views

Includes support for numerous common view


technologies:
JSP & JSTL, XSLT, Velocity, FreeMarker, Tiles,
PDF Docs, Excel Docs, JasperReports

Easy to implement new View technologies

View technology all usable in both Servlets


and Portlets
Although only ones capable of producing HTML
markup fragments generally useful in Portlets

JSP & JSTL is the most common View


technology for Portlets
31
Other Spring MVC Features

Interceptors for wrapping other concerns


around Controller execution

Exception Resolvers to catch Exceptions


coming out of Controllers and mapping to
appropriate Views

Multipart Handling to bind file uploads

Internationalization to load text from custom


languages files

32
Spring Controllers

33
Spring Controllers
Controller (The Interface)
AbstractController
SimpleFormController
AbstractWizardFormController
PortletWrappingController
PortletModeNameViewController

Several others!

Which one should you choose?!


34
Configure Portlet Annotations

Scan and auto-detect annotated components:


<context:component-scan base-package="org.jasig.portlet.cms" />
<context:annotation-config />

Use @Controller

@Controller
@RequestMapping("CONFIG")
public class ConfigController { ... }

35
Spring Handler Mappings

36
HandlerMapping
PortletModeHandlerMapping
Map to a Controller based on current PortletMode
ParameterHandlerMapping
Map to a Controller based on a Parameter value
PortletModeParameterHandlerMapping
Map to a Controller based on current PortletMode
and a Parameter value
Or create your own custom HandlerMapping

37
PortletModeHandlerMapping

<bean id="portletModeHandlerMapping"
class="org.springframework.web.portlet.handler.
PortletModeHandlerMapping">
<property name="portletModeMap">
<map>
<entry key="view" value-ref="viewController"/>
<entry key="edit" value-ref="editController"/>
<entry key="help" value-ref="helpController"/>
</map>
</property>
</bean>
<bean id="viewController" class="ViewController"/>
...

38
HandlerMapping with Annotations
@RequestMapping @ModelAttribute
@ActionMapping @RequestParam
@RenderMapping
...
@Controller
@RequestMapping("HELP")
public class HelpController extends AbstractPortletController {
@RequestMapping
public String getHelpView() {
logDebug("Forwarding request to help view...");
return "help";
}
}
39
Internationalization

40
Internationalization

Put all user visible text into a properties file:

button.home = Home
button.edit = Edit
button.next = Next
button.previous = Previous
button.finish = Finish
button.cancel = Cancel
exception.notAuthorized.title = Access Not Permitted
exception.notAuthorized.message = You do not have
permission to access this area.

41
MessageSource

Define a Spring MessageSource that uses


Resource Bundles by giving it the basename
of the bundle (i.e. the basename of your
properties file):
<bean id="messageSource"
class="org.springframework.context.support.
ResourceBundleMessageSource">
<property name="basenames">
<list>
<value>messages</value>
</list>
</property>
</bean>

42
Using Messages in Views

In your Views, use the appropriate


mechanism to retrieve the messages from
the MessageSource by their identifier.

JSP example:
<%@ taglib prefix="spring"
uri="http://www.springframework.org/tags" %>
...
<p><spring:message
code="exception.notAuthorized.title"/></p>

43
Localization

After creating the default file (e.g.


messages.properties), create files for each
supported Locale and translate contents
accordingly:
messages_de.properties (German)
messages_fr.properties (French)
messages_fr_CA.properties (French Canadian)
...

44
Portlet Exception Handling
with Spring

45
Exception Handling

Map Exceptions to Views using


SimpleMappingExceptionResolver
<bean class="org.springframework.web.portlet.handler. _
SimpleMappingExceptionResolver">

<property name="exceptionAttribute" value="exception" />


<property name="exceptionMappings">
<props>
<prop key="javax.portlet.PortletSecurityException">
notAuthorizedToDoAnything
</prop>
</props>
</property>

<property name="defaultErrorView" value="defaultError" />


</bean>

46
Exception Handling with Annotations
Annotate handler method with
@ExceptionHandler
@Controller
public class SimpleController {
@ExceptionHandler(IOException.class)
public String handleIOException(IOException ex,
HttpServletRequest request) {
return ClassUtils.getShortName(ex.getClass());
}
}

Must be in the same class as the method


throwing the exception! 47
Portlet Event/Resource
Requests with
Spring

48
Handling Portlet Events
@EventMapping: Map Portlet event requests
onto handler methods
@EventMapping(SearchConstants.SEARCH_REQUEST_QNAME_STRING)
protected void searchContent(EventRequest request,
EventResponse response) {
final Event event = request.getEvent();
final SearchRequest query = (SearchRequest) event.getValue();

SearchResults res = new SearchResults();


res.setQueryId(query.getQueryId());
res.setWindowId(request.getWindowID());

SearchResult searchResult = new SearchResult();


searchResult.setTitle(getPortletConfig().getPortletName());
searchResult.setSummary(post.getContent());

res.getSearchResult().add(searchResult);
response.setEvent(SearchConstants.SEARCH_RESULTS_QNAME, res);
}
}
49
Handling Resource Requests
Create a ResourceURL targetting the Portlet:
ResourceUrl url = renderResponse.createResourceURL()

@ResourceMapping

@ResourceMapping
public void handleResourceRequest(ResourceRequest request,
ResourceResponse response) {

...

50
Getting started with
Portlet Development

51
Tools And Libraries

Development Environment
Eclipse, IntelliJ, etc

Apache Maven
Manage builds and dependencies

Apache Ant
Automate portlet deployment tasks

JSR286-Enabled Portal (uPortal 4)


Target deployment environment
52
uMobile Maven Portlet Archetype

Provides a tool for generating a JSR286


portlet template project with support for
mobile views.

Available in Maven Central repository

53
uMobile Maven Portlet Archetype

Use the archetype:


$ mvn archetype:generate
-DarchetypeGroupId=org.jasig.portlet.archetype
-DarchetypeArtifactId=jsr286-archetype

Build/Deploy the project


$ cd TestPortlet
$ mvn clean install
$ cd /path/to/uportal-source
$ ant deployPortletApp
-DportletApp=/path/to/TestPortlet/target/TestPortlet.war

54
uPortal Portlet Deployment
deployPortetApp Ant target
Plutofies the portlet web application file

$ ant deployPortletApp
-DportletApp=/path/to/portet/target/YourPortlet.war

Must redo every time the war file is built!

55
uPortal Portlet Deployment

Pluto plugin to automate deployment


<plugin>
<groupId>org.apache.portals.pluto</groupId>
<artifactId>maven-pluto-plugin</artifactId>
<version>${pluto.version}</version>
<executions>
<execution>
<phase>generate-resources</phase>
<goals><goal>assemble</goal></goals>
</execution>
</executions>
</plugin>

<!-- configure maven-war-plugin to use updated web.xml -->


<plugin>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<webXml>
${project.build.directory}/pluto-resources/web.xml
</webXml>
</configuration>
</plugin> 56
uPortal Portlet Deployment

Move the WAR file into the container on build


<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>integration-test</phase>
<configuration>
<tasks>
<property environment="env"/>
<property name="pluto.home"
value="${env.CATALINA_HOME}"/>
<copy file="target/${pom.name}.war"
todir="${pluto.home}/webapps"/>
</tasks>
</configuration>
<goals><goal>run</goal></goals>
</execution>
</executions>
</plugin>

Use mvn integration-test to invoke 57


Minify Code: YUI Maven Plugin

Apply compression on JS/CSS using YUI


Compressor.
<plugin>
<groupId>net.alchim31.maven</groupId>
<artifactId>yuicompressor-maven-plugin</artifactId>
<version>1.1</version>
<executions>
<execution>
<goals><goal>compress</goal></goals>
</execution>
</executions>
<configuration>
<excludes>
<exclude>**/*.min.js</exclude>
</excludes>
<linebreakpos>10000</linebreakpos>
<suffix>.min</suffix>
<jswarn>false</jswarn>
</configuration>
</plugin> 58
Debugging Portlets

Modify Tomcat's startup script:


set JPDA_ADDRESS=8000
set JPDA_TRANSPORT=dt_socket

#Near the bottom of the script


call "%EXECUTABLE%" jpda start %CMD_LINE_ARGS% %ENDORSED_DIR_PARAM%

Remote Application
debugger for the
portlet project

59
Javascript-Enabled Portlets

60
Javascript-Enabled Portlets

Contemporary, professional, compelling


user experience

Greatly reduce the number of full-page


reloads

3rd-party libraries can help you develop


top-shelf, robust UIs in less time than it
takes to hand-roll a mediocre one
61
Javascript-Enabled Portlets

Cannot assume anything about how other


portlets or the portal are using JavaScript

Cannot assume there will only be one copy of


your own content on the page

62
Javascript-Enabled Portlets
<script src=<c:url value=rs/jquery/1.3.2/jquery.min.js />

<c:set var=n><portlet-namespace/></c:set>
<div id=${n}container>
<script type=text/javascript>
var ${n} = {}
${n}.jQuery = jQuery.noConflict(true);

${n}.jQuery(function() {
//Interesting Javascript code
}

</script>

63
Javascript-Enabled Portlets
Use <c:url> to refer to resources in your
webapp

Alias JS variables with <portlet:namespace/>


(i.e. RenderResponse.getNamespace())

Namespace important HTML tags the same way

Put JS code in:


$(document).ready(function() {...});
64
Javascript-Enabled Portlets

jQuery
http://jQuery.com

jQuery UI
http://jqueryui.com

jQuery plugins
http://plugins.jquery.com

Fluid Project
http://www.fluidproject.org/products/infusion

65
AJAX callbacks using AJAX
Portlet Support

66
AJAX Portlet Support

67
AJAX Portlet Support
AjaxPortletSupport Addon Library
<dependency>
<groupId>org.jasig</groupId>
<artifactId>AjaxPortletSupport</artifactId>
<version>1.0.9</version>
</dependency>

AjaxResponseServlet route the ajax request


to AjaxResponseController

JsonView in applicationContext.xml to
represent the model object as a JSON
68
AJAX Portlet Support
Make an AJAX POST call to an ActionURL

Annotate the receiving method with


@ActionMapping in your controller

@RequestMapping(params="action=ajaxTest")
public void ajaxTest(ActionRequest request,
ActionResponse response)
throws Exception {
final Map<String, Object> model =
new HashMap<String, Object>();
model.put("testData", "foo");
ajaxPortletSupportService.redirectAjaxResponse
(model, request, response);
}
69
Prevent XSS Attacks using
OWASP AntiSamy

70
OWASP AntiSamy

Java API for filtering HTML/CSS

Define allowed tags and attributes using XML

Clean input by stripping unwanted tags


AntiSamy as = new AntiSamy();

Policy policy = Policy.getInstance(policyFile);


CleanResults cr = as.scan(description.getValue(),
policy);

String cleanedHTML = cr.getCleanHTML();

71
OWASP AntiSamy

72
Resources

73
Resources

Main JSR 286 Website


http://jcp.org/en/jsr/detail?id=286

Pluto Portal Container v2.0


http://portals.apache.org/pluto/

OWASP AntiSamy
https://www.owasp.org

AJAX Portlet Support Library


https://wiki.jasig.org/display/PLT/AJAX+in+a+JSR-168+Portlet

Spring Framework Portlet MVC


http://static.springsource.org/spring/docs/current/spring-
framework-reference/html/portlet.html

More Examples:
74
https://github.com/Jasig
Q&A

Misagh Moayyed
Software Developer
Unicon, Inc.

75

Potrebbero piacerti anche