Download Tema 3: Especificación de portlets Java - Anexo: JSR 286

Document related concepts
no text concepts found
Transcript
Tema 3: Especificación de portlets
Java – Anexo: JSR 286
JSR 286 (1)

JSR 286 es la versión 2.0 de la especificación de
portlets Java


La versión final de la especificación saldrá a lo largo del
2008
Principales características

Compatibilidad hacia atrás


El contenedor de portlets debe soportar Servlets 2.4


Es posible utilizar JSP 2.0 y JSTL 1.1
Mecanismos de coordinación entre portlets


Es una extensión de la versión 1.0
Eventos y parámetros públicos de renderización
Anotaciones

Para los métodos que procesan peticiones de acción,
renderización y eventos
JSR 286 (2)

Principales características (cont)

Filtros de portlets


Soporte para servir recursos




Similar a los filtros de servlets
Permite soportar interacciones AJAX
Mejora el soporte para la gestión de la caché de las
respuestas de los servlets
Sincronizada con WSRP 2.0
Más información

Especificación


http://jcp.org/en/jsr/detail?id=286
Stefan Hepper, Oliver Köth, “What’s new in the Java Portlet
Specification V2.0 (JSR 286)”

http://www.ibm.com/developerworks/websphere/library/techar
ticles/0803_hepper/0803_hepper.html
JSR 286 (y 3)

Nos centraremos especialmente en

Mecanismos de coordinación entre portlets



Especialmente en comunicación basada en eventos, y en
menor medida en parámetros públicos de renderización
Anotaciones
Ilustraremos estos conceptos con un ejemplo
Ejemplo (1)


Una sencilla “mashup” formada por tres portlets
Stock Symbol Finder


My Stock Quotes





Muestra las cotizaciones de los símbolos bursátiles añadidos por el usuario a
sus preferencias
Permite buscar la cotización de un símbolo bursátil
My Stock Headlines


Permite buscar símbolos bursátiles a partir de palabras clave del nombre de
la empresa
Muestra noticias de los símbolos bursátiles añadidos por el usuario a sus
preferencias
Permite buscar noticas de un símbolo bursátil
Muestran la misma información en estado de ventana normal y
maximized
Capa modelo simplificada y simulada en los tres portlets
Ejemplo (2)

La búsqueda de símbolos bursátiles (Stock
Quote Finder) está integrada con la
funcionalidad de los portlets My Stock Quotes
y My Stock Headlines




Para cada símbolo bursátil resultante de la búsqueda (Stock
Symbol Finder), se incluyen dos enlaces: “Buscar” y “Añadir
a preferencias”
Ambos enlaces generan un evento que es consumido por My
Stock Quotes y My Stock Headlines
En respuesta al evento del enlace “Buscar” , My Stock
Quotes y My Stock Headlines muestran información de ese
símbolo bursátil
En respuesta al evento del enlace “Añadir a preferencias” ,
My Stock Quotes y My Stock Headlines añaden el símbolo
bursátil a las preferencias
Ejemplo (3)
Click en “Buscar” (SMJ0)
Ejemplo (4)
Ejemplo (5)
Click en “Añadir a preferencias” (SMJ0)
Ejemplo (6)
Ejemplo (y 7)

Observación


La mashup ofrece una funcionalidad similar a la del portlet
Stock Quote
Adicionalmente



Proporciona búsqueda de símbolos bursátiles
Integra la búsqueda de símbolos bursátiles con la funcionalidad
de los portlets My Stock Quotes y My Stock Headlines
Los portlets son más sencillos que el portlet Stock Quote

