Chapter 3. Portlet 2.0 API—portlet objects and container-runtime options

This chapter covers

  • Using the portlet container’s request and response objects
  • Adding external JavaScript and CSS files to a portal page
  • Accessing a logged-in user’s information via user attributes
  • Understanding PortletContext, PortletConfig, and PortletSession
  • Using container-runtime options

In the context of the example User Registration portlet, chapter 2 introduced you to some of the classes and interfaces of the Portlet 2.0 specification. This chapter and the next will provide comprehensive coverage of the Portlet 2.0 API using an example Book Catalog portlet.

In this chapter, we’ll look at portlet objects, methods, and features that you’ll come across often while developing portlets. Chapter 4 will cover advanced portlet features that let you cache portlet content, localize portlet content, define custom portlet modes and window states, and secure portlets from unauthorized access.

 

Note

We’ll cover classes and interfaces specific to serving resources, inter-portlet communication, portlet filters, and personalization in chapters dedicated to these topics.

 

In this and the next chapter, you’ll learn the importance of knowing your portal server before you start developing portlets for it. This will remain important even as new versions of various portal servers are introduced, with more features and fewer limitations. The example Book Catalog portlet in this chapter looks at using portlets with servlets, and will serve as a basis for learning the concepts discussed in this and the next chapter.

The intent of these chapters is to show you that it isn’t difficult to develop portlets that are portable across different portal servers, irrespective of portal server limitations or the dependence of portlets on portal server–specific APIs.

3.1. Requirements for the Book Catalog portlet

If you tried running the User Registration portlet (developed in chapter 2) on portal servers other than Liferay Portal, there’s a good chance that it didn’t work at all, or that it behaved differently. The reason for this is that the other portal server is missing support for an optional feature, or there’s an existing bug in the portlet container or portal server software, or there are portal server–specific configuration requirements for a portlet.

In this chapter, you’ll look at a Book Catalog portlet that allows users to manage a book catalog. With the Book Catalog portlet, you can add, remove, search for, and list books in the catalog. This example portlet will help you learn and allow you to implement the concepts described in this chapter.

The rest of the chapters in this book will follow a similar pattern. We’ll begin with a subset of Book Catalog portlet requirements to implement, and the chapter will discuss and explain the concepts needed to implement the changes in the Book Catalog portlet.

The Book Catalog portlet that we’ll discuss in this chapter is expected to work on Liferay Portal 5.2.3/6.x as well as the following portal servers:

The portlet class in the User Registration portlet (in chapter 2) was responsible for generating content and processing actions. In this chapter there’s a servlet component, BookServlet, that generates content and does the action processing. The Book Catalog portlet class delegates action and render requests to BookServlet to generate content for the portlet and to add books to or remove them from the catalog. Figure 3.1 illustrates the interaction between the Book Catalog portlet class and BookServlet.

Figure 3.1. The Book Catalog portlet makes use of the BookServlet to generate content and process actions. The BookServlet generates HTML markup using JSP pages, and it interacts with the database to obtain or store book information.

In figure 3.1, the Book Catalog portlet receives action and render requests from the portal, which in turn delegates them to the BookServlet for further processing. The content generated by the BookServlet is included in the response generated by the Book Catalog portlet.

 

Warning

In fresh development projects, you shouldn’t use servlets to process actions or generate content for your portlet. Only if you have an existing servlet that contains the processing logic you want to use should you consider using servlets with your portlets.

 

In the Book Catalog portlet, the user action information is sent by the JSP pages to the portlet class using the myaction request parameter. The BookServlet uses a request attribute named myaction to determine which action needs to be taken by BookServlet. The Book Catalog portlet is responsible for setting the myaction attribute in the request before dispatching the request to the BookServlet.

In this chapter, the Book Catalog portlet requirements focus on the following portlet 2.0 concepts:

  • Using servlets for content generation and action processing.
  • Programmatically changing the portlet title.
  • Using the actionScopedRequestAttributes container-runtime option. In chapter 2, you used this option to share request attributes set in the action method with the render method of the portlet. This chapter discusses the pros and cons of using the option.
  • Using optional container-runtime options.
  • Sharing session information between portlet and servlet components in the same portlet application.
  • Including CSS and JavaScript in portlets. This is where we’ll discuss restrictions on the content generated by portlets.

Figure 3.2 shows the home page (also referred to as the initial content) of the Book Catalog portlet.

Figure 3.2. The Book Catalog portlet’s home page. The portlet provides features to search for books, run the portlet in full-screen mode, upload and download book TOCs, and display the current portal server information.

At , you can specify search criteria for the book. The table below the search criteria displays matching books. You can use the Refresh Search Results hyperlink to refresh your search results; if a book was deleted or added and it matches your search criteria, the results will be updated accordingly.

You can download or upload the table of contents (TOC) for a book using Download and Upload hyperlinks. The implementation of this feature will be discussed in chapter 12, which discusses resource serving.

You can use the FULL SCREEN hyperlink to view the Book Catalog portlet in maximized window state. The Book Catalog portlet displays information about the portal server on which the portlet is currently deployed.

The Remove hyperlink allows you to remove a book from the catalog. Clicking Remove displays a JavaScript popup message to confirm the removal.

Links are provided to print the book catalog, set preferences, and view help information about the portlet. The Print option shows the Book Catalog portlet in print portlet mode, to allow users to print the complete list of books in the catalog. In print mode, the Book Catalog portlet shows all books in the catalog with no hyperlinks, text fields, or buttons on the page. If you’re using a portal server that doesn’t support print portlet mode, clicking the Print option will have no effect.

The first and last names of the user are displayed . The current system date and time is displayed in MM-dd-yyyy HH:mm:ss format. Clicking the Add Book button opens the form for adding a new book to the book catalog.

You may have noticed that the hyperlinks in figure 3.2 aren’t underlined and their colors are also different. We’ll be using CSS to specify the color and effects for hyperlinks in our portlet.

Figure 3.3 shows the Add Book page, where you enter information about new books.

Figure 3.3. The Add Book form of the Book Catalog portlet lets you add new book information to the book catalog.

The Home link takes you back to the home page of the Book Catalog portlet, shown in figure 3.2. Clicking the Add Book button saves the book information into the catalog if no validation errors are found in the entered book information. The portlet’s title bar has changed from Book Catalog (refer to figure 3.2) to Book Catalog: Add Book to identify the page.

Once you add book information to the catalog using the Add Book form, the book information will appear on the home page of the Book Catalog portlet (see figure 3.2). You can now upload the TOC for the book using the Upload link. Figure 3.4 shows the TOC upload form.

Figure 3.4. The Upload TOC form used to upload a TOC for a book

The title of the portlet has changed to Book Catalog: Upload TOC. The Home link takes you back to the portlet’s home page. You can upload the TOC by choosing a file from your local filesystem. The maximum file size that can be uploaded is 1 MB. Clicking the Upload TOC button uploads the file to the local filesystem of the portal server, if the size of the selected TOC file is less than or equal to 1 MB. If the TOC file is bigger than 1 MB, an error page is displayed.

The Book Catalog portlet must additionally support the following features:

  • Localization— Like most real-world portlets, the Book Catalog portlet must support localization of text, labels, and messages. For now, it should support the fr_FR locale.
  • Caching— If the portlet container supports a validation-based caching strategy, the Book Catalog portlet must cache content based on that strategy. If validation-based caching isn’t supported, the portlet will retrieve data from the data source every time it receives a render request. We’ll discuss the validation-based caching strategy in detail in chapter 4.

 

Code Reference

The source code for the example Book Catalog portlet is located in the ch3_BookCatalog folder. Before you build or deploy the portlet, make sure you change the value of the uploadFolder initialization parameter in the portlet deployment descriptor. Also, before you build the project, set the liferay.portal.home property in the build.properties file to point to your Liferay Portal installation directory.

 

That’s it for the requirements of the Book Catalog portlet that we’ll develop in this chapter and chapter 4. The rest of this chapter will look at the various portlet concepts mentioned at the beginning of the chapter, and along the way you’ll learn how to use them to implement the Book Catalog portlet.

Let’s now dive into the details of the Portlet 2.0 API, beginning with portlet request objects.

3.2. Portlet request objects

In this section, we’ll look at the different portlet request objects that are made available to portlets by the portlet container, depending upon the portlet’s current lifecycle phase. The request objects are used by the Book Catalog portlet to obtain request parameters, user information, window states, portlet mode, portal server information, and so on. As we go along this section, you’ll learn details about how particular features of the portlet request object are used in implementing the Book Catalog portlet.

Let’s take a quick look at the different lifecycle interfaces available in Portlet 2.0 before we dive into the details of the various request object types.

3.2.1. Portlet request objects and lifecycle interfaces

Which portlet request object is available to a portlet instance depends on the lifecycle phase of the portlet. The different lifecycle phases that a portlet can have depend on the lifecycle interfaces implemented by the portlet class.

Table 3.1 describes the three lifecycle interfaces in portlets: Portlet, EventPortlet, and ResourceServingPortlet.

Table 3.1. Portlet lifecycle interfaces

Lifecycle interface

Description

Portlet Mandatory interface that defines init, destroy, processAction, and render lifecycle methods.
ResourceServingPortlet Optional interface implemented by portlets if they serve resources (such as binary content) to the client. It defines the serveResource method, which accepts ResourceRequest and ResourceResponse objects as arguments.
EventPortlet Optional interface implemented by portlets if they want to receive events from other portlets or the portlet container. It defines the processEvent method, which accepts EventRequest and EventResponse objects as arguments.

The ResourceServingPortlet and EventPortlet interfaces were introduced in the Portlet 2.0 specification to allow portlets to serve resources to clients and to process events generated by other portlets, respectively. We’ll discuss these interfaces in detail in chapters dedicated to serving resources (chapter 12) and inter-portlet communication (chapter 11).

