NEW!! FREE MOCK EXAM SIMULATORS FOR IBM PORTAL TEST 399 & IBM PORTLET CERTIFICATION EXAM TEST 829!!!
Everything You Ever Wanted To Know About JSR-168 Portlet Development . . . PORTAL + TUTORIAL = www.portorials.com
Google
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.
Google



eXTReMe Tracker

ActionRequest ActionResponse GenericPortlet PortletRequestDispatcher . Portlet ..... PortletURL
PortletContext PortletException PortletMode a PortletModeException PortletPreferences
PortalContext PortletResponse PortletSession PortletSecurityException PreferencesValidator
PortletConfig RenderRequest RenderResponse UnavailableException PortletSessionUtil
PortletRequest ValidatorException WindowState WindowStateException UnmodifiableException