460 likes | 601 Views
JSR-168 Portlets and uPortal. Matt Young matt.young@duke.edu. Goals. Familiarity with portlet architecture Familiarity with the services provided to portlets by the spec Ability to write useful portlets Provide examples that can be used as a cut & paste source for common tasks
E N D
JSR-168 Portlets and uPortal Matt Young matt.young@duke.edu
Goals • Familiarity with portlet architecture • Familiarity with the services provided to portlets by the spec • Ability to write useful portlets • Provide examples that can be used as a cut & paste source for common tasks • Explore MVC options
Overview • What’s a portlet? • What is its relationship with a portal? • How is it deployed on a web server? • What deployment descriptors does it need? • How is the code laid out? • What services does it provide?
What is a Portlet? • A portlet produces an HTML fragment that populates a window (or channel) within a portal page • The portlet can communicate with the portal container
Portals and Portlets Pluto Portlet App Portal Weather Portlet Search ControllerPortlet Search Portlet Search Results Portlet Events Calendar Portlet Tomcat Application Server
Weather Portlet Search Portlet Events Calendar Portlet uPortal and Portlets Pluto uPortal Announcements Channel UBC Webmail Weather Portlet Wrapper Search Portlet Wrapper Event Cal. Portlet Wrapper RSS Feed Tomcat Application Server
uPortal uPortal Announcements Channel UBC Webmail Weather Portlet Wrapper RSS Feed Search Portlet Wrapper Event Cal. Portlet Wrapper
A Portlet in uPortal Weather Portlet Wrapper (an instance of CPortletAdapter) edu.duke.oit.ows.portlets.WeatherPortlet
The Portlet Pieces Source Code portlet.xml web.xml
web.xml <?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/j2ee/dtds/web-app_2_2.dtd"> <web-app> <display-name>Hello World Portlet</display-name> </web-app>
portlet.xml <?xml version="1.0" encoding="UTF-8"?> <portlet-app xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd" version="1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd"> <portlet> <portlet-name>HelloWorldPortlet</portlet-name> <portlet-class>edu.duke.oit.ows.HelloWorldPortlet</portlet-class> <expiration-cache>0</expiration-cache> <supports> <mime-type>text/html</mime-type> <portlet-mode>EDIT</portlet-mode> <portlet-mode>HELP</portlet-mode> </supports> <portlet-info> <title>Hello World Portlet</title> </portlet-info> </portlet> </portlet-app>
When changing portlet.xml • You’ve got to restart uPortal for the changes to show up, even after a re-deployment! • I will forget to do this at least once today
Portlet source code • Extend GenericPortlet (or other portlet class, like JSPPortlet) • Override one or more standard methods: doView, doEdit, doHelp, processAction
Portlet Modes • View: The default portlet mode, providing the standard UI for the portlet • Edit: A mode for setting user-configurable preferences • Help: Displays help for using the portlet • Modes can be specified on a per mime-type basis • Custom modes can be defined by the portal to provide more modes
Window States • NORMAL: A regular window • MAXIMIZED: A window taking up the entire content space of the portal page • MINIMIZED: Just the title bar of the portlet • Custom window states make also be defined by the portal • EXCLUSIVE: uPortal adds this mode to facilitate file uploads
processAction • The processAction method is called when the portlet receives an action. This is where any logic that the portlet provides should be tripped, including storing/updating preferences
About the init method • It is not safe to assume that the portlet is in an active portal container until the init method is called. Therefore, make no attempt to access services from the constructor of the portlet or in any location before the init method is called
Deploying the Portlet • Step 1: User uPortal ant target ‘deployPortletApp’ to deploy application to the serverant deployPortletApp -DportletApp=<file> • Step 2: Configure uPortal to see the portlet as a channelPortlet Defintion ID: warFileName.portletName
Notes about Portlet Deployment • If you do something wrong, uPortal is likely to cache the error. Best to restart in a development environment to make sure deployment descriptors are correct • Deployment happens just like a regular web app, except that the ant task alters the web.xml file to make it usable by uPortal
Creating an action • First, generate an actionURLPortletURL actionURL = response.createActionURL(); • Then, actionURL.toString() will provide the URL that will trip a processAction call. • Parameters can be added to the actionURL (or any other PortletURL) with actionURL.setParameter(String name, String value);
Changing Modes • VIEW / EDIT / HELP are default modes • To change modes, generate an action URL:PortletURL actionURL = renderResponse.createActionURL(); • This calls the processAction method when followed, then, within the processAction method, set the appropriate destination mode:actionResponse.setPortletMode(PortletMode.EDIT);
Modes and uPortal buttons • EDIT -> EDIT • HELP -> HELP
Portlet Parameters • Parameters can be set within the portlet.xml file so that compiles are not required to move portlets from installation to installation • There are 2 kinds of parameters, init-params and portlet-preferences
init-param • Initialization parameters (ie. Site dependant constants) specified in portlet.xml<init-param> <name>defaultZipCode</name> <value>27705</value> </init-param> • Readable from a PortletConfig object available in all init methodsString zipCode = config.getInitParameter(“defaultZipCode”);
portlet-preferences • When defined within the portlet.xml file, these are default values for the per-user runtime preferences • Preference values may be set as read-only • Essentially a variable initialization mechanism for runtime user preferences
User Preferences • Each portlet can use the portal’s data store to hold on to per-user preferences • To read in preferences: PortletPreferences prefs = request.getPreferences(); • To read a particular named preference:prefs.getValue(String pref_name, String default); • The above will return default if there is no preference named pref_name for that user, otherwise the value of that preference will be returned
User Preferences • The getValue() method returns a String • The getValues() method returns a String[] • Preferences are read-only in all the “do” methods • Preferences are read-write in the processAction method
User Preferences • To store preferences:PortletPreferences prefs = actionRequest.getPreferences();prefs.setValue(“nickname”, “Matt”);prefs.store(); • Values are not committed until the store() method of PortletPreferences is called • User preferences should not be used as a general purpose database. The intent is only to hold portlet preferences (settings) • Use JNI or another method for getting a database handle if larger scale db operations are needed
User Attributes • Some basic security attributes are available from the request object:request.getAuthType() <-- returns a constantrequest.getRemoteUser() <-- login IDrequest.getUserPrincipal() <-- returns user principalrequest.isUserInRole(String) <-- role (group) checkingrequest.isSecure() <-- https? (or equivalent?)
User Attributes • Portlets can be granted access to the user attributes available in the portal framework • In uPortal terms, these are the attributes defined in the PersonDirs.xml file • Available attributes must be defined in the portlet.xml file (JSR-168) spec in addition to the PersonDirs.xml file (uPortal)
User Attributes • Attribute values can be retrieved in the portlet from the USER_INFO map returnable from a renderRequest or actionRequestMap userInfo; userInfo = request.getAttribute(PortletRequest.USER_INFO);String uniqueID = userInfo.get("uniqueID");
Caching • uPortal caches portlet content until the portlet receives and action or a render request. This means that the ‘reload’ button will not update content in portlets. Only interaction with the portlet will cause an update • This turns out to be a useful mechanism for reducing load on external resources • It also keeps portal response very fast
Better display options • Keeping your (X)HTML in the portlet code is not optimal. Best practice is to separate logic from view. Some options for a better View technology: • JSP • JSF • XSLT • Spring (in beta - coming soon, example in the CVS repository for uPortal)
Request Dispatchers • You can use a PortletRequestDispatcher to send the PortletRequest onto another rendering service • First obtain the request dispatcher from the portletContext:PortletRequestDispatcher rd = getPortletContext.getRequestDispatcher(“/MyPortletView.jsp”); • Then, include the current request and response so that parameters can be seen by the .jsp (or JSF, or other rendering service):rd.include(request,response);
CSS Standards • The JSR-168 spec lists standard CSS class names for use within portlets Adhering to these names is suggested. uPortal will most likely adopt these standards • See Appendix C of the JSR-168 spec
Request Attributes • Request attributes can be used to send data to JSPs or other rendering technology:request.setAttribute(“name”, “Matt”); • In the JSP this attribute can be retrieved with:<% String name = renderRequest.getAttribute(”name"); %>
Response Properties • Properties can be added to the PortletResponse:response.setProperty(“expiration-cache”, 0); • The above is a useful property to set if there’s an exception thrown in the Portlet
What doesn’t uPortal implement? • The portlet title, usually read from a parameter in portlet.xml or a resource bundle, is defined in the channel definitions • Expiration cache has no meaning within uPortal - update: just added • User elements accessed via a portlet must be defined both in portlet.xml and PersonDirs.xml
What does JSR-168 miss? • Inter-portlet communication
“Trick” Inter-portlet communication • A portlet application is a collection of individual portlets • User the PortletSession available from a PortletRequest to transport attributes between portlets within a portlet application
Inter-portlet Communication • Since the processAction method is guaranteed to run first, make any state changes there first:PortletSession ps = actionRequest.getPortletSession();ps.setAttribute(“zip”, zip, PortletSession.APPLICATION_SCOPE); • The SCOPE specified in the setAttribute method allows the attribute to be seen on either the Portlet level or the Portlet Application level
Inter-portlet Communication • Attributes can be retrieved from the session in the “do” methods of a portlet:PortletSession ps = renderRequest.getPortletSession();String zip = (String)ps.getAttribute(“zip”);
Inter-portlet Communication Caution! • There’s no guarantee of execution sequence of doView, doEdit methods of the portlets on a portal page • Some “do” methods may not be fired because of the caching paradigm being applied to that portlet • There is no guarantee that a user might delete one essential part of a portlet app without removing the others, so something like Aggregated Layouts would have to be used