Portlet request objects provide request information such as window state, portlet mode, request parameters, request attributes, and so on, to the portlet instance during request processing. In previous chapters, we saw two different portlet request objects: RenderRequest and ActionRequest. They were made available to the portlet instance depending upon whether the portlet container received a render or action request for the portlet. If your portlet serves resources and handles events, you’ll come across two more request objects: ResourceRequest and EventRequest.

All request objects implement a common interface, PortletRequest, as shown in figure 3.5.

Figure 3.5. PortletRequest is the superinterface of the RenderRequest, ActionRequest, ResourceRequest, and EventRequest interfaces. The subinterfaces define methods and fields specific to the request type.

In figure 3.5, specialized interfaces define methods and fields that are specific to particular request types. For example, RenderRequest defines an ETAG field, which is used in validation-based caching (discussed in chapter 4); ClientDataRequest defines methods to help you upload files; ActionRequest defines an ACTION_NAME field, which is used to identify the name of the action associated with an ActionRequest; and so on. This means that specific request types provide additional request information and methods to allow your portlet class to process these specific request types.

 

Tip

As you can see in figure 3.5, the file upload feature is available to both the ActionRequest and ResourceRequest interfaces because of their common superinterface. You’ll usually use ActionRequest to upload a file and ResourceRequest when downloading a file because the action method invocation is followed by a call to a render method, which generates appropriate content (like a success or validation error message) in response to the upload file action.

 

The request information that’s sent to a portlet instance by all request types consists of the portlet mode, window state, portal context, portlet session, and portlet preferences. The additional information that’s passed as part of the request is specific to that request type (event, resource, action, or render).

 

Note

The portlet container is responsible for providing the portlet with objects implementing the RenderRequest, ActionRequest, ResourceRequest, and EventRequest interfaces, depending upon the lifecycle phase of the portlet.

 

We’ll now take a look at some of the interesting constants that are defined in PortletRequest.

3.2.2. PortletRequest constants

PortletRequest defines many constants. In this chapter we’ll discuss the following ones:

  • LIFECYCLE_PHASE, ACTION_PHASE, RENDER_PHASE, RESOURCE_PHASE, EVENT_PHASE—Constants for identifying the current portlet lifecycle phase
  • ACTION_SCOPE_ID—Constant used by the portlet container for locating action-scoped request attributes
  • RENDER_PART, RENDER_HEADER, RENDER_MARKUP—Constants for use by streaming-(and not buffering-) based portals
  • USER_INFO—Constant that identifies the name of the request attribute that contains user attributes information

Let’s now look at what these constants are and how they’re used.

Using the Lifecycle_Phase Constant

The value of the LIFECYCLE_PHASE constant in PortletRequest is the name of the request attribute that identifies the current request-processing phase.

Portlets have four lifecycle phases (action, render, resource, and event phases) identified by PortletRequest interface constants: ACTION_PHASE, RENDER_PHASE, RESOURCE_PHASE, and EVENT_PHASE. The values of these constants are the same as their names. The value of the LIFECYCLE_PHASE constant is the name of the request attribute that contains the current request-processing phase of the portlet. The valid values (we’re not talking about constants now) are ACTION_PHASE, RENDER_PHASE, RESOURCE_PHASE, and EVENT_PHASE.

You’ll probably never need to use the LIFECYCLE_PHASE constant directly in your portlets, unless you’re writing a framework on top of portlets. The LIFECYCLE_PHASE is used by frameworks to cast request and response objects to the appropriate type based on the lifecycle phase.

The following code fragment shows how the LIFECYCLE_PHASE constant is used by frameworks:

if(portletRequest.getAttribute(PortletRequest.LIFECYCLE_PHASE).equals(
      PortletRequest.RENDER_PHASE)) {
    RenderRequest request = (RenderRequest)portletRequest;
    RenderResponse response = (RenderResponse)portletResponse;
    ...
}

In real-world portlets, you’ll probably use a portlet framework, like Spring Portlet MVC (discussed in chapter 7 and 8), to build your portlets. A portlet framework is ideally suited for developing multipage portlets; it’s responsible for casting portlet requests to appropriate request types based on the request lifecycle phase. For instance, in the Spring Portlet MVC framework, if the lifecycle phase is RENDER_PHASE, the preceding code would cast the PortletRequest object to RenderRequest and the PortletResponse object to RenderResponse and then send them to the render method of the handler object.

 

Portlet bridges

