<<

. 57
( 87 .)



>>

let deployment descriptors. The generated source code, JSPs, and resource
bundle along with their packages and folders should be deleted from the
new project.
After deleting these ¬les, use Copy and Paste in Studio to copy the Java
Source packages and their contents and the WebContent images and jsp
folders from the Poll project to the Poll JSR 168 project. You should have
previously removed the portlet-api.jar and wpsportlets.jar from
the project build path. As a result, you will see a number of errors in the
new project after the copying completes.

PollPortlet
First change the PollPortlet class de¬nition to extend GenericPort-
let and remove “implements ActionListener.” If you have an init
method, then that method signature has changed and so it now throws a
PortletException instead of an UnavailableException.
P1: FCH/SPH P2: FCH/SPH QC: FCH/SPH T1: FCH
WY009-17 WY009-BenNatan-v1.cls May 11, 2004 14:51




340 Chapter 17


The actionPerformed method is replaced by a processAction
method. The processAction method takes ActionRequest and Ac-
tionResponse parameters instead of an Event parameter. With no Event
object available, the event processing is controlled by request parameters
put on the ActionURL as opposed to an action name available from the
Event object. All methods invoked from either processAction or ac-
tionPerformed must be updated to take an ActionRequest object in-
stead of PortletRequest.
/**
* Process an action request
*/
public void processAction(ActionRequest request,
ActionResponse response)
throws PortletException, IOException {

// Get the action handler class and dispatch
String actionClassName = request.getParameter(ACTION);
Action action = ActionClassManager.getAction(actionClassName);

// Dispatch to that class event handler
PortletContext
portletContext=getPortletConfig().getPortletContext();
action.actionPerformed(request, portletContext);
action.setView(request);
}

The PollPortlet service method must be replaced with a doDispatch
method. The doDispatch method for our portlet simply gets the View
class for the current portlet mode and dispatches to it.
/**
* Dispatch to render View class for the current mode.
* The View class name was set in the Action phase or
* is the initial View for the current portlet mode.
*/
protected void doDispatch(RenderRequest request,
RenderResponse response)
throws PortletException, IOException {

View nextView = ViewClassManager.getView(request);
PortletContext portletContext=getPortletConfig().getPortletContext();
nextView.performView(request, response, portletContext);
}

The ViewClassManager getInitialView method must then change
to handle the custom con¬gure mode. A new PortletMode instance is
de¬ned for the “con¬g” mode de¬ned by the portal vendor.
PortletMode CUSTOM_CONFIG_MODE = new PortletMode("config");
P1: FCH/SPH P2: FCH/SPH QC: FCH/SPH T1: FCH
WY009-17 WY009-BenNatan-v1.cls May 11, 2004 14:51




Portlet Interactive Debug and JSR 168 Example 341


Then the current mode can be retrieved from the RenderRequest object
and checked against this mode to determine the appropriate View class.

if (CUSTOM_CONFIG_MODE.equals(request.getPortletMode())) {}



Action Classes
In general, the only change needed for the Action classes is the action-
Performed method changes to the ActionRequest object. One difference
we also need to consider is the portlet mode during action phase process-
ing. With the IBM Portlet API a mode change occurs after the action pro-
cessing. With the JSR 168 API the mode change occurs during the action
processing. So, our portlet code needs to take this into consideration when
the View is set for the current mode in the action phase. The only issue is
during a mode change when we would normally remove the mode-speci¬c
View reference from session. With the new API, since the mode has already
changed we remove View references for all modes from session.
The use of PortletSettings and PortletData must be changed to
use PortletPreferences. Like the PortletSettings and Portlet-
Data objects the PortletPreferences object is available from the re-
quest object. You use the setValue and getValue methods to access the
preference attributes and the store method to save them.


Model Objects
There are no additional changes needed for our model objects. Likewise,
the persistence classes and utility classes require no changes.


View Classes
An additional change (beyond referencing RenderRequest and Render-
Response and changes to use PortletPreferences) is the invocation
of the JSP.
Prior to rendering output to the response, either writing directly to the
response PrintWriter or through a JSP, the response content type must
be explicitly set. If it is not, you will get the following exception:

Nested Exception is java.lang.IllegalStateException: No content
type set.

JSPs are invoked from the RequestDispatcher instead of from the
portletContext. So, an example JSP invocation is

response.setContentType(request.getResponseContentType());
portletContext.getRequestDispatcher(EDIT_JSP).include(request,response);
P1: FCH/SPH P2: FCH/SPH QC: FCH/SPH T1: FCH
WY009-17 WY009-BenNatan-v1.cls May 11, 2004 14:51




