<<

. 50
( 87 .)



>>

// If the user has not already voted show poll question
// otherwise show poll results.
String user = request.getUser().getUserID();
boolean hasUserVoted = broker.hasUserVoted(user, pollName);

if (hasUserVoted) {
pollBean.initializeResults(broker);
request.setAttribute("pollBean", pollBean);
portletContext.include(VIEW_RESULTS_JSP, request, response);
}
else {
request.setAttribute("pollBean", pollBean);
portletContext.include(VIEW_QUESTION_JSP, request, response);
}
}
P1: FCH/SPH P2: FCH/SPH QC: FCH/SPH T1: FCH
WY009-16 WY009-BenNatan-v1.cls May 11, 2004 14:50




300 Chapter 16


You see from this code that the portlet con¬guration information that de¬nes
the name of the poll and the information that speci¬es the datastore are kept
in the portlet settings. With that information, you can ask our datastore
manager class (Broker) for an instantiated Poll object (PollBean) for
the poll with the given name.
You can get the userid of the logged-in user from the User object. The
User object is available from the PortletRequest object. Then determine
if a vote for this poll for the current user has already been registered and
if not invoke the JSP to show the poll question. If the user has voted, get
the vote results from the Broker and invoke the JSP to show the results, as
shown in Figure 16-2.
Next consider the con¬guration pages for this portlet. As you have just
seen, the poll name and the persistent store information are retrieved from
portlet settings. These can initially be con¬gured in the portlet deploy-
ment descriptor but we want to allow the portal administrator to make
modi¬cations to these values after the portlet has been deployed. Also,
the administrator will need to specify the poll question and answers, al-
though that information will be kept in the persistent store, not the portlet
settings. We want that information outside the scope of a single portlet in-
stance since the information may be shared across multiple poll portlet in-
stances. Also we don™t want the data to be lost when the portlet gets recon¬g-
ured.
The implementation for con¬gure mode will be very similar to what you
just did for view mode, except now it gets a bit more complicated, as you
have page navigation issues to consider and action event processing to
handle.




Figure 16-2 The results of the poll.
P1: FCH/SPH P2: FCH/SPH QC: FCH/SPH T1: FCH
WY009-16 WY009-BenNatan-v1.cls May 11, 2004 14:50




Portlet Development 301

/**
* Render the configure mode view
*/
public void doConfigure(PortletRequest request,
PortletResponse response)
throws PortletException, IOException {

// Create a form data object and put it on session
PortletSession session = request.getPortletSession();
SessionData sessionData = new SessionData();
session.setAttribute(SESSION_DATA, sessionData);
ConfigureFormData formData = sessionData.getConfigureFormData();

// Get the portlet settings
PortletSettings portletSettings = request.getPortletSettings();
String persistType = portletSettings.getAttribute(PERSIST_TYPE);
String datasource = portletSettings.getAttribute(DATASOURCE);

// Set the portlet settings in the form data bean on session
formData.setDatasource(datasource);
formData.setPersistType(persistType);

// Invoke the JSP to render
portletContext.include(CONFIGURE_JSP, request, response);

}


This implementation is still simple. We introduce a ConfigureFormData
object that will hold the input data as the user steps through the con¬g-
uration pages. This object will be held in session and so we also create a
SessionData object to hold the portlet data that will go on the actual ses-
sion object. Putting the portlet session data in a single object makes it easier
to clean the session data and also reduces the number of attribute names
that need to be managed.
Now the processing gets a little more complicated as we have three actions
that can occur on the user interface for this ¬rst page. The user can verify
the datasource de¬nition. The user can advance to the next con¬guration
page or cancel from con¬gure mode completely. The speci¬cations for these
action events are in the JSP through encoding in the link URI. The JSP uses a
custom tag from the portlet tag library to create a URI that can be speci¬ed on
links de¬ned by the Action attribute or an href attribute. Two examples
of using the tag are

<portletAPI:createURI>
<portletAPI:URIAction name="verify"/>
</portletAPI:createURI>
P1: FCH/SPH P2: FCH/SPH QC: FCH/SPH T1: FCH
WY009-16 WY009-BenNatan-v1.cls May 11, 2004 14:50




302 Chapter 16


and

<portletAPI:createReturnURI/>


