• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Introduction to Portlets using Liferay Portal (Part 2)
 

Introduction to Portlets using Liferay Portal (Part 2)

on

  • 16,189 views

Presentation about Portlets and Liferay Portal held at Costa Rica Java Users Group

Presentation about Portlets and Liferay Portal held at Costa Rica Java Users Group

Statistics

Views

Total Views
16,189
Views on SlideShare
16,178
Embed Views
11

Actions

Likes
3
Downloads
305
Comments
0

3 Embeds 11

http://bibek.in 8
http://www.docseek.net 2
http://feeds.feedburner.com 1

Accessibility

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Introduction to Portlets using Liferay Portal (Part 2) Introduction to Portlets using Liferay Portal (Part 2) Presentation Transcript

    • ARTISANS OF OPEN SOURCE Introduction to Portlets using Liferay Portal (Part 2) By: Aníbal Gómez-Estrada http://rivetlogic.com/web/agomez October 19th, 2011Rivet Logic Corporation Rivet Logic Costa Rica SRL11410 Isaac Newton Square N. Costa Rica Developers ForgeSuite 210 Edificio María Luisa, 3A officeReston, VA 20190, USA Paseo Colón, San José, Costa RicaPh: 703.955.3480 Fax: 703.234.7711 Ph: (506) 2256-1024 Fax: (506) 2256-1024
    • Rivet Logic Overview ARTISANS OF OPEN SOURCE•  Award-winning consulting and systems integration firmfocused on enabling open source –based software solutionsfor content management, collaboration and community: –  Innovator of the Year: JBoss (2008) –  Solution of the Year: Alfresco (2010) –  Platinum Partner: Liferay (2011)•  We use top-notch open source technology:•  Company Facts: –  Founded in 2005. Consistently Profitable and Employee-owned. 40+ Consultants –  Headquarters in Virginia, USA. Near-shore office in San José, Costa Rica for two years –  Certified Liferay Partner since 2006: •  Conduct all public training on East Coast, USA •  Contributor (software, documentation, forums, training material) •  20+ Liferay projects underway or completed!
    • Agenda ARTISANS OF OPEN SOURCE•  Introduction –  Portals and Portlets –  Liferay SDK Plugin Types –  Liferay Service Builder –  Portlets 1.0 (JSR 168)•  Portlets 2.0 (JSR 286) –  Resource Serving –  Inter-Portlet Communication –  Lifecycle Revisited –  Portlet Filters and PortletURL Listeners –  Enhancements: •  Servlet Programming Features •  Annotations •  Tag Libraries•  Conclusion –  Questions and Answers –  References•  Announcements –  JSF 2.0 Portlets using Liferay Portal is Available Now! –  Rivet Logic Is Hiring!
    • ARTISANS OF OPEN SOURCEIntroduction
    • Portals and Portlets ARTISANS OF OPEN SOURCE In a Nutshell Portal Architecture:A Portal is designed to Liferay Portal is abe a single web-based Portlet Containerenvironment where all and Portal Server users applications Platform and run integrated environment to run/ together in a administer web sites systematic way” and to integrate portlets
    • Liferay SDK Plugin Types ARTISANS OF OPEN SOURCE Themes•  Themes customize the overall structure and look and feel of the Portal pages and are based on HTML, CSS and Velocity/FreeMarker•  Theme Plugins are based on a pre-made theme which gives the site minimal structure (either unstyled or styled) •  Customizations are overlaid against the “base theme” with a overwriting mechanism and differentiation scheme •  Provide control over everything: HTML, CSS and images inside portlets (box) and outside (page) and positioning/behavior of the top navigation elements•  Deployed Themes can be used at level different levels: the overall site, a community/organization or a single page More Info: http://www.liferay.com/community/wiki/-/wiki/Main/Themes
    • Liferay SDK Plugin Types (2) ARTISANS OF OPEN SOURCE Layout Templates•  Layout Templates control how portlets are arranged on a Portal page and are created with a combination of HTML, CSS and Velocity•  They make up the body of the page, the large area where portlets can be dragged and dropped into•  Allow portlets to be embedded into templates•  Deployed Layout Templates are used at page level•  For Instance: More Info: http://www.liferay.com/web/guest/community/wiki/-/wiki/Main/Layout+Template
    • Liferay SDK Plugin Types (3) ARTISANS OF OPEN SOURCE Hooks•  Hooks allow to hook custom code at different extension points in order to either change, override or extend: •  Display: JSPs and Language Properties •  Behavior: Portal Server Lifecycle Events, Services, Model Listeners and Portal Properties•  Hook Plugins are Java code –based and they are hot- deployable, as well as, Themes, Layout Templates and Portlet Plugins do! More Info: http://www.liferay.com/community/wiki/-/wiki/Main/Portal+Hook+Plugins
    • Liferay SDK Plugin Types (4) ARTISANS OF OPEN SOURCE Portlets •  Portlets are componentized user-facing applications that generate a fragment of the Portal page In this presentation, you will learn more about what Portlet Plugins are!  •  For now, let’s take a look at some of the portlets available for Liferay Portal..More Info: http://www.liferay.com/community/wiki/-/wiki/Main/Out+of+The+Box+Portlets
    • Liferay SDK Plugin Types (5) ARTISANS OF OPEN SOURCE Ext•  Ext allow to extend/override built-in code in special scenarios that can not be met by another plugin types: •  Easily extensible: Liferay Portal is implemented on top of Spring, Hibernate and Struts/Tiles, so custom code can be plugged in very easily •  Complete control: It allows access to internal APIs or even overwriting files/classes provided in the Liferay core •  To be carefully used: it is a powerful tool that comes with a cost in terms of complexity and maintenance!•  Ext Plugins are NOT hot-deployable! –  Require server restart –  Can not be un-deployed More Info: https://www.liferay.com/community/wiki/-/wiki/Main/Ext+Plugin
    • Liferay Service Builder ARTISANS OF OPEN SOURCE•  Service Builder is a tool built by Liferay to automate the creation of Services, Models and Persistence –related interfaces and classes relying on Liferay API, Spring and Hibernate: •  Input: an XML file specifying the structure of Model classes and data-storage –related operations •  Ouput: a service JAR that can be exposed either at a global or local (ie. Portlet plugin) levels and a set of implementation classes with beans and basic logic generated for the Model and Service/Persistence classes •  When specified, Service Builder also generates Javascript stubs for remote access (ie. client side / browser)! More Info: http://www.liferay.com/community/wiki/-/wiki/Main/Service+Builder
    • Portlet 1.0 (JSR 168) ARTISANS OF OPEN SOURCE•  JSR 168 in a Nutshell: –  Portlet Container Contract and Portlet Lifecycle –  Packaging and Deployment –  Portlet Modes and Window States –  Portlet Preferences Management –  JSP Support –  User Information and Security –  Localization and Caching•  JSR 168 defined the overall UI component model and provided a few support for building integrated/coordinated composite applications. However, “portlets are islands” in JSR 168: –  Can not generate non-markup content –  Can not communicate with other portlets –  Can not influence the portal page
    • ARTISANS OF OPEN SOURCEPortlet 2.0 (JSR 286)
    • Portlet 2.0 (JSR 286) ARTISANS OF OPEN SOURCE•  JSR 286 addresses limitations identified by many portal vendors that caused custom solutions and not portable to be placed in their products –  Released in June, 2008 –  Expert Group: IBM, ASF, Oracle, BEA, Liferay, among others•  Features introduced in JSR 286’s Portlet API also fill some gaps with related technologies, such as J2EE 1.4, WSRP, Servlets, JSF, among others•  JSR 286 mainly addresses following topics: –  Resource Serving * –  Inter-Portlet Communication: Event-Notification and Public Render Parameters * –  Portlet Filters and PortletURL Listeners * –  Servlet Programming Model Features * –  Enhancement on Annotations, JSP support, Portlet Modes, Caching *
    • Resource Serving ARTISANS OF OPEN SOURCE•  In JSR 168, dynamically generated resources could not be directly served from a portlet instance. An additional servlet was needed to serve the resources: –  Disadvantages: Out of Portal’s Scope (No Access to render parameters, portlet mode, window state, portlet preferences, portlet session, etc). Not under Portal access control (Servlet to be secured separately) –  Advantages: less overhead because the request does not have to pass through the additional portal framework. Adequate when serving large media streams…•  JSR 286 introduces Resource Serving as a lifecycle operation that is dispatched directly from corresponding portlet instance: –  Normally occurs after a render call and can be used to implement AJAX use cases –  Does not generate a full new portal page. Returned content not aggregated with another markup. The resource response allows full control over output stream –  Cannot set new render parameters, portlet mode, or window state since the portal does not have a chance to update other parts of the page•  During a Resource Request, a portlet implementing ResourceServingPortlet interface can create dynamic resources through serveResource() method•  Portlet API provide Resource URLs for Resource Serving requests. They are created with RenderResponse.createResourceURL() and trigger lifecycle serveResource() method. ResourceURLs can be set with params as other URLs
    • Resource Serving (2) ARTISANS OF OPEN SOURCE•  Let’s create a new JSP-based Portlet which returns a greeting on Ajax call: File: /WEB-INF/src/com/sample/jsp/portlets/JSPPortlet.java package com.sample.jsp.portlets; import java.io.IOException; import java.io.OutputStream; import javax.portlet.*; public class JSPPortlet extends javax.portlet.GenericPortlet { @Override protected void doView(RenderRequest request, RenderResponse response) throws PortletException, IOException { PortletRequestDispatcher rd = getPortletContext().getRequestDispatcher("/html/view.jsp"); rd.include(request,response); } @Override public void serveResource(ResourceRequest request, ResourceResponse response) throws PortletException, IOException { OutputStream stream = response.getPortletOutputStream(); response.setContentType("text/html"); stream.write( String.format( "%1$s (Ajax - %2$s)!!”, request.getParameter("ajax-parameter-greeting"), Math.random() ).getBytes() ); } }
    • Resource Serving (3) ARTISANS OF OPEN SOURCE•  Now, let’s create the JSP page invoking the portlet via Ajax: File: /html/view.jsp <%@ page session="false" contentType="text/html; charset=ISO-8859-1" %> <%@ page import="javax.portlet.*"%> <%@ taglib uri=/WEB-INF/tld/liferay-portlet.tld prefix=portlet%> <portlet:defineObjects/> <portlet:resourceURL var="resourceUrl"> <portlet:param name="ajax-parameter-greeting" value="Hello World from Resource Serving Param" /> </portlet:resourceURL> <p> <input type="button" value=Ajax! title=<%=resourceUrl%>’ onclick="javascript:ajaxHelloWorld(<%=resourceUrl%>);” /> </p> <div id="msg_display">The data from the server will go here</div> <script type="text/javascript"> /* PLEASE LOOK AT NEXT SLIDE */ </script>
    • Resource Serving (4) ARTISANS OF OPEN SOURCE•  Now, let’s create the JSP page invoking the portlet via Ajax (2): File: /html/view.jsp ... <script type="text/javascript"> function ajaxHelloWorld(url){ var request = createXMLHttpRequest(); var callback = function() { var msg_display = document.getElementById("msg_display"); if (request.readyState == 4) { if (request.status == 200) { msg_display.innerHTML = request.responseText; } else { msg_display.innerHTML = "ERROR: "+ request.statusText; } } }; request.onreadystatechange = callback; request.open("GET", url, true); request.send(); } function createXMLHttpRequest() { var request; if (window.XMLHttpRequest) { request = new XMLHttpRequest(); } else if (window.ActiveXObject) { try { request = new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { try { request = new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) {} } } return request; } </script>
    • Resource Serving (5) ARTISANS OF OPEN SOURCE•  Finally, let’s add the portlet in corresponding deployment descriptors File: /WEB-INF/portlet.xml <portlet-app ...> ... <portlet> <portlet-name>jsp-hello-world-portlet</portlet-name> <display-name>JSP 2.0 Hello World Portlet</display-name> <portlet-class>com.sample.jsp.portlets.JSPPortlet</portlet-class> <supports> <mime-type>text/html</mime-type> </supports> <portlet-info> <title>JSP 2.0 Hello World Portlet</title> <short-title>JSP 2.0 Hello World Portlet</short-title> <keywords>JSP 2.0 Hello World Portlet</keywords> </portlet-info> </portlet> ... </portlet-app> File: /WEB-INF/liferay-portlet.xml <liferay-portlet-app> <portlet> <portlet-name>jsp-hello-world-portlet</portlet-name> <icon>/icon.png</icon> <instanceable>true</instanceable> </portlet> </liferay-portlet-app> File: /WEB-INF/liferay-display.xml <display> <category name="category.sample"> <portlet id=”jsp-hello-world-portlet" /> </category> </display>
    • Resource Serving (6) ARTISANS OF OPEN SOURCE•  After re-deploying our Portlet plugin and clicking portlet’s button:
    • Resource Serving (7) ARTISANS OF OPEN SOURCE•  An additional resource ID can be set on the resource URL that clearly identifies the resource through ResourceURL.setResourceID() method, such as: –  resourceUrl.setResourceID("WEB-INF/jsp/xmlcontent.jspx"); –  When extending GenericPortlet, a serveResource call is automatically dispatched to the JSP, which can then make use of the portlet state information by including the portlet tag library•  Serving static resources using the portlets serveResource() method causes unnecessary performance overhead: –  Static resources like image files packaged in the portlet WAR should normally be referenced with static resource URLs, such as: String url = response.encodeURL(request.getContextPath()+"/icons/myimage.gif"); •  In contrast to RenderURLs, all HTTP methods (GET, POST or DELETE) can be leveraged with ResourceURLs (not only GET) which means: –  Methods to change state can be used in the serveResource() call. But, changes should be limited to private state of portlet: Portlet-scoped session and Portlet Preferences –  State that affects other portlets should not be modified because the portal framework has no chance to update another portions of the page on serveResource()
    • IPC: Event Notifications ARTISANS OF OPEN SOURCE•  In JSR 168, the only way to achieve communication between portlets was through portlet session. Only possible with portlets in same web-app…•  JSR 286 provides a loosely coupled publish/subscribe model that allows portlets in different web applications to send and receive events•  An event is a lifecycle operation that occurs before the rendering phase and allow portlets to respond on actions or state changes•  Descriptor portlet.xml must declare events and define what portlets are allowed to produce and consume them: –  Event name is represented as QName (Namespace + Localpart) to identify it uniquely –  Event payload (argument) is represented by a java.io.Serializable class•  During action and event lifecycle operations, a portlet can publish events through inherited StateAwareResponse’s setEvent() method•  During event lifecycle operation, a portlet implementing EventPortlet interface can handle events through processEvent() method
    • IPC: Event Notifications (2) ARTISANS OF OPEN SOURCE•  Lets create a new "Hello World" portlet which issues an event once its action button is clicked: File: /WEB-INF/src/com/sample/generic/portlets/HelloWorldPortlet.java package com.sample.generic.portlets; import java.io.IOException; import java.io.PrintWriter; import javax.portlet.*; import javax.xml.namespace.QName; public class HelloWorldPortlet extends javax.portlet.GenericPortlet { @Override protected void doView(RenderRequest request, RenderResponse response) throws PortletException, IOException { PrintWriter writer = response.getWriter(); writer.write( String.format( "<form action=%1$s method=POST>" + "<input type=submit value=Change! />"+ "</form>", response.createActionURL().toString() ) ); } @Override public void processAction(ActionRequest request, ActionResponse response) throws PortletException, IOException { response.setEvent( new QName("http://sample.com/events", "ipc.speak.world"), "The Event PayLoad!!" ); } }
    • IPC: Event Notifications (3) ARTISANS OF OPEN SOURCE•  Lets create a new "Hello World" portlet which issues an event once its action button is clicked: File: /WEB-INF/src/com/sample/generic/portlets/GoodbyeWorldPortlet.java package com.sample.generic.portlets; import java.io.IOException; import java.io.PrintWriter; import javax.portlet.*; public class GoodbyeWorldPortlet implements javax.portlet.Portlet, javax.portlet.EventPortlet { public void init(PortletConfig config) throws PortletException {} public void destroy() {} public void render(RenderRequest request, RenderResponse response) throws PortletException, IOException { PrintWriter writer = response.getWriter(); String renderParameter = request.getParameter("render-param-greeting"); writer.write( String.format( "<p>%1$s</p>”, (renderParameter != null) ? renderParameter : "Waiting for Greeting...” ) ); } public void processAction(ActionRequest request, ActionResponse response) throws PortletException, IOException {} public void processEvent(EventRequest request, EventResponse response) throws PortletException, IOException { Event event = request.getEvent(); if ("{http://sample.com/events}ipc.speak.world".equals(event.getQName().toString()) && "The Event PayLoad!!".equals(event.getValue())) { response.setRenderParameter("render-param-greeting", "Goodbye World!!"); } } }
    • IPC: Event Notifications (4) ARTISANS OF OPEN SOURCE•  Let’s now declare the event and add the portlets in the standard deployment descriptor: File: /WEB-INF/portlet.xml <portlet-app ...> ... <portlet> <portlet-name>generic-hello-world-portlet</portlet-name> <display-name>Generic 2.0 Hello World Portlet</display-name> <portlet-class>com.sample.generic.portlets.HelloWorldPortlet</portlet-class> <supports> <mime-type>text/html</mime-type> </supports> <portlet-info> <title>Generic 2.0 Hello World Portlet</title> <short-title>Generic 2.0 Hello World Portlet</short-title> <keywords>Generic 2.0 Hello World Portlet</keywords> </portlet-info> <supported-publishing-event> <qname xmlns:x="http://sample.com/events">x:ipc.speak.world</qname> </supported-publishing-event> </portlet> ... <event-definition> <qname xmlns:x="http://sample.com/events">x:ipc.speak.world</qname> <value-type>java.lang.String</value-type> </event-definition> </portlet-app>
    • IPC: Event Notifications (5) ARTISANS OF OPEN SOURCE•  Let’s now declare the event and add the portlets in the standard deployment descriptor (2): File: /WEB-INF/portlet.xml <portlet-app ...> ... <portlet> <portlet-name>generic-goodbye-world-portlet</portlet-name> <display-name>Generic 2.0 Goodbye World Portlet</display-name> <portlet-class>com.sample.generic.portlets.GoodbyeWorldPortlet</portlet-class> <supports> <mime-type>text/html</mime-type> </supports> <portlet-info> <title>Generic 2.0 Goodbye World Portlet</title> <short-title>Generic 2.0 Goodbye World Portlet</short-title> <keywords>Generic 2.0 Goodbye World Portlet</keywords> </portlet-info> <supported-processing-event> <qname xmlns:x="http://sample.com/events">x:ipc.speak.world</qname> </supported-processing-event> </portlet> ... </portlet-app>
    • IPC: Event Notifications (6) ARTISANS OF OPEN SOURCE•  Finally, let’s add liferay -specific configuration for our new Portlets: File: /WEB-INF/liferay-portlet.xml <liferay-portlet-app> ... <portlet> <portlet-name>generic-hello-world-portlet</portlet-name> <icon>/icon.png</icon> <instanceable>true</instanceable> </portlet> <portlet> <portlet-name>generic-goodbye-world-portlet</portlet-name> <icon>/icon.png</icon> <instanceable>true</instanceable> </portlet> ... </liferay-portlet-app> File: /WEB-INF/liferay-display.xml <display> <category name="category.sample"> ... <portlet id="generic-hello-world-portlet" /> <portlet id="generic-goodbye-world-portlet" /> ... </category> </display>
    • IPC: Event Notifications (7) ARTISANS OF OPEN SOURCE•  After re-deploying our Portlet plugin, adding both portlets to the same page and click on “Hello World” portlet’s button…
    • IPC: Event Notifications (8) ARTISANS OF OPEN SOURCE•  JSR 286 defines some additional features for event definition and declaration available from portlet.xml: –  Default namespace: a namespace defined through <default- namespace> element can be applied to all events defined only with a local name (<name> element) –  Aliases: an alternative name defined through <alias> element can be used to coordinate communication between portlets that need to use different names for same event –  Wildcards: <supported-processing-event> and <supported- publishing-event> elements can use trailing-dot -based wildcards to match events names which local part is defined in hierarchical manner using the dot (.) as a separator. For example: •  “x:foo.event.” can match “x:foo.event.one” and “x:foo.event.two”, but not “x:foo.bar.event” •  “x:foo..” can match “x:foo.event.one” and “x:foo.event.two” and “x:foo.bar.event”
    • IPC: Event Notifications (9) ARTISANS OF OPEN SOURCE•  JSR 286 defines some additional features for event definition and declaration available from portlet.xml: File: /WEB-INF/portlet.xml <portlet-app ...> ... <portlet> <portlet-name>generic-hello-world-portlet</portlet-name> ... <supported-processing-event> <qname xmlns:x="http://sample.com/events">x:ipc..</qname> </supported-processing-event> </portlet> ... <portlet> <portlet-name>generic-goodbye-world-portlet</portlet-name> ... <supported-processing-event> <name>ipc.speak.world</name> </supported-processing-event> </portlet> ... <default-namespace>http://sample.com/events</default-namespace> ... <event-definition> <name>ipc.hello.world</name> <alias xmlns:x="http://sample.com/events">x:ipc.speak.world</alias> <value-type>java.lang.String</value-type> </event-definition> ... </portlet-app>
    • IPC: Public Render Parameters ARTISANS OF OPEN SOURCE•  In JSR 168, render parameters set in processAction() method are only available in the render phase of the same portlet•  JSR 286 allows render parameters to be shared across portlets of same web page. They enable coordination between portlets (parameter passing) and avoid the additional process event call•  Public render parameters are available in all lifecycle methods and can be viewed or changed by other portlets or components•  Descriptor portlet.xml must declare public render parameters and specify which ones are to be shared for each portlet: –  Name is represented as QName (Namespace + Localpart) to identify it uniquely –  Identifier defines how it can be referenced from different portlets configuration•  Similarly to Events, features for public render parameters available from portlet.xml: –  Default namespace: a namespace defined through element <default-namespace> can be applied to all public render parameters defined only with a local name (<name>) –  Aliases: an alternative name defined through element <alias> can be used to coordinate portlets that need to use different names for same public render parameter
    • IPC: Public Render Parameters (2) ARTISANS OF OPEN SOURCE•  Let’s replace mechanism for Inter-Portlet communication through Public Render Parameters: File: /WEB-INF/src/com/sample/generic/portlets/HelloWorldPortlet.java package com.sample.generic.portlets; import java.io.IOException; import java.io.PrintWriter; import javax.portlet.*; import javax.xml.namespace.QName; public class HelloWorldPortlet extends javax.portlet.GenericPortlet { ... @Override public void processAction(ActionRequest request, ActionResponse response) throws PortletException, IOException { response.setRenderParameter ( "render-param-greeting", "Goodbye World from Public Render Parameter!!" ); //response.setEvent //( // new QName("http://sample.com/events", "ipc.speak.world"), "The Event PayLoad!!" //); } }
    • IPC: Public Render Parameters (3) ARTISANS OF OPEN SOURCE•  Let’s now declare the public render parameter in the standard deployment descriptor: File: /WEB-INF/portlet.xml <portlet-app ...> ... <portlet> <portlet-name>generic-hello-world-portlet</portlet-name> ... <supported-public-render-parameter> render-param-greeting </supported-public-render-parameter> </portlet> ... <portlet> <portlet-name>generic-goodbye-world-portlet</portlet-name> ... <supported-public-render-parameter> render-param-greeting </supported-public-render-parameter> </portlet> ... <default-namespace>http://sample.com/events</default-namespace> ... <public-render-parameter> <identifier>render-param-greeting</identifier> <name>ipc.render.world</name> </public-render-parameter> ... </portlet-app>
    • IPC: Public Render Parameters (4) ARTISANS OF OPEN SOURCE•  After re-deploying our Portlet plugin and clicking on “Hello World” portlet’s button…
    • Contract and Lifecycle Revisited ARTISANS OF OPEN SOURCE•  Request handling sequence after lifecycle methods introduced by JSR 286:
    • Let’s Take a Break! ARTISANS OF OPEN SOURCE Introduction to Portlets using Liferay Portal (Part 2) By: Aníbal Gómez-Estrada http://rivetlogic.com/web/agomez October 19th, 2011Rivet Logic Corporation Rivet Logic Costa Rica SRL11410 Isaac Newton Square N. Costa Rica Developers ForgeSuite 210 Edificio María Luisa, 3A officeReston, VA 20190, USA Paseo Colón, San José, Costa RicaPh: 703.955.3480 Fax: 703.234.7711 Ph: (506) 2256-1024 Fax: (506) 2256-1024
    • Portlet Filters ARTISANS OF OPEN SOURCE•  JSR-268 introduces Portlet Filters as a means to intercept any lifecycle call to a portlet and manage custom behavior in centralized way•  Portlet Filters are reusable pieces of code that can transform content in both request and response of the portlet•  Functionality implementable through Portlet Filters: –  Pass additional data into the portlet (as attributes or parameters) –  Output filtering for security enforcement or markup compliance –  Collecting diagnostic information –  Bridging between Web application frameworks•  Portlet Filter model is based on the Servlet Filter model...
    • Portlet Filters (2) ARTISANS OF OPEN SOURCE•  Depending on type of lifecycle call to be filtered, a Portlet Filters must implement one of the following interfaces: –  javax.portlet.filter.RenderFilter –  javax.portlet.filter.ActionFilter –  javax.portlet.filter.EventFilter –  javax.portlet.filter.ResourceFilter•  Portlet Filters have the following lifecycle: –  Initialization: init() called when filter is instantiated. FilterConfig holding init parameters and PortletContext is provided for resource initialization –  Deinitialization: destroy() called when filter is being taken out of service. To contain logic that cleans it up (ie, memory, file handles, threads, etc) –  Filtering: doFilter () called each time an action request/response pair is passed through the chain due to a client request
    • Portlet Filters (3) ARTISANS OF OPEN SOURCE•  At runtime, a filter chain of all filters is applied: –  Each filter gets the current request/response and the filter chain –  After doing its pre/post processing, the filter can either: •  Terminate the request processing, or •  Call the next element in the chain by passing in either the received request and response, or wrapped versions –  The last element in the filter chain is the portlet itself!•  Descriptor portlet.xml must define: –  Filters with a name, intended lifecycle phase (ACTION_PHASE, EVENT_PHASE, RENDER_PHASE or RESOURCE_PHASE), PortletFilter class and init parameters –  Filter mappings by associating filters to portlets. Order of filter- mapping defines the order in which they are applied at runtime
    • Portlet Filters (4) ARTISANS OF OPEN SOURCE•  Let’s create a PortletFilter to agregate content at beginning/end on render response: File: /WEB-INF/src/com/sample/generic/filters/RenderFilter.java package com.sample.generic.filters; import java.io.IOException; import java.io.PrintWriter; import javax.portlet.*; import javax.portlet.filter.*; public class RenderFilter implements javax.portlet.filter.RenderFilter { private String prologueMessage, epilogueMessage; public void init(FilterConfig config) throws PortletException { prologueMessage = config.getInitParameter("filter-init-parameter-prologue"); epilogueMessage = config.getInitParameter("filter-init-parameter-epilogue"); } public void destroy() { } public void doFilter(RenderRequest request,RenderResponse response, FilterChain chain) throws IOException, PortletException { PrintWriter writer = response.getWriter(); writer.write(String.format("<p>%1$s</p>", prologueMessage)); chain.doFilter(request, response); writer.write(String.format("<p>%1$s</p>", epilogueMessage)); } }
    • Portlet Filters (5) ARTISANS OF OPEN SOURCE•  Now, let’s define/enable our PorletFilter on each existing portlet: File: /WEB-INF/portlet.xml <portlet-app ...> ... <portlet>...</portlet> ... <filter> <filter-name>render-filter</filter-name> <filter-class>com.sample.generic.filters.RenderFilter</filter-class> <lifecycle>RENDER_PHASE</lifecycle> <init-param> <name>filter-init-parameter-prologue</name> <value>Good Morning,</value> </init-param> <init-param> <name>filter-init-parameter-epilogue</name> <value>Have a Good Day!</value> </init-param> </filter> <filter-mapping> <filter-name>render-filter</filter-name> <portlet-name>generic-hello-world-portlet</portlet-name> <portlet-name>generic-goodbye-world-portlet</portlet-name> <portlet-name>jsp-hello-world-portlet</portlet-name> </filter-mapping> ... <default-namespace>...</default-namespace> ... </portlet-app>
    • Portlet Filters (6) ARTISANS OF OPEN SOURCE•  After re-deploying our Portlet plugin:
    • Portlet URL Listeners ARTISANS OF OPEN SOURCE•  JSR-268 introduces Portlet URL Listeners as a means to intercept URLs in centralized way, before they get generated (ie. when methods toString() or write() are called on URLs)•  Functionality implementable through Portlet URL Listeners is around managing specific Portlet –related properties on URLs: –  Parameters, portlet mode, window state –  Security, Cache level of resources, etc•  In order to receive a callback whenever a Portlet URL is generated, Portlet URL Listeners must implement interface javax.portlet.PortletURLGenerationListener with methods: –  filterRenderURL() for RenderURLs –  filterActionURL() for ActionURLs –  filterResourceURL() for ResourceURLs
    • Portlet URL Listeners (2) ARTISANS OF OPEN SOURCE•  Descriptor portlet.xml must register Portlet URL Listeners with a <listener> element for each PortletURLGenerationListener class•  Order of <listener> elements defines the order they are applied at runtime•  Let’s create a Portlet URL Listener to override parameter value for Ajax call on previously created Portlet: File: /WEB-INF/src/com/sample/generic/listeners/ResourceURLListener.java package com.sample.generic.listeners; import javax.portlet.*; public class ResourceURLListener implements PortletURLGenerationListener { public void filterActionURL(PortletURL actionURL) { } public void filterRenderURL(PortletURL renderURL) { } public void filterResourceURL(ResourceURL resourceURL) { resourceURL.setParameter ( "ajax-parameter-greeting", "Hello World from Resource URL Listener" ); } }
    • Portlet URL Listeners (3) ARTISANS OF OPEN SOURCE•  Now, let’s define/enable our PorletFilter on each existing portlet: File: /WEB-INF/portlet.xml <portlet-app ...> ... <public-render-parameter>...</public-render-parameter> ... <listener> <display-name>Hello World Portlet URL Listener</display-name> <listener-class>com.sample.generic.listeners.ResourceURLListener</listener-class> </listener> ... </portlet-app> After re-deploying our Portlet plugin and clicking on Portlet’s button:
    • Servlet Programming Features ARTISANS OF OPEN SOURCE•  If compared to Servlets, JSR-168 restricted the portlet programming model in some areas because some Servlet model features -assuming only one component on the page- are not easily applied on Portlets•  JSR-268 provides nearly the same capabilities as the Servlet programming model plus the portlet specific extensions…•  Document head section elements, HTTP headers and Cookies: JSR-268 allows the portlet to contribute to sections of portal page outside its portlet window: –  Document head section elements: a two-part render call (RENDER_HEADER and RENDER_MARKUP) is enabled in order portlets can return content outside the portlet window (ie. HTML ones such as meta, link, or style) through GenericPortlet.doHeaders() –  HTTP Headers (ie. app-specific Pragma headers) via PortletResponse.setProperty() –  Cookies through PortletResponse.addProperty() at the response of each life-cycle method (processAction, processEvent, render, and serveResource): •  Cookies are not guaranteed to be shared across different portlets and may be stored by the portal (not at the client) •  To set cookies in the render method, the renderHeaders option should be turned on and the cookies should be set in the RENDER_HEADERS part by using overriding GenericPortlet.doHeaders()•  Dispatching to Servlets and JSPs: A portlet can invoke servlets and JSPs in all lifecycle methods by using methods include() or forward() via a request dispatcher (PortletContext.getRequestDispatcher()): –  Action/event can be dispatched to logic written in a servlet, or do forward in serving resource –  Servlet request/response objs given to the servlet/JSP are based on portlet request/response: •  Attributes set in the portlet request are available in the included servlet request •  The portlet and the included servlet or JSP share the same output stream •  Attributes set in the portlet session are accessible from the servlet session and vice versa
    • Annotations ARTISANS OF OPEN SOURCE•  JSR-268 introduces Annotations for directly dispatching requests when using GenericPortlet to ease configuration pain –  Annotation @ProcessEvent for event calls @ProcessEvent(qname="{http://sample.com/events}ipc.speak.world") public void processSpeakWorldEvent(EventRequest req, EventResponse res){...} –  Annotation @ProcessAction for action calls via a ActionURL with parameter "javax.portlet.action” set: @ProcessAction(name="speakWorld”) public void speakWorld(ActionRequest request, ActionResponse response){...} –  Annotation @RenderMode for render calls for a corresponding Portlet Mode @RenderMode(name="VIEW") public void speakWorld(RenderRequest request, RenderResponse response){...}
    • Tag Libraries ARTISANS OF OPEN SOURCE•  JSR-268 provides new tags to ease JSP development: –  <portlet:resourceURL>: build ResourceURL refering back to the portlet –  Attributes copyCurrentRenderParameters and escapeXML on RenderURL, ActionURL and ResourceURL –  <portlet:namespace>: returns unique value for the current Portlet window•  Since Portlet’s markup is aggregated in same page, name of items that should be unique should be “namespaced” through PortletRequest.getNamespace(): –  Returned value is same/preserved for the entire lifetime of the Portlet window –  To be used to prefix names that should be unique (ie. html ids/names, javascript functions/variables, etc) <script type="text/javascript”> … function <portlet:namespace/>ajaxHelloWorld(url){...} … </script> … <input type="button" value=Ajax! title=<%=resourceUrl%>’ onclick="javascript:<portlet:namespace/>ajaxHelloWorld(<%=resourceUrl%>);” />
    • ARTISANS OF OPEN SOURCEConclusion
    • Questions? ARTISANS OF OPEN SOURCE Introduction to Portlets using Liferay Portal (Part 2) By: Aníbal Gómez-Estrada http://rivetlogic.com/web/agomez October 19th, 2011Rivet Logic Corporation Rivet Logic Costa Rica SRL11410 Isaac Newton Square N. Costa Rica Developers ForgeSuite 210 Edificio María Luisa, 3A officeReston, VA 20190, USA Paseo Colón, San José, Costa RicaPh: 703.955.3480 Fax: 703.234.7711 Ph: (506) 2256-1024 Fax: (506) 2256-1024
    • References ARTISANS OF OPEN SOURCE JSR 286: Portlet Specification 2.0 http://www.bluesunrise.com/portlet-api/javax/portlet/ package-summary.htmlhttp://www.ibm.com/developerworks/websphere/library/ techarticles/0803_hepper/0803_hepper.htmlhttp://developers.sun.com/portalserver/reference/techart/ jsr286/jsr286.htmlhttp://download.oracle.com/docs/cd/E15919_01/wlp.1032/ e14244/javaportlets.htm#BCGIBGBJ http://www.liferay.com
    • ARTISANS OF OPEN SOURCEAnnouncements
    • Available At My Blog! ARTISANS OF OPEN SOURCEJSF 2.0 Portlets using Liferay Portal Available At My Blog! http://rivetlogic.com/web/agomez/ Contents Introduction to Portlet Bridges Setup and Hello World Portlet Internationalization Actions and Navigation Portlet Preferences Inter-Portlet Communication
    • Rivet Logic Is Hiring! ARTISANS OF OPEN SOURCE We are hiring! Java developers – mcalvo@rivetlogic.com•  Award-winning consulting and systems integration firmfocused on enabling open source –based software solutionsfor content management, collaboration and community: –  Innovator of the Year: JBoss (2008) –  Solution of the Year: Alfresco (2010) –  Platinum Partner: Liferay (2011)•  We use top-notch open source technology:•  Company Facts: –  Founded in 2005. Consistently Profitable and Employee-owned. 40+ Consultants –  Headquarters in Virginia, USA. Near-shore office in San José, Costa Rica for two years –  Certified Liferay Partner since 2006