Programming in HATS portlets
This chapter assumes that you are familiar with developing portlets for WebSphere Portal. HATS User's and Administrator's Guide explains how to convert HATS projects into portlets in HATS Studio. You must have WebSphere Portal Toolkit Version 5.0.2 installed on your Studio machine. The Portal API documentation (Javadoc) is installed with the toolkit and contains information that will be useful in performing the tasks described in this chapter.You can use the Portal API in business logic or JSPs.
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 click this check box, HATS will create 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, will cause 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.
Use 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 plug-in called WebSphere Portal Credential Vault Credential Mapper. This plug-in will appear in the Add Credential Mapper plug-in dialog only for a portlet project. This plug-in will retrieve a passive user-password credential from a vault slot whose name is specified via the single plugin parameter Slot ID. The actual vault slot ID that is used is the slotID concatenated using spaces with the host name, then the application name. The three elements of the slot ID will be encoded to replace spaces with underscores. To see how this slotID is generated, refer to the sample credential vault business logic methods. These methods are added to a new business logic class when you click 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 plug-in 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 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 Plug-in. This plug-in will appear in the Add Network Security plug-in dialog only for a portlet project.
As described in Create plug-ins for Web Express Logon, Web Express Logon uses two types of plug-ins, Network Security plug-ins and Credential Mapper plug-ins. Any of the Network Security plug-ins supplied with HATS can be used in a HATS portlet. Here are some possible combinations of plug-ins you can use in your portlet:
Table 4. Network Security plug-in Credential Mapper plug-in WebSphere Portal NS plug-in any supplied or custom CM plug-in none WebSphere Portal Credential Vault CM plug-in custom NS plug-in custom CM plug-in Here is a possible set of steps you can use to 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 they 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 user's host credentials have not already been supplied, follow these steps:
- 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), 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, 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. 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 above, 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 tab of the HATS Studio, and select New HATS > Business Logic. Click 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. Here is a sample method:
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 V5.0 InfoCenter 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.
- Configure some portlets to publish properties
- Configure 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 click the Portlet integration samples check box, always passes a HATS global variable. So begin by choosing one or more global variables that you will use to contain the properties you will publish. Then follow these steps:
- Create a business logic class. Click 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, follow these steps:
- Create a business logic class. Click 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. Click 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.
Here is an example of tracing the incoming properties. 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 downloaded with the tool for instructions.
Example of converting a HATS Model-1 application to a portlet
If you have a HATS project application based on Model-1 pages, you can convert it directly to a portlet. This approach requires that your application contain Integration Objects driven by Java Server Pages (JSPs). Follow these steps to convert your application to a portlet:
- Create a new portlet application. Click File > New > Portlet Development > Portlet Application Project.
- Complete the wizard. Name your project and accept the default values.
- Export all your Integration Objects to your new project.
- Copy all your JSPs to your new project. Choose one of your JSPs to be the default view.
- Modify your portlet to emulate the Model-1 application.
public class JSPFlowPortlet extends PortletAdapter implements ActionListener { public static final String HP_PAGE_TARGET = "HostPublisherTargetedJsp"; public static final String DEFAULT_VIEW_JSP = "/jsp/HPPage1.jsp"; public static HashMap actionMap = new HashMap(); static { actionMap.put("action1","/jsp/HPPage2.jsp"); actionMap.put("action2","/jsp/HPPage3.jsp"); actionMap.put("action3","/jsp/HPPage4.jsp"); } 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 page to which information is submitted using a form, and add it to the actionMap as in the static block of code above.
- 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
- Add the include statement for portlet.tld tag library:
<%@ taglib uri="/WEB-INF/tld/portlet.tld" prefix="portletAPI" %>- Replace the FORM tag's action attribute with the following JSP tag, replacing the action attribute with the mapping you used above.
<portletAPI:createURI> <portletAPI:URIAction name="action1" /> </portletAPI:createURI>.
Home