307
CHAPTER 13
Exposing an Existing
Application As
a Portlet
I
N THIS CHAPTER WE
take an existing web application, the YAZD forum software, and
adapt it to provide a portlet front end. Initially, we install the forum software in its
unaltered state; then we show the decisions and changes we make in the process
of building the portlet.
Overview of the YAZD Forum Software
The YAZD forum software is available from
http://yazd.yasna.com
as an open source
product under the Apache License. This means that you are allowed to make any
changes you want to the source code as long as you keep all of the original copy-
right messages and as long as you call your resulting product something different.
This software has quite a few rough edges. Sometimes errors will be displayed
to the user instead of being caught and handled nicely. The initial configuration
of the application is quite complex. However, the code is readily adaptable and
sensibly designed, and the flaws can be fixed in the process of adapting it to a portal
environment.
All the code used in this example is available from our web site (
http://
portalbook.com/
), and it is the aim of the authors to make a complete package
available.
Using YAZD
Before we embark on a conversion of the YAZD application, we need to install and
configure it for our purposes. If you want to get a feel for the behavior of the forums
Configuring
Although the “general use” forums are mostly pretty slick, the forum administration
page is quite idiosyncratic (probably because it has received less feedback from
users). One particularly annoying bug causes a newly created forum to disappear
if you haven’t assigned it a moderator. To prevent this problem, we recommend
that you assign the default Administrator user all privileges immediately after cre-
ating a forum.
You should then assign “read messages” and “post messages” privileges to all
anonymous users.
Deciding What to Change
If you are building a portlet as a part of a large, well-funded project team—perhaps
portletizing a company’s premiere project—your aim in the process of portletization
will be to keep as much of the existing functionality as possible.
If like most project teams you have limited time and resources, you’ll be
looking to cut down the scope of the project as much as possible. For our exam-
ple chapter, we will be drastically trimming functionality from that offered by the
complete YAZD forums—we will dispense with the user account management of
the system so that only unauthenticated (anonymous) users will have access to
the system. We will also omit the search functionality (based on Lucene, which we
discussed in Chapter 10).
This leaves our portlet as a tool to allow anonymous users to view and post
into the YAZD forums. The basic administration functionality required to create
new forums and assign privileges to anonymous users can still be accessed via
the original application, since all message and account information is stored in
the database.
Giving Up Control
Probably the first thing to remember when you sit down to design the portlet
version of an existing application is that your application is not the only game in
town. You have given up some control over your environment in return for the
additional features offered by that environment.
311
Figure 13-3. The application as a portlet
Figure 13-4. The expanded portlet display
In Figure 13-4, you can see how the portlet presents the expanded list of
forums once the More link is selected. Note that this is still not as wordy as
the pre-portletization version shown earlier.
2840ch13.qxd 7/13/04 12:44 PM Page 311
Download at Boykma.Com
Chapter 13
312
Moving Around the Application
Most of the time, writing a portlet is not so different from writing a servlet, but in
one unexpected aspect they really are quite different: you cannot render URLs
directly if you want the link to appear within the portlet rather than as a page in
its own right.
NOTE
Actually the authors are quite perplexed by just how difficult rendering
a portlet URL has been made—sufficiently so that we suspect this is largely an
oversight by the developers of the standard.
The YAZD application has a GUI primarily built from JSP pages, so our solution
to this problem has been to create a tag library specifically for rendering links so
that the directed page will appear within the portlet.
To recap, one of your tasks when converting an existing application into
a portlet will be to determine which links need to leave the user in the portlet
rather than directing to an external page, and then rewriting those links appro-
priately.
Displaying Screens in a Portlet
Our application is to operate as a single portlet, but we want to base it on an
application that was designed as a number of JSPs (effectively servlets). We could
reconcile the two by discarding the JSPs and rewriting the portlet based on the
*
* @param path The path to the JSP to include
* @param request The request object to pass in
* @param response The response object to pass in
* @throws PortletException Thrown if there is a
* problem accessing the context
* @throws IOException Thrown if there is a
* problem writing the page fragment
*/
private void include(String path, RenderRequest request,
RenderResponse response) throws PortletException, IOException
{
getPortletContext().getRequestDispatcher(path).include(request,
response);
}
Here’s where most of the work is done—the
doView()
method looks in the
parameters supplied with the request for an
HREF
(the JSP page) and the
QUERY
(everything to be appended to the page). These are used to invoke a JSP page
stored in the WEB-INF directory, which therefore cannot be loaded directly by
the user.
The response from the page is rendered directly into the portlet’s response
stream.
The result is that we can invoke JSP pages quite simply with a minimal portlet.
Most of the additional effort involves adapting the JSP pages to remove unnecessary
or harmful tags (such as
getPortletContext().log("Query retrieved: " + query);
if ((href != null) && (query != null))
href += ("?" + query);
if (href == null)
href = VIEW;
if (state.equals(WindowState.NORMAL))
{
include(PORTLET_GUI + NORMAL + href, request, response);
}
else if (state.equals(WindowState.MINIMIZED))
{
include(PORTLET_GUI + MINIMIZED + href, request, response);
}
else if (state.equals(WindowState.MAXIMIZED))
{
include(PORTLET_GUI + MAXIMIZED + href, request, response);
}
2840ch13.qxd 7/13/04 12:44 PM Page 314
Download at Boykma.Com
Exposing an Existing Application As a Portlet
315
else
{
throw new PortletException(
"Unrecognized WindowState in View mode: "
+ state.toString());
}
}
/**
* Invoked by the portal to determine the title of
}
2840ch13.qxd 7/13/04 12:44 PM Page 315
Download at Boykma.Com
Chapter 13
316
// The name of the forums
private String forumName;
// The configuration name in the portlet.xml file
private static final String FORUM_NAME = "title";
// The location (relative to the portal's webapp) from which to obtain
// the GUI components which are all written as JSPs
private static final String PORTLET_GUI = "/WEB-INF/skins/portalized/";
// The path in the skin directory containing the various
// window-state versions of the display
private static final String MINIMIZED = "minimized/";
private static final String MAXIMIZED = "maximized/";
private static final String NORMAL = "normal/";
// The paths in the appropriate skin directories for
// the mode views of the portlet
private static final String VIEW = "view.jsp";
// The identifier for an unknown user
private static final String UNKNOWN = "anonymous";
}
Building a Tag Library
As we’ve just discussed, our controller portlet looks out for the configuration
parameters
HREF
and
QUERY
and converts them into a URL, which if followed by
on initialization.
Because of this, a relative URL like
images/postnewmsg.gif
cannot be used to
reference resources such as images that are not a part of the portlet itself. You
might think that you could work out what the “real” URL would be, but since the
mechanism used is not mandated by the standard, there’s no guarantee that your
solution would work on another platform.
To illustrate the mess this can make of your URL, the image mentioned if
rendered as a relative URL from the viewForum.jsp page in Pluto could end up
as (with line breaks introduced to fit it on the page):
http://localhost:8080/pluto/portal/test/_rp_test_row_col1_p3_href/1_post0x2jsp/
_st_test_row_col1_p3/normal/_md_test_row_col1_p3/view/
_pm_test_row_col1_p3/view/_ps_test_row_col1_p3/normal/
_rp_test_row_col1_p3_query/1_forum=2/_pid/
test_row_col1_p3/images/postnewmsg.gif
Obviously, there’s some method in this madness—we can make out the port-
let mode (view) and window state (normal) in there, along with the parts of the
URL we tried to add directly, but it’s far from obvious that what should have been
provided was
http://localhost:8080/yazd/images/postnewmsg.gif
And even if you knew the rule that Pluto had used to create this, there’s no
reason to imagine that any other portlet container will use the same mechanism.
We must therefore use the mechanism that we described in the introduction
to this section, and we’ll build a tag to do this. The following class achieves this:
2840ch13.qxd 7/13/04 12:44 PM Page 317
Download at Boykma.Com
Chapter 13
318
package com.portalbook.forums.tags;
* attribute relative to the context in which this
* portlet is running.
*
* @return SKIP_BODY
* @throws JspException if the output stream cannot be written
*/
public int doStartTag()
throws JspException
2840ch13.qxd 7/13/04 12:44 PM Page 318
Download at Boykma.Com