Portlet API
Contents
- Overview
- Portlet concepts
- Elements of the Portlet API
- Core objects
- Listeners
- Configuration objects
- Miscellaneous objects
- Portlet events
- PortletService
- Deployment descriptors
Overview
Portlets are reusable components that provide access to Web-based content, applications, and other resources. Web pages, web services, applications, and syndicated content feeds can be accessed through portlets. Companies can create their own portlets or select portlets from a catalog of third-party portlets. Portlets are intended to be assembled into a larger portal page, with multiple instances of the same portlet displaying different data for each user.
From a user's perspective, a portlet is a window on a portal site that provides a specific service or information, for example, a calendar or news feed. From an application development perspective, portlets are pluggable modules that are designed to run inside a portlet container of a portal server.
The portlet container provides a runtime environment in which portlets are instantiated, used, and finally destroyed. Portlets rely on the portal infrastructure to access user profile information, participate in window and action events, communicate with other portlets, access remote content, lookup credentials, and to store persistent data. The Portlet API provides standard interfaces for these functions. The portlet container is not a stand-alone container like the servlet container. Instead, it is implemented as a thin layer on top of the servlet container and reuses the functionality provided by the servlet container.
IBM is working with other companies to standardize the Portlet API, making portlets interoperable between portal servers that implement the specification.
Portlets and the Servlet API
The abstract Portlet class is the central abstraction of the Portlet API. The Portlet class extends HTTPServlet, of the Servlet API. All portlets extend this abstract class indirectly, and inherit from HttpServlet, as shown:
... +--javax.servlet.http.HttpServlet | +--org.apache.jetspeed.portlet.Portlet | +--org.apache.jetspeed.portlet.PortletAdapter | +--com.myCompany.myApplication.myPortletTherefore, portlets are a special type of servlet, with properties that allow them to easily plug into and run in the portal server. Unlike servlets, portlets cannot send redirects or errors to browsers directly, forward requests, or write arbitrary markup to the output stream. The portlet container relies on the J2EE architecture implemented by WebSphere Application Server. As a result, portlets are packaged similar to J2EE Web applications and are deployed like servlets.
Generally, portlets are administered more dynamically than servlets. The following updates can be applied without having to start and restart the portal server:
- Portlet applications consisting of several portlets can be installed and removed using the portal administration user interface.
- The settings of a portlet can be changed by an administrator with appropriate access rights
- Portlets can be created and deleted dynamically by administration portlets. For example, the clipping portlet can be used to create new portlet instances whenever an administrator creates a new clipping.
The portlet container relies on the J2EE architecture implemented by WebSphere Application Server. As a result, portlets are packaged in WAR files similar to J2EE Web applications and are deployed like servlets. Like other servlets, a portlet is defined to the appserver using the servlet deployment descriptor (web.xml). This file defines the portlet's class file and read-only initialization parameters.
The following figure shows a portlet after its WAR file is deployed. For each portlet deployed on the portal server, it creates a servlet, or portlet class instance, on the appserver.
The initialization parameters are set by the portlet developer and can be read by the portlet using the PortletConfig object. The servlet deployment descriptor can contain multiple Web applications, each defined by the <servlet> element. In addition, each servlet definition can point to the same portlet class file, thus creating different PortletConfig objects with different initialization parameters for each portlet class instance. For more information, see Web application deployment descriptor.
Portlet deployment descriptor
In addition to the servlet descriptor, portlets must also provide a portlet deployment descriptor (portlet.xml) to define the portlet's capabilities to the portal server. This information includes configuration parameters specific to a particular portlet or portlet application as well as general information that all portlets provide, such as the type of markup that the portlet supports. The portal server uses this information to provide services for the portlet. For example, if a portlet registers its support for help and edit mode in the portlet deployment descriptor, the portal server will render icons to allow the user to invoke the portlet's help and edit pages.
The following is an example portlet deployment descriptor with the minimum tags.
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE portlet-app-def PUBLIC "-//IBM//DTD Portlet Application 1.1//EN" "portlet_1.1.dtd"> <portlet-app-def> <portlet-app uid="com.myCompany.myPortletApp.54321"> <portlet-app-name>My portlet application</portlet-app-name> <portlet id="Portlet_1" href="WEB-INF/web.xml#Servlet_1"> <portlet-name>My portlet</portlet-name> <supports> <markup name="html"> <view output="fragment"/> </markup> </supports> </portlet> </portlet-app> <concrete-portlet-app uid="com.myCompany.myConcretePortletApp.54321"> <portlet-app-name>My concrete portlet application</portlet-app-name> <concrete-portlet href="#Portlet_1"> <portlet-name>My concrete portlet</portlet-name> <default-locale>en</default-locale> <language locale="en_US"> <title>My portlet</title> </language> </concrete-portlet> </concrete-portlet-app> </portlet-app-def>
For detailed information, including a description of each tag, see Deployment descriptors .
Portlet concepts
The following figure shows different variations of a portlet as it is created, placed on a page, and accessed by users. Notice that the first two steps involve the use of persistent data, but for the third step, the data is available only for the duration of the session.
The portal administrator uses the administrative interface to deploys a new portlet application WAR file or install a copy of a portlet. Either action creates a concrete portlet, which is a portlet parameterized by a single PortletSettings object. There can be many concrete portlets for each portlet. PortletSettings are read/write accessible and persistent. The PortletSettings contains configuration parameters initially defined in the portlet deployment descriptor.
The use of concrete portlets allows many instances of a portlet to run with different configurations, without creating extra portlet class instances. During the lifecycle of a single portlet, many concrete portlets can be created and destroyed. There is no object that explicitly represents the concrete portlet. The same concrete portlet can be shared across many users.
The portlet is placed on a page by a user or an administrator. This creates a concrete portlet instance, which is a concrete portlet parameterized by a single PortletData object. There can be many concrete portlet instances per concrete portlet. PortletData stores persistent information for a portlet that has been added to a page. For example, a user can edit a stock quotes portlet and save a list of stock symbols for the companies to track.
The scope of the PortletData depends on the scope of the page that the concrete portlet is on.
- If an administrator puts a concrete portlet on a group page, then the PortletData object contains data stored for the group of users. This holds true for a group of users who have view access to the page. However, if users have edit access to the portlet on a group page, then a new concrete portlet instance is created for each user that edits the portlet. In this case, PortletData contains data for each user that edits the portlet.
- If a concrete portlet is put on a user's page, the PortletData contains data for that user.
When a user accesses a page that contains a portlet, that creates a user portlet instance. When a user logs into the portal, the portal server creates a PortletSession for each of the user's portlets. A concrete portlet instance parameterized by a PortletSession is known as a user portlet instance. There can be many user portlet instances per concrete portlet instance.
A user portlet instance is a concrete portlet instance parameterized by a single PortletSession. There can be many user portlet instances per concrete portlet instance. The PortletSession stores transient information related to a single use of the portlet.
Portlet Applications
Portlet applications provide the means to package a group of related portlets that share the same context. The context contains all resources, for example, images, properties files, and classes. All portlets must be packaged as part of a portlet application.
Concrete Portlet Application
A concrete portlet application is a portlet application parameterized with a single PortletApplicationSettings object. For each portlet application, there may be many concrete portlet applications. PortletApplicationSettings are read/write accessible and persistent. There is no object that explicitly represents the concrete portlet application.
A concrete portlet application contains at least one concrete portlet from the portlet application, but it is not required to contain all of them.
Portlet applications provide no code on their own but form a logical group of portlets. Beside this more logical gain, portlets of the same portlet application can also exchange messages.
Portlet modes
Portlet modes allow a portlet to display a different user interface, depending on the task required of the portlet. A portlet has four modes of display, which is defined in the portlet deployment descriptor . The portlet container maintains the portlet mode in the Portlet.Mode object. The following modes are provided by the Portlet API:
- View
- When a portlet is initially constructed on the portal page for a user, it is displayed in its view mode. This is the portlet's normal mode of operation.
- Help
- If this mode is supported by a portlet, the portlet provides a help page for users to obtain more information about the portlet.
- Edit
- If this mode is supported by a portlet, the portlet provides a page for users to customize the portlet for their own needs. For example, a portlet can provide a page for users to specify their location for obtaining local weather and events. Users must be logged into the portal to access edit mode.
- Configure
- If this mode is supported by a portlet, the portlet provides a page for portal administrators to configure a portlet for a user or group of users.
The Portlet API provides methods for the portlet to determine the current or previous mode. All portlets must support the VIEW mode. The portlet container provides controls for users to interact with portlets on their portal pages. Clicking on one of these controls can change the portlet's mode or state. The following shows a blank title bar of a portlet in view mode.
This title bar displays the Edit, Help, Minimize, and Maximize icons. Clicking the pencil icon places the portlet in edit mode.
Portlet states
Portlet states allow users to change how the portlet window is displayed within the portal. In a browser, users invoke these states with icons in the title bar in the same way that Windows applications are manipulated. Portlet states are maintained in the PortletWindow.State object with a boolean value.
- Normal When a portlet is initially constructed on the portal page, it is displayed in its normal state - arranged on the page along with other portlets.
- Maximized When a portlet is maximized, it is displayed in the entire body of the portal, replacing the view of other portlets.
- Minimized When a portlet is minimized, only the portlet title bar is displayed on the portal page.
The Portlet API provides methods for the portlet to determine the current state.
Elements of the Portlet API
This section describes the basic interfaces, classes, and methods of the Portlet API. The following figure shows a map of many of the common objects in the Portlet API.
- Portlet
extended by PortletAdapter
- service()1 PortletResponse
- createURI() PortletURI
- service()1 PortletRequest
- getPortletSettings() PortletSettings
- getPortletApplicationSettings PortletApplicationSettings
- getMode() Portlet.Mode
- getClient() Client
- getData() PortletData
- getWindow() PortletWindow
- getWindowState() PortletWindow.State
- getPortletSession() PortletSession
- getUser() User
- getPortletConfig() PortletConfig
- getContext() PortletContext
- getLog() PortletLog
- getService() PortletService
1 PortletRequest and PortletResponse are passed by helper methods of PortletAdapter, such as doView().
Portlet class
The abstract Portlet class is the central abstraction of the Portlet API. All portlets extend this abstract class by extending one of its subclasses, such as PortletAdapter, that provide methods helpful for the developer.
Portlet life cycle
The portlet container calls the following methods of the abstract portlet during the portlet's life cycle 2:
- init()
- The portlet is constructed, after portal initialization, and then initialized with the init() method. The portal always instantiates only a single instance of the portlet, and this instance is shared among all users, exactly the same way a servlet is shared among all users of an appserver.
- initConcrete()
- After constructing the portlet and before the portlet is accessed for the first time, the concrete portlet is initialized with the PortletSettings.
- service()
- The portal calls the service() method when the portlet is required to render it's content. During the life cycle of the portlet, the service() method is typically called many times. For each portlet on the page, the service() method is not called in a guaranteed order and may even be called in a different order for each request.
- destroyConcrete()
- The concrete portlet is taken out of service with the destroyConcrete() method. This can happen when an administrator deletes a concrete portlet during runtime on the portal server.
- destroy()
- When the portal is terminating, portlets are taken out of service, then destroyed with the destroy() method. Finally the portlet is garbage collected and finalized.
2 This represents the methods called on all portlets. Other methods are called for portlets that implement listeners. See the Listener lifecycle for more information.
getLastModified()
In addition to methods that are called during the portlet life cycle, the portlet container calls the getLastModified() method for each request. This method returns the last time the content of the portlet changed, in milliseconds, between the current time and midnight, January 1, 1970 UTC (java.lang.System.currentTimeMillis()) or a negative value if it is unknown. For more information about when to use getLastModified(), see Refreshing the portlet cache .
Portlet Adapter
Portlets do not extend the abstract Portlet class directly, but rather extend PortletAdapter or any other helper class that in turn extends Portlet. Extending one of these classes helps protect your portlet from changes in the abstract Portlet class. Moreover it saves you the work of having to implement all of the methods of the Portlet interface, even if your portlet does not need to use them all. Using the PortletAdapter class, you only have to overwrite the methods you really need.
In its service() method, the PortletAdapter class invokes methods corresponding to the portlet mode. Portlets that extend this class can overwrite the doView(), doEdit(), and doHelp() methods without having to test the mode or write a specific service() method.
Additionally, the PortletAdapter enables a portlet to store variables with the concrete portlet. Concrete portlet variables differ from Java instance variables because they are bound to the portlet class or non-concrete portlet. PortletAdapater provides the methods setVariable(), getVariable() and removeVariable() to work with concrete portlet variables.
Core objects
The following objects are most often used by a portlet:
Each of these objects is an extension of its counterpart in the Servlet API.
PortletRequest
The PortletRequest object is passed to the portlet through the login(), beginPage(), endPage() and service() methods, providing the portlet with request-specific data and the opportunity to access further important information as listed below.
- Attributes
- Attributes are name/value pairs associated with a request. Attributes are available only for the scope of the request. The portlet can get, set, and remove attributes during one request.
- Parameters
- Parameters are name/value pairs sent by the client in the URI query string as part of a request. Often the parameters are posted from a form. Parameters are available for the scope of a specific request. The portlet can get but not set parameters from a request.
- Client
- The Client object encapsulates request-dependent information about the user agent of a specific request. Information from the Client includes the manufacturer of the user agent or the type of markup that the client supports. The Client is extracted from the PortletRequest using the getClient() method. The following information can be obtained from the Client:
- User agent
- The portlet can get the String sent by the user agent to identify itself to the portal.
- Markup name
- The portlet can get the String that indicates the markup language that the client supports, for example, "wml".
- MIME type
- The portlet can get the String that indicates the MIME types supported by the client (for example: text/vnd.wap.wml). If the portlet supports multiple types of devices, it should get the markup name rather than the MIME type. The following table shows MIME types and their corresponding markup types. Retrieving MIME type does not distinguish between HTML and cHTML markup.
MIME types Markup types Text/html html Text/vnd.wap.wml wml Text/html chtml - Capabilities
- The Capability object contains more detailed information than the markup type about what the client can support, such as the level of HTML, Javascript, or WML tables.
- User data
- The PortletData object represents represents data for a concrete portlet instance that is saved to persistent store. For example, a user can set a portlet e-mail application to check for new mail every 30 minutes. This preference is stored for the instance in the PortletData object.
- Session
- The PortletSession represents user-specific, transient data for more than one request. In contrast with the request, which does not retain data after the request is completely processed, session attributes can be remembered/saved over more than one request.
- Portlet settings
- The PortletSettings object represents the configuration for a concrete portlet that is saved to persistent store. For example, an administrator can set to which host and port a Stock portlet should connect to get live data. This preference is stored for the concrete portlet in the PortletSettings object.
- Mode
- Portlet.Mode provides the current or previous mode of the portlet.
- PortletWindow
- The PortletWindow object represents the state of the current portlet window. The portlet can access this object to determine if the portlet is currently maximized, minimized, or rendered in its normal view.
- ModeModifier
- This object can be used in a PortletAction to set the portlet mode to its current, previous, or requested mode before the portlet is rendered. For example, a portlet in edit mode could process a user action and return the portlet to edit mode for more input before returning to view mode.
PortletResponse
The response object encapsulates information to be returned from the server to the client. PortletResponse is passed via the beginPage(), endPage(), and service() methods and can be used by the portlet to return portlet output using a Java PrintWriter.
The response also includes methods for creating the PortletURI object or qualifying portlet markup with the portlet's namespace.
Use one of the following methods to create the PortletURI:
- createURI()
- Creates a PortletURI object pointing to the calling portlet with the current mode
- createURI(PortletWindow.State state)
- Creates a PortletURI object pointing to the calling portlet with the current mode and given portlet window state.
- createReturnURI()
- Creates a portletURI pointing at the caller of the portlet. For example, createReturnURI() can used to create a back button in an edit mode.
Each portlet runs in its own unique namespace. The encodeNamespace() method is used by portlets to bring attributes in the portlet output to avoid name clashes with other portlets. Attributes can include parameter names, global variables, or javascript function names.
PortletURI
The PortletURI object contains a URI pointing to the portlet instance and can be further extended by adding portlet-specific parameters and by attaching actions.
Actions are portlet-specific activities that need to be performed as result of the incoming request, but before the service() method of the portlet is called. For example, when a user is entering data in the portlet's edit mode and clicks a Save button, the portlet needs to process the posted data before the next markup is generated. This can be achieved by adding a Save action to the URI that represents the Save button.
The complete URI can be converted to a string which is ready for embedding into markup.
PortletSession
The PortletSession holds user-specific data for the concrete portlet instance of the portlet, creating a portlet user instance. Concrete portlet instances differ from each other only by the data stored in their PortletData. Portlet user instances differ from each other only by the transient data stored in their PortletSession. Any persistent data must be stored using PortletData. Information stored in a portlet's instance variables is shared between all concrete portlet instances and even between all concrete portlets - with read and write access. Make sure you do not use instance attributes for user-specific data.
On the other hand, you have to be cautious about what the portlet adds to the session, especially if the portlet ever runs in a cluster environment where the session is being serialized to a shared database. Everything being stored in the session must be serializable, too.
Like the HttpSession, a PortletSession is not available on an anonymous page. During login, a PortletSession is automatically created for each portlet on a page. To get a PortletSession, the getSession() method (available from the PortletRequest) has to be used. The method returns the current session or, if there is no current session and the given parameter "create" is true, it creates one and returns it.
Listeners
The Portlet API provides listeners, which can add more functionality for a portlet. To enable the listener's functionality, one of the following interfaces must be implemented by the portlet.
- PortletSessionListener
- PortletPageListener
- PortletTitleListener
- PortletSettingsAttributesListener
- PortletApplicationSettingsAttributesListener
PortletSessionListener
In addition to the concrete portlet instance, which exists for each portlet occurrence on a page, a portlet may have an even finer granularity. The PortletSessionListener allows a portlet to recognize the lifecycle of a user portlet instance:
- login()
After a user logs in to a portal, each portlet creates a session for the user. The combination of the concrete portlet instance and the user session creates the user portlet instance. The start of a user instance is signaled by the portal calling the login() method at the portlet. This method allows the portlet to initialize the user's session instance of the portlet, for example, to store attributes in the session.
- logout()
When the user ends the session with the portal, the portal server calls the logout() method to inform the portlet that the user's session instance is terminating. The portlet should then clean up any resources for the portlet user instance.
PortletPageListener
A portlet has no control or awareness of the order in which the output from all of the portlets on the page is written. The PortletPageListener allows a portlet to insert markup at the beginning and ending of a page.
- beginPage()
At the beginning of each page and before any service() method of any portlet on the page is called, the beginPage() method is called for each portlet residing on the page. Like the service() method, the beginPage() method for each portlet on the page is not called in a guaranteed order and can even be called in a different order for each request. This method allows a portlet to output Javascript that is visible to all portlet's service() methods or even to set cookies or headers.
- endPage()
At the end of each page, and after all service() methods of all portlets on the page are called, the endPage() method is called for each portlet residing on the page. Like the service() method, the endPage() method is not called in a guaranteed order and can even be called in a different order for each request. For example, the portlet can insert Javascript to the end of the page that needs to occur after all other elements of the page have been written.
Listener lifecycle
When implementing PortletSesssionListener and PortletPageListener, the following methods are called on the portlet during its lifecycle.
- init()The non-concrete portlet is initialized with PortletConfig.
- initConcrete()The concrete portlet is initialized with PortletSettings.
- login()The user portlet instance is initialized with PortletSession.
- beginPage()The portlet may render output at the beginning of each page for each request.
- service()The portlet may render output in the portlet window for each request.
- endPage()The portlet may render output at the end of each page for each request.
- logout()The user portlet instance is destroyed.
- destroyConcrete()The concrete portlet is destroyed.
- destroy()The non-concrete portlet is destroyed.
PortletTitleListener
The PortletTitleListener interface is used to allow the portlet title, as it is displayed in the title bar, to be changed based on a condition (for example, the type of device used to access the portal) or user input (for example, a preference that the user sets on the edit page). If the Listener is not implemented, the portlet displays the title specified on the <title> element (under <language>) of the portlet deployment descriptor.
PortletSettingsAttributesListener
This interface listens for changes to the attributes of the PortletSettings, like when an administrator configures a concrete portlet.
PortletApplicationSettingsAttributesListener
This interface listens for changes to the attributes of the PortletApplicationSettings, like when an administrator configures a concrete portlet application.
Configuration objects
The following objects are used by the portlet to retrieve and store data, depending on how the data is used:
PortletConfig
The PortletConfig provides the non-concrete portlet with its initial configuration. The configuration holds information about the portlet class. This information is valid for every concrete portlet derived from the portlet.
A portlet's configuration is initially read from its servlet deployment descriptor. This information is set by the portlet developer. The configuration is read-only and cannot be changed by the portlet.
The PortletConfig is passed to the portlet in the init() method of the abstract Portlet and is used to access portlet-specific configuration parameters using getInitParameters(). PortletConfig parameters are name/value pairs available for the complete life cycle of the non-concrete portlet. Non-concrete portlet's parameters are defined by the <init-param> tag in the servlet deployment descriptor.
PortletSettings
The PortletSettings object provides the concrete portlet with its dynamic configuration. The configuration holds information about the concrete portlet. This information is valid for every concrete portlet instance of the concrete portlet.
A concrete portlet's configuration is initially read from the portlet deployment descriptor. The configuration is read-only and can be written by the portlet only when the portlet is in configure mode. This information is normally maintained by the portal administrator and may be changed while the portal server is running. The portlet can get, set, and remove attributes during one request. To commit the changes, the store() method has to be called.
The PortletSettings object can be accessed with the getPortletSettings() method, available from the PortletRequest. Often, it is used to access portlet-specific configuration parameters using getAttribute(). Attributes are name/value pairs available for the complete life cycle of a concrete portlet. Concrete portlet attributes are defined by the <config-param> tag in the portlet deployment descriptor.
PortletApplicationSettings
The PortletApplicationSettings object provides the concrete portlet application with its dynamic configuration. The configuration holds information about the portlet application that is shared across all concrete portlets included in the application.
A concrete portlet application's configuration is initially read from the portlet deployment descriptor. The configuration is read only and can be written by the portlet only when the portlet is in configure mode. This information is normally maintained by the portal administrator and may be changed while the portal server is running. A portlet in the application can get, set, and remove attributes during one request. To commit the changes, the store() method has to be called.
The PortletApplicationSettings can be accessed with the getApplicationSettings() method, available from the PortletSettings object. It is used to access portlet-specific configuration parameters using getAttribute(). Attributes are name/value pairs available for the complete life cycle of a concrete portlet application. Concrete portlet application attributes are defined by the <context-param> tag in the portlet deployment descriptor.
PortletData
The PortletData holds data for the concrete portlet instance. For each occurrence on a page there is a concrete portlet instance. The PortletData contains persistent information about the concrete portlet instance while the PortletSession contains only the transient data of the user portlet instance.
There is one concrete portlet instance for each occurrence of a portlet on a page. A page can be owned by either a single user (personal page) or by a single group of users (group page). PortletData contains user-specific data on a personal page and group-specific data on a group page.
The PortletData object stores attributes as name/value pairs. The portlet can get, set, and remove attributes during one request. To commit the changes, the store() method has to be called. The data is read only and can be written by the portlet only when the portlet is in edit mode.
Miscellaneous objects
The following objects are used by portlets:
PortletContext
The PortletContext interface defines a portlet's view of the portlet container within which each portlet is running. PortletContext also allows a portlet to access resources available to it. For example, using the context, a portlet can access the portlet log, access context parameters common to all portlets within the portlet application, obtain URL references to resources or access portlet services .
The most important information related to the PortletContext is described in detail below.
- InitParameters
- Parameters are name/value pairs available to all portlets within the web application. These are defined in the web deployment descriptor under the <context-param> element. For example, if a group of portlets share a context parameter called "Webmaster" that contains the portal site's administrator email, each portlet could get that value and provide a "mailto" link in their help.
- Attributes
- Attributes are name/value pairs available to all portlets within the web application. The portlet can get, set and remove attributes. Attributes of the context are stored on a single machine and are not distributed in a cluster.
- Localized text
- The getText() method is used by the portlet to access resource bundles within a given locale.
- Resources
- It is through the PortletContext that a portlet can load or include resources located in the portlet's application scope. Available methods are include() and getResourceAsStream(). The include() method is typically used to invoke JSPs for output.
- Messaging
- Through messaging it is possible to communicate between portlets and share data or send notifications. A message is sent by using the send() method. For more information, see Portlet messaging
- Portlet services
- The PortletService object allows portlets to use pluggable services via dynamic discovery.
- Log
- The PortletLog object provides the portlet with the ability to log informational, warning, or error messages. The log is maintained by the portlet container. Whether logging is enabled or not is at the discretion of the portlet container. For more information, see Message and trace logging .
This object is also available from the getPortletLog() method from the PortletAdapter class.
PortletWindow
The PortletWindow object represents the window that encloses a portlet. For example, on an HTML page, the portlet window can typically be rendered as a table cell. The portlet window can send events on manipulation of its various window controls, like when the user clicks minimize or close. The portlet, in turn, can interrogate the window about its current state. For example, a portlet may render its content differently depending on whether its window is maximized or not. The PortletWindow is available using the getWindow() method of the PortletRequest object.
User
The User interface contains methods for accessing attributes about the user, such as the user's full name or user name.
Portlet events
Portlet events contain information about an event to which a portlet might need to respond. For example, when a user clicks a link or button, this generates an action event. To receive notification of the event, the portlet must have an event listener implemented within the portlet class.
- Action events: generated when an HTTP request is received by the portlet container that is associated with an action, such as when the user clicks a link.
- Message events: generated when another portlet within the portlet application sends a message.
- Window events: generated when the user changes the state of the portlet window.
The portlet container delivers all events to the respective event listeners (and therefore the portlets) before generating the new content that the event requires. Should a listener, while processing the event, find that another event needs to be generated, that event will be queued by the portlet container and delivered at a point of time that is at the discretion of the portlet container. It is only guaranteed that it will be delivered and that it will happen before the content generation phase.
Once the content generation phase has started, no further events will be delivered. For example, messages cannot be sent from within the beginPage(), service() and endPage() methods. The resulting message event would not be delivered and essentially discarded.
The event listener is implemented directly in the portlet class. The listener can access the PortletRequest from the event and respond using the PortletRequest or PortletSession attributes.
Action events
An ActionEvent is sent to the portlet when an HTTP request is received that is associated with a PortletAction. To receive action events, the portlet class must implement the ActionListener interface and an object with the type PortletAction. The PortletAction is linked to a URI that references the action by using the PortletURI class and its addAction() method. The ActionEvent can be used to get the associated PortletAction and the PortletRequest.
Typically, a PortletAction is linked with HTTP references or buttons in HTML forms. The ActionEvent of the clicked link then carries the associated PortletAction back to the portlet, which in turn is able to implement different processing paths based on the users' actions. A portlet action can carry any information. However, it should not store a request, response, or session object. This information is part of the action event that will be sent to the registered action listener.
The following shows how a JSP uses the URI, including the PortletAction. When the user clicks the "Add" button, a new HTTP request is sent to the action URL of the FORM.
<FORM method='POST' action='<%=editBean.getAddURI()%>'> Name: <INPUT name='bookmark.name'><br> URL: <INPUT name='bookmark.url'><br> <INPUT type='submit' name='addButton' value='Add'><br> </FORM>The following shows how the ActionListener differentiates between actions.
public void actionPerformed (ActionEvent event) { PortletAction _action = event.getAction(); if (_action instanceof DefaultPortletAction) { ... DefaultPortletAction action = (DefaultPortletAction)_action; if (action.getName().equals("add")) { ...See Using persistence for code examples that show how to add an action to the portlet and create an ActionListener .
DefaultPortletAction
The Portlet API provides a DefaultPortletAction class with default parameters, which can be used by a portlet to implement the PortletAction object. You can create a PortletAction based on DefaultPortletAction or use it to implement your own PortletAction. The following shows how to create a DefaultPortletAction:
DefaultPortletAction addAction = new DefaultPortletAction("add");The following example shows how to include the PortletAction to an URI:
PortletURI addURI = response.createURI(); DefaultPortletAction addAction = new DefaultPortletAction("add"); addURI.addAction(addAction);
Window events
A WindowEvent is sent by the portlet container whenever a user clicks on one of the control buttons that change the window's state, such as maximize, minimize or restore. A WindowEvent can be used, for example, to display more information when the user maximizes the portlet that would be shown in its normal state. To receive window events, the WindowListener interface must be implemented at the portlet class.
The Portlet API provides a WindowAdapter class that implements empty methods of the WindowListener. By extending WindowAdapter, the portlet developer needs to implement only those callback methods needed by the portlet. Without the WindowAdapter, implement all callback methods, even if the method is empty. See Refreshing the portlet cache for an example of a WindowListener.
Message events
Message events can be sent from one portlet to others if the recipient portlets are members of the same portlet application and are placed on the same page as the sending portlet. Additionally, a DefaultPortletMessage can cross portlet application boundaries and may be send to all portlets on a page. A MessageEvent can be sent actively to other portlets only when the portlet is in the event processing cycle of the portlet container, otherwise an exception is thrown. There are two different types of messages:
- Single addressed messages: Messages sent to a specific portlet by specifying the portlet name on the send() method.
- Broadcast messages: Messages sent to all portlets on the page.
Message events are useful when changes in one portlet should be reflected in another one. An object with the type PortletMessage has to be implemented which is passed via the MessageEvent. The portlet receiving the message must implement the MessageListener interface and an object with the type PortletMessage.
For an example of how portlets can send messages to each other, see Portlet messaging .
PortletService
To enable portlets to use pluggable services via dynamic discovery, the Portlet API provides the PortletService interface. A PortletService is accessed from the PortletContext.getService() method that looks up the appropriate factory for the service, creates the service and returns it to the portlet.
Various services may be implemented by different vendors, for example, a SearchService, LocationService, ContentAccessService, or a MailService. The Portlet API provides a ContentAccessService.
Create your own portlet service
Writing a portlet service consists of four steps:
- Defining the interface
- Writing the service implementation
- Writing the service's factory
- Registering the service
Step 1 is not required if you want to implement your service against an existing interface. This is also the case for step 3 if you want to reuse an existing service factory.
Defining the interface
Defining a portlet service interface requires the same careful considerations as defining any public API interface. A portlet service interface just must extend the PortletService interface defined in the org.apache.jetspeed.portlet.service package which serves as a flag like the Serializable interface of the Java API.
The following is an example interface for the HelloWorldService .
package my.portlet.service; import org.apache.jetspeed.portlet.service.*; public interface HelloWorldService extends PortletService { // my service's method public String sayIt(); }
Writing the service implementation
The service implementation must implement the PortletServiceProvider interface of the org.apache.jetspeed.portlet.service.spi package to be able to make use of the portlet service life cycle methods in addition to your service interface. The PortletServiceConfig parameter of the init method allows you, for example, to access the configuration of the service (see Registering the service for more information.
package my.portlet.service.impl; import org.apache.jetspeed.portlet.service.*; import org.apache.jetspeed.portlet.service.spi.*; public class HelloWorldServiceImpl implements HelloWorldService, PortletServiceProvider { private String it = null; public void destroy() { // do nothing - no resources in use } public void init(PortletServiceConfig config) { it = config.getInitParameter("MY_MESSAGE"); if (it == null) it = "Hello world!!!"; } public String sayIt() { return it; } }
Writing the service's factory
Usually you will not have to write a factory of your own as there are two generic factories being shipped with the portal server in the org.apache.jetspeed.portletcontainer.service package. The PortletServiceDefaultFactory always returns a new instance of a given service and the PortletServiceCacheFactory always returns the same instance of a given service. You can use one of these factories rather than implementing your service as a singleton. Factories have to implement the PortletServiceFactory interface of the org.apache.jetspeed.portlet.service.spi package.
The following is the factory class for HelloWorldService:
package my.portlet.service.factory; import org.apache.jetspeed.portlet.service.*; import org.apache.jetspeed.portlet.service.spi.*; public class HelloWorldServiceFactory implements PortletServiceFactory { PortletServiceProvider psp = null; public PortletService createPortletService(Class service, Properties serviceProperties, ServletConfig servletConfig) throws PortletServiceUnavailableException { if (psp != null) { return psp; } else { psp = new HelloWorldServiceImpl(); psp.init(new PortletServiceConfigImpl( service, serviceProperties, servletConfig)); return psp; } } }
Registering the service
To plug the service into the portal server, the corresponding class files must be copied to was_root/lib/app. Then the PortletServices.properties file in the wp_root/app/wps.ear/wps.war/WEB-INF/conf directory must be changed:
- Register the implementation as the corresponding service type
- Register the factory for the implementation
- Provide configuration parameters for the implementation
# PortletServices.properties org.apache.jetspeed.portlet.service.default.factory = org.apache.jetspeed.portletcontainer.service.PortletServiceDefaultFactory ... my.portlet.service.HelloWorldService = my.portlet.service.impl.HelloWorldServiceImpl my.portlet.service.impl.HelloWorldServiceImpl.factory = my.portlet.service.factory.HelloWorldServiceFactory my.portlet.service.impl.HelloWorldServiceImpl.MY_MESSAGE = Hello World (properties)! ...
Content access service
Various services could be implemented by different vendors (for example, a SearchService or a MailService). The Portlet API provides a ContentAccessService that retrieves content from sources outside the intranet, often when a proxy must be used. This service allows portlets to access content from remote web sites or from JSPs and servlets in the portal web application. (In contrast, the PortletContext.include method only can include JSPs local to the portlet application.)
import org.apache.jetspeed.portlet.service.ContentAccessService; . . . ContentAccessService service = (ContentAccessService)portletContext.getService(ContentAccessService.class); //get a URL URL url = service.getURL("http://www.ibm.com", request, response); //include the content of a web site into the portlet service.include("http://www.ibm.com", request, response); //include a JSP or servlet belonging to the portal web application service.include("/templates/weather.jsp", request, response); . . .
Hint: The disadvantage when accessing internet resources directly is that the content is simply taken and written to the portlet's output. This means that all relative links to other pages or images will be broken. This can be solved by parsing the content or use some enhanced browser portlet.
The ContentAccessService can also open an SSL connection to remote applications. The code is the same as for nonsecure connections (see Example: ContentAccessService) except that you specify a secure protocol (HTTPS) in the URL for the include() method. However, the portal must be configured to support SSL as described in Portal configuration, see PortletServices.properties .
Deployment descriptors
The WAR file for a portlet application must contain two descriptor documents: the Web application deployment descriptor and the portlet deployment descriptor. The definition of the servlets in the Web application deployment descriptor must be in the same order as the definition of portlets in the portlet deployment descriptor.
Web application deployment descriptor
As with other servlets following the J2EE model, portlets are packaged as WAR or EAR files with a Web application deployment descriptor (web.xml). This descriptor defines each portlet as a servlet within the Web application, including unique identifiers for each portlet, the portlet class, and initialization parameters.
For more information about the Web application deployment descriptor, see the Java Servlet Specification V2.3.
Portlet deployment descriptor
The DTD for the portlet deployment descriptor is located at wp_root/app/web/dtd/portlet_1.1.dtd. The descriptor for a single WAR file is saved as the file portlet.xml and must begin with the following XML and DOCTYPE declarations:
<?xml version="1.0"?> <!DOCTYPE portlet-app-def PUBLIC "-//IBM//DTD Portlet Application 1.1//EN" "portlet_1.1.dtd">The following shows the structure of the portlet deployment descriptor (portlet.xml). Click any tag to get more information about it's use.
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE portlet-app-def PUBLIC "-//IBM//DTD Portlet Application 1.1//EN" "portlet_1.1.dtd"> <portlet-app-def> <portlet-app uid="uid"> <portlet-app-name>portlet_application_name</portlet-app-name> <portlet id="portlet_id" href="WEB-INF/web.xml#servlet_id" major-version="version" minor-version="version"> <portlet-name>portlet_name</portlet-name> <cache> <expires>number</expires> <shared>yes|no</shared> </cache> <allows> <maximized/> <minimized/> </allows> <supports> <markup name="html|wml|chtml"> <view output="fragment"/> <edit output="fragment"/> <help output="fragment"/> <configure output="fragment"/> </markup> </supports> </portlet> </portlet-app> <concrete-portlet-app uid="uid"> <portlet-app-name>portlet_application_name</portlet-app-name> <context-param> <param-name>name</param-name> <param-value>value</param-value> </concrete-param> <concrete-portlet href="#portlet_id"> <portlet-name>portlet_name</portlet-name> <default-locale>locale</default-locale> <language locale="locale"> <title>title</title> <title-short>short title</title-short> <description>description</description> <keywords>keyword1, keyword2</keywords> </language> <config-param> <param-name>name</param-name> <param-value>value</param-value> </config-param> </concrete-portlet> </concrete-portlet-app> </portlet-app-def>
<portlet-app-def>
Required. Top level element that contains information about the portlet application. This element includes exactly one <portlet-app> element and one or more <concrete-portlet-app> elements.
- <portlet-app uid="uid">
- Required. Contains information about the portlet application. The uid for each portlet must be unique within the portlet application. See Guidelines for portlet UIDs. The following are subelements of <portlet-app>.
- <portlet-app-name>
- Exactly one is required. Indicates the name of the portlet application.
- <portlet id="id" href="href" major-version="version" minor-version="version">
- At least one is required. Contains elements describing a portlet that belongs to this portlet application. id and href is required. The id must be unique within the portlet application. The href attribute points to the identifier of the servlet, as in WEB-INF/web.xml#servlet_id .
Use the version attributes for maintaining and supporting multiple versions of the portlet. The following are subelements of <portlet>:
- <portlet-name>
- Required. The name of the portlet. This name does not appear on the portal page.
- <cache>
- Optional. Describes how the portal handles caching the output of this portlet. The following are subelements of <cache>:
- <expires>
- Required if <cache> is specified. Indicates the number of seconds after which the portlet's output is refreshed.
- 0 indicates that the portlet's output always expires. Each request causes the portlet to refresh its output. This is the default setting if <cache> is not present.
- Any number greater than 0 indicates the number of seconds the portlet output is cached. After the cache time expires, subsequent requests cause the portlet to refresh its output.
- -1 indicates that the portlets output never expires. After the portlet is initialized, its content is no longer refreshed.
- <shared>
- Required if <cache> is specified. Indicates if the portlet output is cached and shared with all users or for each individual user. Specify "yes" or "no".
- <allows>
- Optional. Indicates the states supported by the portlet. No more than one <allows> element can be specified for a portlet. These settings only affect the rendering of portlets in HTML. The following are subelements of <allows>:
- <maximized/>
- Optional. Indicates whether the portlet can be maximized. When maximized, the portlet replaces all other portlets on the portal page. If this element is present, the maximize button is rendered on the portlet's title bar.
- <minimized/>
- Optional. Indicates whether the portlet can be minimized. When minimized, the portlet is rendered only as a title bar. If this element is present, the minimize button is rendered on the portlet's title bar.
<supports> Required. Indicates the modes and markup types supported by the portlet. All portlets must support the view mode. Other modes must be provided only if they are supported by the portlet. The following are subelements of <supports>:
- <markup name="name">
- At least one is required. Indicates the type of markup this portlet supports. name is one of the following values:
Indicate one <markup> tag for each markup type, for example:
- html
- wml
- chtml
<markup name="html"> ... </markup> <markup name="wml"> ... </markup>The following are subelements of <markup>:
- <view/>
- Required. Indicates that this portlet supports view mode.
- <edit/>
- Optional. Indicates that this portlet supports edit mode. This element is optional. If edit mode is supported, the portlet must supply methods that users can invoke to customize the portlet for their own use.
- <help/>
- Optional. Indicates that this portlet supports help mode. This element is optional. If help mode is supported, the portlet must supply help output that will display in place of the portlet when the user clicks the help icon.
- <configure/>
- Optional. Indicates that this portlet supports configure mode. This element is optional.
<concrete-portlet-app uid="uid"> At least one is required. Contains information about the concrete portlet application. The following are subelements of <concrete-portlet-app>.
- <portlet-app-name>
- Exactly one is required. Indicates the name of the portlet application.
- <context-param>
- Optional. Contains a pair of <param-name> and <param-value> elements that this concrete portlet application can accept as input parameters. A concrete portlet application can accept any number of context parameters. Administrators can change the context parameters when they configure the concrete portlet application. Provide help information using XML comments to explain what values the portlet application can accept. The unique configuration settings for a concrete portlet application make up its PortletApplicationSettings.
- <concrete-portlet id="id" href="href">
- At least one is required. Contains elements describing the concrete portlet that belongs to this concrete portlet application. id and href are required. The id must be unique within the portlet application. The href attribute points to the identifier of the portlet, as in #portlet_id . The following are subelements of <concrete-portlet>:
- <portlet-name>
- Required. The name of the portlet. This name does not appear on the portal page.
- <default-locale>
- Required. Indicate the locale that will be used if the client locale cannot be determined.
- <language locale="locale">
- At least one is required. Provide one <language> element for each locale that your portlet supports. locale can have one of the following values:
- en English
- de German
- fr French
- es Spanish
- ja Japanese
- ko Korean
- zh Simplified Chinese
- zh_TW Traditional Chinese
- pt_BR Brazilian Portuguese
- it Italian
- he Hebrew
- cs Czechoslovakian
- tr Turkish
- pl Polish
The following are subelements of <language>:
- <title>
- Exactly one <title> is required for each <language> element. Specify a portlet title translated for the given locale.
- <title-short>
- Optional. Indicates a translated short title.
- <description>
- Optional. Provides a translated description of the portlet.
- <keywords>
- Optional. Provides any translated keywords associated with your portlet.
- <config-param>
- Contains a pair of <param-name> and <param-value> elements that this portlet can accept as input parameters. A portlet can accept any number of configuration parameters. Administrators can change the configuration parameters when they configure the concrete portlet. Provide help information using XML comments to explain what values the portlet application can accept. The unique configuration settings for a concrete portlet make up its PortletSettings.
Linking the servlet, portlet, and concrete portlet
The definition of the servlets in the web.xml must be in the same order as the definition of portlets in the portlet.xml . The servlet identifier must be referenced by the portlet deployment descriptor, using the href attribute of the <portlet> tag. As shown in the following table, the href attribute indicates the path of the Web application descriptor in the WAR file appended by the servlet ID as the anchor.
portlet.xml web.xml <portlet id="Portlet_1" href="WEB-INF/web.xml#Servlet_1"> <portlet-name>Mail</portlet-name> ... </portlet> <servlet id="Servlet_1"> <servlet-name>MailPortlet</servlet-name> ... </servlet> <portlet id="Portlet_2" href="WEB-INF/web.xml#Servlet_2"> <portlet-name>Calendar</portlet-name> ... </portlet> <servlet id="Servlet_2"> <servlet-name>CalendarPortlet</servlet-name> ... </servlet>Each concrete portlet definition indicates its parent portlet using the href attribute of the <concrete-portlet> tag. As shown in the following table, the href attribute indicates the portlet ID as an anchor.
Portlet tag Concrete portlet tag <portlet id="Portlet_1" href="WEB-INF/web.xml#Servlet_1"> <portlet-name>Mail</portlet-name> ... </portlet> <concrete-portlet href="#Portlet_1"> <portlet-name>Mail Box</portlet-name> ... </concrete-portlet> <portlet id="Portlet_2" href="WEB-INF/web.xml#Servlet_2"> <portlet-name>Calendar</portlet-name> ... </portlet> <concrete-portlet href="#Portlet_2"> <portlet-name>Group calendar</portlet-name> ... </concrete-portlet>
Guidelines for portlet application UIDs
The UIDs of portlet applications and concrete portlet applications must identify them unambiguously in the area of their usage, which could be wworldwide To make this possible, it is strongly recommended to follow these guidelines.
- Include the portlet's namespace in the UID, using the same format that is used for Java packages
- Add some portlet application specific description
- Add some arbitrary characters to guarantee uniqueness within the namespace, for example:
com.ibm.wps.samplet.mail.4969- Add postfixes for the corresponding concrete portlet applications, for example:
com.ibm.wps.samplet.mail.4969.1Portlet IDs must be unique within the application.
See also
WebSphere is a trademark of the IBM Corporation in the United States, other countries, or both.
IBM is a trademark of the IBM Corporation in the United States, other countries, or both.