04 469513 Ch01.qxd 1/16/04 11:04 AM Page 3 The Java Por tlet API (JSR 168) This chapter discusses the centerpiece of portal development, the Java Portlet API, Java Specification Request 168 (JSR 168). The chapter explains the concepts in the specification, explaining how they fit into portal architectures to enable the developer to be an effective portal developer. Por tlet Fundamentals A portal server handles client requests.
04 469513 Ch01.qxd 1/16/04 11:04 AM Page 4 Chapter 1 Web Browser Web Browser Web Browser Por tal Ser ver Por tlet Container Web Container Enterprise Data Figure 1.
04 469513 Ch01.qxd 1/16/04 11:04 AM Page 5 The Java Portlet API (JSR 168) As you can see, the servlet container is the basis for any portal, upon which the portlet container extension is built. Likewise, a portal is built on top of that portlet container, which manages the portlets required to handle client requests. Before describing the relationships between portlets and servlets, we should discuss a few of the fundamental definitions related to the Portlet API.
04 469513 Ch01.qxd 1/16/04 11:04 AM Page 6 Chapter 1 The differences between portlets and servlets are as follows: ❑ Portlets generate fragments, whereas servlets generate complete documents. ❑ Unlike servlets, portlets are not bound directly to a URL. ❑ Portlets have a more sophisticated request scheme, with two types of requests: action and render. ❑ Portlets adhere to a standardized set of states and modes that define their operating context and rendering rules.
04 469513 Ch01.qxd 1/16/04 11:04 AM Page 7 The Java Portlet API (JSR 168) Portal Page Portal Server Fragments Portlet Container Portlets 1 2 3 4 5 Figure 1.
04 469513 Ch01.qxd 1/16/04 11:04 AM Page 8 Chapter 1 The Por tlet Interface and the GenericPor tlet The Portlet interface defines the behaviors that all portlets must implement. Typically, you would prefer to extend the GenericPortlet class to build a portlet, because it provides structures for providing all of the typical portlet implementation methods, not simply the required ones.
04 469513 Ch01.qxd 1/16/04 11:04 AM Page 9 The Java Portlet API (JSR 168) necessary to tweak that state to handle customized views of the portlet. For example, say you have an employee directory portlet. Obviously, it would require certain preferences to get it running.
04 469513 Ch01.qxd 1/16/04 11:04 AM Page 10 Chapter 1 1. Action 2. Render Figure 1.3 ActionRequest As previously mentioned in the discussion of portlet request handling, action requests handle changing the state of a portlet based on the action request parameters. This is done using the processAction method, which takes an ActionRequest and ActionResponse object as parameters.
04 469513 Ch01.qxd 1/16/04 11:04 AM Page 11 The Java Portlet API (JSR 168) ❑ The portlet session ❑ The window state ❑ The portlet preferences object ❑ The portal context To change the portlet mode or window state, you call the appropriate method on the ActionResponse object. The change becomes evident when the render method is called subsequent to the end of processing in the processAction method. You can also pass render parameters using the ActionResponse object.
04 469513 Ch01.qxd 1/16/04 11:04 AM Page 12 Chapter 1 import javax.portlet.GenericPortlet; import javax.portlet.PortletException; import javax.portlet.PortletMode; import javax.portlet.PortletRequestDispatcher; import javax.portlet.RenderRequest; import javax.portlet.
04 469513 Ch01.qxd 1/16/04 11:04 AM Page 13 The Java Portlet API (JSR 168) *
* In this case, we will dispatch the method to a JSP * located in the portlet root directory called “view.jsp” */ protected void doView(RenderRequest request, RenderResponse response) throws PortletException, IOException { PortletRequestDispatcher prd = getPortletContext().getRequestDispatcher(“/view.jsp”); prd.
04 469513 Ch01.qxd 1/16/04 11:04 AM Page 14 Chapter 1 Other Elements of the Java Por tlet API Now that you have examined the high-level concepts of the Portlet API, this section addresses the lowerlevel components within the specification, providing a portlet developer’s perspective on the internals of the specification, highlighting important concepts and potential pitfalls.
04 469513 Ch01.qxd 1/16/04 11:04 AM Page 15 The Java Portlet API (JSR 168) Portlet developers should use the PortletURL objects (or their accompanying tag libraries) instead of directly manipulating HTTP query strings. The corollary to this is that developers should not use GET in HTML forms. This is because portals may encode internal state parameters in the PortletURL.
04 469513 Ch01.qxd 1/16/04 11:04 AM Page 16 Chapter 1 Window States The window state indicates to the portlet how much space is being allocated to it. This enables the portlet to modify its rendering to suit that window state. The following table contains the window states specified by the Portlet API. State Definition NORMAL The portlet will share the screen with other portlets. This means that the portlet should limit its markup. MINIMIZED The portlet should provide little or no output.
04 469513 Ch01.qxd 1/16/04 11:04 AM Page 17 The Java Portlet API (JSR 168) portlet, and following that example, you could have a preference called “cities,” with values representing the zip codes of the cities for which you want the weather. Note that preferences are only meant for configuring the portlet, so maintaining the list of all cities available in a preference would be an inappropriate use of preferences.
04 469513 Ch01.qxd 1/16/04 11:04 AM Page 18 Chapter 1 The following code is an example of retrieving and setting preferences: try { PortletPreferences myPrefs = request.getPreferences(); String [] cities = myPrefs.getValues(“cities”, new String[] {“20112”,”90210”}); for (int i=0; i < cities.length; i++) { System.out.println(cities[i]); } String [] newCities = new String[] {“20169”,”22124”}; myPrefs.setValues(“cities”,newCities); myPrefs.store(); } catch (ValidatorException ve) { System.out.
04 469513 Ch01.qxd 1/16/04 11:04 AM Page 19 The Java Portlet API (JSR 168) identification number). This attribute name prevents namespace collision with other portlets storing their session variables with similar names. Despite having a special system for naming its attributes, PORTLET_SCOPE doesn’t protect its attributes from other Web components. In addition, the namespace application is done completely under the hood.
04 469513 Ch01.qxd 1/16/04 11:04 AM Page 20 Chapter 1 This time we used the getNamedDispatcher method with the name of our servlet in order to get a PortletRequestDispatcher. This is another important point to consider if you choose to do the following: String reqPath = “/calView.jsp?user=Jennifer”; PortletRequestDispatcher prd = portContext.getRequestDispatcher(reqPath); prd.
04 469513 Ch01.qxd 1/16/04 11:04 AM Page 21 The Java Portlet API (JSR 168) populated. Likewise, HttpServletResponse has restrictions on what is accessible.
04 469513 Ch01.qxd 1/16/04 11:04 AM Page 22 Chapter 1 ❑ Have a Web application deployment descriptor located at WEB-INF/web.xml ❑ Are packaged as Web archives (WAR files) In addition to these features, the portlet application contains a portlet application deployment descriptor, located at WEB-INF/portlet.xml. This file is described in detail later in this chapter, in the section “Portlet Application Deployment Descriptor.
04 469513 Ch01.qxd 1/16/04 11:04 AM Page 23 The Java Portlet API (JSR 168) Attribute Name Description portlet-sectionselected This style is used for highlighting a particular set of cells for the user. portlet-sectionsubheader If you have subheadings in your table that you need to distinguish from your table header, you use this style. portlet-section-footer If you include a footer to your table, this style would be used for those cells.
04 469513 Ch01.qxd 1/16/04 11:04 AM Page 24 Chapter 1 User Information Attributes User attributes are used to create a profile for a user. They are meant to be standardized on the World Wide Web Consortium’s (W3C) Platform for Privacy Preferences (P3P) 1.0 (www.w3.org/TR/P3P/). These attributes are also consistent with the efforts of the OASIS Web Services for Remote Portals standard. The following table lists the user attributes and their descriptions. 24 Attribute Name Description user.
04 469513 Ch01.qxd 1/16/04 11:04 AM Page 25 The Java Portlet API (JSR 168) Attribute Name Description user.home-info.telecom. telephone.number The user’s home telephone local number (for example, 555-1111, etc.) user.home-info.telecom. telephone.ext The user’s home telephone extension, if they have one (for example, 745, 2918, etc.) user.home-info.telecom. telephone.comment Comments about the user’s home telephone (optional) user.home-info.telecom. fax.
04 469513 Ch01.qxd 1/16/04 11:04 AM Page 26 Chapter 1 Attribute Name Description user.home-info.online.email The user’s home e-mail address 26 user.home-info.online.uri The user’s home Web page user.business-info. postal.name The name that should appear at the top of a work address (for example, Sun Microsystems or XYZ, Inc., etc.) user.business-info. postal.street The street address of the user’s work (for example, 1600 Pennsylvania Avenue or 742 Evergreen Terrace) user.business-info. postal.
04 469513 Ch01.qxd 1/16/04 11:04 AM Page 27 The Java Portlet API (JSR 168) Attribute Name Description user.business-info. telecom.mobile.intcode The international access code for the user’s work mobile telephone (for example, 44 for the United Kingdom and 1 for the United States) user.business-info. telecom.mobile.loccode The user’s work mobile telephone area code (for example, 703, 818, etc.) user.business-info. telecom.mobile.number The user’s work mobile telephone local number (555-1111, etc.
04 469513 Ch01.qxd 1/16/04 11:04 AM Page 28 Chapter 1 You grab a Map of the deployed user attributes by getting that attribute from the PortletRequest. Then, you simply look up the appropriate value; in this case, the user’s work e-mail (stored under “user.business-info.online.email”). User attributes are very important in deploying personalized portlet solutions. Be sure to familiarize yourself with these attributes.
04 469513 Ch01.qxd 1/16/04 11:04 AM Page 29 The Java Portlet API (JSR 168) Portlet Declarations This is the first part of the declaration of one portlet. In this, we give it a description, a local name, a display name, and a class name. The description and display name are meant to make it more human-friendly, while the local name and the class actually provide the nuts and bolts required to programmatically load and reference the portlet.
04 469513 Ch01.qxd 1/16/04 11:04 AM Page 30 Chapter 1 Pre-configured title Example JSR 168, Portlet API, Example, Simple This section shows the portlet preferences. Of course, the preferences you define must be unique. The index-location preference is read-only, so it cannot be changed programmatically; instead, it must be changed here.
04 469513 Ch01.qxd 1/16/04 11:04 AM Page 31 The Java Portlet API (JSR 168) Portlet Customization Declarations This defines a custom portlet mode called MY_MODE. Of course, whenever an application defines a custom portlet mode, it must not only be available through the targeted portal server, but also needs to have portlets that actually use the mode (while programming defensively enough to avoid breaking in unsupported portal servers).
04 469513 Ch01.qxd 1/16/04 11:04 AM Page 32 Chapter 1 This defines the end of the portlet application. Building a Portlet Now, let’s work through a complete example of a portlet. This portlet is a little more complex than our previous example, but it is not as involved as the portlets found in Chapter 9, which covers building portlet applications. The first thing to do in building the portlet is to build the portlet class.
04 469513 Ch01.qxd 1/16/04 11:04 AM Page 33 The Java Portlet API (JSR 168) RenderRequest request, RenderResponse response) throws PortletException, IOException { PortletRequestDispatcher prd = getPortletContext().getRequestDispatcher(“/searchEdit.jsp”); prd.include(request, response); } We declare our LucenePortlet, which extends GenericPortlet. When we are in EDIT mode, we display the searchEdit.jsp.
04 469513 Ch01.qxd 1/16/04 11:04 AM Page 34 Chapter 1 Rendering the VIEW mode depends on whether we passed in a query mode RenderRequest parameter. If there is a queryMode parameter, we display the results; if not, we display the search box. /* This method is overriden to specify * the title programmatically */ protected String getTitle(RenderRequest request) { return “Lucene Portlet”; } /* This method is the meat of the portlet * manipulations of the portlet’s state are done * through this method.
04 469513 Ch01.qxd 1/16/04 11:04 AM Page 35 The Java Portlet API (JSR 168) * know it came from a form. */ if (aReq.getParameter(“Submit”) != null) { PortletPreferences prefs = aReq.getPreferences(); String indexPath = aReq.getParameter(“indexPath”); prefs.setValue(“indexPath”, indexPath); try { prefs.store(); aRes.setRenderParameter( “success”, “The update was successful.”); } catch (ValidatorException ve) { System.out.println(“Preferences did not validate.”); aRes.
04 469513 Ch01.qxd 1/16/04 11:04 AM Page 36 Chapter 1 package org.opensourceportals.validator; import java.io.File; import java.util.ArrayList; import java.util.List; import javax.portlet.PortletPreferences; import javax.portlet.PreferencesValidator; import javax.portlet.ValidatorException; /** * @author Clay Richardson */ public class LuceneValidator implements PreferencesValidator { /* * In order to create a validator, we implement the * javax.portlet.PreferencesValidator interface.
04 469513 Ch01.qxd 1/16/04 11:04 AM Page 37 The Java Portlet API (JSR 168) want to use a validator as a mechanism to check a condition that is more complicated than simply “present” or “not present.” If either of these conditions is false, then the LuceneValidator will throw a ValidatorException. Now that we have managed the major logical parts of the LucenePortlet, we will review the presentation aspects of the portlet. The following code shows search_view.
04 469513 Ch01.qxd 1/16/04 11:04 AM Page 38 Chapter 1 } else { shaded = “white”; } %>
”> <%=(i+1+startRow)%>. ( <%=form.format((hits.score(i)*100))%>%) ”><%=doc.get(“title”)%> <%=doc.get(“summary”)%> |
<% } %> As you can see, this is a simplistic search result page, providing only twenty-five search results, and no paging capability.04 469513 Ch01.qxd 1/16/04 11:04 AM Page 39 The Java Portlet API (JSR 168) Summar y This chapter focused on explaining the Java Portlet API. It provided a basic end-to-end example of a portlet to demonstrate the API in a practical use. However, for a more comprehensive chapter on building portlet applications, see Chapter 9.
04 469513 Ch01.