JSR
286 Features:
One of
the major feature added to JSR 286 is communication between Portlets through
Eventing and Public Render Parameter.
Following features added to JSR286 are.
1. Events
2. Public
Render Parameter
3. Serving
Resources
4. Portlet
filters
5. Cookies,
document head section elements, and HTTP headers
6. Leveraging
the servlet life-cycle listeners
7. Portlet
URL listeners
8. Portlet-managed modes
9. Container runtime options
10. Java
5 features
a) Using
Generics
b) Introducing
a new enum class for all user profile attributes
c) GenericPortlet
also lets you use the following annotations to make dispatching life-cycle
calls to specific handler code easier:
ProcessAction.
This annotation allows you to annotate a method that should process a specific
action. To allow dispatching, the Action URL needs to include the parameter
javax.portlet.action.
ProcessEvent.
This annotation allows you to annotate methods that should process specific
events.
RenderMode.
This annotation allows you to annotate methods that should render a specific
portlet mode.
11. New
caching features
12. Taglib
additions
a) The
define objects tag is now enhanced and gives you the following additional
variables beyond the request, response, portletConfig from the V1.0:
b) portletSession. For
access to the portlet-scoped session.
c) portletSessionScope.
For access to the portlet-scoped session attribute key/values map.
d) portletPreferences.
For access to the portlet preferences.
e) portletPreferencesValues.
For access to the portlet preferences key/values map.
f) Each
of the URL generation tags has the following additional attributes:
copyCurrentRenderParameters.
For copying the current private render parameters to the URL.
escapeXml.
For turning the default XML escaping of the URL. As mentioned previously, in
JSR 168 it was not defined if a URL is XML-escaped or not. JSR 286 now has
defined the same behavior as the Java Standard Tag Library: by default all URLs
are escaped, but you can turn it off using the escapeXml attribute.
For
action URLs, there is also the additional name attribute that allows you to set
the javax.portlet.action parameter that is evaluated by the GenericPortlet for
dispatching to the ProcessAction annotated methods.
Other
additions made in the JSR 286 specification include these:
Adding a
new resourceURL tag for generating resource URLs
Adding
the new propertyTag that can be used inside portlet URL tags for attaching
properties to URLs
<portlet-app xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd"
version="2.0" 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" id="com.ibm.sender.SendEventPortlet.05f3b8ead2">
<portlet>
<portlet-name>SendEvent</portlet-name>
<display-name xml:lang="en">SendEvent</display-name>
<display-name>SendEvent</display-name>
<portlet-class>com.ibm.sender.SendEventPortlet</portlet-class>
<init-param>
<name>wps.markup</name>
<value>html</value>
</init-param>
<expiration-cache>0</expiration-cache>
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>view</portlet-mode>
</supports>
<supported-locale>en</supported-locale>
<resource-bundle>com.ibm.sender.nl.SendEventPortletResource</resource-bundle>
<portlet-info>
<title>SendEvent</title>
<short-title>SendEvent</short-title>
<keywords>SendEvent</keywords>
</portlet-info>
<supported-publishing-event>
<qname xmlns:customns="http://dtoNS">
customns:publishEvent</qname>
</supported-publishing-event>
</portlet>
<default-namespace>http://Sender/</default-namespace>
<event-definition>
<qname xmlns:customns="http://dtoNS">
customns:publishEvent</qname>
<value-type>com.ibm.sender.DataTransferObject</value-type>
</event-definition>
</portlet-app>
public void processAction(ActionRequest
request, ActionResponse response) throws
PortletException, java.io.IOException {
if(
request.getParameter(FORM_SUBMIT) != null ) {
// Set form
text in the session bean
SendEventPortletSessionBean
sessionBean = getSessionBean(request);
if( sessionBean !=
null )
sessionBean.setFormText(request.getParameter(FORM_TEXT));
}
System.out.println("Process
Action");
System.out.println("!!!!!!!!!!!Event
Triggered by portlet!!!!!!!!!");
//Initialize the fields in the class
as per your requirement
com.ibm.sender.DataTransferObject sampleObject = new
com.ibm.sender.DataTransferObject();
QName
sampleName = new QName("http://dtoNS", "publishEvent");
sampleObject.setDtoStr(request.getParameter(FORM_TEXT));
response.setEvent(sampleName,
sampleObject );
}
Public render parameters allow JSR 286 portlets to share navigational state information. They are specially useful for coordinating the multiple navigation or viewer portlets that display different information items that are all related to the same parameter name. The portal stores all portlet render parameters, including public render parameters, as an encoded part of the current portal URL. Therefore public render parameters are correctly preserved by typical browser navigation actions such as Back button and bookmarking.
In order to allow coordination of render parameters with other portlets, within the same portlet application or across portlet applications, the portlet can declare public render parameters in its deployment descriptor using the public-render-parameter element in the portlet application section. Public render parameters are available in all lifecycle methods of the portlet: processAction, processEvent, render, and serveResource. Public render parameters can be viewed and changed by other portlets or components. In the portlet section each portlet can specify the public render parameters it would like to share via the
supported-public-render-parameter element. The supportedpublic-render-parameter element must reference the identifier of a public render parameter defined in the portlet application section in a public-render-parameter element.
The portlet should use the defined public render parameter identifier in its code in order to access the public render parameter.
The portlet container
must only send those public render parameters to a portlet which the
portlet has defined
support for using supported-public-render-parameter element in the
portlet.xml.
The portlet container must only share those render
parameters of a portlet which the portlet has
declared as supported public render parameters using supported-public-render-parameter
element in the portlet.xml.
Portlet
1
<portlet-app>
<Portlet>
<supported-public-render-parameter> publicparam
</supported-public-render-parameter>
...
</Portlet>
<public-render-parameter>
<identifier>publicparam</identifier>
<qname
xmlns:customns="http://dtoNS ">customns:publicparam
</qname>
</public-render-parameter>
</portlet-app>
Portlet
2
<portlet-app>
<Portlet>
<supported-public-render-parameter> publicparam
</supported-public-render-parameter>
...
</Portlet>
<public-render-parameter>
<identifier>publicparam</identifier>
<qname
xmlns:customns="http://dtoNS ">customns:publicparam
</qname>
</public-render-parameter>
</portlet-app>
Set the parameter In processAction,
processEvent or serveResource
response.setRenderParameter
("publicparam
", “test”); // StateAwareResponse
Resource Serving
The resource serving feature provides the ability for a portlet to serve a resource.
Portlets can create two different kinds of resource links in order to serve resources:
1. Direct links to the resource in the same portlet web application. These links are constructed by the portlet and encoded with the PortletResponse.encodeURL() method.
Note that this method might not return a valid URL.
Direct links are not guaranteed to pass through the portal server and will not have
the portlet context available.
Direct links should be used for use cases where the access to the portlet context
and access through the portal is not needed, as they are more efficient than
resource serving requests via resource URLs through the portal.
2. Resource URL links pointing back to the portlet. Via these links the
serveResource method of the ResourceServingPortlet interface is called and
the portlet can serve the resource. Thus resources served via resource URLs may
be protected by the portal security and can leverage the portlet context.
Static resources should still be served with direct links in order to allow portal
applications to configure and optimize static resource serving in a consistent
manner.
Example:
Home.jsp
<script type='text/javascript'>
function <portlet:namespace/>setCurrentDateTime() {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if(xhr.readyState == 4) {
var messageText = document.getElementById("<portlet:namespace/>messageText");
messageText.innerHTML = xhr.responseText;
}
};
var url = '
<portlet:resourceURL id="dateTime"/>' + "?fakeId=" + Math.random();
xhr.open("GET", url, true);
xhr.send();
}
</script>
<table>
<tr>
<td><b>
<a href="#" onclick="<portlet:namespace/>setCurrentDateTime();" style="color: black;">Refresh</a></b></td>
</tr>
</table>
<br/>
<div id="<portlet:namespace/>messageText">
</div>
DateTimeController
@Controller(value="dateTimeController")
@RequestMapping(value = "VIEW")
public class DateTimeController {
@ResourceMapping("dateTime")
public ModelAndView getDateTime(ResourceRequest request, ResourceResponse response) throws IOException {
SimpleDateFormat sdf = new SimpleDateFormat(
"dd-MMM-yyyy hh:mm:ss a");
Map<String, Object> model = new HashMap<String, Object>();
request.setAttribute("test", "test123");
request.getPortletSession().setAttribute("test1", "test1");
model.put("dateTime", sdf.format(new Date()));
return new ModelAndView("dateTimeAjax", model);
}
}
dateTimeAjax.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html" isELIgnored="false" %>
This is from dateTimeAjax.jsp page ::::::
<c:out value="${dateTime}"/>
<br/><br/><br/>
${test}
<br/><br/><br/>
${test1}
Portlet Filter in brief
Portlet filter are one of the major feature added on JSR 286.
A portlet
filter is a Java component that can be used to modify portlet request and
response before/after any lifecycle method of the portlet is being executed.
The concept of
Portlet filter is same as that of servlet filter. The only difference is that a
servlet has only one request handling method i.e. service() method and
therefore there is only one type of the servlet filter.
A portlet has
four types of request handling methods and therefore there are 4 different
types of portlet filters.
The portlet
API defines following interfaces for creating Portlet filter:
javax.portlet.filter.ResourceFilter
(for serveResource method)
javax.portlet.filter.RenderFilter
(for render method)
javax.portlet.filter.ActionFilter
(for processAction method)
javax.portlet.filter.EventFilter
(for processEvent method)
The portlet filter
programming model is modeled on the servlet filter model:
1. Define
the filters in the deployment descriptor. This definition is done using the
<filter> element, where you also need to state the life-cycle call to
which the filter should be applied.
2. Implement
the corresponding Filter interface in your filter. You can also list multiple
life-cycle entries and implement multiple Filter interfaces with your class.
3. Provide
a filter-mapping element where you describe to which portlets your filter
should be applied (you can also use an asterisk as a wildcard if it should be
applied to all portlets in the application).
A single filter class can provide filter
functionality for more than one lifecycle methods and also a single filter can
provide filter functionality for more than one portlet. There can be multiple filter associated with one lifecycle
method of a portlet. The javax.portlet.filter.FilterChain class (created by
Portlet container) is used to invoke the sequence of filters applicable for a
particular lifecycle method of a portlet. The doFilter() method of a portlet
filter may create customized request and response objects by using \*RequestWrapper
and \*ResponseWrapper classes and passing these wrappers to the doFilter()
method of FilterChain.
In order to
write a portlet filter, the developer is required to do the folowing 2 things :
1) Write a
filter class - A filter class should implement one or more of the above
mentioned four interfaces and should provide a no argument public constructor.
The filter class is also required to override init() and destroy() method of
javax.portlet.filter.PortletFilter interface.
2) Add entry
of filter in portlet.xml - After writing a portlet filter class, it can be
configured by adding following 2 xml fragements in portlet.xml.
<filter>
<filter-name>RenderFilterOne</filter-name>
<filter-class>com.test.filter.RenderFilterOne</filter-class>
<lifecycle>RENDER_PHASE</lifecycle>
<lifecycle>ACTION_PHASE</lifecycle>
<init-param>
<name>message</name>
<value>Filter
1 - portlet-container 2.0 Filter demo :)</value>
</init-param>
</filter>
<filter-mapping>
<filter-name>RenderFilterOne</filter-name>
<portlet-name>HelloWorld</portlet-name>
</filter-mapping>
* @author Saurabh.srivastava
*
*/
public class RenderFilterOne
implements RenderFilter,
ActionFilter {
/* (non-Javadoc)
*
@see javax.portlet.filter.RenderFilter#doFilter(javax.portlet.RenderRequest,
javax.portlet.RenderResponse, javax.portlet.filter.FilterChain)
*/
public void
doFilter(RenderRequest req, RenderResponse res,
FilterChain chain) throws IOException,
PortletException {
chain.doFilter(req, res);
}
/* (non-Javadoc)
*
@see javax.portlet.filter.PortletFilter#destroy()
*/
public void destroy() {
// TODO
Auto-generated method stub
}
/* (non-Javadoc)
*
@see javax.portlet.filter.PortletFilter#init(javax.portlet.filter.FilterConfig)
*/
public void
init(FilterConfig arg0) throws PortletException {
// TODO
Auto-generated method stub
}
/* (non-Javadoc)
*
@see javax.portlet.filter.ActionFilter#doFilter(javax.portlet.ActionRequest,
javax.portlet.ActionResponse, javax.portlet.filter.FilterChain)
*/
public void
doFilter(ActionRequest req, ActionResponse res,
FilterChain chain) throws IOException,
PortletException {
chain.doFilter(req, res);
}
The first xml
fragment defines a filter by providing a logical name to it. It tell portlet
container about the filter class and the lifecycle phases supported by it. You
can specify initialization parameters also.
The Second xml
fragment specifies the portlet(s) for which this filter will be applicable. You
can specify a single portlet name or mapping to a group of portlets using the
‘\*’ as a wildcard.
Portlet URL listeners
In some cases,
you may want to centrally manage setting specific properties on portlet URLs or
to enhance the portlet URL creation of existing portlets. One example involves
implementing a mapping of resources to shared IDs. You implement this mapping
only once in the listener, and the listener checks if the resource URL is
targeting a resource for which a shared QName exists and then sets the SHARED
property with the corresponding QName. For these use cases, the JSR 286
specification gives you the portlet URL listeners.
Container runtime options
Container
runtime options allow the portlet to supply specific options to the portlet
container that either change default behavior defined in the Java Portlet
Specification or add additional behaviors. JSR 286 defines a list of container
runtime options that are all optional except for actionScopedRequestAttributes.
javax.portlet.escapeXml. Allows you to turn off the XML escaping of
portlet URLs for each default, in case you have written a JSR 168 portlet that
assumes that URLs are not XML escaped and have migrated this to a JSR 286 portlet.
·
javax.portlet.renderHeaders. Enables the two-part rendering mechanism that lets you
set headers in streaming-based portal implementations.
·
javax.portlet.servletDefaultSessionScope. Allows you to change the default scope of the session
object provided to servlets or JSPs that are called from the portlet through
forward or include from application scope to portlet scope. That way, these
resources access the same session data using portlet and servlet APIs, which is
particularly convenient if your JSPs are written for a servlet-based Web
framework.
·
javax.portlet.actionScopedRequestAttributes. Allows Web frameworks to pass complex objects from the
action or event phase to the render phase through the request. You are able to
access these attributes until the next request with an action semantic (which
may be an action triggered through an Action URL or an event) occurs. This
feature likely is implemented by the portlet container by storing these
attributes in the session. Therefore, use this feature only if you cannot avoid
it, as it will probably cause some performance degradation. This option is the
only one that JSR 286 requires to be supported by all containers.
Enable two phase rendering in portlet
To overcome the problem that version 1.0 faced with contributing content outside the current portlet window, version 2.0 added a two-part render call:
- RENDER_HEADER part that allows the portlet to return content outside the current portlet window such as portlet title, preferred next possible portlet modes, cookies, document head section elements, and HTTP headers.
- RENDER_MARKUP part that allows the portlet to return its normal markup.
Starting from JSR 286 (Portlet Specification
2.0), portlets support two phase rendering and it defines doHeaders() method
that you can implement if you want to do one of the following things
·
Change title of the portal page
·
Add header
·
Add cookie
The two phase request processing is disabled by
default, you can enable it by setting value of javax.portlet.renderHeaders
container run time option to true like this
<portlet>
…
<container-runtime-option>
<name>javax.portlet.renderHeaders</name>
<value>true</value>
</container-runtime-option>
…
</portlet>
protected void
doHeaders(RenderRequest renderRequest,
RenderResponse renderResponse){
//Setting cookie
Cookie cssKeyCookie = new Cookie(“Key”,
“Value”);
cssKeyCookie.setPath(“/”);
cssKeyCookie.setMaxAge(3600000);
renderResponse.addProperty(cssKeyCookie);
}
Resource: