Developing Custom Portlets |
Overview: Steps for Developing a Custom Portlet |
To create a custom portlet, follow these steps:
Create a portlet deployment descriptor.
Each portlet that you deploy must be defined in a portlet deployment descriptor. A portlet deployment descriptor is an XML file that provides all of the information that the SAS Information Delivery Portal requires in order to deploy one or more portlets. The file includes information about the portlet's initialization, actions, security settings, and resource paths.
Create display resources files.
The display resources file contains text strings for the portlet's title and description for use in the portlet's metadata. If you create multiple display resources files for different locales, the SAS Information Delivery Portal uses these files to localize the portlet title and description at the time of deployment, according to the default locale for the SAS Information Delivery Portal.
Develop presentation JSP pages.
Each portlet must have a JSP page to serve as the presentation component.
Create action classes.
You can use the resources of the SAS Information Delivery Portal to develop the following types of action classes for your portlets:
initializer classes
portlet action classes
postprocessing classes
error handling classes
Implement portlet help.
If you want to provide customized use instructions for a portlet, you can create an action class with an associated JSP page that contains the help text. When the user clicks a help button in the portlet's title bar, the help appears in a pop-up window.
Create a PAR file to deploy in the SAS Information Delivery Portal.
To enable automatic deployment of a portlet into the SAS Information Delivery Portal, you must provide a PAR file that contains all of the needed files. A PAR file can contain files for one portlet or for multiple related portlets.
For examples of fully developed portlet code, see Sample Portlets.
Creating a Portlet Deployment Descriptor |
For each PAR file that you create for deployment in the SAS Information Delivery Portal, you must create a portlet deployment descriptor. The portlet deployment descriptor is an XML file that provides all of the information that the SAS Information Delivery Portal needs to deploy the portlets that are contained in the PAR file. The portlet deployment descriptor file must be named portlet.xml.
A PAR file, and its associated portlet deployment descriptor, can contain one portlet or it can contain multiple related portlets; there is no limit to the number of portlets that a PAR file and its associated descriptor can contain.
In addition, a PAR file and its associated portlet deployment descriptor can contain local portlets, remote portlets, or a combination of local and remote portlets.
To create a portlet deployment descriptor, use the element tags that are defined in the portlet deployment descriptor document type definition (DTD). You can view the portlet deployment descriptor DTD at SAS-installation-directory\SASInformationDeliveryPortal\4.2\Static\wars\sas.portal\WEB-INF\classes\portlet.dtd.
The following examples show portlet deployment descriptors for a local portlet and a remote portlet. You can use these examples as templates for creating deployment descriptors for your own portlets.
After you create the deployment descriptor file, include it in the PAR file that you create for your portlet or group of portlets. For more information, see Creating a PAR File for Deploying the Portlet in an Application.
A local portlet is a portlet that meets the following criteria:
The portlet is deployed within the SAS Information Delivery Portal.
The portlet executes inside the portlet container.
The portlet consumes the computing resources (for example, CPU, memory, and disk storage) of the server machine on which the portal container runs.
The portlet can include resources such as Web pages, images, resource bundles, and Java classes that are deployed inside the SAS Information Delivery Portal.
You can use the following example as a template for creating portlet deployment descriptors for your own local portlets.
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE portlets SYSTEM "http://www.sas.com/idp/portlet.dtd"> <portlets> <local-portlet name="simplejsp" title="SimpleJspPortlet" icon="images/ndd.jpg"> <localized-resources locales="en" /> <deployment scope="user" autoDeploy="false" userCanCreateMore="true"> </deployment> <initializer-type> com.sas.portal.portlets.JspPortlet.JspPortletInitializer </initializer-type> <init-param> <param-name>display-page</param-name> <param-value>simpleJspTest.jsp</param-value> </init-param> <portlet-path>/sample/portlets</portlet-path> <portlet-actions> <portlet-action name="display" default="true"> <type>com.sas.portal.portlets.JspPortlet.JspPortlet</type> </portlet-action> </portlet-actions> </local-portlet> </portlets>
Remote portlets are portlets that execute outside of the portal container. You can use remote portlets to incorporate data from external applications into the SAS Information Delivery Portal. When a user interacts with a remote portlet, the remote portlet appears to be the same as a local portlet.
Many of the elements in the portlet deployment descriptor DTD relate only to local portlets. Therefore, a portlet deployment descriptor for a remote portlet requires fewer elements than a descriptor for a local portlet.
You can use this example as a template for creating portlet deployment descriptors for your own remote portlets:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE portlets SYSTEM "http://www.sas.com/idp/portlet.dtd"> <portlets> <remote-portlet name="MyRemotePortlet" title="MyRemotePortlet"> <localized-resources locales="en" /> <deployment scope="user" autoDeploy="false" userCanCreateMore="true"> </deployment> <portlet-path>/sample/portlets/remote</portlet-path> <portlet-actions> <portlet-action name="display" default="true"> <url>http://d9999.mycompany.com:8080/test.html</url> </portlet-action> </portlet-actions> </remote-portlet> </portlets>
Creating Display Resources Files |
A display resources file is a file that contains key=value statements to define text strings for a portlet's title and description. You can create display resources files for the following purposes:
to specify a description for your portlet. If you do not provide a display resources file, the SAS Information Delivery Portal uses the portlet's name to create a default description.
Note: The <local-portlet> and <remote-portlet> elements of the portlet deployment descriptor contain a description attribute. However, this description is only for internal documentation purposes. It is not displayed to users.
to enable the SAS Information Delivery Portal to localize the portlet title and description at the time of deployment, according to the default locale for the SAS Information Delivery Portal. When the portlet is first deployed, the deployment process determines which locale to use. Based on this locale, the deployment process uses the title and description from the appropriate display resources file to create metadata and register the portlet in the SAS Metadata Repository. The following rules apply:
For editable portlets, the portlet name that is displayed in the drop-down list of portlet selections is localized based on the browser locale when the user first logs into the portal.
Note: The locale does not apply to new portlet instances created from the template because the user enters an explicit name and description that are stored in metadata for the portlet instance.
For portlets with user scope and the autoDeploy="true" attribute in the deployment descriptor, the browser locale when the user first logs into the portal determines which display resources file is selected to provide the title and description for the portlet.
For portlets with group scope and the autoDeploy="true" attribute in the deployment descriptor, the locale used to start the Web application server determines which display resources file is selected to provide the title and description for the portlet. Starting the Web application server with one locale specified and then starting it again with a different locale specified will result in two instances of the portlet.
If your portlet is deployed in only one locale, then the display resources files can be omitted. The portlet name in the default locale is used.
Note: The SAS Metadata Repository cannot store multiple localized values for metadata. Therefore, the portlet title and description are translated only into the default locale for the SAS Information Delivery Portal. They cannot be translated based on the user's locale preference.
If your portlet does not include any display resources files, the portlet deployment mechanism sends a warning message to the server log. The message indicates that no localized title or description can be found.
To create display resources files, follow these steps:
Create a separate file for each language (or each country and language combination) that you need to support. In each file, use key=value statements to define text strings for portlet.title and portlet.description, as in the following examples:
portlet.title=Welcome Portlet portlet.description=Welcome Portlet
portlet.title=Portlet de bienvenida portlet.description=Portlet de bienvenida
Name the files as follows:
Use the base name portletDisplayResources.properties.
If you are creating files for multiple locales, append each file's name with the appropriate locale identifier (for example, portletDisplayResources_en.properties for English, portletDisplayResources_fr.properties for French, and so on). The file for the default locale does not need to have a locale identifier.
Place the files in the /portlet-name/classes directory of the PAR file.
Add the locale identifier for each supported locale to the locales attribute value of the <localized-resources> element in the portlet deployment descriptor (portlet.xml) file.
Creating the Presentation JSP Page |
JavaServer Page (JSP) pages are the presentation components of local portlets. Because you can define a local portlet's initialization, actions, security settings, and resource paths in the portlet deployment descriptor, the JSP page does not need to contain this information.
In developing the JSP page, you can use the following tags:
tags from the JSP Standard Tag Libraries (JSTL).
tags from the Struts tag libraries.
SAS custom tags, which are available if your site has licensed SAS AppDev Studio software in addition to the SAS Information Delivery Portal. For information about these tags, see the SAS Custom Tags Reference page on the AppDev Studio Developer's Site at http://support.sas.com/rnd/appdev.
When you create a JSP page for a portlet, the only requirements are the following:
The JSP page must be an HTML fragment:
If the JSP page includes custom tags from a tag library, you must include a taglib directive before the first use of a tag from that library. For the JSTL format tag library, use the following taglib directive:
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
You must include a UTF-8 directive if you want the JSP page to provide full support for internationalization. This directive causes all user input to be encoded in the 8-bit Unicode Transformation Format, which supports all of the world's languages, including those that use non-Latin1 characters.
Note: The SAS Information Delivery Portal supplies this directive when it displays portlets on a portal page. However, you must supply the directive to ensure correct internationalization when your portlet is displayed from the Search Results panel. You should consider making your portlet actions extend the HTMLPortletAction class, because that class supplies the directive.
The syntax for the UTF-8 directive is:
<%@ page contentType= "text/html; charset=UTF-8"%>
The JSP cannot import Java classes from the portlet's PAR file.
Creating Action Classes |
You can use the resources of the SAS Information Delivery Portal to develop the following types of action classes for your local portlets:
Initializer classes
Portlet action classes
Postprocessing classes
Error handling classes
The Portlet API includes classes that you can use to create your own action classes for custom portlets. For a summary of these classes, see Using the Portlet API. For detailed information, see SAS Information Delivery Portal API documentation at http://support.sas.com/92api.
Any action classes that you develop must be defined in the portlet's deployment descriptor file and included in the portlet's PAR file. These classes cannot be accessed by the portlet's JSP pages.
Note: You can also develop classes other than action classes for your portlet and include them in the portlet's PAR file. These classes do not need to be defined in the portlet deployment descriptor file. However, the additional classes can be accessed only by the action classes. They cannot be accessed from the portlet's JSP pages.
Portlet actions, like Struts actions, are multithreaded. There is only a single instance of your PortletAction subclass, and you must make your actions thread-safe, as follows:
You cannot use class properties to share values between member methods.
If you use member methods, be sure to pass all values through the method's signature. The signature passes all values through the thread-safe stack.
When you develop a local portlet, you can implement an initializer class that runs before the portlet is displayed for the first time on a SAS Information Delivery Portal page. The initializer does not execute again if the user interacts with your portlet or with other portlets on the same page. It also does not execute again if the user navigates to another page and then back again. However, the initializer does run again if the user logs off, logs on again, and displays the page that contains the portlet.
Uses for an initializer might include reading initial parameters that are specified in your portlet's deployment descriptor file (portlet.xml) or connecting to an external resource such as a database.
The SAS Information Delivery Portal is delivered with a default initializer class named JspPortletInitializer, which requires a parameter named display-page. The initializer places the value of this parameter in the PortletContext object so that it can be used by the portlet's action class. To pass additional parameters, you would need to create your own initializer class.
When you create an initializer class, ensure that the following steps have been taken:
The class must be specified in the <initializer-type> element of the portlet's deployment descriptor file (portlet.xml).
The class must implement com.sas.portal.portlet.PortletInitializerInterface.
The com.sas.portal.portlet.PortletInitializerInterface class includes one method named initialize(). The following objects are passed to the initialize() method:
contains all of the initial parameters that are specified in your portlet's deployment descriptor. If your portlet's action class or JSP page requires access to these parameters, you should place them in the portlet context object using its setAttribute() method.
provides a getter method for the HttpSession object so that you can access or set session attributes.
The following example shows an initialize() method that places initial parameters into the portlet context:
/** * Puts initial properties into the PortletContext object. * These come from the portlet.xml. * @param initProperties a Properties object * @param context the PortletContext for this portlet */ public void initialize(Properties initProperties, PortletContext context) { context.setAttribute("display-page", initProperties.getProperty("display-page")); context.setAttribute("image-location", initProperties.getProperty("image-location")); }
When developing a local portlet, you can implement one or more action classes for the portlet. If you use an action class, then the following requirements must be met:
You must specify the class in your portlet deployment descriptor file (portlet.xml).
The class must implement com.sas.portal.portlet.PortletActionInterface.
The class can extend DefaultPortletAction or HTMLPortletAction in com.sas.portal.portlet. The DefaultPortletAction and HTMLPortletAction contain two simple methods for setting and getting an instance of com.sas.portal.portlet.PortletActionInfoInterface, as shown in the following example:
public void setInfo(PortletActionInfoInterface pai) { _actionInfo = pai; }
public PortletActionInfoInterface getInfo() { return _actionInfo; }
The primary method, named service(), runs every time the action is executed. For the portlet's display action, that occurs before the portlet is displayed and every time the portlet is redisplayed. For example, it runs after a user interacts with the portlet or with a different portlet on the same page.
The service() method is provided with the HttpServletRequest, HttpServletResponse, and PortletContext objects. From the PortletContext object, you can obtain the HttpSession object, which provides access to many important servlet objects.
Your service() method must return a string representing a valid URL for the portlet. Typically, the URL is the name of the portlet's JSP page. If your initializer places the display-page property of the portlet deployment descriptor file into the PortletContext object, then you can obtain the URL as in the following example:
String url = (String) context.getAttribute("display-page");
If user interaction with your portlet requires a different URL string, then you can return that URL instead.
The service() method can handle any type of exception subclass that is thrown by code within your action. If your portlet action needs to throw an exception, then you can use the portlet error handler. For more information, see Creating an Error Handling Action.
The com.sas.portal.portlet.PostProcessorInterface is available for implementing activity that should occur when a local portlet is no longer on display. Like other parts of the portlet architecture, it must be defined in your deployment descriptor file. You can use the post-processor phase to free resources that you attached to in the portlet initializer. You could also remove HttpSession attributes that were set in the initializer or action. This is especially important to consider because multiple copies of your portlet could exist on other SAS Information Delivery Portal pages or even on the same page.
The com.sas.portal.portlet.ErrorHandlerInterface is available for handling any errors that your local portlets encounter. This interface has one method, which is named service(). The service() method has the same arguments as the service() method of the PortletActionInterface, plus an additional object named Exception.
If you specify an error handler in your portlet deployment descriptor file (portlet.xml), the error handler is called if the portlet action throws an exception. You can direct your error handler to send messages to the server log and to return a URL string representing an error page for the user to view.
If your portlet initializer encounters an exception, the error handler is not called. If you want to ensure that the error handler executes, you can store the exception object in the portlet context. Then, in your action class's service() method, you can get the exception object out of the context and re-throw it. In the following example, this code is put into a method that should be called at the start of the action's service() method:
/** * Check the PortletContext for an exception object. If * present, throw it so that the error handler is executed. * @param context the PortletContext */ private static void errorCheck(PortletContext context) throws Exception { Exception e = (Exception) context.getAttribute("PORTLET_EXCEPTION"); if (e != null) { throw e; } }
The following example shows a simple error handler that logs the exception and calls a static error page. The error page supplies a general error message from the portlet's localized resource bundles.
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.sas.portal.Logger; import com.sas.portal.portlet.PortletContext; import com.sas.portal.portlet.ErrorHandlerInterface; import com.sas.portal.portlet.NavigationUtil; /** * Error handler for some portlets. * It logs the exception and returns ErrorPage.jsp * for the portlet to display. */ public class MyErrorHandler implements ErrorHandlerInterface { private final String _loggingContext = this.getClass().getName(); /** * Returns the URL for the portlet controller to call. This is the * name of the error page JSP. * @param request the HttpServletRequest * @param response the HttpServeltResponse * @param context the PortletContext * @param exception the exception thrown by a portlet action * @return the URL to call */ public String service(HttpServletRequest request, HttpServletResponse response, PortletContext context, Exception thrownException) { // Prepare the localized resources for use by the jsp. try { NavigationUtil.prepareLocalizedResources( "com.mycompany.portlets.Resources", request, context); } catch (java.io.IOException ioe) { Logger.error(ioe.getMessage(), _loggingContext, ioe); } Logger.error(thrownException.getMessage(), _loggingContext, thrownException); return "ErrorPage.jsp"; } }
Implementing Portlet Help |
You can easily implement help for a custom portlet. If you implement help for a portlet, then a help icon appears in the portlet's title bar. When a user clicks the icon, the portlet help appears in a resizable, scrollable window that is by default 400 pixels wide and 200 pixels high, as shown in the following example:
To implement portlet help, use these steps:
Create an action class to display the JSP page for the help (or, if you want, you can use an instance of com.sas.portal.portlet.JspPortlet). The following example shows the code for an example of a custom action class to display portlet help:
package com.sas.portal.portlets.welcome; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.sas.portal.portlet.HTMLPortletAction; import com.sas.portal.portlet.PortletContext; public class HelpAction extends HTMLPortletAction { public String service(HttpServletRequest request, HttpServletResponse response, PortletContext context) throws Exception { return "help.jsp"; } }
Create a JSP page that contains the help text. The JSP page must have the following characteristics:
The JSP page must be an HTML fragment. That is, it must not contain starting and ending <HTML> , <HEAD> , or <BODY> tags.
The JSP page must have the filename help.jsp. The example JSP page for the help window that was shown previously consists of the following lines:
<h1>Portlet Help</h1> <p>Portlet ID: <%= pid %></p> <p>This is where portlet help would be displayed</p>
In the portlet's deployment descriptor (portlet.xml) file, add a <portlet-action> element for the action class. Set the element's help attribute to true.
The following example of the <portlet-action> element for a portlet uses a custom action to display its help:
<portlet-action name="help" help="true"> <type>com.sas.portal.portlets.welcome.HelpAction</type> </portlet-action>
The following example of a <portlet-action> element for a portlet uses an instance of com.sas.portal.portlet.JspPortlet to display its help:
<portlet-action name="help" help="true"> <type>com.sas.portal.portlet.JspPortlet</type> </portlet-action>
Creating a PAR File for Deploying the Portlet in an Application |
A PAR file contains all of the files needed in order to deploy a portlet or a group of portlets into the SAS Information Delivery Portal. A single PAR file can contain files for multiple portlets. A PAR file can contain local portlets, remote portlets, or a combination of local and remote portlets.
For correct deployment, the portlet files must be archived in a PAR file using the following directory structure:
contains the portlet deployment descriptor file, which must be named portlet.xml.
contains associated subdirectories for each portlet that is defined in portlet.xml. The directory name must match the name of the portlet as specified in the name attribute of the <local-portlet> or <remote-portlet> element in portlet.xml.
contains portlet action classes, other custom classes that are used by the portlet, and display resources files that are used by the portlet. Replicate any package structure as subdirectories of /portlet-name/classes. Portlet action classes (but not other classes) must be defined in the portlet deployment descriptor file (portlet.xml).
contains Web resources used by the portlet, including JSPs, HTML files, and images. Each portlet can have only one content directory. However, the content directory can have an unlimited number of subdirectories.
contains any custom JAR files that are used by the portlet.
Note: The scripting facility provided with SAS Information Delivery Portal automates the process of building the PAR file with the necessary directory structure. For more information, see Creating Portlets Using the Testportlet Scripting Facility.
Copyright © 2010 by SAS Institute Inc., Cary, NC, USA. All rights reserved.