La funcionalidad se ha descompuesto en portlets más
pequeños
Stock Symbol Finder – searchStockSymbol.jsp
...
<c:forEach var="stockSymbol" items="${stockSymbols}"
varStatus="status">
<portlet:actionURL var="searchStockSymbolURL">
<portlet:param name="javax.portlet.action"
value="SearchStockSymbol"/>
<portlet:param name="stockSymbol"
value="${stockSymbol.symbol}"/>
<portlet:param name="companyKeywords"
value="${companyKeywords}"/>
</portlet:actionURL>
<portlet:actionURL var="addStockSymbolToPreferencesURL">
<portlet:param name="javax.portlet.action"
value="AddStockSymbolToPreferences"/>
<portlet:param name="stockSymbol"
value="${stockSymbol.symbol}"/>
<portlet:param name="companyKeywords"
value="${companyKeywords}"/>
</portlet:actionURL>
...
Stock Symbol Finder – StockSymbolFinderPortlet (1)
private final static QName SEARCH_STOCK_SYMBOL_EVENT =
new QName("http://es.udc.portlets/events", "SearchStockSymbol");
private final static QName ADD_STOCK_SYMBOL_TO_PREFERENCES_EVENT =
new QName("http://es.udc.portlets/events",
"AddStockSymbolToPreferences");
// ...
@ProcessAction(name="SearchStockSymbol")
public void sendSearchStockSymbolEvent(ActionRequest request,
ActionResponse response) throws PortletException, IOException {
response.setRenderParameter("companyKeywords",
request.getParameter("companyKeywords"));
response.setEvent(SEARCH_STOCK_SYMBOL_EVENT,
request.getParameter("stockSymbol"));
}
Stock Symbol Finder – StockSymbolFinderPortlet (y 2)
@ProcessAction(name="AddStockSymbolToPreferences")
public void sendAddStockSymbolToPreferencesEvent(
ActionRequest request, ActionResponse response)
throws PortletException, IOException {
response.setRenderParameter("companyKeywords",
request.getParameter("companyKeywords"));
response.setEvent(ADD_STOCK_SYMBOL_TO_PREFERENCES_EVENT,
request.getParameter("stockSymbol"));
}
Stock Symbol Finder – portlet.xml (1)
<?xml version="1.0" encoding="UTF-8"?>
<portlet-app xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd"
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"
version="2.0">
<portlet>
<description>
A portlet allowing to search stock symbols by company name
</description>
<portlet-name>StockSymbolFinderPortlet</portlet-name>
...
Stock Symbol Finder – portlet.xml (2)
<supported-publishing-event>
<qname
xmlns:x="http://es.udc.portlets/events">x:SearchStockSymbol</qname>
</supported-publishing-event>
<supported-publishing-event>
<qname
xmlns:x="http://es.udc.portlets/events">x:AddStockSymbolToPreference
s</qname>
</supported-publishing-event>
</portlet>
Stock Symbol Finder – portlet.xml (y 3)
<event-definition>
<qname
xmlns:x="http://es.udc.portlets/events">x:SearchStockSymbol</qname>
<value-type>java.lang.String</value-type>
</event-definition>
<event-definition>
<qname
xmlns:x="http://es.udc.portlets/events">x:AddStockSymbolToPreference
s</qname>
<value-type>java.lang.String</value-type>
</event-definition>
</portlet-app>
Anotación ProcessAction

El procesamiento de las peticiones de acción se
podría haber implementado al estilo de la versión 1.0


Redefinir processAction + if’s para tomar decisión
Anotación ProcessAction



En la versión 2.0, la implementación de processAction
en GenericPortlet intenta delegar el procesamiento de
la petición de acción en un método anotado con
ProcessAction, cuyo elemento name especifique el valor
del parámetro javax.portlet.action
Evita tener que redefinir processAction como una
colección de if’s
Los métodos anotados con ProcessAction se deben
declarar como

void <methodname> (ActionRequest,
ActionResponse) throws PortletException,
java.io.IOException;
Definición de eventos


Sincronizada con WSRP
portlet.xml



Los eventos se definen (event-definition) dentro de
portlet-app
El portlet tiene que declarar los eventos que publica
(supported-publishing-event) y los que desea recibir
(supported-processing-event)
El tipo del valor del evento debe ser serializable
(java.io.Serializable) y poder mapearse a XML vía
JAXB (para eventos remotos)

Un evento puede ser una estructura de datos compleja (e.g. un
Transfer Object)
Envío de eventos


Un evento se puede enviar durante el procesamiento
de una petición de acción o una petición de evento
(se explica más adelante)
Las interfaces ActionResponse y EventResponse
extienden a la interfaz StateAwareResponse, que
incluye el método

void setEvent(QName name, Serializable
value)


El evento no se envía en este momento, sino que se
añade a la respuesta (ActionResponse o
EventResponse, dependiendo del tipo de petición)
Para especificar el nombre del evento se utiliza
javax.xml.QName


