Programming in HATS portlets
The HATS User's and Administrator's Guide explains how to convert HATS projects into portlet projects in HATS Studio. You must have WebSphere Portal Toolkit Version 5.0.2.2 installed on your Studio machine. WebSphere Portal Toolkit Version 5.0.2.2 is installed with Rational Studio. A detailed example of using HATS business logic with the Portal API can be found on the HATS Information Center.
For some types of portlet customization, create business logic classes. When you use the Create Business Logic wizard in HATS Studio, you will see a check box labeled Portlet integration samples. If you select this check box, HATS creates sample methods, related to portlet communications, in your business logic class. These methods are identified in the appropriate sections of this chapter. Another check box, labeled Credential vault samples, causes HATS to include sample methods that you can use if you implement security in your portlet.
Adding JavaServer Pages to a portlet
If you copy a .jsp file from a non-portlet project into a HATS portlet project, convert it by right-clicking the file name and selecting Convert JSP for Portal. You can convert several .jsp files at a time by selecting them in the tree view. This menu item is available only if the Portal Toolkit has been installed and the .jsp is in a HATS portlet project and has not already been converted. If you select several .jsp files and one or more of the files have already been converted, they will be skipped.
Using security in portlets
If you are using a credential vault with your WebSphere Portal, you can configure your HATS portlets to work with the credential vault. HATS provides a Web Express Logon plugin called WebSphere Portal Credential Vault Credential Mapper. This plugin appears in the Add Credential Mapper plugin window only for a portlet project. This plugin retrieves a passive user-password credential from a vault slot whose name is specified using the single plugin parameter SlotID. The actual vault slot ID that is used is the slot ID concatenated using spaces with the host name, then the application name. The three elements of the slot ID are encoded to replace spaces with underscores. To see how this slot ID is generated, refer to the sample credential vault business logic methods. These methods are added to a new business logic class when you select the Credential vault samples check box.
You, the HATS developer, are responsible for creating and populating the vault slot for your users. The Web Express Logon plugin can be used directly with credentials created using the business logic setUserCredential() method, because it observes the same naming convention for the slots. You can populate the vault slot with credentials that are specified in your business logic or retrieved from another source. If you want to use the Portal user ID, you can retrieve it using the WebSphere Portal Network Security plugin. This plugin will appear in the Add Network Security plugin window only for a portlet project.
As described in Creating plugins for Web Express Logon, Web Express Logon uses two types of plugins, Network Security plugins and Credential Mapper plugins. Any of the Network Security plugins that are supplied with HATS can be used in a HATS portlet. Table 4 lists some possible combinations of plugins you can use in your portlet:
Table 4. Plugin combinations Network Security plugin Credential Mapper plugin WebSphere Portal NS plugin Any supplied or custom CM plugin None WebSphere Portal Credential Vault CM plugin Custom NS plugin Custom CM plugin The following steps are an example of how you can add Web Express Logon capability to your portlet. Add this logic to the Start event for your HATS portlet.
When a user opens the portlet, check a global variable to determine whether the user's host credentials have already been supplied.
- If the host credentials have already been supplied, show the user the first screen he should see after being authenticated. This might be the screen that appears at the end of the Web Express Logon logon macro.
- If the host credentials have not already been supplied, use the getUserCredential() method to request the user's credentials from the vault.
- If the credentials are received successfully (the method does not return null), do the following:
- Set the global variable to show that the user's host credentials have been supplied.
- Run the Web Express Logon logon macro.
- If getUserCredential() returns null, do the following:
- Present a sign-on screen to request the user's information. This can be a transformed host screen or an HTML page you have created for this purpose.
- Store the input in global variables and add it to the vault.
- Set the global variable to show that the user's host credentials have been supplied.
- Show the user the first screen he should see after being authenticated.
Extending the Entry portlet
One way to add function to your HATS portlet is by extending the Entry portlet. For example, you might want to extend it in order to have your portlet listen for messages, or to exchange properties as a cooperative portlet. To extend the Entry portlet create a new class file. Follow these steps:
- Click File > New > Java > Class file. Your new class must extend com.ibm.hats.runtime.EntryPortlet.
- Expand your project and the WEB-INF folder. Open the web.xml file in the Web deployment descriptor editor. On the Servlets tab, select EntryPortlet in the Servlets and JSPs section, then click Browse in the details sections for the Servlet class field. Select the class you created in step 1, and save the descriptor.
- Extend any of the following methods to provide custom function. Right click in the source and select Override/Implement methods.You must call the super() when overriding any of these methods. Refer to the WebSphere Portal Javadoc for more information.
- doHelp
- doEdit
- doConfigure
- doView
- actionPerformed
- beginPage
- endPage
- init
- destroy
- logout
- login
- Add one of the following interfaces. Refer to the WebSphere Portal Javadoc for more information.
- MessageListener
- PropertyListener
- EventPhaseListener
- PortletTitleListener
- WindowListener
- PortletSettingsAttributesListener
- PortletApplicationSettingsAttributesListener
Portlet messaging
Portlets can send messages to one another. A message can be directed toward a particular portlet or broadcast to all portlets. Follow the steps in this section to enable your portlet to send or receive messages.
Sending messages
Follow these steps to send messages from your HATS portlet:
- Create new business logic. Right-click in the HATS Project view of the HATS Studio, and select New HATS > Business Logic. Select the Portlet integration samples check box. Use one of the sample functions: broadcastPortletMessage to broadcast a message to all listening portlets, or sendPortletMessage to direct a message to a specifc portlet.
- Choose a screen customization or application event that you want to use to trigger the message.
- Create a prepresentation block in the screen customization or application event. Add an execute business logic action to this block to execute the business logic you just created.
Receiving messages
To receive messages, extend the Entry portlet, as described in Extending the Entry portlet. Your custom class must implement the org.apache.jetspeed.portlet.event.MessageListener interface. Implement the corresponding method. When you retrieve the information from the message, store it in a shared global variable so it can be accessed in a normal HATS fashion, or used in a screen recognition. A sample method follows:
public void messageReceived(MessageEvent event) throws PortletException { PortletRequest request = event.getRequest(); PortletSession session = request.getPortletSession(); DefaultPortletMessage dpm = (DefaultPortletMessage) event.getMessage(); ClientSpecificInfo csi = ClientContainer.getInstance().accessClient(session.getId()); if (csi == null) { System.out.println("mesg receiver could not access csi"); return; } Hashtable gvs = csi.getGlobalVariables(); IGlobalVariable gv = new GlobalVariable("msg", dpm.getMessage()); gvs.put("msg", gv); }Cooperative portlets
Cooperative portlets are portlets that exchange information through the property broker. Cooperative portlets can react to changes to other cooperative portlets on the page, resulting in a simultaneous update to multiple portlets with minimal user intervention. Refer to the WebSphere Portal Information Center for a complete description of cooperative portlets.
If you have not already implemented cooperative portlets in your WebSphere Portal, begin by downloading the Portlet Wiring Tool from the WebSphere portlet catalog at https://www-3.ibm.com/services/cwi/portal/_pagr/105 to your WebSphere Portal machine. Install this portlet and deploy it to a Portal page.
Modify the web.xml file of your HATS portlet application to wrap the portlet in a special class as follows:
<servlet id="Servlet_1"> <servlet-name>EntryPortlet</servlet-name> <display-name>entry</display-name> <servlet-class>com.ibm.wps.pb.wrapper.PortletWrapper</servlet-class> <init-param> <param-name>c2a-application-portlet-class</param-name> <param-value>com.ibm.hats.runtime.EntryPortlet</param-value> </init-param> <load-on-startup>-1</load-on-startup> </servlet>Implementing cooperative portlets requires three steps. These steps are described in the following sections.
- Configuring some portlets to publish properties
- Configuring some portlets to receive properties
- Establishing the wires connecting the portlets that publish and receive each property
Publishing properties from your HATS portlet
To publish properties, first register the properties that you will publish. The publishPortletProperty method, which is created in new business logic classes when you select the Portlet integration samples check box, always passes a HATS global variable. Then...
- Choose one or more global variables that you will use to contain the properties that you will publish.
- Create a business logic class. Select the Portlet integration samples check box.
- Use the registerProducedProperty sample method to register the names of all the global variables you plan to share.
- Add this business logic to the Start event for your application. Refer to HATS User's and Administrator's Guide for information about adding actions to events.
To publish the properties,...
- Create a business logic class. Select the Portlet integration samples check box.
- Use the publishPortletProperty sample method to publish a global variable. This method informs the property broker that the value of the property, which is contained in the global variable, has changed.
- Choose a screen customization or application event that you want to use to publish the global variable.
- Create a prepresentation block in the screen customization or application event. Add an execute business logic action to this block to execute the business logic you just created.
Receiving properties in your HATS portlet
Just as register the names of the global variables you plan to publish, also register the names of the global variables for which you want to receive updates. Follow these steps:
- Create a business logic class. Select the Portlet integration samples check box.
- Use the registerConsumedProperty sample method to register the names of all the global variables for which you want to receive updates.
- Add this business logic to the Start event for your application. Refer to HATS User's and Administrator's Guide for information about adding actions to events.
To receive property update messages, extend the Entry portlet, as described in Extending the Entry portlet. Your custom class must implement the PropertyListener interface. Implement the corresponding method. You can retrieve properties from the array of Properties and modify your current set of global variables in much the same way as in the portlet messaging case.
Following is an example of tracing the incoming properties. You can use a similar technique to step through the received properties and trace them.
public void setProperties(PortletRequest arg0, PropertyValue[] pvs) { for(int i=0;i<pvs.length;i++) { PropertyValue pv = pvs[i]; System.out.println("prop name: "+pv.getProperty().getName()+" type " +pv.getProperty().getType()); System.out.println("with val: "+pv.getValue().toString()); } }Connecting the portlets
After you have deployed your portlets, use the Portlet Wiring Tool to establish wires for each property between the publishing and receiving portlets on the Portal page. Refer to the information that is downloaded with the tool for instructions.
Example of converting a HATS Model 1 application to a portlet
If you have a HATS project application that is based on Model 1 pages, you can create a portlet with the same functionality. This approach requires that your application contain Integration Objects that are driven by Java Server Pages (JSPs). Follow these steps to create the portlet:
- Create a new portlet project. Click File > New > Portal > Portlet Project.
- Name the project, accept the default values, and complete the wizard. For the purpose of these instructions, suppose you name the project model1. You might see a confirmation dialog for switching the perspective. You can select the perspective of your choice.
- Export all your Integration Objects to your new project by following steps 1 through 6 of Using an Integration Object in a Web container (custom servlet or JSP). The portlet project that you create in step 1 serves as the target project to which you will export the Integration Objects. The main portlet class referenced by portlet.xml is the custom servlet used to drive the Integration Objects. Any method calls used for initiating the HATS runtime should be added to the init method of the portlet class.
- Copy all of your Model 1 JSPs to your new project. For example, copy Input.jsp and Output.jsp to the Web Content/model1/jsp/html folder. Choose one of your JSPs to be the default view. This is the JSP that displays when the portlet is first accessed.
- Modify your portlet to emulate the Model 1 application. Locate the Java source file referenced by portlet.xml. This file extends the PortletAdapter class and is typically Java Source/model1/model1Portlet.java. Add the following to the class:
public static final String HP_PAGE_TARGET = "/model1/jsp/Output.jsp"; public static final String DEFAULT_VIEW_JSP = "/model1/jsp/Input.jsp"; public static HashMap actionMap = new HashMap(); static { actionMap.put("action1","/model1/jsp/Output.jsp""); actionMap.put("action2","/jsp/HPPage2.jsp"); actionMap.put("action3","/jsp/HPPage3.jsp"); }- Replace the doView method and the actionPerformed method with the following methods:
public void doView(PortletRequest request, PortletResponse response) throws PortletException, IOException { String jspTarget = (String) request.getAttribute(HP_PAGE_TARGET); if(jspTarget==null) { //for a simple refresh jspTarget = (String) request.getPortletSession().getAttribute(HP_PAGE_TARGET); } if(jspTarget==null) { //for the initial portlet view jspTarget = DEFAULT_VIEW_JSP; } request.getPortletSession().setAttribute(HP_PAGE_TARGET,jspTarget); getPortletConfig().getContext().include(jspTarget, request, response); }public void actionPerformed(ActionEvent event) throws PortletException { String actionString = event.getActionString(); PortletRequest request = event.getRequest(); if(actionMap.containsKey(actionString)) { request.setAttribute(HP_PAGE_TARGET,actionMap.get(actionString)); } }- Create an action name for every JSP to which information is submitted using a form, and add it to the actionMap as in the static block of code in step 5.
- Modify each JSP file.
- Strip the HTML, HEAD, and BODY tags so that each JSP is a fragment. Refer to the WebSphere Portal Coding Practices for fragment guidelines at http://www7b.software.ibm.com/wsdd/zones/portal/portlet/portletcodingguidelines.html
- Replace the FORM tag's action attribute with the following JSP tag, replacing the value of the action attribute with the mapping you used in step 5.
<portletAPI:createURI> <portletAPI:URIAction name="action1" /> </portletAPI:createURI>- For every page that you add the portletAPI as described, add the <portletAPI:init/> tag before any other portlet tag processing.
- Remove the reference to hats.tld from the JSPs.
- Remove the reference to BasicIoError.jsp from the JSPs.
- Open the deployment descriptor located at Web Content/WEB-INF/web.xml for the portlet and add a "." (period) at the beginning of the display name tag value. For example, change <display-name>model1</display-name> to <display-name>.model1</display-name>.