The ¬rst tag creates a URI that encodes both the portlet reference and
a trigger for an action event. The portlet container will interpret this URI
and call the portlet™s actionPerformed method, that is, if the portlet class
implements that ActionListener interface. The action event is named so
the actionPerformed method can interrogate the Event object, retrieve
the name, and execute the correct behavior for this action event. The same
actionPerformed method will get called for all action events for this
portlet so the event name is needed to distinguish events.
The second tag does not associate an action event with the URI and simply
asks the portal container to return the portlet to its previous mode. For
example, if the user had been in view mode prior to con¬gure mode, then
this URI will return the portlet to view mode.
The following listing shows a complete JSP for the ¬rst page of con¬g-
ure mode. This is slightly different than the version that is available via
download. It has been changed somewhat to reduce the size. If you are
implementing this in Studio, this ¬le is named configure.jsp and is in
a JSP directory under WebContent.

<%@ page contentType="text/html"%>
<%@ page import="com.ibm.sample.portlet.poll.beans.ConfigureFormData"%>
<%@ page import="com.ibm.sample.portlet.poll.portlet.PollConstants"%>
<%@ taglib uri="/WEB-INF/tld/portlet.tld" prefix="portletAPI"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jstl/fmt"%>

<jsp:useBean id="sessionData"
class="com.ibm.sample.portlet.poll.beans.SessionData" scope="session"/>
<fmt:setBundle basename="nls.polling"/>
<portletAPI:init />

<%
ConfigureFormData formData = sessionData.getConfigureFormData();
String message = sessionData.getMessage();
String dataSource = formData.getDatasource();
String persistType = formData.getPersistType();
%>

<form method="post" name="<portletAPI:encodeNamespace value="form"/>">
<table align="left" width="400">

<tr>
<td class="wpsInlineHelpText" colspan="2">
<img src='<%=response.encodeURL("/images/msg_inline_help.gif")%>'
P1: FCH/SPH P2: FCH/SPH QC: FCH/SPH T1: FCH
WY009-16 WY009-BenNatan-v1.cls May 11, 2004 14:50




Portlet Development 303


border="0"/>&nbsp;
<fmt:message key="configure.initinfo"/>
</td>
</tr>

<tr>
<td class="wpsPortletHead">
<input type='radio' name='persist_type' value='memory'>
</td>
<td class="wpsPortletHead">
Memory
</td>
</tr>

<tr>
<td class="wpsPortletHead">
<input type='radio' name='persist_type' value='database'>
>
</td>
<td class="wpsPortletHead">
Database - specify datasource name
</td>

</tr>
<td class="wpsPortletHead"></td>
<td class="wpsPortletSmText">
<input type='text' name='datasource' value='' size='40'>
</td>
</tr>

</tr>
<td class="wpsPortletHead"></td>
<td align="left" valign="bottom" nowrap>
<input class="wpsButtonText"
type='submit' value='Verify' name='verify'
onClick="document.<portletAPI:encodeNamespace
value='form'/>.action=
'<portletAPI:createURI>
<portletAPI:URIAction name="verify"/>
</portletAPI:createURI>'">
</td>
</tr>

<tr>
<td class="wpsPortletSmText" colspan="2">
<input class="wpsButtonText"
type='submit' value='Next'
onClick="document.<portletAPI:encodeNamespace
value='form'/>.action=
'<portletAPI:createURI>
P1: FCH/SPH P2: FCH/SPH QC: FCH/SPH T1: FCH
WY009-16 WY009-BenNatan-v1.cls May 11, 2004 14:50




304 Chapter 16


<portletAPI:URIAction name="config_pg2"/>
</portletAPI:createURI>'">

<input class="wpsButtonText"
type='submit' value='Cancel'
onClick="document.<portletAPI:encodeNamespace
value="form"/>.action=
'<portletAPI:createReturnURI>
<portletAPI:URIAction name="Cancel"/>
</portletAPI: createReturnURI>">
</td>
</tr>
</table>
</form>


Notice in the JSP that we namespace-encode the document object names.
Instead of encoding each individually we encode the name of the form
object. That way any references to objects within the form are namespace-
protected as well. To do this we use the <portletAPI:encodeName
space/> tag.
Also, as of Portal version 5 the preferred method to get text strings from
resource bundles is through the Java Server Pages Standard Tag Libraries
(JSTL) fmt tag library. You will need to get the open source libraries, stan-
dard.jar and jstl.jar, and add them to your portlet application li-
braries folder.
You will also notice a reference to an image ¬le in the JSP. This ¬le is
packaged with the portlet in an images folder under WebContent. The
URI reference to that resource must also be encoded to successfully resolve
the reference. To do that we used the encodeURL method from the portlet
response object:

<%=response.encodeURL("/images/msg_inline_help.gif")%>

The JSP also uses style de¬nitions from the portal Cascading Style Sheet
(CSS) ¬le named styles.css. The JSP has access to this style sheet. The

<<

. 50
( 87 .)



>>