Representa un nombre cualificado
Forma parte del API de Java SE
My Stock Quotes – MyStockQuotesPortlet (1)
@ProcessEvent(qname="{http://es.udc.portlets/events}SearchStockSymbol")
public void processSearchStockSymbolEvent(EventRequest request,
EventResponse response) throws PortletException, IOException {
Event event = request.getEvent();
String stockSymbol = (String) event.getValue();
// FIXME: in Liferay Portal 5.0.1 RC, getPortletMode always
// returns PortletMode.VIEW.
if (request.getPortletMode().equals(PortletMode.VIEW)) {
response.setRenderParameter("stockSymbol", stockSymbol);
response.setRenderParameter("command", "SearchStockQuote");
}
}
My Stock Quotes – MyStockQuotesPortlet (y 2)
@ProcessEvent(
qname="{http://es.udc.portlets/events}AddStockSymbolToPreferences")
public void processAddStockSymbolToPreferencesEvent(
EventRequest request, EventResponse response)
throws PortletException, IOException {
Event event = request.getEvent();
String stockSymbol = (String) event.getValue();
// FIXME: it does not work in Liferay Portal 5.0.1 RC.
// "stockSymbol" is not added to preferences, even though
// JSR 286 (section PLT.17.1) allows to modify them when
// processing an event.
addStockSymbolToPreferences(request, stockSymbol);
}
My Stock Quotes – portlet.xml (1)
<?xml version="1.0" encoding="UTF-8"?>
<portlet-app ...>
<portlet>
<description>
A portlet allowing to monitor stock quotes
</description>
<portlet-name>MyStockQuotesPortlet</portlet-name>
...
<!-- FIXME: disabled. In Liferay Portal 5.0.1 RC, the portlet's
markup (in "view" mode) is not refreshed after sending an
event to a portlet if its markup is cached. JSR 286
(section PLT.22.1) forces the portlet container to discard
the portlet's cached markup after sending it an event.
<expiration-cache>1200</expiration-cache>
-->
My Stock Quotes – portlet.xml (2)
...
<supported-processing-event>
<qname
xmlns:x="http://es.udc.portlets/events">x:SearchStockSymbol</qname>
</supported-processing-event>
<supported-processing-event>
<qname
xmlns:x="http://es.udc.portlets/events">x:AddStockSymbolToPreference
s</qname>
</supported-processing-event>
</portlet>
My Stock Quotes – portlet.xml (y 3)
<event-definition>
<qname
xmlns:x="http://es.udc.portlets/events">x:SearchStockSymbol</qname>
<value-type>java.lang.String</value-type>
</event-definition>
<event-definition>
<qname
xmlns:x="http://es.udc.portlets/events">x:AddStockSymbolToPreference
s</qname>
<value-type>java.lang.String</value-type>
</event-definition>
</portlet-app>
Anotación ProcessEvent

El procesamiento de las peticiones de acción se
podría haber implementado redefiniendo
processEvent


Conjunto de if’s para procesar cada evento
Anotación ProcessEvent



La implementación de processEvent en
GenericPortlet intenta delegar el procesamiento del
evento en un método anotado con ProcessEvent, cuyo
elemento qname especifique el nombre del evento
Evita tener que redefinir processEvent como una
colección de if’s
Los métodos anotados con ProcessEvent se deben
declarar como

void <methodname> (EventRequest, EventResponse)
throws PortletException, java.io.IOException;
Procesamiento de una petición de acción que devuelve un evento (1)

Si una petición de acción devuelve un evento, el
contenedor

Invoca processEvent sobre todos los portlets
consumidores de dicho evento


Idem si processEvent también devuelve un evento
Invoca render sobre todos los portlets cuyo contenido no
esté cacheado o sean receptores del evento
Procesamiento de una petición de acción que devuelve un evento (y 2)
Portal
Contenedor
Portlet 1
1: Interacción
(acción) sobre
el portlet 1
1.1: processAction
El usuario está
actuando sobre
una página que
contiene los
portlets 1, 2, ...
N
[consumidor del evento]
1.2: processEvent
...
[consumidor del evento]
1.N+1: processEvent
[consumidor del evento ||
respuesta no en caché]
1.N+2: render
...
[consumidor del evento ||
respuesta no en caché]
1.2N+1: render
...
Portlet N
Parámetros públicos de renderización (1)


Los parámetros públicos de renderización son otro mecanismo de
coordinación entre portlets
Un portlet puede declarar en portlet.xml los parámetros de
renderización que desea compartir con otros portlets