If you want to expose an existing web application as a portlet, you’ll need to use a portlet bridge. A portlet bridge is responsible for making your existing web application compatible with the portlet specification. For instance, if you want to expose an existing JavaServer Faces (JSF) application as a portlet, you could do so by using the reference implementation for JSR 301 (Portlet 1.0 Bridge for JSF 1.2) or JSR 329 (Portlet 2.0 Bridge for JSF 1.2) from the MyFaces Portlet Bridge project (http://myfaces.apache.org/portlet-bridge/index.html). Chapter 15 discusses portlet bridges in detail.

 

Using the ACTION_SCOPE_ID Constant

As you saw earlier, action-scoped request attributes (specified using the javax.portlet.actionScopedRequestAttributes container-runtime option) are available in the subsequent render method invocations. The portlet container internally stores the action-scoped request attributes at the end of the action or event lifecycle phase and sets a render parameter with the name javax.portlet.as (which is the value of the PortletRequest interface’s ACTION_SCOPE_ID constant). (Render parameters were discussed more fully in section 2.6.8 of chapter 2.) The value of the javax.portlet.as render parameter is used by the portlet container to obtain the internally stored request attributes and make them available when calling subsequent render methods. In a way, the javax.portlet.as render parameter has container-specific semantics and is used to send a pointer to the internally stored request attributes from the action method to the render method.

You don’t need to work directly with the ACTION_SCOPE_ID constant; I explain it here only so you can understand how the actionScopedRequestAttributes container-runtime option works in portlet containers.

Using the RENDER_PART, RENDER_HEADER, and RENDER_MARKUP Constants

You only need to know about these constants if you’re using a streaming-based portal (Jetspeed, Liferay Portal, and GateIn Portal are buffering portals). Streaming-based portals directly stream portlet content from data sources.

In streaming-based portals, portlet rendering is divided into two different phases, represented by the RENDER_HEADER and RENDER_MARKUP constants. In such portals, a request attribute whose name is the value of the RENDER_PART constant is set by the portal server, and this value identifies the rendering phase (RENDER_HEADER or RENDER_MARKUP). In the RENDER_HEADER render phase, the header and title of the portlet are set, and in the RENDER_MARKUP render phase, the markup of the portlet is set. This rendering behavior of streaming-based portals is like watching a video on a website, where the title and window (in which the video will appear) are rendered before the video.

Using the USER_INFO Constant

There could be many portlet requirements where you need to show user information for the logged-in user. For instance, the Book Catalog portlet shows a greeting, “Hello! <first-name> <last-name>,” inserting the first and last names of the logged-in user, as shown in figure 3.2.

Portal user information is maintained by portal servers in the portal server–specific database, and you probably won’t find enough documentation about the database structure to directly retrieve the user information. You could consider using the portal server APIs to extract the user information from the database, but that would have the downside of making your portlet dependent on the current portal server. If you managed to get the user information by directly accessing the database or using your portal server APIs, your portlet would be unlikely to work if it were migrated from one portal server to another, because it would be tied to that specific portal server API or database. The Portlet 2.0 specification defines a way of retrieving user information in a portal server–agnostic way with user attributes.

User attributes are defined in portlet.xml (using the <user-attribute> elements) and are made available as a request attribute by the portlet container to the portlets. The name of the request attribute is the value of the PortletRequest interface’s USER_INFO constant. Portlets can obtain user attributes from the request and display them in the portlet or use it in processing the request. Chapter 9 (which discusses integration with databases) shows how the Book Catalog portlet uses user attributes to associate a book with the user who added (or updated) it.

 

Code Reference

At this point, you should import the ch3_BookCatalog source code into your Eclipse workspace. That will allow you to follow along with the code referenced in the rest of this chapter.

 

The following listing shows the portlet.xml file for the Book Catalog portlet and demonstrates how user attributes are defined.

Listing 3.1. Defining user attributes in the Book Catalog’s portlet.xml file

The <user-attribute> element is used to define a user attribute. The <user-attribute> element is a subelement of the <portlet-app> element, which implies that user attributes defined in the portlet.xml file are available to all the portlets that form part of the portlet application. The <description> subelement provides a description of the user attribute, and <name> identifies the name of the user attribute that should be made available to the portlet application.

The user attributes defined in the portlet.xml file are available to a portlet as a request attribute; the name of the request attribute is the value of the PortletRequest.USER_INFO constant, and the attribute value is of type java.util.Map. The attribute value contains a map of user attribute name to user attribute value. The following code fragment shows how the BookCatalogPortlet class (from the Book Catalog portlet) obtains the user attribute map from a request:

Map<String, Object> userAttributeMap =
  (Map<String, Object>)request.getAttribute(PortletRequest.USER_INFO)
String firstName = (String)userAttributeMap.get("user.name.given");

 

Code Reference

Refer to the BookCatalogPortlet class’s showBooks render method in ch3_BookCatalog to see how the Book Catalog portlet makes use of user attributes.

 

The question that you might be asking at this point is how the values of the user.name.given and user.name.family attributes were set in the request. A portal server usually has predefined user attributes, the values of which are made available if they are referred to by the <user-attribute> elements of a portlet deployment descriptor. The Portlet 2.0 specification recommends that the names of commonly used user attributes should be made available by portal servers to portlets that have defined them in their portlet deployment descriptors. These recommended user attribute names are defined in the PortletRequest interface’s P3PUserInfos nested class.

 

Note

A portal server (like Liferay Portal or Jetspeed) may also allow you to create custom user attributes. If a portal server allows this and if you migrate a portlet application to another portal server, the portlet application deployer needs to map these custom user attributes to the user attributes available in the new portal server environment.

 

Now let’s take a look at some of the important methods of the PortletRequest interface.

3.2.3. PortletRequest methods

PortletRequest defines methods that are useful for obtaining request parameters, cookies, request attributes, and so on. Most of the methods defined in PortletRequest have similar semantics to the methods defined in the HttpServletRequest interface. Table 3.2 lists some of the interesting methods of the PortletRequest interface.

Table 3.2. Methods defined in the PortletRequest interface

Method

Description

getParameterMap getPrivateParameterMap getPublicParameterMap Portlets make use of public render parameters (explained in chapter 11) that are shared between portlets. PortletRequest provides the getPublicParameterMap method, which returns a Map of the public render parameters, and the getPrivateParameterMap, which returns a Map of the parameters that aren’t shared between portlets. If you want to obtain a Map of all the request parameters, irrespective of whether they’re public or private, you should use the getParameterMap method.
getPortalContext Returns a PortalContext object (discussed later in this chapter) that contains information about the portal server in which the portlet is deployed.
getPreferences Returns a PortletPreferences object (discussed in chapter 10) that contains the user preferences associated with the portlet.
getProperties getProperty Obtain any properties associated with the portlet request. You can add a property to a request using the <property> tag, as described in chapter 6.
getPortletSession Returns the PortletSession associated with the current request (discussed later in this chapter).
getWindowState Returns the WindowState object representing the current window state of the portlet sending the request. (WindowState is discussed in chapter 4.)
isPortletModeAllowed Checks whether a portlet mode is allowed for the current portlet request.
isWindowStateAllowed Checks whether a window state is allowed for the current portlet request.
getPortletMode Returns the PortletMode object (discussed in chapter 4) representing the portlet mode associated with the current request.

The PortletRequest methods defined in table 3.2 are available to specific request types (action, render, event, and resource requests) and will be used extensively in the Book Catalog portlet example. For instance, when the user enters search criteria, the getParameter method is used to retrieve it, the getPortletSession method is used to obtain the PortletSession object to store the search results, and so on.

Table 3.2 mentions that the PortalContext object provides portal server information to the portlet instance. We’ll now see how portlets can use the PortalContext object to customize their request-handling logic for a particular portal server.

3.2.4. Handling portal server–specific requests using PortalContext

The PortalContext object provides portal server information, such as the portal server name, version number, supported window states, supported portlet modes, and any other properties that are set by the portal server. You should use the PortalContext object in the following cases:

  • To customize the portlet’s request-handling logic based on the portal server in which the portlet is deployed. This is similar to customizing the presentation logic in HTML pages, using JavaScript, based on the browser type and version.
  • To check whether the portlet can add custom JavaScript and CSS DOM elements to the head section of a portal page (discussed later in this chapter).
  • To obtain a list of portlet modes supported by the portal server.
  • To obtain a list of window states supported by the portal server.

You can retrieve a PortalContext object using the PortletRequest object’s getPortalContext method. Listing 3.2 shows how the Book Catalog portlet makes use of the PortalContext object (refer to figures 3.2 and 3.3) to customize request-handling logic for the Jetspeed portal server.

Listing 3.2. Using PortalContext to customize request-handling logic

BookCatalogPortlet overrides the GenericPortlet class’s doHeaders method. The doHeaders method is invoked internally by the default implementation of the GenericPortlet class’s render method; you should override doHeaders in your portlet class if you want to set response headers before the content is rendered.

Request handling is customized if the portal server is Jetspeed. The PortletRequest object’s getPortalContext method is used to obtain the PortalContext object, and that object’s getPortalInfo method is used to retrieve the portal server name and version information. The portal server information retrieved via getPortalInfo is then checked to determine whether the portlet is deployed on the Jetspeed portal server. (The value of the Constants.JETSPEED constant used in the code is Jetspeed.) If the portal server is Jetspeed, you can set Jetspeed-specific response headers in the doHeaders method.

The PortalContext object defines getSupportedWindowStates and getSupportedPortletModes methods, which you can use to obtain information about the window states and portlet modes supported by your portal server. You’ll probably never use these methods directly in your portlets, except in situations where you want to discover window states and portlet modes supported by your portal server. For instance, if you retrieve the list of window states supported by Liferay Portal, you’ll find that there are two custom window states: exclusive and pop_up. If you want to use these custom window states, you can explicitly set them in the action response, as shown here:

actionResponse.setWindowState(new WindowState("exclusive"));

You’ve now seen the constants and methods defined by the PortletRequest object and how they can be used by a portlet. You also saw how you can use the PortalContext object to perform portal server–specific request handling.

Once the request is received by the portlet, the portlet is responsible for responding by generating content or performing some action, like updating database tables. Portlets respond to requests by using response objects whose type depends on the life-cycle phase of the portlet. Let’s look at the portlet response objects and how they’re used by the Book Catalog portlet.

3.3. Portlet response objects

The Book Catalog portlet responds to user actions by generating content or updating the data store that contains the catalog. For instance, when you enter search criteria in the Book Catalog portlet, the portlet accesses the data store to find matching books and generates markup showing the books found.

To respond to portlet requests, portlets use response objects. For instance, the Hello World portlet in chapter 1 wrote a “Hello World” response using the PrintWriter object obtained from the RenderResponse object, and the User Registration portlet in chapter 2 generated a response using JSP pages.

The different lifecycle methods in portlets are designed to accept different portlet request and response objects, because each method requires some additional request information and response generation functionality. Like portlet requests, portlet response objects implement a common interface, PortletResponse, as shown in figure 3.6.

Figure 3.6. The RenderResponse, ResourceResponse, ActionResponse, and EventResponse interfaces have a common superinterface, PortletResponse. The subinterfaces define additional fields and methods specific to the response types.

In figure 3.6, PortletResponse represents the base interface for all the response objects used by portlets. Table 3.3 describes the purposes of the various response interfaces in the figure.

Table 3.3. Portlet response types

Response interface

Description

PortletResponse Defines methods that add DOM element properties to the response (see section 3.3.5 of this chapter for example usage), and retrieve the portlet namespace (see chapter 12, which is on creating highly interactive portlets, and the discussion of the <namespace> tag in chapter 6 for examples).
MimeResponse Extends the PortletResponse interface and defines additional methods that create action, resource, and render URLs and that set the content type of the response. MimeResponse also defines constants that are used in expiration-based and validation-based caching (discussed in chapter 4).
RenderResponse Extends the MimeResponse interface and defines additional methods that set the title of the portlet window and that set the possible portlet modes that the portlet can have next.
ResourceResponse Extends the MimeResponse interface and allows portlets to serve resources (such as binary content) to the client. The ResourceResponse interface is different from RenderResponse in the sense that the portal server doesn’t add any additional markup (like window decoration) to the content served by ResourceResponse (see chapter 12 for details).
StateAwareResponse Extends the PortletResponse interface and defines additional methods that set render parameters, events to be published, portlet mode, and window state.
ActionResponse Extends the StateAwareResponse interface and defines additional methods that redirect users to different URLs.
EventResponse Extends the StateAwareResponse interface and defines an additional method that sets the same render parameters in the response that were received by the portlet in the event request (refer to chapter 11 for details).

Table 3.3 describes the various response types in portlets. In portlet methods you’ll only work directly with objects implementing the RenderResponse, ActionResponse, ResourceResponse, and EventResponse interfaces. These objects are made available to portlets by the portlet container.

The PortletResponse interface’s encodeURL method plays an important role in addressing portlet portability issues, and we’ll discuss it next.

3.3.1. Encoding URLs with the encodeURL method

The PortletResponse interface provides an encodeURL method to let portlets encode portal server or portlet container–specific data (like session ID) in the URL. Such URLs can refer to resources like JSPs, servlets, images, and static files (like JavaScript and CSS) in the portlet application.

 

Tip

URLs referring to resources within the portlet application must be encoded to ensure that the portlet application is portable across different portal servers and portlet containers. You don’t need to encode URLs that refer to resources outside the portlet application.

 

The following code snippet shows the encodeURL method in the Book Catalog portlet encoding a URL referring to BookServlet:

  PortletRequestDispatcher dispatcher = request.getPortletSession().
      getPortletContext().getRequestDispatcher(
      response.encodeURL("/myservlet/bookServlet")
);

In this case, the /myservlet/bookServlet URL refers to the BookServlet servlet.

In the preceding code, the /myservlet/bookServlet URL is encoded using the PortletResponse interface’s encodeURL method. The following listing shows how the BookCatalogPortlet class encodes URLs referring to the BookServlet servlet and JavaScript and CSS files.

Listing 3.3. Using encodeURL in the BookCatalogPortlet class

The encodeURL method is used to encode a URL to the bookCatalog.css CSS file. It’s used to encode a URL to the bookCatalog.js JavaScript file . Finally, it’s used to encode a URL to the BookServlet servlet , which resides in the same portlet application as the Book Catalog portlet.

 

Note

Listing 3.3 shows that the BookCatalogPortlet class creates URLs to JavaScript and CSS files. In section 3.3.5, you’ll see the rationale for doing so.

 

Next, let’s look at some of the specific PortletResponse types that help portlets generate content and respond to actions.

3.3.2. Generating content using RenderResponse

Portlets use RenderResponse to write content. It can also be used to set the title of a portlet and the next possible portlet modes.

In the examples that we’ve covered so far, portlet titles were either specified in the portlet deployment descriptor or the portlet resource bundle, but the Book Catalog portlet requires the portlet title to change when the Add Book form is shown to the user (see figure 3.3). This can be done by using the RenderResponse object’s setTitle method, as shown here:

response.setTitle("Book Catalog: Add Book");

If you want to localize the messages based on locale, you can use portlet resource bundles to store the portlet titles and retrieve them programmatically, as shown here:

ResourceBundle bundle = ResourceBundle.getBundle("content.messages",
   request.getLocale());
response.setTitle(bundle.getString("portlet.title.books"));

In this code, content.messages identifies the location of the messages properties file containing the portlet title, response refers to the RenderResponse object, and bundle refers to the resource bundle used by the portlet.

You can programmatically load the portlet resource bundle using the java.util.ResourceBundle class, or you can use the getResourceBundle convenience method of the GenericPortlet class to retrieve the resource bundle configured for the portlet in the portlet deployment descriptor.

 

Note

The setTitle method is defined only in the RenderResponse interface; you can only change the portlet title in the render request-processing phase.

 

The RenderResponse object not only allows you to generate content; its setNextPossiblePortletModes method allows you to set the next possible portlet modes that a portlet can have. Here’s an example:

response.setNextPossiblePortletModes(portletModeList);

In this code line, portletModeList is a list of the next possible portlet modes in which the portlet can be invoked.

The BookCatalogPortlet class retrieves the portlet title from the resource bundle based on the value of the myaction session attribute, as shown in here.

Listing 3.4. Dynamically setting the portlet title in the BookCatalogPortlet class

portlet.title is prepended to the value of the myaction session attribute to create the title key used to store the title in the resource bundle. The value of the myaction session attribute is same as the value of the myaction request parameter received by the BookCatalogPortlet class. The RenderResponse object’s setTitle method is invoked to set the title of the portlet window. The GenericPortlet class’s getResourceBundle convenience method is used to obtain the resource bundle for the Book Catalog portlet.

Let’s now look at how you can respond to an action request by using the ActionResponse object.

3.3.3. Responding to an action using ActionResponse

The ActionResponse object allows portlets to respond to action requests. This response may include redirecting the user to another URL, setting render parameters, or setting the portlet mode or window state.

Let’s say an organization’s portal consists of multiple pages: Welcome, Contact Us, Latest Wins, and Articles, as shown in figure 3.7. The Welcome portal page provides a What’s New portlet that shows a summary of two major projects won by the organization. It also shows a Learn More About Wins link that takes you to the Latest Wins page, which provides detailed descriptions about the projects recently won by the organization. The Latest Wins page can be accessed by several other pages in the portal, so its Go Back button should always take the user back to the page they came from.

Figure 3.7. The What’s New portlet shows two major project wins. The Learn More About Wins link takes you to the Latest Wins portal page.

So far we’ve only looked at creating links with URLs that invoke a portlet’s render and action methods. Because ActionResponse is the only portlet response object with redirection capability, we’ll create the Learn More About Wins link referring to the What’s New portlet’s action URL. When the Learn More About Wins link is clicked, the action method of the What’s New portlet is invoked, allowing the portlet to redirect the user to the Latest Wins page, as shown here:

actionResponse.sendRedirect("/myportal/latestWins?referrer=
http://orgportal.com/myportal/welcome");

In this code, /myportal/latestWins is the full URI to the Latest Wins portal page, and the referrer query parameter refers to the page from which the user came to the Latest Wins portal page.

The http://orgportal.com/myportal/welcome URL in the preceding code line is the absolute URL for the Welcome portal page, and it’s used by the Go Back button to return the user to the referrer (the Welcome page in this case).

That code line also uses the ActionResponse object’s sendRedirect(String location) method to redirect the user to the Latest Wins page. The location argument specifies the full URI or absolute URL to which the user should be redirected.

 

Warning

If you call the ActionResponse object’s setPortletMode, setWindowState, removePublicParameter, setRenderParameter, or setRenderParameters methods before invoking the sendRedirect(String location) method, it will result in an IllegalStateException.

 

ActionResponse also defines a less frequently used sendRedirect(String location, String renderUrlparam) method that additionally appends the render URL of the portlet doing redirection as a query parameter named renderUrlParam.

 

Note

The render URL passed as a query parameter may be of no use if the redirection is outside the portal.

 

In section 2.6.8 of chapter 2, we touched on using render parameters to share information between a portlet’s action method and the following render method. The Book Catalog portlet makes use of the myaction render parameter to communicate view information to the render method, which internally uses BookServlet to render content.

The next listing show the use of render parameters in the Book Catalog portlet.

Listing 3.5. Setting render parameter in the Book Catalog portlet

The showBooks render method is used for VIEW mode in the Book Catalog portlet. The dispatcher.include (request, response) statement in the showBooks method dispatches a render request to the BookServlet servlet to generate content. Though it’s not shown in the above code, the showBooks method retrieves the myaction request parameter and sets it as a request attribute with the same name before dispatching the request to the BookServlet. The BookServlet makes use of the myaction request attribute to determine which JSP page to use for generating content.

The removeBook action method is used to remove a book from the book catalog. The response.setRenderParameter("myaction", "showCatalog") statement sets showCatalog as the value of the myaction render parameter.

The uploadToc action method is used to upload the TOC file for a book. If the TOC file is uploaded successfully, the response.setRenderParameter("myaction", "showCatalog") statement sets the value of the myaction render parameter to showCatalog.

If the TOC file upload fails, the myaction render parameter is set to error, and the exceptionMsg render parameter represents an error message.

In listing 3.5, the showBooks method receives render parameters set by the removeBook and uploadToc action methods as request parameters. As the value of the myaction render parameter is used indirectly by the BookServlet to render the appropriate JSP page, each action method is able to control the view that needs to be rendered after the action request is processed.

3.3.4. Choosing an appropriate phase for an action

Each request-processing phase of a portlet has access to different request and response objects, which lets you perform certain functions in one phase that can’t be performed in other phases. Table 3.4 lists which functions should be performed in which request-processing phases.

Table 3.4. Request-processing phases suited for handling a particular portlet action

Function

Request-processing phase

Set window state and portlet mode Action
Set render parameters Action
Redirect user to a different page Action
Programmatically create render, action, and resource URLs Render
Change window title Action
Add JavaScript and CSS to the portal page Render
Dispatch events to portlets Action
Generate markup content Render
Submit forms Action
Set expiration timestamp Render
Upload files Action
Download files Resource
Send events to other portlets Action or event
Process events Event

 

Tip

As a general rule, you should avoid doing computationally intensive or resource-intensive tasks in the render method (or in the render phase) because it’s called every time a portal page is rendered. Such tasks should be performed in the action method (or in the action phase), because it’s called only when a user interacts with the portlet.

 

A portlet’s content may change in response to a render request if there’s change in the data displayed by the portlet and the expiration time has been reached or a validation token has become invalid. Actions performed by a portlet that are repeatable (with no side effects) and idempotent should be performed in the render phase. The non-repeatable and non-idempotent actions should be performed in the action phase. Examples of non-repeatable or non-idempotent actions are uploading a file, storing data in a PortletSession, and saving data in a data store.

The RenderResponse object can also be used to add <script> and <link> elements (for including JavaScript and CSS respectively) to the HEAD element of the generated markup. We’ll now look at some approaches you can follow to add custom JavaScript and CSS to your portal page, which, in turn, will apply to your portlets on the portal page.

3.3.5. Adding custom JavaScript and CSS files to a portal page

How you add custom JavaScript and CSS to a portal page varies from one portal server to another. You can either use a portal server–specific approach to add them, or you can use the RenderResponse object’s MARKUP_HEAD_ELEMENT, as suggested by the portlet specification.

Let’s first look at how you can use the RenderResponse object’s MARKUP_HEAD_ELEMENT to add custom JavaScript and CSS to your portal page.

Using MARKUP_HEAD_ELEMENT

PortalContext defines a single constant, MARKUP_HEAD_ELEMENT_SUPPORT, that refers to the name of a property in the PortalContext object. A non-null value for the MARKUP_HEAD_ELEMENT_SUPPORT property indicates that the portal server supports adding DOM elements to the head section of the HTML markup that’s sent by the portal server to the browser for rendering. This element is useful when you want to add portlet-specific JavaScript and CSS to the head section of the generated markup so that your portlets can make use of custom CSS and JavaScript functions.

Support for adding DOM elements to the head section of the markup is optional for portal servers. If your portlet application requires JavaScript and CSS, make sure that your portal server provides documentation on how you can introduce your custom JavaScript and CSS files as part of the markup.

Table 3.5 compares MARKUP_HEAD_ELEMENT support in different portal servers on which the Book Catalog portlet will be deployed.

Table 3.5. Comparing MARKUP_HEAD_ELEMENT support in different portal servers

Portal server

Portlet container

MARKUP_HEAD_ELEMENT support

Alternate approaches

Liferay Portal 5.2.3/6.x Default portlet container Not supported You can configure your JavaScript and CSS files in the liferay-portlet.xml file of your portlet.
Jetspeed 2.2 Pluto 2.0.0 Supported  
GlassFish Server v3.0.1 OpenPortal Portlet Container 2.1.2 Supported  

You may be wondering if it’s important to worry about which portal servers allow you to include JavaScript and CSS when you can easily incorporate that content in the <HEAD> tag of the JSPs used by the portlet. It turns out that there’s a restriction on the content generated by portlets; portlets must not generate the following tags as part of their markup content: <head>, <html>, <body>, <title>, <base>, <frame>, and <frameset>. If you use these tags in your markup, there’s no guarantee that your portal page won’t break. You can use the <iframe> tag in portlet markup, but the portal and portlet context isn’t available to content displayed by the <iframe> tag. As you’ll see in chapter 14, the <iframe> tag may be used by a portlet to expose an external web application as a portlet.

Let’s say that you define a <HEAD> tag in your JSP page and include <link> and <script> tags to include custom CSS and JavaScript files. If you have two <HEAD> tags in your HTML markup, it’s not valid HTML markup, and it may not be rendered correctly by some browsers. Some portal servers don’t put any restrictions on these tags in the markup, and others simply ignore them.

You should add <link>, <script>, <meta>, and so on, tags either by adding DOM elements to the head section of the markup, or by using portal server–specific configuration files to configure your JavaScript and CSS files for the portal page. If none of these approaches are supported by your portal server, your last option is to modify the CSS and JavaScript files that are included by the base portal pages of your portal server.

 

Note

The <link> and <meta> tags must be inside the <head> element of the HTML document. The <script> element can also appear in the body of an HTML document, which means it’s possible to use the <script> tag in your JSP page to write JavaScript code specific to your portlet. Using the <script> tag in the JSP page helps you with namespacing JavaScript variables and functions, which we’ll discuss in chapter 6.

 

The following listing shows how the Book Catalog portlet adds <link> and <script> tags to the head section of the markup to include the bookCatalog.css and bookCatalog.js files in the portal page.

Listing 3.6. Adding a <link> element to the head section

The PortalContext object is obtained using the RenderRequest object’s getPortalContext method. The value of the PortalContext.MARKUP_HEAD_ELEMENT_SUPPORT property in PortalContext is checked for a non-null value.

The link DOM element is created using the RenderResponse object’s createElement method and is added to the response. The href, rel, and type attributes of the link element are set using the Element object’s setAttribute method, and the link element is added to the response using the addProperty method. The name of the property must be MimeResponse.MARKUP_HEAD_ELEMENT.

The script DOM element is created and added to the response . The src and type attributes of the script element are set using the Element object’s setAttribute method. The script element is added as a response property using the addProperty method, and the name of the property must be MimeResponse.MARKUP_HEAD_ELEMENT.

The code in listing 3.6 adds <link> and <script> tags to the head section of the markup sent by the portal server to the browser, as shown here:

<head>
  ...
  <link href="/ch3_BookCatalog/css/bookCatalog.css"
    rel="stylesheet" type="text/css">
  <script src="/ch3_BookCatalog/css/bookCatalog.js"
    type="text/javascript">
  ...
</head>

Now that you know how to programmatically create and add DOM elements to the response, the next question is, where should this code that adds these elements be written? If your portlet class extends from GenericPortlet, you should set the response properties in the doHeaders method. The default implementation of doHeaders in the GenericPortlet class does nothing.

 

Note

If you’re using a portlet framework, instead of directly extending GenericPortlet class, you are required to extend the portlet framework’s portlet class. For instance, if you’re using Spring Portlet MVC to develop portlets, you need to extend the DispatcherPortlet class (which in turn extends the GenericPortlet class) and override the doHeaders method, as described in chapter 8.

 

As of Jetspeed 2.2, a call to portalContext.getProperty(PortalContext.MARKUP_HEAD_ELEMENT_SUPPORT) returns null, even though it supports adding DOM elements to the markup’s head section. In this case, you need to make use of the server information returned by getPortalInfo to determine whether the portlet is deployed on Jetspeed or not. If it is, you should create and add DOM elements to the response even if the value of the MARKUP_HEAD_ELEMENT_SUPPORT property is null.

Using Portal Server–Specific Configuration

As table 3.5 indicates, Liferay Portal 5.2.3/6.x doesn’t support adding DOM elements to the head section, but it provides a much simpler alternative. You can use the liferay-portlet.xml file, as shown here:

<liferay-portlet-app>
 <portlet>
  <portlet-name>bookCatalog</portlet-name>
  <instanceable>true</instanceable>
  <header-portlet-css>/css/bookCatalog.css</header-portlet-css>
  <header-portlet-javascript>/js/bookCatalog.js</header-portlet-javascript>
 </portlet>
</liferay-portlet-app>

The liferay-portlet.xml file shown here makes use of <header-portlet-css> and <header-portlet-javascript> to add <link> and <script> tags to the generated markup; those tags in turn include the bookCatalog.css and bookCatalog.js files.

 

Tip

If several of your portlets on the same or different portal pages need to use the same JavaScript file, you can consider including the JavaScript file as part of the portal theme. Because the portal theme applies to all of your portal pages, the JavaScript file will be included by default in all of your portal pages. See section 5.5.2 of chapter 5 for an example Liferay Portal theme that includes a JavaScript file.

 

The lifetime of a portlet request object is limited to the lifecycle method of a portlet. That means that if you store user-specific information in a portlet request, it won’t be available in the next request. If you want to maintain user-specific information across multiple requests, you should use a portlet session.

3.4. Storing user-specific data in a portlet session

Portlet containers provide the PortletSession object so you can store user-specific data across portlet requests. PortletSession is similar to HttpSession, and it provides methods to maintain session attributes, get and set the maximum interval of time for which the session can remain inactive, get PortletContext, and so on. Just as each web application has a unique HttpSession per user, each portlet application has a unique PortletSession per user.

In this section, we’ll look at PortletSession scopes, PortletSession methods, and when to use which scope when developing portlets. We’ll also look at how the Book Catalog portlet makes use of PortletSession scopes and methods to achieve its intended functionality.

3.4.1. PortletSession object and methods

PortletSession is different from HttpSession because PortletSession provides you with two different scopes to store session attributes, identified by the constants APPLICATION_SCOPE and PORTLET_SCOPE in the PortletSession interface. HttpSession doesn’t have the concept of scoped attributes. You should choose an appropriate scope for your session attributes based on your application’s requirements.

If a portlet stores session attributes in PORTLET_SCOPE, the attributes are only available to the same portlet instance (an instance in this paragraph and the following refers to a single occurrence of a portlet in a portal page) and are not shared with other web components (portlets, servlets, and JSPs) in the same portlet application. PORTLET_SCOPE session attributes aren’t even shared between portlet instances if you’re using the same portlet multiple times on the same or different portal pages.

If a portlet stores session attributes in APPLICATION_SCOPE, the attributes are accessible to other web components (portlets, servlets, and JSPs) in the same portlet application and to instances of the same portlet on the same or different portal pages.

The PortletSession interface defines the following methods to set session attributes:

  • setAttribute(String name, Object attribute)—Stores attribute in PORTLET_SCOPE with the name specified.
  • setAttribute(String name, Object attribute, int scope)—Stores attribute in the specified scope with the name specified. The possible values of scope are the PortletSession interface’s APPLICATION_SCOPE and PORTLET_SCOPE constants.

You can retrieve session attributes from PortletSession using following methods:

  • getAttribute(String name)—Retrieves session attribute with the specified name from PORTLET_SCOPE.
  • getAttribute(String name, int scope)—Retrieves session attribute with the specified name from the specified scope.

Now that you know the methods provided by the PortletSession object and the different scopes it supports, let’s look at how the Book Catalog portlet makes use of them.

3.4.2. PortletSession usage in the Book Catalog portlet

In the Book Catalog portlet, the BookCatalogPortlet class stores search criteria in APPLICATION_SCOPE when the user enters the search criteria and clicks the Search button (see figure 3.2). When the user clicks the Refresh Search Results hyperlink, the BookServlet servlet uses HttpSession to retrieve the search criteria stored in APPLICATION_SCOPE.

Listing 3.7 shows code snippets from the BookCatalogPortlet and BookServlet classes to show how the search criteria is stored in PortletSession (by the BookCatalogPortlet class) and retrieved from HttpSession (by the BookServlet class).

Listing 3.7. Sharing session data using PortletSession's APPLICATION_SCOPE

The BookCatalogPortlet class’s searchBook action method is responsible for searching for books when the user clicks the Search button. The search criteria is saved to the PortletSession’s APPLICATION_SCOPE for later use by the BookServlet servlet. The BookServlet’s doGet method creates an instance of BookServiceImpl , passing ServletContext to the constructor, and it obtains the myaction request attribute from the request. The search criteria that was stored in the PortletSession’s APPLICATION_SCOPE at is retrieved using the HttpSession object , and the BookService’s searchBooks method is responsible for finding books matching the search criteria.

Listing 3.7 illustrates a couple of interesting points in the design of the Book Catalog portlet:

  • BookCatalogPortlet portlet class delegates most method calls to the BookServlet servlet, including render and action requests.
  • The myaction request attribute is used by BookServlet to identify the action to be performed, which may be rendering a JSP page or processing an action (like searching for books).
  • The ServletContext object is passed to the BookService object at creation time because ServletContext holds the book catalog information.

In some scenarios, you may want to access attributes stored in PORTLET_SESSION scope from other web components, such as servlets and JSPs. To do this, you can use the PortletSessionUtil class.

3.4.3. Obtaining session attributes using PortletSessionUtil

In the Book Catalog portlet, BookServlet accesses the search criteria stored in the PortletSession’s APPLICATION_SCOPE using HttpSession.

In scenarios where servlets and JSPs included by your portlet need to access the PORTLET_SCOPE session attributes, you should use the PortletSessionUtil class, because, behind the scenes, the session attributes added to PORTLET_SCOPE are added to APPLICATION_SCOPE with a fabricated (or encoded) name, which makes them accessible to included JSPs and servlets.

The use of PORTLET_SCOPE and APPLICATION_SCOPE gives the impression that the session attributes are stored in two differently scoped containers, with the APPLICATION_SCOPE scoped container being accessible to other web components in the portlet application. In reality, when you add a session attribute to PORTLET_SCOPE, what happens is that the portlet container stores the attribute in APPLICATION_SCOPE with a fabricated (or encoded) name. The fabricated name for the PORTLET_SCOPE session attributes follows this format:

javax.portlet.p. <window_id>?<attribute_name>

Here, window_id is the window ID (an identifier assigned to a portlet instance by the portal server to uniquely identify it in the web portal) obtained by using the PortletRequest’s getWindowID method. attribute_name is the name of the attribute specified in the PortletSession’s setAttribute method.

Let’s say you set your PORTLET_SCOPE session attribute using the following code:

portletSession.setAttribute("myAttr", myAttr);

Assuming that the PortletRequest’s getWindowID method returns the window ID as XX, the session attribute would be stored in the APPLICATION_SCOPE with this name:

javax.portlet.p.XX?myAttr

If you want to retrieve the PORTLET_SCOPE session attributes stored by a portlet in other portlets, servlets, or JSPs of the same portlet application, you need to programmatically construct the name used to store the PORTLET_SCOPE session attribute in the APPLICATION_SCOPE. This is where PortletSessionUtil class comes into the picture. It lets you decode the name and scope of an attribute based on its encoded (or fabricated) name.

For instance, the following piece of code can be used in a servlet that’s part of the same portlet application to obtain a PORTLET_SCOPE session attribute:

session.getAttribute(
  PortletSessionUtil.decodeAttributeName(<encoded_attr_name>)
);

Here, encoded_attr_name refers to the encoded (fabricated) name of the attribute (which has the format javax.portlet.p.XX?myAttr, with XX being the window ID) in the APPLICATION_SCOPE.

In the preceding code, you need to know the encoded attribute name to obtain it using the PortletSessionUtil class, but you won’t know the encoded name in a JSP or servlet component. To obtain a PORTLET_SCOPE portlet session attribute in your JSP or servlet, you need to iterate over the session attribute names, which are obtained by calling the HttpSession’s getAttributeNames() method and decoding each attribute name to find a match for the attribute. For instance, the following listing shows a servlet that looks for the myAttr attribute in PORTLET_SCOPE.

Listing 3.8. An example of using PortletSessionUtil

The PortletSessionUtil’s decodeAttributeName method is used on the attribute name obtained from HttpSession. You check whether the decoded name of the attribute is myAttr . If it is, you use the PortletSessionUtil’s decodeScope method to check whether the attribute belongs to PORTLET_SCOPE or not.

If the decoded name of the attribute is myAttr and it belongs to PORTLET_SCOPE, it’s the myAttr attribute you want. It’s important to check whether the attribute belongs to PORTLET_SCOPE because the decodeAttributeName method in listing 3.8 checks both PORTLET_SCOPE and APPLICATION_SCOPE PortletSession attributes. If you have an attribute named myAttr in APPLICATION_SCOPE, the PortletSessionUtil’s decodeAttributeName method will return myAttr as its decoded name because decodeAttributeName returns the name of an APPLICATION_SCOPE attribute unchanged. If you don’t check the scope, you could end up with a wrong match.

You’ve seen how different portlet session scopes are used, so let’s take an in-depth look at their differences and the things that you need to take care of while storing data in a portlet session.

3.4.4. An in-depth look at portlet session scopes

Figure 3.8 summarizes the concept of PORTLET_SCOPE and APPLICATION_SCOPE in the PortletSession.

Figure 3.8. The HttpSession can access PortletSession attributes, which are stored with fabricated names in PORTLET_SCOPE. It can also access PortletSession attributes stored in APPLICATION_SCOPE using the names under which they were stored.

The portlet sets a session attribute named portletAttr in PORTLET_SCOPE. The attribute is stored in the APPLICATION_SCOPE with a fabricated name. The included or forwarded servlet or JSP component tries to retrieve the portletAttr attribute from the HttpSession (which looks for session attributes stored in APPLICATION_SCOPE), but it can’t retrieve the session attribute because portletAttr is stored with a fabricated name. The portlet stores a session attribute named appAttr in APPLICATION_SCOPE , so it’s stored with the same name as was specified by the portlet. The included or forwarded servlet or JSP component successfully retrieves the appAttr attribute from HttpSession.

The use of the window ID in the fabricated name of the PORTLET_SCOPE session attribute plays an important role in ensuring that PORTLET_SCOPE session attributes are easily accessible only to included or forwarded servlets or JSPs, and not to every servlet or JSP in the portlet application. The included or forwarded JSPs or servlets have access to the window ID of the portlet invoking them, making it easy for the JSP or servlet to access PORTLET_SCOPE attributes using the PortletSessionUtil class. If you have two instances of the same portlet on a portal page, the unique window IDs of the two portlets help differentiate between PORTLET_SCOPE session attributes set by those portlets.

 

Warning

Because both PORTLET_SCOPE and APPLICATION_SCOPE session attributes are accessible to other web components in a portlet application, you should synchronize access to session attributes by methods that intend to modify them. It’s best to avoid setting session attributes during the portlet’s render phase because the render phase isn’t meant to modify the state of the application, and it should be repeatable with no side effects.

 

Let’s now look at how the portlet session comes in handy if you don’t want to use the caching strategy provided by the portlet container, or if your portlet container doesn’t support caching.

3.4.5. Portlet session and content caching

In some situations, you may have no other option than to set session attributes in the render phase. Suppose you’ve developed a portlet that reads information from the database during its render phase. If the information retrieved from the database rarely changes, it might be preferable to use an expiration-based or validation-based caching strategy (discussed in chapter 4) to let the portlet container cache the portlet content and redisplay it without calling the portlet’s render method. Support for caching is an optional feature for portlet containers; if your portal server doesn’t support caching, the portlet’s render method will be called every time to retrieve information from the database, affecting the load time of the portal page.

If your target portlet container doesn’t support content caching, and you still want to use a caching mechanism to reduce the load time of the portal page, you can load data from the database and store it in a PortletSession to avoid round trips to the database in the render phase. If you don’t want to overload your sessions by storing application data in them, you can consider caching data using a caching library like Ehcache.

 

Warning

You shouldn’t store huge amounts of application data in the PortletSession because if your portlet application is deployed in a clustered environment, the session replication requires your sessions to have small memory footprints.

 

You’ve now seen the differences between PortletSession and HttpSession. There are also many similarities between the two session types that make it possible for portlets to reuse some HttpSession listeners for PortletSession.

3.4.6. Similarities between HttpSession and PortletSession

The portlet specification mandates that if you store an attribute in PortletSession, it must be accessible to HttpSession, and vice versa. The specification also requires that the portlet container must invalidate the PortletSession if HttpSession is invalidated by the web container, and vice versa.

Because both HttpSession and PortletSession mirror stored attributes and follow the same lifecycle, you can use the following HttpSession-related listeners for PortletSession too: HttpSessionAttributeListener, HttpSessionBindingListener, and HttpSessionActivationListener.

PortletSession attributes aren’t shared by all the portlets deployed on a portal server. The PortletSession attributes are accessible only to portlets (and to included or forwarded JSPs and servlets) that form part of the same portlet application, as described next.

3.4.7. Sharing session data across portlet applications

We briefly discussed portlet applications in chapter 1, but we didn’t cover the impact of having portlets in different portlet applications. A portlet application is packaged like any other web application; you create a WAR file consisting of portlets, servlets, and JSPs. If portlets belong to different WAR files, they’re parts of different portlet applications and they won’t share PortletSession attributes. This is true even for two portlets on a single portal page.

 

Note

In chapter 11, you’ll see how PortletSession can also be used to achieve inter-portlet communication.

 

You saw the PortletContext and PortletConfig objects used in the User Registration example in chapter 2. Let’s take a more comprehensive look at these objects.

3.5. Discovering the portlet environment using PortletContext

PortletContext provides portlets with access to its environment, which includes the portlet application and the portlet container. Each portlet application has its own unique PortletContext; if you have portlets in different portlet applications, they don’t share attributes set in the PortletContext. You saw earlier that you can use PortletContext to obtain a PortletRequestDispatcher to generate portlet content by including or forwarding portlet requests to a JSP page using the PortletRequestDispatcher object’s getRequestDispatcher method. In this section, we’ll look at some of the important methods of the PortletContext interface.

Table 3.6 describes some of the important PortletContext methods.

Table 3.6. Important PortletContext methods

Method

Description

getAttribute, setAttribute, removeAttribute Get, set, and remove context attributes. The context attributes that are available to portlets through PortletContext are also accessible to JSPs and servlets (that form part of the same portlet application) through ServletContext, and vice versa.
getInitParameter Obtains the context initialization parameters. Context initialization parameters are different from portlet initialization parameters in the sense that they’re available to all portlets in the same portlet application. Context initialization parameters are specified in web.xml using the contextparam element.
getContainerRuntimeOptions Returns an enumeration of portlet container-runtime options supported by the portlet container. The return type is Enumeration<String>.
getNamedDispatcher Accepts the servlet name to which the returned RequestDispatcher refers.
getMimeType Accepts a filename as an argument and returns its MIME type (such as text/html and application/pdf).

A portlet application is also a web application, and like any web application it has a ServletContext. Like HttpSession and PortletSession, PortletContext and ServletContext mirror attributes stored in the context and they follow the same lifecycle. If you store an attribute in PortletContext, it’s available to ServletContext, and vice versa. If the ServletContext is destroyed by the servlet container, the PortletContext is also destroyed by the portlet container. Because PortletContext mirrors the ServletContext attributes and follows the same lifecycle, you can use the following ServletContext listeners for your PortletContext: ServletContextListener and ServletContextAttributeListener.

 

Code Reference

The book catalog data is accessed by the BookCatalogPortlet class as well as the BookService class. Because any attribute stored in ServletContext is accessible to portlets using PortletContext, the Book Catalog portlet uses BookCatalogContextListener (a ServletContextListener configured in the web.xml file) to store book catalog data in ServletContext with an attribute named bookCatalog. The BookCatalogPortlet class’s showBooks method obtains the bookCatalog attribute using the PortletContext object, and BookService obtains it using ServletContext.

 

PortletContext provides information at the portlet application level. If you want to obtain portlet information for a specific portlet, you should use the PortletConfig object.

3.6. Retrieving portlet configuration using PortletConfig

The PortletConfig object provides portlets with the portlet configuration information specified within its <portlet> element in the portlet deployment descriptor. This portlet configuration information includes the supported container-runtime options, initialization parameters, resource bundles, public render parameter names, and so on.

Table 3.7 lists some of the important methods defined by the PortletConfig interface.

Table 3.7. Important PortletConfig methods

Method

Description

getContainerRuntimeOptions Returns the portlet container-runtime options supported by the container and their corresponding settings for the portlet. Return type is Map<String[ ]>.
getSupportedLocales Returns the locales supported by the portlet. You specify supported locales using the <supported-locale> element.
getInitParameter(String name) Returns the value of the initialization parameter.
getPortletContext Returns the PortletContext object of the portlet application that contains the portlet.
getPortletName Returns the name of the portlet.

Table 3.7 shows that PortletConfig defines the getContainerRuntimeOptions method, which isn’t the same as the PortletContext’s getContainerRuntimeOptions method, as is evident from the difference in the return types of the two methods. In chapter 11, we’ll discuss additional PortletConfig methods related to obtaining supported public render parameters, events that a portlet can dispatch, and events that a portlet can receive or process.

 

Code Reference

The BookCatalogPortlet uses the GenericPortlet class’s getInitParameter method to obtain the uploadFolder initialization parameter (which identifies the folder on the portal server where the uploaded book TOCs are stored). If you create your portlet class by directly implementing the Portlet interface, you’ll need to use the PortletConfig object in your code to obtain the portlet initialization parameter.

 

Now let’s look at the container-runtime options that can ease your development efforts by providing additional runtime features to your portlets. We’ll also look at how the Book Catalog portlet can make use of the actionScopedRequestAttributes’ container-runtime option to simplify portlet development.

3.7. Container-runtime options

You saw the javax.portlet.actionScopedRequestAttributes (actionScopedRequestAttributes, for short) option in chapter 2, in the context of the User Registration portlet. This section covers that option in more detail, and also the remaining container-runtime options that may be supported by your portlet container. We’ll spend a little more time discussing actionScopedRequestAttributes because it’s the most often used container-runtime option, and it’s more complex to understand than the others. Because container-runtime options can be defined for a portlet or for the complete portlet application, we’ll wrap this section up by looking at configuring portlet- and portlet application–level container-runtime options in the portlet deployment descriptor.

The container-runtime options defined by the Portlet 2.0 specification are outlined in table 3.8.

Table 3.8. Portlet container-runtime options

Container-runtime option

Description

actionScopedRequestAttributes If set to true, the request attributes set in the action, event, or resource requests are available until the next action request is sent to the portlet. The default is false.
escapeXml If set to true, the URL generated by the tag library is XML-escaped. If set to false, the URL isn’t XML-escaped. The default is true.
renderHeaders If set to true, portlets can write headers in the render phase.
servletDefaultSessionScope If set to true, the session attributes stored by portlets in their PORTLET_SCOPE are available to included or forwarded JSPs or servlets. The default is false.

Before we discuss the portlet container-runtime options defined in table 3.8, let’s take a look at what the PortletContext’s getContainerRuntimeOptions method returns for the portal servers on which we want to deploy the Book Catalog example portlet. Table 3.9 shows the container-runtime options supported by different portal servers.

Table 3.9. Container-runtime options support in different portal servers

Portal server

Supported container-runtime options (obtained by using the PortletContext's getContainerRuntimeOptions method)

Liferay Portal 6.x/5.2.3 Returns null, which means Liferay Portal 6.x/5.2.3 doesn’t support any container-runtime options, including actionScopedRequestAttributes. We’ll see shortly that Liferay Portal 5.2.3/6.x does provide a feature similar to actionScopedRequestAttributes.
Jetspeed 2.2 Returns escapeXML and javax.portlet.servletDefaultSessionScope.
GlassFish Server (with Open-Portal portlet container 2.1.2) Returns javax.portlet.actionScopedRequestAttributes and javax.portlet.escapeXml.

 

Tip

While developing your portlet applications, if you plan to use any of the portlet container-runtime options, make sure either that the options are supported by all the target portlet containers or that there is some workaround available to ensure that the portlet application works as expected. There are normally workarounds available for portlet container-runtime options to help you develop portlets with or without container-runtime options.

 

Let’s look at the various container-runtime options in detail.

3.7.1. Using actionScopedRequestAttributes

The javax.portlet.actionScopedRequestAttributes is the most important container-runtime option and supporting it is mandatory for Portlet 2.0 containers. It ensures that the request attributes set in the action request are available to the subsequent render, resource, and event requests, until a new action request is sent to the portlet instance. In the User Registration portlet in chapter 2, you used actionScopedRequestAttributes to allow request attributes set in the ActionRequest to be available in the subsequent RenderRequest.

Table 3.9 shows that Liferay Portal 6.x doesn’t support the actionScopedRequestAttributes option, so you might wonder why the actionScopedRequestAttributes container-runtime option was specified for the User Registration portlet. The reason was to ensure that the portlet works on other portlet containers that do support the actionScopedRequestAttributes container option.

You might also wonder how the User Registration portlet retrieved request attributes set in ActionRequest from RenderRequest, given that Liferay Portal 6.x doesn’t support the actionScopedRequestAttributes option. The portlet container in Liferay Portal 5.2.3/6.x allows request attributes set in ActionRequest to be available to the following RenderRequest only, and then they’re gone; it’s a one-time thing. Also note that the request attributes aren’t available to subsequent render, event, and resource requests. Subsequent requests aren’t part of the current portlet request.

Figure 3.9 shows a sequence diagram with multiple requests being dispatched to a portlet. Let’s compare the behavior of a portlet when it’s deployed on Liferay Portal 6.x, Jetspeed 2.2, and GlassFish Server 3.0.1 (with OpenPortal Portlet Container 2.1.2).

Figure 3.9. A series of action and render requests is sent to a portlet to demonstrate the behavior of the portlet on different portal servers: Liferay Portal 5.2.3/6.x, Jetspeed 2.2, and GlassFish Server (with OpenPortal Portlet Container 2.1.2).

An action request is sent to the portlet. The portlet sets a request attribute named “x” in the ActionRequest object . The render request is called on the portlet by the portlet container because, in the portlet lifecycle, an action request is always followed by a render request. The portlet attempts to get the value of the “x” attribute from RenderRequest. A render request is sent to the portlet, which attempts to get the value of the “x” attribute from RenderRequest . An action request is sent to the portlet , which attempts to get the value of attribute “x” from RenderRequest .

Table 3.10 shows what happens when you try to retrieve the value of request attribute “x” at , , and for different portal servers. We’ll assume that the actionScopedRequestAttributes container-runtime option is enabled for the portlet in the portlet deployment descriptor.

Table 3.10. Availability of request attribute “x” (from figure 3.9) on different portal servers

Portal server

Request attribute “x” available?

Liferay Portal 5.2.3/6.x At : Yes
  At : No
  At : No
Jetspeed 2.2 At : No
  At : No
  At : No
GlassFish Server v3.0.1 (with OpenPortal Portlet Container 2.1.2) At : Yes
  At : Yes
  At : No

From table 3.10, we can conclude the following about the behavior of the portal servers:

  • Jetspeed doesn’t support the actionScopedRequestAttributes option, so request attributes set in the ActionRequest aren’t available in the following RenderRequest.
  • GlassFish Server v3.0.1 (with OpenPortal Portlet Container 2.1.2) supports the actionScopedRequestAttributes option, so request attributes set in ActionRequest are available in the following and subsequent RenderRequests.
  • Liferay Portal 5.2.3/6.x doesn’t support the actionScopedRequestAttributes option, but it allows request attributes set in ActionRequest to be available in the following RenderRequest, but not in subsequent RenderRequests.

If you’re only looking to make your ActionRequest’s attributes available to the following RenderRequest, you can consider setting the request attribute as a render parameter in the ActionResponse. As was mentioned in chapter 2, render parameters only allow you to pass String objects and can’t be used for passing complex objects to the following render request. If your container doesn’t support the actionScopedRequestAttributes option (as in the case of Jetspeed 2.2), and you need to pass complex objects to the following render method, you should consider using the PortletSession to hold the attributes.

If your application requirement is to share the request attributes (String type or complex objects) with subsequent render, event, and resource requests, and your portlet container doesn’t support the actionScopedRequestAttributes option (as in the case of Liferay Portal 5.2.3/6.x and Jetspeed 2.2), you should consider storing the attributes in the PortletSession.

 

Warning

Attributes stored in the PortletSession are accessible to other web components, and you could have problems if they’re modified accidentally. Also, if the user opens the portal page that contains the portlet in multiple browser windows, any change in PortletSession is reflected in the portlet in all browser windows.

 

Scope of Action-Scoped Request Attributes

The scope of action-scoped request attributes lies between two subsequent action requests. The starting point of the scope is when an action request is received for a portlet by the portlet container, and the scope ends when another action request is received by the portlet container for the same portlet. The attributes added to the portlet request (ActionRequest, EventRequest, ResourceRequest, and RenderRequest) from the beginning of scope, until it ends, are available to all of the lifecycle methods of the portlet.

You may also specify a numberOfCachedScopes value for actionScopedRequestAttributes, which specifies that the portlet container should cache action-scoped request attributes. Caching action-scoped request attributes is useful when users navigate in a portal using the Back and Forward browser buttons. The action-scoped attributes in the cache additionally record whether the render method following the action method was invoked or not. That means that if the user presses the browser’s Back button and then attempts to invoke the action method (for example, by submitting a form) the portlet container checks whether the render method following the action method was previously invoked or not. If it was, the portlet container simply invokes the render method. If the render method wasn’t invoked previously, the action method is invoked, followed by the render method. This results in a consistent user experience even when the user moves backward and forward using the browser buttons.

Use Case for Actionscopedrequestattributes

In the Book Catalog portlet, the Refresh Search Results hyperlink refreshes the search results. Let’s look at how this feature is usually implemented in web applications: Usually, the search criterion is cached in the session when the search is first made by clicking the Search button. When the user clicks the Refresh Search Results link, the search is executed again to get fresh results from the database.

This approach can also be used by the Book Catalog portlet for searching, as follows:

1.  The user clicks the Search button, and the book and author name search criteria is sent to an action method of the portlet. The action method stores the book and author name criteria in the PortletSession.

2.  The portlet’s render method retrieves the search criteria from PortletSession and executes the search function to obtain the results from the database. The render method then generates the necessary markup by dispatching the request to a JSP page or servlet.

3.  When the user clicks the Refresh Search Results link, it sends a render request to the Book Catalog portlet. The render method obtains the search criteria from the PortletSession and executes the search function, as in step 2.

The problem with the preceding approach is storing data in the PortletSession—the portlet developer is responsible for removing the search criteria from the PortletSession when it’s no longer required. For instance, when the user clicks the Add Book button and goes to the Add Book form, the search criteria doesn’t need to be maintained in the PortletSession. If the preceding approach is followed for a multipage portlet, the PortletSession becomes heavy as the user accesses portlet functionality on different portlet pages. A heavy portlet session can cause problems when it comes to migrating or replicating sessions in a clustered environment, impacting the performance of your web portal.

In contrast, the actionScopedRequestAttributes option makes it easy to share data between an action request and the subsequent render, resource, and event requests by letting the portlet container take care of making request attributes available to subsequent requests, and cleaning them up when a new action request is received for the portlet. The following steps show how the Book Catalog portlet will function if the actionScopedRequestAttributes option is used:

1.  The user clicks the Search button, and the book and author name search criteria are sent to an action method of the portlet. The action method stores the book and author name criteria in ActionRequest.

2.  The portlet’s render method retrieves the search criteria from RenderRequest and executes the search function to obtain results from the database. The render method then generates the necessary markup by dispatching the request to a JSP page or servlet.

3.  When the user clicks the Refresh Search Results link, it sends a render request to the Book Catalog portlet. The render method obtains the search criteria from RenderRequest and executes the search function, as in step 2.

In the preceding steps, you’re no longer dealing with the PortletSession because the portlet container takes care of making request attributes (set in the action request) available to subsequent render requests.

Using the actionScopedRequestAttributes container-runtime option isn’t a silver bullet solution for sharing data between portlet requests. You may find yourself in situations where using this approach may cause problems. For instance, in the Book Catalog portlet, the FULL SCREEN link (see figure 3.2) sends an action request to the portlet to show the portlet in maximized window state. In the preceding steps, if a user clicks the FULL SCREEN link after step 2, it will wipe out the search criteria set in the ActionRequest in step 1. Then, if the user clicks the Refresh Search Results link, the previous search criteria won’t be available to the render request.

 

Tip

Consider using actionScopedRequestAttribute in your portlet in combination with PortletSession to hold data that’s required across portlet requests. PortletSession keeps data that spans multiple action requests, and actionScopedRequestAttribute mandates that the portlet container keep data between two consecutive action requests. For instance, the search criteria in the Book Catalog portlet spans multiple action requests, so it should be stored in PortletSession. You should, by default, enable the actionScopedRequestAttributes option for your portlets and specify an appropriate default value for numberOfCachedScopes for it. Don’t set a high value for numberOfCachedScopes, because caching action-scoped request attributes will require the portlet container to use more memory and resources to maintain the cache.

 

3.7.2. Using servletDefaultSessionScope

You saw in figure 3.8 and listing 3.7 that, by default, HttpSession retrieves and stores attributes in the PortletSession’s APPLICATION_SCOPE. If you want your included or forwarded JSPs and servlets to retrieve and set attributes in the PortletSession’s PORTLET_SCOPE, you should use the servletDefaultSessionScope container-runtime option.

The following XML fragment shows how you can specify the servletDefaultSessionScope container-runtime option in the portlet deployment descriptor:

<container-runtime-option>
  <name>javax.portlet.servletDefaultSessionScope</name>
  <value>PORTLET_SCOPE</value>
</container-runtime-option>

In the preceding definition, the value of the <value> element specifies the PortletSession’s PORTLET_SCOPE scope within which the included or forwarded JSP or servlet should look for or store session attributes. The default value of the <value> element is APPLICATION_SCOPE, which means that the included or forwarded JSP or servlet should look for or store session attributes in the PortletSession’s APPLICATION_SCOPE.

Table 3.9 shows that the servletDefaultSessionScope option is supported by Jetspeed and not by Liferay Portal 5.2.3/6.x and GlassFish Server (with OpenPortal Portlet Container 2.1.2). If you want to test this container-runtime option, you can do it on the Jetspeed portal server. Figure 3.10 is a modified version of figure 3.8, showing what happens when your portlet or portlet application makes use of the servletDefaultSessionScope portlet container-runtime option.

Figure 3.10. The servletDefaultSessionScope container-runtime option allows included or forwarded JSPs or servlets to set or retrieve attributes directly to and from the PortletSession’s PORTLET_SCOPE. The APPLICATION_SCOPE session attributes are no longer accessible to included or forwarded servlets and JSPs.

The portlet sets an attribute named portletAttr in the PortletSession’s PORTLET_SCOPE. The portlet sets an attribute named appAttr in the PortletSession’s APPLICATION_SCOPE. The included or forwarded servlet or JSP fails to retrieve the appAttr session attribute because HttpSession looks for attributes in PORTLET_SCOPE and not in APPLICATION_SCOPE when the servletDefaultSessionScope container-runtime option is set to PORTLET_SCOPE. The included or forwarded servlet or JSP successfully retrieves the portletAttr session attribute from HttpSession.

Figure 3.10 shows that the HttpSession looks for session attributes in PORTLET_SCOPE when the servletDefaultSessionScope container-runtime option is set to PORTLET_SCOPE. So how can you retrieve an APPLICATION_SCOPE session attribute from HttpSession? Well, you can’t access APPLICATION_SCOPE session attributes any longer, because the HttpSession is now completely focused on the session attributes in the PortletSession’s PORTLET_SCOPE. This means that if you want to share session attributes stored in the PortletSession’s APPLICATION_SCOPE with included or forwarded servlets and JSPs, you must not set the value of the servletDefaultSessionScope container-runtime option to PORTLET_SCOPE.

3.7.3. Using escapeXml

Escaping XML refers to converting special characters, like &, >, <, and so on, into character entity codes, like &amp;, &gt;, &lt;, and so on. If a portlet relies on a URL generated by the portlet tag library (discussed in chapter 6) that isn’t XML-escaped, you should set this container-runtime option to false. In the Portlet 2.0 specification, all URLs generated by the portlet tag library are XML-escaped by default.

 

Escaping XML in Portlet 1.0

Portlet 1.0 didn’t specify whether the portlet URLs generated by the portlet tag library tags (actionURL and renderURL) are XML-escaped or not. This lack of clarity resulted in mixed implementations of this feature: some portlet containers escaped XML and some didn’t. Because some portlet developers assumed in their implementations that portlet URLs aren’t XML-escaped, the escapeXml attribute and javax.portlet.escapeXml container-runtime option were introduced in portlet 2.0 to clarify that the portlet container must generate XML-escaped portlet URLs or not, depending upon the values of escapeXml and javax.portlet.escapeXml. If you have a portlet that was developed assuming that portlet URLs aren’t XML-escaped (during the Portlet 1.0 days), you can still use the portlet with Portlet 2.0–compliant portlet containers by setting the javax.portlet.escapeXml container-runtime option to false.

 

3.7.4. Using renderHeaders

The renderHeaders container-runtime option is meant for streaming portals, where content is streamed, and not for buffering portals, where content is buffered. We’re mainly talking about buffering portals in this book, so this container-runtime option isn’t covered.

3.7.5. Specifying Portlet and Portlet application container-runtime options

Portlet container-runtime options can be specified at the portlet- or portlet application–level or both. Keep your portlet requirements in mind as you decide whether the container-runtime option should apply to all portlets in the portlet application or only to specific portlets. For instance, if one of your portlets has form functionality, you’ll probably want to implement the portlet with the actionScopedRequestAttribute container-runtime option enabled, to simplify development.

 

Tip

Portlet runtime options add overhead on the portlet container, which can result in reduced performance. If a portlet can function without a container-runtime option, it’s better not to enable the option for that portlet.

 

This listing shows how you can specify container-runtime options at portlet and portlet application levels.

Listing 3.9. Container-runtime options in the portlet.xml file

The userRegistration portlet is defined , and it doesn’t specify any portlet-specific container-runtime options. The bookCatalog portlet is defined , specifying the portlet-specific actionScopedRequestAttributes container-runtime option. The actionScopedRequestAttributes container-runtime option is set to false for the bookCatalog portlet. The actionScopedRequestAttributes container-runtime option is specified for the portlet application (for all the portlets in the portlet application).

 

Code Reference

Refer to the Book Catalog portlet’s portlet.xml file, which specifies the actionScopedRequestAttributes container-runtime option at the portlet application level.

 

Portlets that don’t define container-runtime options inherit any such options defined at the portlet application level. For instance, the userRegistration portlet in listing 3.9 inherits the actionScopedRequestAttributes option defined at the portlet application level, so the value of the actionScopedRequestAttributes option is true for the userRegistration portlet.

A portlet may also override the container-runtime options set for the portlet application by redefining the container-runtime options in its definition. The bookCatalog portlet in listing 3.9 overrides the actionScopedRequestAttributes option by redefining it and setting its value to false.

3.8. Summary

This chapter discussed the Portlet 2.0 API in the context of the Book Catalog portlet. We’ll continue building the Book Catalog portlet in the next chapter and use it to create a sample Book Portal in chapter 5.

In this chapter, you saw the importance of having a detailed understanding of the portal servers on which your portlet application will be deployed. Portal servers are currently moving to the Portlet 2.0 API, and it’s important to consider their limitations, their specific features, and also their open bugs when you decide on an approach to make your portlets work across different portal servers.

In the next chapter, we’ll continue to explore the Portlet 2.0 API, and we’ll discuss an approach to designing portlets that use portal server–specific APIs and still need to be portable across different portal servers.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.139.105.159