342 Chapter 17


User Identi¬er
The API to retrieve the user pro¬le information is quite a bit different be-
tween the APIs. The Poll portlet uses the id of the user to uniquely register
a vote and to determine if the user has already voted. This function is
implemented in the VoteAction action class and MainView state class,
respectively. The IBM Portlet API returns the user identi¬er from the User
object:
String user = request.getUser().getUserID();

The JSR 168 API returns the user identi¬er from the java.security
.Principle object:
Principal principal = request.getUserPrincipal();
String user = principal.getName();

Note that WebSphere Applicaton Server security must be enabled for the
Principal object to be created. If security is not enabled then the
getUserPrinciple method will return null. By default for an LDAP con-
¬guration the getName() method will return the UID attribute.
Therefore, change the code in both classes to return the user name using
the Principle object, making sure to check for a null object and return
a meaningful error message if security is not enabled. The following code
snippet assumes that the appropriate error message is de¬ned in the re-
source bundle.
Principal principal = request. getUserPrincipal();
if (principal == null) {
ResourceBundle bundle = ResourceBundle.getBundle("nls.polling",
request.getLocale());
throw new PollMessageException
(bundle.getString("exception.security"));
}
String userName = principal.getName();




JSPs
The JSP must also change to use the new tag library. Instead of the
portlet.tld tag library that was available with the IBM Portlet API,
the std-portlet.tld is provided with the JSR 168 API implementation.
This library contains the following tags:
- <portlet:defineObjects/> initialize RenderRequest,
RenderResponse, and PortletConfig objects support for use within the JSP
- <portlet:actionURL/> create a URL to invoke the processAction method
in the portlet.
P1: FCH/SPH P2: FCH/SPH QC: FCH/SPH T1: FCH
WY009-17 WY009-BenNatan-v1.cls May 11, 2004 14:51




Portlet Interactive Debug and JSR 168 Example 343


- <portlet:renderURL/> create a URL to invoke the doDispatch method
in the portlet.
- <portlet:namespace/> provide the encoded namespace of the portlet.

For example, to generate a URL for the portlet specifying an action you
would use the following tag:
<portlet:actionURL>
<portlet:param name="action" value="anActionClassName"/>
</portlet:actionURL>




Summary
This chapter reviewed the interactive test environment of WebSphere Studio
using the Poll portlet you developed in the previous chapter. You learned
how to con¬gure the test server and how to use the debugging environment
using a local Portal test environment.
In the second part of the chapter you modi¬ed that Poll portlet to use the
JSR 168 API instead of the IBM Portlet API used in its initial development.
The needed changes were reviewed.
P1: FCH/SPH P2: FCH/SPH QC: FCH/SPH T1: FCH
WY009-17 WY009-BenNatan-v1.cls May 11, 2004 14:51




344
P1: FCH
WY009-18 WY009-BenNatan-v1.cls May 11, 2004 14:51




CHAPTER

18

Struts Portlet Framework

This chapter discusses the implementation of a portlet using Struts Portlet
Framework. Struts is an Apache Jakarta project providing an open-source
framework for building Web applications. WebSphere Portal provides Struts
Portlet Framework that supports the deployment of Struts applications as
portlets.
Like you did for the JSR 168 API portlet implementation, you will convert
the Poll portlet developed using the IBM Portlet API for using Struts Portlet
Framework.
After the implementation process has been discussed, various approaches
to portlet development will be discussed, with recommendations given on
when each approach is appropriate.



Creating the New Project
We initially designed and implemented the Poll portlet separating action
event processing from our controller function and maintained clearly sep-
arated model and view classes. Because of this design our transition of this
code to the struts framework will be very straightforward.
The ¬rst step in creating a portlet using Struts Portlet Framework is
to import the PortalStrutsBlank.war ¬le into your project. In Web-
Sphere Portal V5.0 you will ¬nd the PortalStrutsBlank.war ¬le in
the <portal_root>\dev\struts\StrutsPortlet directory. Import-
ing this war ¬le adds the Struts jar ¬les for both Jakarta Struts and IBM™s
Struts Portlet Framework to the project lib directory. Again, we will use
WebSphere Studio for this development. The speci¬c steps shown here are

345
P1: FCH
WY009-18 WY009-BenNatan-v1.cls May 11, 2004 14:51




346 Chapter 18


based on WebSphere Studio 5.1.0 with Portal Toolkit version 5.0.2. Follow
these steps to create the base project:
1. Import Struts Portlet Framework into a new project. To do so, follow
these steps:
a. Select File ➪ Import ➪ AR ¬le from the Studio menu bar.

<<

. 57
( 87 .)



>>