| This is the Rock, Paper, Scissors challenge coded into a JSF Portlet. This is a very simple example of a Java Server Faces, JSR-168 Portlet. This is highly recommended if you want a simple and straight forward introduction into how to code a JSF portlet. |
NEWLY ADDED!!!
rpsjsfportletfromtutorial.war |
| Another simple and straight forward example, but this time, demonstrating the struts portlet framework. This is the rock, paper, scissors application coded into a JSR168 portlet application using the apache struts portlet bridge. This is a great war file to examine if you want to learn the basics of struts development from within a portlet. |
NEWLY ADDED!!!
rpsstrutsportletfromtutorial.war |
|
|
Learing Portlet Development By Example
Here are the completed war files for a number of my tutorials, both from this website, and samples from my book on JSR-168 development as well. Enjoy!
And remember, if you find something on this site useful, please support our site. Tell some friends about it, link to it, charge some books to your corporate credit card, and check out what our sponsors are up to! Thanks, and Happy Portal!
|
| Just your average, everyday, HelloWorld portlet. |
HelloWorldPortlet.war |
| This simple portlet explores the request and response cycle. |
CountrySnooperPortlet.war |
| Again, this portlet examines the request-response cycle, examining incoming headers, and printing them out to the client. |
GettingHeadersPortlet.war |
| This portlet demonstrates how to forward to a JSP page and obtain user input in a portlet. |
JSPDisplayNoDefineObjectsTag.war
JSPDisplay_USING_DefineObjectsTag.war |
| Having trouble displaying an image in a JSR168 portlet? These war files do just that. Not too sure what the difference is between the two war files? Not sure if there is any, really? |
ImageDisplay.war
ImageDisplay02.war |
| This portlet keeps a hitcount using the PortletSession. User state is a terrible thing to waste, unless the state is Texas. :) |
SimplePortletSession.war |
| There's a new application scope with JSR168. This complete war file takes advantage of that new PortletSession scope, APPLICATION_SCOPE. |
PortletSessionApplicationScope.war |
| This war file uses the action processing phase of a portlet to shit the window state. |
StateShiftingAction.war |
| Ever try to implement a custom mode? This portlet war file does just that. Only works on portal servers that support a configure mode, such as WebSphere Portal Server. |
CustomModePortlet.war |
| This war file takes advantage of the PortletConfig and PortletContext objects. It is a very, kewl, war file. |
GenericTaxPortlet.war
|
|
| This war file is the first iteration of the NumberGuesser portlet. |
NumberGuesserBasics.war |
| This war file encodes the namespace of a form element. |
NumberGuesserEncodedNamespaces.war |
| This iteration of the NumberGuesserPortlet takes advantage of action processing. |
NumberGuesserProcessAction.war |
| This portlet application keeps track of the number of guesses a user takes to guess the right number, using, of course, the PortletSession. |
NumberGuesserPortletSession.war |
| This iteration works the edit mode into the NumberGuesserPortlet. |
NumberGuesserEdit.war |
| This iteration of the NumberGuesser takes advantage of portlet preferences, along with the PortletPreferencesValidator. |
NumberGuesserPortletPreferences.war |
| This is the Rock, Paper, Scissors challenge coded into a JSF Portlet. This is a very simple example of a Java Server Faces, JSR-168 Portlet. This is highly recommended if you want to learn how to code a JSF portlet. |
rpsjsfportletfromtutorial.war |
| This is the rock, paper, scissors application coded into a JSR168 portlet application using the apache struts portlet bridge. This is a great war file to examine if you want to learn the basics of struts development from within a portlet. |
rpsstrutsportletfromtutorial.war |
Any preliminary look at the portlet API
will demonstrate a major similarity between portlets and servlets. Both
portlets and servlets handle the request-response cycle, both are Java
centric components, and both have access to the J2EE runtime
environment. But there are some major differences between portlets and
servlets as well. One of the most significant ways portlets are
different from regular servlets is their support for various modes,
namely view, edit and help. When it comes to portlet modes, there is no
applicable analogy to typical servlet and JSP programming. This chapter
will look at the various modes available to the portlets you create, and
how a developer can programmatically take advantage of these modes.
Breaking Away from a Portlet as a Servlet Mentality Handling a
request-response cycle is the most fundamental aspect of portlet
programming, but inspecting a request and sending out a response to the
client through a portlet is by no means revolutionary. After all,
request-response programming is exactly what we do in a Java servlet.
Let?s compare a Portlet to a Servlet: instead of a doView method, a Java
Servlet has a doPost or a doGet method. Instead of being passed a
PortletRequest or a PortletResponse object, a Java servlet is given an
HttpServletRequest and HttpServletResponse object. In many ways,
handling the request-response cycle of a portlet is very similar to
handling the request-response cycle of a Servlet. In fact, one of the
great things about portlets is the fact that they leverage our existing
knowledge of the Servlet and JSP APIs. But what makes a portlet so
incredibly sexy is all of the features and services the Portlet API
affords us, over and above that of the Servlet API. The most fundamental
difference between a Portlet and a Servlet is the various modes in which
a Portlet can participate. A portlet has three standard, and any number
of custom, implementable modes, namely: F The View Mode F The Edit Mode
F The Help Mode The most common, and only required mode of a Portlet, is
the view mode. When a Portlet is displayed on a page, it is typically
displaying its view mode. In fact, the specification requires every
portlet to have a doView method so that the portlet can render itself on
a portal page. Optionally, a portlet can provide an implementation of
any of the other standard modes, with perhaps the most useful mode being
edit, and the most helpful, being help. J Figure 7-1The wrench, pencil,
and question mark represent the config, edit and help modes of a
portlet.Note that config is a custom mode. Basic Portlet Mode
Implementation At the most basic level, to support the standard portlet
modes, a portlet must implement a doEdit, doHelp, and doView method.
Figure 7-2 ----------------------------------------------- package
com.examscam.portlet; import java.io.*;import javax.portlet.*; public
class MultiModePortlet extends GenericPortlet { protected void
doView(RenderRequest request, RenderResponse response) throws
PortletException, IOException {
response.setContentType("text/html");
response.getWriter().print("This is the View mode."); }
protected void doEdit(RenderRequest request, RenderResponse response)
throws PortletException, IOException {
response.setContentType("text/html");
response.getWriter().print("This is the Edit mode."); }
protected void doHelp(RenderRequest request, RenderResponse response)
throws PortletException, IOException {
response.setContentType("text/html");
response.getWriter().print("This is the help mode."); } }
Along with an implementation of the appropriate do <Mode> method,
the deployment descriptor of the portlet must also indicate all of the
modes the portlet supports. """ <portlet>
<portlet-name>MultiModePortlet</portlet-name>
<display-name>MultiModePortlet</display-name>
<portlet-class> com.examscam.portlet.MultiModePortlet
</portlet-class> <supports>
<mime-type>text/html</mime-type>
<portlet-mode>view</portlet-mode>
<portlet-mode>edit</portlet-mode>
<portlet-mode>help</portlet-mode> </supports>
<portlet-info>
<title>MultiModePortlet</title></portlet-info>
</portlet> """ Portlet Mode Visualization When the
MultiModePortlet from Figure 7-2 is rendered by the portal, the skin of
the view mode displays edit, help, minimize and maximize icons. Clicking
on the question mark generates a pop-up window that displays the
contents of the doView method. Clicking on the pencil takes a user into
the edit mode of the portlet. The edit mode conveniently contains a
caret icon that can return a user to the view mode. Help Mode and the
doHelp Method The easiest portlet mode to implement has got to be the
help mode. The help mode is designed to simply display to the user
information about how to use the portlet. The help mode for the
NumberGuesserPortlet will simply inform the user that they need to keep
guessing a number until they get it right. Implementing the help mode
simply requires the implementation of a doHelp method in your code and
an update to the portlet.xml file to inform the portlet container that
your Portlet supports the help mode. User Customization and the Edit
Mode One of the main benefits of a portlet is the fact that it can be
customized by a user. If you have gone to any of the mega portals like
yahoo.com or excite.com, or have even installed the WebSphere Portal
Server and played around with some of the Pinnacore portlets, you have
inevitably run into a number of portlets you can customize by providing
the portlet any number of personalized parameters. The ubiquitous
weather portlet, the one that tells you the weather for three or four
major international cities the first time you see it, but also gives you
the ability to customize the portlet by telling it your ZIP code or the
city in which you live, is a prime example of a customizable portlet.
The weather portlet provides an edit mode that asks the user their zip
code or city of interest. The portlet stores that information
permanently, and then the next time the user views the weather portlet,
it will additionally display the weather for the specified city or zip
code of interest. The edit mode provides the user an opportunity to
provide personal preferences to a portlet. That information is then used
in the view mode to provide customized content delivery to the user. An
edit mode provides a user the opportunity to customize a portlet. To
handle these user requests for customizations, the portlet API matches
the edit mode of a portlet, to the doEdit method of a developer?s
portlet code. Figure 7-3 To implement the help and edit modes, a portlet
needs a doHelp and doEdit method. """protected void
doHelp(RenderRequest request, RenderResponse response) throws
PortletException, IOException {
response.setContentType("text/html");
response.getWriter().print("Just guess a number! ");
}"""protected void doEdit(RenderRequest request,
RenderResponse response) throws PortletException, IOException { String
url = "/numberguesseredit.jsp" ;
getPortletContext().getRequestDispatcher(url).include(request,
response);}""" Edit Mode and PortletPreferences Any
personal preferences provided to a portlet through the edit mode are
stored permanently. The next time the user visits that portal page, this
personalized information is retrieved for that user, and that user
specific information can be utilized to provide a customized view for
the user. As you could imagine, storing all of these user preferences
persistently, and tying that data to a specific user and a specific
portlet on a certain portal page is quite a bit of work. Fortunately,
implementing this functionality is not shouldered by the portlet
developer. Instead, the portlet API provides a very special component
called the PortletPreferences object. While in the action processing
phase of the edit mode of a portlet, a developer is allowed to stuff any
number of Strings into the PortletPreferences object, using the very
straightforward setValue(name, value) method. PortletPreferences prefs =
request.getPreferences(); if
(request.getParameter("guessedit") != null) { String newLimit
= request.getParameter("newlimit");
prefs.setValue("upperlimit", newLimit); prefs.store(); } Any
mode can access data stored in the PortletPreferences object, but only
during the action processing phase of the edit mode can you actually
change, add or update information stored as PortletPreferences. Store,
Store, Store! When a developer stuffs a Java object into a portlet?s
PortletData object, and subsequently calls the preferences.store()
method, the data that was stuffed into the preferences object is stored
persistently. A real rookie mistake is forgetting to call the store()
method after shoving Strings into the PortletPreferences object. There
is no design time type-checking to ensure the store method is called
after working with the PortletPreferences object, so you really have to
be diligent to ensure your preferences are stored permanently.
Initialization of PortletPreferences: portlet.xml One of the challenges
in working with the edit mode is initializing default values for
PortletPreferences, or as it was known in the Jetspeed API, PortletData.
With JSR-168, each portlet can configure any number of initial values by
specifying them in the portlet-preferences section of the deployment
descriptor. Furthermore, preferences can be multivalued, and stored as
an array of Strings, as opposed to just single value Strings. Finally,
PortletPreferences can be set as read-only. This essentially ensures
that a given PortletPrefernce will be common to all users of the
portlet. <portlet-preferences> <preference>
<name>upperlimit</name><value>10</value>
<read-only>false</read-only> </preference>
</portlet-preferences> It should also be noted that in order for a
portlet to support the edit mode, the portlet.xml file must have the
appropriate entry for the portlet. Manipulating PortletPreferences is
pretty much a moot endeavor if you haven?t specified in the deployment
descriptor that the portlet supports the edit mode. <supports>
<mime-type>text/html</mime-type>
<portlet-mode>view</portlet-mode>
<portlet-mode>edit</portlet-mode>
<portlet-mode>help</portlet-mode> </supports>
PortletPreferences and the NumberGuesser So, how can we take our simple,
NumberGuesserPortlet and complicate it to the n?th degree by adding user
customization through PortletPreferences? Well, by default, the user
guesses a number between 1 and 10. But perhaps we want the user to
customize the experience by choosing a number between 1 and 100, or 1
and 1000? We could easily make the range customizable through a
PortletPreference. Figure 7-6xxx Without preferences, our number
guessing game always uses 10 as the upper limit. We could store a String
value named upperlimit in the PortletPreferences object, and use the
portlet.xml file to give this value a default of 10.
<portlet-preferences> <preference>
<name>upperlimit</name><value>10</value>
<read-only>false</read-only> </preference>
</portlet-preferences> When the user starts the number guessing
game, we could use the upperlimit value, stored in the
PortletPreferences, to generate the magic number. /*obtain the
PortlePreferences object from the request*/ PortletPreferences prefs =
request.getPreferences(); /*pull the upperlimit String from the
preference*/ String upperLimit = prefs.getValue("upperlimit",
null); /*use the upperLimit to generate the new random number to be
guessed*/ long number
=(System.currentTimeMillis()%Integer.parseInt(upperLimit))+1; /*put the
new number in the session*/
session.setAttribute("magicnumber", new Long(number)); Figure
7-5 Updating the processAction method. public void processAction
(ActionRequest request, ActionResponse response) throws
PortletException, java.io.IOException {/* get the preferences and
session from the request object */ PortletPreferences prefs =
request.getPreferences();PortletSession session =
request.getPortletSession();/* if we are in the edit mode, get the new
range limit */ if (request.getParameter("guessedit") != null)
{ String newLimit = request.getParameter("newlimit");
prefs.setValue("upperlimit", newLimit); prefs.store();}/*
Obtain application data from the session. */Long magicNumber = (Long)
session.getAttribute("magicnumber");Long guess = new
Long(request.getParameter("number"));String guesses = (String)
session.getAttribute("guesses");String message = "Guess
Higher!!!";/* If a number was guessed, see if it is correct */if
(request.getParameter("guesssubmit") != null) { /* if the
magicNumber is null, this is their first guess. */ if (magicNumber ==
null) { String upperLimit = prefs.getValue("upperlimit",
null); /* use the range limit from preferences to calc the number */
long number = (System.currentTimeMillis()%Integer.parseInt(upperLimit))
+ 1; session.setAttribute("magicnumber", new Long(number));
guesses = "1"; }else { guesses = "" +
(Integer.parseInt(guesses) + 1); } if (guess.intValue() >
magicNumber.intValue()) { message = "Guess Lower."; } if
(guess.intValue() == magicNumber.intValue()) { message = magicNumber +
" is correct. # of guesses: " + guesses;
session.setAttribute("guesses","0");
session.removeAttribute("magicnumber"); }}/* appropriately set
the message and guess number in the session
*/session.setAttribute("message",
message);session.setAttribute("guesses", guesses);}
Customization Through the Edit Mode Figure 7-7 The user sets an custom
upper limit through the edit mode. While default values will be provided
through the portlet.xml file, the user can change the range by using the
edit mode of the portlet. The edit mode could be used to update the
preference, allowing the user to set a range larger than 1 to 10. /*if
the user clicked the button named guessedit from the edit page */ if
(request.getParameter("guessedit") != null) { String newLimit
= request.getParameter("newlimit");
prefs.setValue("upperlimit", newLimit); prefs.store(); } After
updating their preferences through the edit mode, when the user returns
to the view mode, all numbers will be generated based upon the new
range, as set in PortletPreferences. An additional code snippet in the
jsp allows the new upper range limit to be displayed to the user:
<%=renderRequest.getPreferences() .getValue("upperlimit",
null) %> Figure 7-8 Notice how the user has set the upper limit to
999, as opposed to the default of 10. Figure 7-9 Code used for the View
JSP in this example. Notice how the message is coming from the
PortletSession. <%@ page
contentType="text/html"%><%@taglib
uri="http://java.sun.com/portlet"
prefix="portlet"%><portlet:defineObjects
/><%=renderRequest.getPortletSession().getAttribute("message")%><FORM
action="<portlet:actionURL />">Pick a number between
1 and
<%=renderRequest.getPreferences().getValue("upperlimit",
null) %> <INPUT name="number" size="10"
type="text" /> <INPUT name="guesssubmit"
value="Guess!!" type="submit"
/></FORM>Number of
guesses:<%=renderRequest.getPortletSession().getAttribute("guesses")%>
Fig 7-10 The JSP used for the Edit mode, numberguesseredit.jsp <%@
page contentType="text/html"%><%@taglib
uri="http://java.sun.com/portlet"
prefix="portlet"%><portlet:defineObjects /> <FORM
action="<portlet:actionURL />">Choose the
range.<BR>The number will be between 1 and...<INPUT
name="newlimit" size="10" type="text"
/> <INPUT name="guessedit" value="Submit"
type="submit" /></FORM> Figure 7-11 Full portlet.xml
file. Notice the support for multiple modes, and the default value given
for the upperlimit preference. <portlet>
<portlet-name>NumberGuesser</portlet-name>
<display-name>NumberGuesser portlet</display-name>
<portlet-class> com.examscam.portlet.NumberGuesserPortlet
</portlet-class> <supports>
<mime-type>text/html</mime-type>
<portlet-mode>view</portlet-mode>
<portlet-mode>edit</portlet-mode>
<portlet-mode>help</portlet-mode> </supports>
<portlet-info> <title>NumberGuesser portlet</title>
</portlet-info> <portlet-preferences> <preference>
<name>upperlimit</name> <value>10</value>
<read-only>false</read-only> </preference>
</portlet-preferences></portlet> Fig. 7-12 The doEdit method
simply points to the edit.jsp. protected void doEdit (RenderRequest
request, RenderResponse response) throws PortletException, IOException {
String url = "/numberguesseredit.jsp" ;
this.getPortletContext().getRequestDispatcher(url) .include(request,
response);} Figure 7-11 NumberGuesser (Sorry it is so small, but I
wanted it on one page) package com.examscam.portlet;import
java.io.*;import javax.portlet.*;public class NumberGuesserPortlet
extends GenericPortlet { protected void doView(RenderRequest request,
RenderResponse response) throws PortletException, IOException {
PortletContext context = this.getPortletContext(); PortletSession
session = request.getPortletSession(); if
(session.getAttribute("message") == null) {
session.setAttribute("guesses", "0");
session.setAttribute("message", "Guess the
number!"); } String url = "/numberguesser.jsp";
context.getRequestDispatcher(url).include(request, response); }
protected void doHelp(RenderRequest request, RenderResponse
response)throws PortletException, IOException {
response.setContentType("text/html");
response.getWriter().print("You should be able to figure this
out!!!"); } protected void doEdit(RenderRequest request,
RenderResponse response) throws PortletException, IOException { String
url = "/numberguesseredit.jsp";
getPortletContext().getRequestDispatcher(url).include(request,response);
} public void processAction(ActionRequest request, ActionResponse
response) throws PortletException, java.io.IOException { PortletSession
session = request.getPortletSession(); /* obtain the PortlePreferences
object from the request */ PortletPreferences prefs =
request.getPreferences(); if
(request.getParameter("guessedit") != null) { String newLimit
= request.getParameter("newlimit");
prefs.setValue("upperlimit", newLimit); prefs.store(); } if
(request.getParameter("guesssubmit") != null) { if
(session.getAttribute("magicnumber") == null) { /* pull the
upperlimit String from the preference */ String upperLimit =
prefs.getValue("upperlimit", "3"); /* use the
upperLimit to generate the new random number to be guessed */ int
magicNumber = (int)((System.currentTimeMillis() %
Integer.parseInt(upperLimit)) + 1); /* put the new number in the session
*/ session.setAttribute("magicnumber", new
Integer(magicNumber)); session.setAttribute("guesses",
"0"); } Integer magicNumber =
(Integer)session.getAttribute("magicnumber"); String guesses =
(String) session.getAttribute("guesses"); guesses =
"" + (Integer.parseInt(guesses) + 1);
session.setAttribute("guesses", guesses);
session.setAttribute("message", "Guess higher!");
Integer guess = new Integer(request.getParameter("number"));
if (guess.intValue() > magicNumber.intValue()) {
session.setAttribute("message", "Guess lower!"); }
if (guess.intValue() == magicNumber.intValue()) { String message =
magicNumber + " is correct. Play again!";
session.setAttribute("message", message);
session.removeAttribute("magicnumber"); } } }} Figure 7-9 The
JSP used for the View mode, numberguesser.jsp <%@ page
contentType="text/html"%><%@ taglib
uri="http://java.sun.com/portlet"
prefix="portlet"%><portlet:defineObjects
/><%=renderRequest.getPortletSession().getAttribute("message")%><FORM
action="<portlet:actionURL />">I'm thinking of a
number between 1 and <%=renderRequest.getPreferences()
.getValue("upperlimit", null) %><INPUT
name="number" size="10" type="text" />
<INPUT name="guesssubmit" value="Guess!!"
type="submit" /></FORM>Number of
guesses:<%=renderRequest.getPortletSession().getAttribute("guesses")%>
Fig 7-10 The JSP used for the Edit mode, numberguesseredit.jsp <%@
page contentType="text/html"%><%@taglib
uri="http://java.sun.com/portlet"
prefix="portlet"%><portlet:defineObjects /> <FORM
action="<portlet:actionURL />">Choose the
range.<BR>The number will be between 1 and...<INPUT
name="newlimit" size="10" type="text"
/> <INPUT name="guessedit" value="Submit"
type="submit" /></FORM>Upper
Limit:<%=renderRequest.getPreferences().getValue("upperlimit",
null)%> PortletPreferences and the PreferencesValidator Part of the
JSR-168 API is a convenient interface called the PreferencesValidator.
PortetPreferences provide the end user the ability to customize their
user experience, but as with any type of input taken from a user, there
is the possibility that data provided to the server won?t be valid for a
particular scenario. To provide some level of control over how users
configure a particular preference, a PreferencesValidator can be coded,
and subsequently configured in the portlet.xml file. The
PreferencesValidator has only one method that needs to be overridden:
the validate(PortletPreferences prefs) method. The job of the developer
is to code a custom class that implements this interface, and then
configure the portlet.xml file, thus making the portal server aware of
the validator. The contract between the portlet.xml file and the portal
server ensures that before any data is saved into PortletPreferences,
the validate method of the PreferencesValidator will be invoked. If
validation fails, the validate method must throw the special
ValidatorException, which is part of the JSR-168 Portlet API. To ensure
that only numeric data is stored as an upper limit of the number
guessing game, a class that implements the PreferencesValidator was
coded, and configured in the portlet.xml file. PreferencesValidator and
ValidatorException NumberGuesserValidator As you can see, the
NumberGuesserValidator is relatively straight forward. The preference of
interest, the upperlimit, is pulled from the preferences object passed
into the validate method, and if the upperlimit field does not pass
muster, then a ValidatorException is thrown. package
com.examscam.portlet; import javax.portlet.*; public class
NumberGuesserValidator implements PreferencesValidator { public void
validate(PortletPreferences preferences) throws ValidatorException { try
{ String upperLimit = preferences.getValue("upperlimit",
null); if (upperLimit != null) { Integer.parseInt(upperLimit); } } catch
(NumberFormatException nfe) { throw new
ValidatorException("upperlimit", nfe, null); } } } Catching
PortletPreference Exceptions If you code a PreferencesValidator, it
makes sense that you would then catch the corresponding
ValidatorException in your portlet code; specifically, when you add new
data to your PortletPreferences. Notice that there are actually three
exceptions being handled in the following code snippet:
""" if (request.getParameter("guessedit") !=
null) { String newLimit = request.getParameter("newlimit");
try { prefs.setValue("upperlimit", newLimit); prefs.store(); }
catch (ValidatorException e) {e.printStackTrace(); } catch
(ReadOnlyException e) {e.printStackTrace(); } catch (IOException e)
{e.printStackTrace(); } } """ PortletPreference Related
Exceptions PortletPreferences are typically stored in a centralized
database, where the portal server can easily retrieve user
customizations. Because the act of storing data to a database, or even
just sending data across a network, can be problematic, the store method
of the PortletPreferences object can potentially throw the
java.io.IOException. More curiously though, the store method can throw
the javax.portlet.ReadOnlyException. In the portlet.xml file,
PortletPreferences can be configured, and default values can be assigned
to them. These default values will be used unless a user goes to the
edit mode and further customizes their preferences. However, in the
portlet.xml file, a preference can be marked as read-only. If a
preference is marked as read-only in the portlet.xml file, and an
attempt is made to edit that preference at runtime, a ReadOnlyException
is thrown. Finally, we should mention again that the PortletPreferences
object can potentially call the ValidatorException. If a
PreferencesValidator is configured in the portlet.xml file, and that
validator throws an exception when a particular field is placed into the
PortletPreferences, a ValidatorException will be triggered. Class
Diagram of the ReadOnlyException PreferencesValidator and the
portlet.xml File <?xml version="1.0"
encoding="UTF-8"?> <portlet-app
xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd"
version="1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd
http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd"
id="com.examscam.portlet.NumberGuesserPortlet.420453eee0">
<portlet> <portlet-name>NumberGuesser</portlet-name>
<display-name>NumberGuesser portlet</display-name>
<portlet-class> com.examscam.portlet.NumberGuesserPortlet
</portlet-class> <supports>
<mime-type>text/html</mime-type>
<portlet-mode>view</portlet-mode>
<portlet-mode>edit</portlet-mode>
<portlet-mode>help</portlet-mode> </supports>
<supported-locale>en</supported-locale> <portlet-info>
<title>NumberGuesser portlet</title> </portlet-info>
<portlet-preferences> <preference>
<name>upperlimit</name> <value>10</value>
<!--Setting read-only to true will trigger a ReadOnlyException if the
preference is updated at runtime.-->
<read-only>false</read-only> </preference> <!-- If
validation fails, a preferences-validator will throw a
ValidatorException.--> <preferences-validator>
com.examscam.portlet.NumberGuesserValidator
</preferences-validator> </portlet-preferences>
</portlet> </portlet-app> Question xxx-1 The decision as to
which of the various do methods to invoke, such as doEdit or doHelp,
occurs in which method? ˇ a) initˇ b) destroyˇ c) actionProcessˇ d)
doDispatch Question xxx-2 PortletPrefernces are not being saved. What
are two possibilities as to why this might be happening ¨ a) the store()
method is not being invoked¨ b) the save() method is not being invoked¨
c) the PortletPreferences are being configured in the doView method¨ d)
the PortletPreferences are being manipulated in the processAction method
Answer xxx-3 What are the standard, JSR-168, portlet modes? ¨ a) edit¨
b) view¨ c) help ¨ d) config Question xxx-4 To ensure a
PortletPreference has a default value, even if the user hasn?t
customized their portlet, the best plan of action is to: ¨ a) code a
default value in the web.xml file¨ b) code a default value in the
portlet.xml file¨ c) provide a default value as the second parameter of
the PortletPreferences getValue() method¨ d) accept a null value as a
valid PortletPreference Question 6-5 Which of the following checked
exceptions could be thrown by a call to the PortletPreferences store
method? ¨ a) ReadOnlyException¨ b) PortletException¨ c)
ValidatorException¨ d) IOException Answer xxx-9 Minimize, Maximize and
Normal are all valid: ˇ a) window statesˇ b) window modesˇ c) Portlet
statesˇ d) Portlet modes Answer 7xxx-7 Where is a PortletPreference
defined as being read only. ˇ a) programmatically through the
PortletPreferences objectˇ b) by adding a read-only parameter to the
portlet.xml fileˇ c) by adding a read-only parameter to the web.xml
fileˇ d) PortletPreferences are always editable Answer xxx-1 The
decision as to which of the various do methods to invoke, such as doEdit
or doHelp, occurs in which method? ˇ a) initˇ b) destroyˇ c)
actionProcessˇ d) doDispatch Option d) is correct.The init method is
called when a portlet is first loaded, and destroy is called when the
portlet is unloaded, but neither of those lifecycle methods have
anything to do with the render phase of a portlet. Similarly, the
actionProcess can help decide which mode or state in which a portlet
will appear, but it does not directly call doEdit or doView. It is the
doDispatch method that is responsible for figuring out which of the
do<mode> methods should be invoked for portlet rendering. Answer
xxx-2 PortletPrefernces are not being saved. What are two possibilities
as to why this might be happening ¨ a) the store() method is not being
invoked¨ b) the save() method is not being invoked¨ c) the
PortletPreferences are being configured in the doView method¨ d) the
PortletPreferences are being manipulated in the processAction method
Options a) and c) are correct.There are two common reasons why
PortletPreferences don?t get saved. First of all, developers forget to
call the store method, and secondly, developers try to manipulate
PortletPreferences in the wrong mode. Answer xxx-3 What are the
standard, JSR-168, portlet modes? ¨ a) edit¨ b) view¨ c) help ¨ d)
config Options a) b) and c) are correct.All JSR-168 compliant portal
servers must support view, edit and help modes. However, portal servers
are free to support any custom modes. The WebSphere Portal Server has
built in features for supporting a configure mode. Answer xxx-4 To
ensure a PortletPreference has a default value, even if the user hasn?t
customized their portlet, the best plan of action is to: ¨ a) code a
default value in the web.xml file¨ b) code a default value in the
portlet.xml file¨ c) provide a default value as the second parameter of
the PortletPreferences getValue() method¨ d) accept a null value as a
valid PortletPreference Options b) and c) are correct.Making sure
there?s a default value for a user configurable property is always a
challenge. With the PortletPreferences, we can code a default value in
two ways. First, we can put a preference value in the portlet.xml file.
Secondly, the getValue() method takes two parameters, the first being
the name of the property you wish to extract, and the second parameter
being a default value, just in case the property you are looking for
doesn?t exist. Answer 6-5 Which of the following checked exceptions
could be thrown by a call to the PortletPreferences store method? ¨ a)
ReadOnlyException¨ b) PortletException¨ c) ValidatorException¨ d)
IOException Options a) c) and d) are correct.PortletPreferences are
stored persistently, typically in a centralized database, and that
database write can throw an IOException. Furthermore, PortletPreferences
can be associated with a PreferencesValidator, which throws a
ValidatorException if a preference doesn?t pass a validation test.
Finally, PortletPreferences can be configured as being read-only, and if
someone tries to overwrite a read-only preference, a ReadOnlyException
is thrown. Answer xxx-6 Minimize, Maximize and Normal are all valid: ˇ
a) window statesˇ b) window modesˇ c) Portlet statesˇ d) Portlet modes
Answer a) is correct. Minimize, maximize and normal are the three
standard window states. Sometimes the terms state and modes are easily
confused. View and edit are modes, minimize and maximize are states.
Answer 7-7 Where is a PortletPreference defined as being read only. ˇ a)
programmatically through the PortletPreferences objectˇ b) by adding a
read-only parameter to the portlet.xml fileˇ c) by adding a read-only
parameter to the web.xml fileˇ d) PortletPreferences are always editable
Answer b) is correct. There is no programmatic way to set a
PortletPreference to be read-on; this can only be done by setting the
preference through the portlet.xml file, and subsequently adding a tag
indicating that the preference is read only. l Chapter 8Custom Portlet
Modes The JSR-168 portlet specification requires all portal servers to
provide services for the three standard portlet modes: view, edit and
help. However, portal administrators are allowed to provide support for
any number of extra portlet modes they think would be helpful. For
example, it is envisioned that many portlets would benefit from a print
mode that would make it possible to print out a portlet with the simple
click of a button. IBM always provided support for a configure mode with
their legacy portlet API, so it?s no surprise that the WebSphere Portal
Server comes with built in support for a configure mode. Portal Support
for Custom Modes First of all, I want to make it clear that you can
follow all of the programming steps required to create a portlet that
has a custom mode, but if the portal server you are deploying to doesn?t
support that custom mode, that custom mode just ain?t going to work. If
you want your portlets to render a custom portlet mode, that custom
portlet mode must be enabled on the portal server to which you are
deploying. Now, the WebSphere Portal Server supports the configure mode,
so I will demonstrate how to write a portlet that supports the configure
mode. The assumption is that we will be deploying to WebSphere.
Implementing Custom Portlet Modes The first step in coding a custom
portlet mode it overriding the inherited doDispatch method of the
GenericPortlet. The doDispatch method is always invoked before the
doView or doEdit modes, so, if we override this method and inspect to
see if our custom portlet mode is being invoked, we can capture the
request, and send it to our own custom do method, which in this case,
will be doCustomConfig(). And what do we do in our doCustomConfig ()
method? Well, anything we want. This method will be responsible for
rendering the config mode of the portlet. This method can do anything
you want it to do, but in all likelihood, the method will forward to a
jsp file. Figure xxx WebSphere Portal Server 6.x has inherent support
for the custom config mode. Even if custom modes are coded properly, if
a portal server is not configured to support that custom mode, the
custom mode simply will not be available to the end user. The Custom
do<mode> Method When the custom configure mode is being requested,
we call to our custom do<mode> method named doCustomConfig(). In
our example, the config mode simply prints a message about its own
self-actualization to the console. However, this method will never be
called, unless we override the doDispatch method. protected void
doCustomConfig( RenderRequest request, RenderResponse response) throws
PortletException, IOException { response.setContentType(?text/html?);
response.getWriter().print("I have a custom config mode!!!");
} Overriding the doDispatch Method When overriding the doDispacth
method, we first check to see if the portlet is minimized. The mode
being requested really doesn?t matter if the portlet is minimized, so if
it is, we just skip the whole render phase processing. If the portlet
isn?t minimized, then we check to see if the portlet mode being
requested is the config portlet mode. If it is, then we call our
doCustomConfig method. If our custom portlet mode is not being invoked,
we simply call super.doDispatch(), which essentially allows the portlet
to run as though our custom, overridden doDispatch method was never
called. protected void doDispatch( RenderRequest request, RenderResponse
response) throws PortletException, IOException{ /* don?t do anything if
the window is minimized */ if
(!WindowState.MINIMIZED.equals(request.getWindowState())) { /* find out
which portlet mode is being requested */ PortletMode requestedMode =
request.getPortletMode(); PortletMode customPortletMode = new
PortletMode("config"); /* if our custom mode is requested,
call our custom do method */ if
(requestedMode.equals(customPortletMode)) { /* this is the call to our
custom do <mode> method */ doCustomConfigure(request, response);
return; } /*if our custom portlet wasn?t called, allow the regular
portlet mode processing happen*/ super.doDispatch(request, response); }
} Editing the Portlet Deployment Descriptor Along with the overridden
doDispatch method, and the custom do<mode> method, the deployment
descriptor of the portlet application must be updated to indicate that a
new portlet mode is being supported. <?xml version="1.0"
encoding="UTF-8"?> <portlet-app
xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd"
version="1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd
http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd
id="com.examscam.portlet.CustomModePortlet.051cf00ef0">
<portlet>
<portlet-name>CustomModePortlet</portlet-name>
<display-name>CustomModePortlet</display-name>
<display-name xml:lang="en"> CustomModePortlet
</display-name> <portlet-class>
com.examscam.portlet.CustomModePortlet </portlet-class>
<expiration-cache>0</expiration-cache> <supports>
<mime-type>text/html</mime-type>
<portlet-mode>view</portlet-mode> <!-- This entry
indicates the portlet supports the config mode -->
<portlet-mode>config</portlet-mode> </supports>
<supported-locale>en</supported-locale> <portlet-info>
<title>CustomModePortlet</title> </portlet-info>
</portlet> <!-- This entry indicates the portlet application
supports config--> <custom-portlet-mode>
<portlet-mode>config</portlet-mode>
</custom-portlet-mode> </portlet-app> The Full
CustomModePortlet package com.examscam.portlet; import java.io.*;import
javax.portlet.*; public class CustomModePortlet extends GenericPortlet {
protected void doView (RenderRequest request, RenderResponse response)
throws PortletException, IOException {
response.setContentType(?text/html?);
response.getWriter().println("Custom Portlet View Mode"); }
protected void doCustomConfigure (RenderRequest request, RenderResponse
response) throws PortletException, IOException {
response.setContentType(?text/html?);
response.getWriter().println("Custom Config Mode!!!?); } protected
void doDispatch (RenderRequest request, RenderResponse response) throws
PortletException, IOException{ /* don?t do anything if the window is
minimized */ if
(!WindowState.MINIMIZED.equals(request.getWindowState())) { /* find out
which portlet mode is being requested */ PortletMode requestedMode =
request.getPortletMode(); PortletMode customPortletMode = new
PortletMode("config"); /* if our custom mode is requested,
call our custom do method */ if
(requestedMode.equals(customPortletMode)) { /* this is the call to our
custom do <mode> method */ doCustomConfigure(request, response);
return; } /*if our custom portlet wasn?t called, allow the regular
portlet mode processing happen*/ super.doDispatch(request, response); }
} } Answer 6-6 Special icons associated with a particular custom portlet
mode are defined: ˇ a) in the web.xml fileˇ b) in the portlet.xml fileˇ
c) in the render phase of the portletˇ d) in a portal skin Option d) is
correct.The cute little icons, such as the pencil for the edit mode, or
the wrench for the custom config mode, are part of a portal skin, and
defined outside of the actualy portlet application. The fact that icons
for custom modes is defined at the portal server level, not the portlet
level, is part of the reasons why portlets cannot simply define custom
portal modes on their own.
|