Esos parámetros se denominan parámetros públicos de renderización
Al igual que los eventos, disponen de un nombre cualificado
Se recuperan (request.getParameter) y establecen
(response.setParameter) como cualquier otro parámetro
de renderización
Cuando un portlet le da valor a un parámetro de renderización que es
público, el contenedor incluirá dicho parámetro en las invocaciones a
render de los portlets que han declarado que desean compartirlo
Son una opción eficiente y cómoda (no hay necesidad de hacer
programación adicional) cuando varios portlets comparten un mismo
conjunto de parámetros de renderización (parámetros públicos de
renderización)
Parámetros públicos de renderización (2)

Ejemplo




Portlet Weather: muestra el tiempo a partir de un código
postal (parámetro zipCode)
Portlet Map: muestra una ubicación geográfica en un mapa
a partir de un código postal (parámetro zipCode)
Portlet Tourist Information: muestra información turística a
partir de un código postal (parámetro zipCode)
Si los tres portlets declaran el parámetro zipCode como
parámetro público de renderización, cuando el usuario
introduzca el código postal en cualquiera de los tres portlets,
los otros dos actualizarán su salida de acuerdo a ese código
postal (porque el contenedor les pasa automáticamente ese
parámetro)
Parámetros públicos de renderización (3)

Ejemplo: portlet.xml en el portlet Weather
<?xml version="1.0" encoding="UTF-8"?>
<portlet-app ...>
<portlet>
<portlet-name>WeatherPortlet</portlet-name>
...
<supported-public-render-parameter>
zipCode
</supported-public-render-parameter>
</portlet>
<public-render-parameter>
<identifier>zipCode</identifier>
<qname xmlns:x="http://example.com/params">x:zipCode</qname>
</public-render-parameter>
</portlet.app>
Parámetros públicos de renderización (y 4)

El mecanismos de eventos

Es un mecanismo general de comunicación



En respuesta a un evento, el portlet puede modificar estado
(e.g. cambiar preferencias, actualizar una base de datos,
realizar una operación no idempotente, etc.), establecer
parámetros de renderización o enviar un nuevo evento
El dato del evento puede ser un tipo complejo
El mecanismo de parámetros públicos de
renderización

Es un mecanismo cómodo y eficiente para el caso
particular de portlets que comparten un conjunto de
parámetros de renderización
Otros aspectos del ejemplo (1)

Anotación RenderMode



La implementación de doDispatch (que es llamado por
render) en GenericPortlet primero intenta delegar la
petición en un método anotado con RenderMode, cuyo
elemento name especifique el modo a tratar (view, edit o
help
Si no lo encuentra, delega en doView, doEdit o doHelp
en función del modo
La anotación no aporta mucho sobre la alternativa de los
métodos doXXX
 El código de los ejemplos utiliza la anotación RenderMode
por consistencia con el uso del resto de anotaciones

Los métodos anotados con RenderMode se deben declarar
como

void <methodname> (RenderRequest,
RenderResponse) throws PortletException,
java.io.IOException;
Otros aspectos del ejemplo (2)

Anotación RenderMode (cont)

Ejemplos
@RenderMode(name="view")
public void processViewMode (RenderRequest request,
RenderResponse response throws PortletException, IOException {
// ...
}
@RenderMode(name="edit")
public void processViewMode (RenderRequest request,
RenderResponse response throws PortletException, IOException {
// ...
}
@RenderMode(name="help")
public void processViewMode (RenderRequest request,
RenderResponse response throws PortletException, IOException {
// ...
}
Otros aspectos del ejemplo (3)

JSP 2.0

Se usan expresiones JSP en las páginas JSP en cualquier
situación y no sólo con los tags de JSTL


Se usan páginas JSP (notación clásica) y no documentos JSP


Código JSP más sencillo
El markup que se devuelve es HTML y no XHTML, por lo que
resulta más cómodo usar la notación clásica
Librerías de tags


JSTL 1.1 y librería de tags del API de portlets (versión 2.0)
commonHeader.jsp (en cualquiera de los tres portlets)
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="portlet" uri="http://java.sun.com/portlet_2_0" %>
Otros aspectos del ejemplo (y 4)

Problemas con Liferay Portal 5.0.1 RC


FIXMEs de las transparencias anteriores
Además, cuando se interactúa con un portlet, no se
conservan los parámetros de renderización del resto de
portlets (lo que contraviene a la especificación)

El problema se observa rápidamente en los portlets My Stock
Quotes y My Stock Headlines, que tienen deshabilitada la caché
(como especifica uno de los FIXMEs anteriores)