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

Linking Back to the Portal: The PortletURL

Programming portlets presents the web developer with many new challenges, not the least of which is figuring out how to invoke a particular portlet from an html form. A portlet can be placed on a variety of different web pages at runtime. How can we invoke a web-based resource when we don?t know the web address of the page on which it will appear?

Another challenge is making sure that the data submitted through our form goes to our portlet, and our portlet only. We don?t want other portlets on the page using data submitted from our form.

Fortunately, the portlet API addresses these very challenges.

The Challenge of Linking Back to a Portlet

When a user clicks the submit button on a form, there must be an object sitting on the server that is ready to process the user?s request. With typical Servlet/JSP applications, form submissions are forwarded to a servlet, and the name of the servlet is specified as the action of the form; however, we can?t do that with a portlet.

This tutorial looks at the PortletURL object (formerly the PortletURI), and how it can be used to link back to a portlet running on the portal server, regardless of which page the portlet appear on at runtime.

Please support our site, link to us, buy some books, and remember: Happy Java!

Rendering a View with Java Server Pages l Chapter 4Linking Back to the Portal Forwarding to a JSP to spit out a little ?Hello World? message isn?t going to win you any Programmer of the Year awards. On the other hand, using a JSP to generate an html form that helps process input from the user would be a fastidious application of your programming talents. Creating Basic HTML Forms for User Input To grab input from a user, we simply use html forms. For example, if we wanted the user to guess a magic number between one and ten, we might provide an html form that looks something like figure 4-1: Figure 4-1 Using html Forms to obtain User InputWeb based forms are used to grab input from the user. This form asks a user to enter a number between one and ten and then click Guess!!. Using html forms to obtain input from a user is nothing new to a web developer, but using forms in a portlet environment presents a few unique and annoying challenges. The Number Guesser Portlet For this chapter, we?re going to develop the NumberGuesserPorlet. The idea is that when the portlet is first viewed, it will ask the user to guess a magic number between one and ten: When the user clicks Guess!!!, the NumberGuesserPortlet will check to see what the number was that the user typed in, and tell the user whether they guessed the magic number correctly or not. For this example, we will hard code the magic number to be 5. The Portlet will then generate a response, telling the user if they guessed correctly or not: The response, telling the user if they guessed correctly, will be generated through print statements in the portlet. The form that takes input from the user will be implemented as a jsp, creatively named numberguesser.jsp The Try Again link will then return the user back to the original screen, prompting the user to guess the magic number. And remember, all of this is being performed on a portlet, that could potentially be sharing screen space with two or twenty other portlets. Furthermore, a portlet can be placed on any number of different pages in the portal. This introduces a level of complexity to your portlet applications that you would never encounter in a typical Servlet and JSP type of application. Linking Back to a Portlet Programming portlets presents the web developer with many new challenges, not the least of which is figuring out how to invoke a particular portlet from an html form. A portlet can be placed on a variety of different web pages at runtime. How can we invoke a web-based resource when we don?t know the web address of the page on which it will appear? Another challenge is making sure that the data submitted through our form goes to our portlet, and our portlet only. We don?t want other portlets on the page using data submitted from our form. Fortunately, the portlet API addresses these very challenges. The Challenge of Linking Back to a Portlet When a user clicks the submit button on a form, there must be an object sitting on the server that is ready to process the user?s request. With typical Servlet/JSP applications, form submissions are forwarded to a servlet, and the name of the servlet is specified as the action of the form; however, we can?t do that with a portlet. For example, if our number guessing application was implemented as a servlet, there would be an HttpServlet, perhaps named NumberGuesserServlet, that would respond to the submission of the form, and subsequently extract the user?s input. The Servlet would constitute the action of the form, and the form tag would look like this: <FORM action = ?NumberGuessServlet?> But a portlet can?t make a direct call back to itself that easily. The best a portlet could do is make a call back to the page the portlet is displayed on, but even that?s impossible to configure in an html form, because at development time, we don?t know which page, or on how many pages, our portlet will potentially appear. Submitting HTML Forms to a Portlet Notice how the action attribute of the html form element in figure 4-2 points to a question mark. Typically, this would point to a Servlet or a CGI script that handles the submission of a form. How can we direct the submission of our form back to our portlet? Figure 4-2We don?t know the name of the page our portlet may appear on at runtime. This makes hard coding a target for the action attribute of the form element impossible. In this case, the action attribute of the form has been left as a question mark (?). <FORM action = ??? >I'm thinking of a number between 1 and 10.<BR><BR><I>What is it? </I> <INPUT type="text" name="number" size="10"> <INPUT type="submit" name="SUBMIT" value="Guess!!"> </FORM> The PortletURL Object Life would be simple if we could tell a form to directly call the NumberGuesserPortlet, but we can?t. When a request is made to the portal server, a single portlet can?t be invoked directly. Instead, the user must request a portal page, and the portal server takes care of rendering all of the portlets that are part of that page. So, how do we make a new request to the portal to have our portlet, and the portal page with which it is associated, re-invoked? The answer is to have the RenderResponse create a PortletURL object, which essentially represents a link back to the current portal page, along with all of the portlets that appear on that page. response.createRenderURL(); //link back to the portlet response.createActionURL(); //triggers action phase The PortletURL Object ?The PortletURL interface represents a URL that reference the portlet itself. A PortletURL is created through the RenderResponse. Parameters, a portlet mode, a window state and a security level can be added to PortletURL objects. The PortletURL must be converted to a String in order to embed it into the markup generated by the portlet. There are two types of PortletURLs: Action URLs, they are created with RenderResponse.createActionURL, and trigger an action request followed by a render request. Render URLs, they are created with RenderResponse.createRenderURL, and trigger a render request.? Portlet API JavaDoc, http://jcp.org/aboutJava/communityprocess/final/jsr168/ Creating the RenderURL Link To create a link back to a portlet from within an html form, we need to dynamically generate that action attribute of our form. This can be done using a JSP expression: <FORM ACTION = ?<%=renderResponse.createRenderURL()%>? > Unfortunately, right out of the box, this line of code will not successfully compile. A little taglib directive, along with a <portlet:defineObjects/> custom tag must be added to the JSP make everything kosher. Required Custom Tags for Portlet Based JSPs While all JSPs understand that the word response, when used inside of an expression or a scriptlet, is a reference to the HttpServletResponse object, a standard JSP has no knowledge of what a portetResponse object is, even if the reference occurs in a JSP that is part of a portlet application. To get the Java compiler to understand that when we say renderResponse in our JSPs, that we are referring to a subtype of the PortletResponse object, we need to add two lines to the top of our Java Server Page: 1.<%@taglib uri="http://java.sun.com/portlet" prefix="portlet"%> 2.<portlet:defineObjects/> The first line is the taglib, also known as a tag library directive. This taglib directive indicates that the JSP is going to employ the services of the portlet custom tag library. The second line, <portlet:defineObjects/>, is an actual portlet custom tag in action. The sole purpose of the <portlet:DefineObjects/> tag is to expose three important portlet API objects: The RenderRequest object: renderRequest The RenderRepsonse object: portletResponse The PortletConfig object: portletConfig With local access to the renderRequest, renderResponse, and portletConfig objects, you have access all othe other important portlet API components, including the PortletSession, PortletContext, PortletURL and others. Figure 4-3 demonstrates how to create a PortletURL object, while including the taglib directive, and the <portlet:defineObjects/> custom tag. Figure 4-3 renderResponse.createRenderURL() To create a link back to the page a portlet appears on, the createRenderURL() method othe RenderResponse must be used. Notice the added custom tag and taglib directive. <%@page contentType="text/html"%><%@taglib uri="http://java.sun.com/portlet" prefix="portlet"%>< portlet:defineObjects /><FORM action="<%=renderResponse.createRenderURL()%>">I'm thinking oa number between 1 and 10.<BR><BR><I>What is it?</I><INPUT name="number" type="text" size="10" /><INPUT name="submit" value="Guess!!" type="submit" /></FORM> Grabbing Form Input From Within a Portlet With an html form that contains a textfield named ?number?, all we have to do to figure out what a user typed into that textfield is call the getParameter method othe request object, and provide the name othe textfield, in this case ?number?. The input othe user will be returned to our program as a String. Again, anything you want to know about the user, which includes what the user typed into a given textfield, is obtained through the PortletRequest object, or more specifically during the rendering phase, the RenderRequest. With the taglib directive, and the <portlet:defineObjects/> tag, any expression that uses objects defined in the portlet API will compile and run successfully, including references to the action attribute oa form that references the portletResponse and the createRenderURL method. Coding the NumberGuesserPortlet The text in figure 4-4 shows the code required to improve our NumberGuesserPortlet to the point where it can extract form data from the user. Notice how this portlet acts largely as a controller, displaying the input form (numberguesser.jsp) ino data has been submitted, and alternatively, ia number has been submitted, the portlet provides interactive feedback to the user, namely information on whether the user correctly guessed the magic number. Figure 4-4 Code used to grab data from a textfield named number. 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 {/*see ia number is passed to the server as a parameter*/ String number = request.getParameter("number"); //ino number was entered, just show the form i(number == null) { String url = "/numberguesser.jsp"; getPortletContext() .getRequestDispatcher(url) .include(request, response); } else { /*ia number was entered, display the correct answer*/ response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.print("You guessed " + number); out.print("<BR>The number was 5"); out.print("<BR>Try again."); /*create a link back to the portlet using a PortletURL*/ out.print("<A href=\""); out.print(response.createRenderURL()); out.print("\">Try Again</A>"); } }} Data Clashes on the Portal Server With our funky new code, and the clever use othe PortletURL object, our NumberGuesserPortlet works pretty darn good; but there is a hidden little problem buried in the JSP. Our portlet uses the request.getParameter(?number?) method to figure out what the user typed into the textfield we named ?number?. But remember, our Portlet isn?t necessarily the only portlet on the page. What ianother portlet also uses an html form, with a textfield also named number? That other portlet would get access to our portlet?s number, and that isn?t good. Furthermore, our portlet might end up reading the number from the other portlet, and respond to a submission with which it had no business interacting. This isn?t a good scenario. Multiple Portlets and Handling Form Data Remember, our portlets don?t exist in a vacuum. The page that contains our NumberGuesserPortlet might also include a StockSellingPortlet that wants to know the number oshares a user wants to sell. That same page might also have a SpousalBenefitsPortlet that needs to know the number owives or husbands a user has. Ieach othose portlets makes a request.getParameter(?number?) call in their doView method, each one will get the number that was typed into the form othe NumberGuesserPortlet. When a portal page is rendered, the doView method oevery portlet on the page is invoked, not just that one portlet with which you might currently be interacting. Encoding Form Data with getNamespace( ) To ensure that form data being sent from our portlet to the server doesn?t get confused with the form data oanother portlet, the RenderResponse object gives us a special method called getNamespace(); this method will return a unique, alpha-numeric character set that uniquely identifies a portlet on a particular page. Iwe use the getNamespace() call, and attach that identifying String to each data element being sent back to the server, no other portlet on the portal page will mistakenly use our portlet?s data. All form elements should be encoded using the getNamespace() method of the response, and all fields being read in a portlet should assume the field has been namespace encoded. Note: For simplicity sake, this book will use examples that exclude the namespace call, which is fine for training, but is completely unacceptable in development or production. Uniquely identify all oyour form data, or JavaScripts, by using the getNamespace call to uniquely encode their names. ***Iyou encode a field in a JSP, make sure you use the same encoding scheme when retrieving that field on the server, as in the example below: Encoding an Attribute in the Form: <INPUT name="<%=renderResponse.getNamespace()%>number"/> Un-Encoding the Same Attribute in the Portlet: String num = request.getParameter(response.getNamespace( ) + "number"); Figure 4-5To ensure form data is only sent back to the intended portlet, the getNamespace method othe RenderResponse object needs to be used. <%@ page contentType="text/html"%><%@taglib uri="http://java.sun.com/portlet" prefix="portlet"%><portlet:defineObjects /><FORM action="<%=renderResponse.createRenderURL()%>">I'm thinking oa number between 1 and 10.<BR><BR><I>What is it?</I><INPUT name="<%=renderResponse.getNamespace()%>number"/><INPUT name="submit" type="submit" value="Guess!!" /></FORM> ***Note: a code change must be made in our Portlet in order to be able to read the namespace encoded field from the form: String number=request.getParameter(response.getNamespace()+"number"); Displaying Images in a Portlet A similar problem to linking back to a portlet, is figuring out how to display an image in a portlet. After all, iwe have trouble creating a URL from our JSP to point back to our original portlet, how do we code a JSP to link back to a resource, such as a jpg or gifile, in an images subdirectory oour portlet application? The solution is to use a special method in the renderRequest called getContextPath(). This returns a path to the root othe portlet application. From there, you can map to resources such as image files in subfolders. So, iyou had an image named wiw.jpg in an images folder ofthe root othe war, the following code would pull the image out: renderRequest.getContextPath() + "/images/wiw.jpg"; To display the image in a portlet, you would combine this code with the standard html IMG tag: <IMG src='<%=renderRequest.getContextPath()+"/images/wiw.jpg" %>'/> Ultimately though, the resource should also be encoded, so the getContextPath() method is nested in a call to encode the URL: <img src='<%= renderResponse.encodeURL( renderRequest.getContextPath() + "/images/wiw.jpg") %>' /> The Updated NumberGuesserPortlet The NumberGuesserPortlet has been updated to demonstrate the changes that needs to be made in order to read a namespace encoded variable that is accessed as a parameter through the PortletRequest object. Figure 4-6 Code used to grab user input from a textfield named ?number?, taking into account namespace encoded attributes. 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 {/*see ia number is passed to the server as a parameter/* /*String number = request.getParameter("number");*/ String number = request.getParameter(response.getNamespace()+"number"); /*if no number was entered, just show the form*/ i(number == null) { String url = "/numberguesser.jsp"; getPortletContext() .getRequestDispatcher(url) .include(request, response); } else { /*ia number was entered, tell the user the correct answer*/ response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.print("You guessed " + number); out.print("<BR>The number was 5"); out.print("<BR>Try again.");/*create a link back to the current portlet using a PortletURL*/ out.print("<A href=\""); out.print(response.createRenderURL()); out.print("\">Try Again</A>"); } }} A Quick Look at Some Portlet Custom Tags Since creating render and action URLs, not to mention namespace encoding form variables, are such common tasks in our JSP files, the Portlet API provides a couple ohandy-dandy custom tags that make these tasks just a little bit easier. Comparatively speaking, it is much slicker to use the <potlet:renderURL/> custom tag to spit out a link back to the current portal page, than it is to use the corresponding scriptlet. With a JSP Expression: <FORM action=?<%=renderResponse.createRenderURL()%>?> With a Custom Tag: <FORM action="<portlet:renderURL/>"> Similarly, using a custom tag to encode a variable name used in a form is much more readable and maintainable than using a JSP expression. Additionally, portlet parameters can be attached to a URL with the param tag: <portlet:renderURL> <portlet:param name=?book? value=?portal?/> </portlet:renderURL> With a JSP: Expression: <INPUT name=?<%=renderResponse.getNamespace()%>number"/> With a Custom Tag: <INPUT name="<portlet:namespace/>number"/> There are five custom tags defined by the portlet tag library descriptor (tld). They include actionURL, renderURL, param, namespace and defineObjects. Our Input Form with Portlet Custom Tags Figure 4-7Custom tags make Java Server Pages a little easier to write, and a little easier to read, although some might debate just how much more readable custom tags make a JSP. <%@ page contentType="text/html"%><%@taglib uri="http://java.sun.com/portlet" prefix="portlet"%><portlet:defineObjects /><FORM action="<portlet:renderURL/>">I'm thinking oa number between 1 and 10.<BR><BR><I>What is it?</I><INPUT name="<portlet:namespace/>number" type="text" size="10" /><INPUT name="submit" value="Guess!!" type="submit" /></FORM> Figure 4-8 Rendering with Scriptlets vs. Custom TagsWhile portlet custom tags are used to develop a JSP, the end user has no knowledge othe behind the scenes implementation. Deployment Descriptors With the JSPs coded, and the NumberGuesserPortlet doing what it should, the last thing our portlet application needs before being zipped up, is a good portlet.xml file, and web.xml file. <!--portlet.xml file for the NumberGuesserPortlet application --> <?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>NumberGuesserPortlet</portlet-name> <display-name>NumberGuesserPortlet</display-name> <portlet-class> com.examscam.portlet.NumberGuesserPortlet </portlet-class> <supports> <mime-type>text/html</mime-type> <portlet-mode>view</portlet-mode> </supports> <portlet-info> <title>NumberGuesserProject</title> </portlet-info> </portlet> </portlet-app> <-- web.xml file for the NumberGuesserPortlet Project --> <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"> <web-app id="WebApp_ID"> <display-name>NumberGuesserProject</display-name> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <taglib id="PortletTLD"> <taglib-uri>http://java.sun.com/portlet</taglib-uri> <taglib-location> /WEB-INF/tld/std-portlet.tld </taglib-location> </taglib> </web-app> Packaging the WAR Once the manifest file has been created, which simply states Manifest-Version: 1.1, the NumberGuesserPortlet application can be zipped up as a war file and deployed to the portal server. Question 4-1 How would the following legacy Jetspeed Portlet API use othe namespace tag be migrated over to JSR-168?<input name="<portletAPI:encodeNamespace value='name'/>"> a) <portlet:namespace/>nameb) <portlet:namespace>name</portlet:namespace>c) <portlet:namespace value=?name?/>d) <portlet:namespace name=?value?/> Question 4-2 How would the following code, used to display an image in using the legacy Jetspeed Portlet API, be migrated over to JSR-168?<%=portletResponse.encoeUrl(?/img/car.jpg?) %> a) renderRequest.encodeURL(renderResponse.getContextPath() + ?img/car.jpg?)b) renderResponse.encodeURL(renderRequest.getContextPath() + ?img/car.jpg?)c) renderRequest.encodeURL(renderResponse.getContextPath() + ?img/car.jpg?)d) renderResponse.encodeURL(renderRequest.getContextPath() + ?img/car.jpg?) Question 4-3 Which othe following tags are associated with the JSR-168 API? ¨ a) <portlet:defineObjects/>¨ b) <portlet:actionURL/>¨ c) <portlet:namespace/>¨ d) <portlet:parameter/> Question 4-4 What is the correct usage othe <portlet:param/> tag when placed within a <portlet:actionURL></portlet:actionURL/> tag? a) <portlet:param name=?id?>007</portlet:param/>b) <portlet:param>007</portlet:param>c) <portlet:param name=?id? value=?007?/>d) <portlet:param name=id value=?007?/>patron</portlet:param/> Question 4-5 The namespace custom tag uniquely identifies a script or field with: a) a particular portlet, as defined in the portlet.xml file b) a specific portlet and portlet window on the current portal pagec) a specific portlet applicationd) a specific portal page Question 4-6 Which othe following are non-required attributes othe renderURL and actionURL custom tags? ¨ a) portletMode¨ b) portletState¨ c) secure¨ d) variable Question 4-7 The JSR-168 PortletRequestDispatcher allows: ¨ a) Forwarding to a JSP¨ b) Forwarding to a Servlet¨ c) Including the output oa JSP¨ d) Including the output oa Servlet Question 4-8 The JSR-168 PortletRequestDispatcher is directly accessed through which object? a) PortletContextb) PortalContextc) RenderRequestd) RenderResponse Answer 4-1 How would the following IBM Portlet API use othe namespace tag be migrated over to JSR-168?<input name="<portletAPI:encodeNamespace value='name'/>"> a) <portlet:namespace/>nameb) <portlet:namespace>name</portlet:namespace>c) <portlet:namespace value=?name?/>d) <portlet:namespace name=?value?/> Option a) is correct, although it may be a little non-intuitive. The namespace tag simply prefixes the name othe textfield, so a simple, single tag sits before the name othe field. Answer 4-2 How would the following code, used to display an image in using the IBM Portlet API, be migrated over to JSR-168?<%=portletResponse.encoeUrl(?/img/car.jpg?) %> a) renderRequest.encodeURL(renderResponse.getContextPath() + ?img/car.jpg?)b) renderResponse.encodeURL(renderRequest.getContextPath() + ?img/car.jpg?)c) renderRequest.encodeURL(renderResponse.getContextPath() + ?img/car.jpg?)d) renderResponse.encodeURL(renderRequest.getContextPath() + ?img/car.jpg?) Option d) is correct. To display the image in a JSR-168, you first obtain the path from the RenderRequest, and then encode the URL using the renderResponse. Note that the command would work without the encodeURL, but would not be as programmatically sound. Answer 4-3 Which othe following tags are associated with the JSR-168 API? ¨ a) <portlet:defineObjects/>¨ b) <portlet:actionURL/>¨ c) <portlet:namespace/>¨ d) <portlet:parameter/> Options a) b) and c) are correct. Along with these three tags, the JSR-168 specification defines a <portlet:param/> tag and <portlet:renderURL/> tag. Choice d) is incorrect, as the proper name is <portlet:param/>, not the full name parameter. Answer 4-4 What is the correct usage othe <portlet:param/> tag when placed within a <portlet:actionURL></portlet:actionURL/> tag? a) <portlet:param name=?id?>007</portlet:param/>b) <portlet:param>007</portlet:param>c) <portlet:param name=?id? value=?007?/>d) <portlet:param name=id value=?007?/>patron</portlet:param/> Option c) is correct. There can be no content within the body othe <portlet:param/> tag. The information intended to be added as a parameter to the URL must be defined as name and value attributes othe tag, not as body content wrapped by the tag. Answer 4-5 The namespace custom tag uniquely identifies a script or field with: a) a particular portlet, as defined in the portlet.xml file b) a specific portlet and portlet window on the current portal pagec) a specific portlet applicationd) a specific portal page Option b) is correct. The namespace feature uniquely identifies a script or field with a particular portlet on a portal page. Ithe same portlet appears multiple times on a page, each portlet that has its own portlet window have its own, unique namespace identifier. Answer 4-6 Which othe following are non-required attributes othe renderURL and actionURL custom tags? ¨ a) portletMode¨ b) portletState¨ c) secure¨ d) variable Options a) and c) are correct. The four attributes oa URL custom tag is portletMode, windowState, secure and var. Answer 4-7 The JSR-168 PortletRequestDispatcher allows: a) Forwarding to a JSPb) Forwarding to a Servletc) Including the output oa JSPd) Including the output oa Servlet Options c) and d) are correct. The JSR-168 PortletRequestDispatcher does not allow any forwarding for content generation. Only including content generated by a web based resource is possible for a PortletRequestDispatcher, although using a JSP for content generation is more common than using a Servlet. Answers c) and d) are correct. Answer 4-8 The JSR-168 PortletRequestDispatcher is directly accessed through which object? a) PortletContextb) PortalContextc) RenderRequestd) RenderResponse Option a) is the correct answer. The method getRequestDispatcher is found in the PortletContext. In a good model-veiw-controller type of application, a Java centric component should never be polluted with lots of lousy html. With typical servlet and struts based applications, html is usually generated by a Java Server Page (JSP); in this regard, portlet applications are no different. However, portlet applications do present some unusual complications when deferring to a JSP for markup generation. How does a JSP link back to a specific portlet on a page? How does a portlet call a JSP? How do we gain access to the portlet specific PortletRequest and PortletResponse object in JSP? This chapter deals with basic JSP development, and the issues that present themselves when deferring to a JSP for markup generation. Deferring to a JSP for Markup Generation While accessing the PrintWriter from the request object and printing content directly back to the client in the doView method of a portlet is easy to do, it certainly isn?t a best practice. We have been spoiled so far with portlets that are relatively light on html tags. However, for content generation, a portlet should defer to a Java Server Page (JSP). JSPs are web centric artifacts that are written largely in static html, but can be interspersed with Java code to make them more interactive. Figure 3-1 A Sample Java Server Page (JSP), welcome.jsp A JSP is mostly markup, with a little bit of Java code (in bold) interspersed. Java Server Pages facilitate the development of complex, dynamic web pages. <%@ page session="false" contentType="text/html" %> <B>Welcome to this simple JSP<B><BR> We did some snooping on you.<BR> This is what we learned about your browser: <I><BR> <%=request.getHeader("user-agent")%> </I><BR> And we know what language you speak, it's: <I> <%=request.getLocale().getDisplayLanguage()%> </I> Invoking the welcome.jsp from a Portlet While the concept of delegating to a JSP for view generation is relatively simple and straight forward, the code is actually a little bit intimidating. Assuming the code from Figure 3-1 was saved in a file named welcome.jsp, and that welcome.jsp file was saved in the root of the war, invoking the welcome.jsp would require the following lines of code in a portlet: String url = "welcome.jsp"; getPortletContext() .getRequestDispatcher(url).include(request,response); Using a JSP for Markup Generation When a particular portlet is requested, the custom coded Java class that extends GenericPortlet, and is specified in the portlet.xml file, will be invoked by the portal server. The portlet class is then responsible for delegating to a JSP for markup generation. This is done using the include method of the PortletRequestDispatcher, during the portlet?s rendering phase. The full code for the JSPDisplay portlet that forwards to the welcome.jsp file is as follows: package com.examscam.portlet; import java.io.*; import javax.portlet.*; public class JSPDisplay extends GenericPortlet { protected void doView (RenderRequest request, RenderResponse response) throws PortletException, IOException { String url = "/welcome.jsp"; getPortletContext() .getRequestDispatcher(url).include(request,response); } } Where is the Portal Finding the JSP? Legacy portal development tools would pull jsp files from a variety of different folders, depending upon the client device and the preferred language of the user making the request. For JSR-168 portlets, the PortletRequestDispatcher, quite sensibly searches for jsp files starting from the root of the war. So, with the JSPDisplay portlet, the welcome.jsp file would be found right there in the root. JSP Deferment and Multiple Markup Support For supporting multiple markup languages, it is customary, and automatic with the portlet wizards of many rapid application development tools, that subdirectories exist for each of your markup languages, under a folder named jsp. By following this convention, multiple markup languages can be easily integrated by simply creating new JSP files in the appropriately named subfolders, and using these JSPs at the appropriate times. Figure 3-2 A well formed folder structure helps in the development of multi-device capable portlets. Deployment Descriptor for JSPDisplay Portlet Assuming the JSPDisplay portlet is packaged in its own war file, the portlet.xml file for the JSPDisplay portlet would be as follows: <?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.JSPDisplay.9afc93cee0" > <portlet> <description>JSPDisplay</description> <portlet-name>JSPDisplay</portlet-name> <display-name>JSPDisplay</display-name> <portlet-class> com.examscam.portlet.JSPDisplay </portlet-class> <supports> <mime-type>text/html</mime-type> <portlet-mode>view</portlet-mode> </supports> <portlet-info><title>JSPDisplay</title></portlet-info> </portlet> </portlet-app> Something Wrong with our welcome.jsp Portlets build extensively upon the Servlet and JSP API, and the welcome.jsp file in Figure 3-1 was coded as though it were part of a typical Servlet and JSP application. When you?re doing portlet development, not respecting your jsp files as portlet artifacts is a very bad thing. A Java Server Page, by virtue of the fact that it runs in a Java web container, has implicit access to eight very important object types defined by the Servlet and JSP API, namely: the ServletRequest, ServletResponse, ServletConfig, ServletContext, HttpSession, JSPWriter, pageContext, and HttpJspPage object. Now we?re actually not supposed to access these implicit variables within our portlet jsps. Remember, with Portlets, we don?t use the ServletRequest and ServletResponse objects, but instead, we use the RenderRequest and RenderResponse objects. The RenderRequest and RenderResponse objects are not implicitly available to jsp pages that run within a portlet application; however, the portlet API does provide a special custom tag that indeed makes it possible to use them. Any Java Server Page that needs easy and implicit access to classes defined in the portlet API needs only to add a special custom tag, portlet:defineObjects, to their JSP page. This makes the RenderRequest, RenderResponse, and even the PortletConfig object implicitly available with the names renderRequest, renderResponse and portletConfig. There are several configuration steps required to use the <portlet:defineObjects/> custom tag, namely: 1. a reference to the portlet.tld file must be placed in the web.xml file 2. a taglib directive must be added to the top of the JSP page that uses the portlet.tld custom tags 3. the <portlet:defineObjects/> custom tag must appear in the portlet JSP page Once you have followed these steps, you can implicitly reference the renderRequest, renderResponse and portletConfig objects within JSP scriptlets, declarations and expressions. 1: taglib Entry in the web.xml file To access the various custom tags associated with the portlet API, including <portlet:defineObjects/>, a reference to the tag library must be configured in the web.xml file. <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"> <web-app id="WebApp_ID"> <display-name>agboPortlets3</display-name> <welcome-file-list><welcome-file>index.jsp</welcome-file></welcome-file-list> <taglib id="PortletTLD"> <taglib-uri>http://java.sun.com/portlet</taglib-uri> <taglib-location> /WEB-INF/tld/std-portlet.tld </taglib-location> </taglib> </web-app> 2 & 3: Taglib Directive and defineObjects in JSP After defining the taglib in the web.xml file, you must add a taglib directive, and the <portlet:defineObjects/> tag to your JSP. After those elements have been added, you have implicit access to the renderRequest, renderResponse and the portletConfig variable names. <%@ page session="false" contentType="text/html" %> <%@taglib uri="http://java.sun.com/portlet" prefix="portlet"%> <portlet:defineObjects/> <B>Welcome to this simple JSP<B><BR> We did some snooping on you.<BR> This is what we learned about your browser:<I> <%=renderRequest.getProperty("user-agent")%> </I><BR> And we know what language you speak, it's: <I> <%=renderRequest.getLocale().getDisplayLanguage()%> </I>Question 3-1 The four lifecycle methods of a portlet are defined in:Which of the following variable names are made available to JSP files with the addition of the <portlet:defineObjects/> tag? ¨ a) the Portlet interfaceportletRequest ¨ b) the GenericPortlet interfaceportletResponse ¨ c) the abstract class PortletrenderRequest ¨ d) the abstract class GenericPortletrenderResponse Question 3-2 During a portlet?s request-response cycle which of the following methods will be invoked first?To use the portlet custom tags, the taglib-uri entry must appear in: a) the portlet.xml file b) the web.xml file c) the custom portlet that extends GenericPortlet d) JSP pagesa) doView b) doEdit c) doHelp d) doDispatch Question 3-3 The methods doView, doEdit and doHelp correspond to:Which of the following methods are defined by the PortletRequestDispatcher? a) Portlet configsforward(String url) b) Portlet phasesinclude(String url) c) Portlet statesforward(RenderRequest req, RenderResponse resp) d) Portlet modesinclude(RenderRequest req, RenderResponse resp) Question 3-4 A typical JSR-168 portlet will:Compiled portlet source files are stored in a package aware structure under which folder? a) extend Portlet interfaceWEB-INF b) extend GenericPortletMETA-INF c) extend AbstractPortletWEB-INF\classes d) extend PortletRendererMETA-INF\classes Question 3-5 In the MVC paradigm, a JSP is typically considered which MVC component? a) View b) Data c) Controller d) Model Answer 3-1 The four lifecycle methods of a portlet are defined in:Which variable names are made available to JSP files with the addition of the <portlet:defineObjects/> tag? ¨ a) the Portlet interfaceportletRequest ¨ b) the GenericPortlet interfaceportletResponse ¨ c) the abstract class PortletrenderRequest ¨ d) the abstract class GenericPortletrenderResponse Options c) and d) are correct. When you use the defineObjects tag, you can reference the renderRequest and renderResponse objects within scriptlets and expressions. Furthermore, these objects provide enough getter methods to allow you to navigate to just about any object in the Portlet API. It should also be noted that a third variable, portletConfig, becomes available to a JSP developer when the defineObjects tag is added to a JSP page. Answer 3-2 During a portlet?s request-response cycle which of the following methods will be invoked first?To use the portlet API custom tags, the taglib-uri entry must appear in which file? a) portlet.xml b) web.xml c) GenericPortlet d) JSP pagesa) doView b) doEdit c) doHelp d) doDispatch Option b) is correct. The tagilb-uri must be defined in the web.xml file, otherwise your JSP files will not be able to properly resolve the portlet API custom tags. The JSP pages themselves then need a taglib directive, along with the <portlet:defineObjects/> tag. For the most part, we steer clear of the web.xml file when we?re working in the portlet world. It?s important to take note of the few times we where do have to finger the deployment descriptor of the web module. Answer 3-3 The methods doView, doEdit and doHelp correspond to:Which of the following methods are defined by the PortletRequestDispatcher? a) Portlet configsforward(String url) b) Portlet phasesinclude(String url) c) Portlet statesforward(RenderRequest, RenderResponse) d) Portlet modesinclude(RenderRequest, RenderResponse) Option d) is correct. While the Servlet API?s RequestDispatcher provides both forward and include methods, only the include method is defined for the PortletRequestDispatcher. The String for the url being forwarded to is provided during the call to getRequestDispatcher(String url). Answer 3-4 A typical JSR-168 portlet will:Compile portlet source files are stored in a package aware structure under which folder? a) extend Portlet interfaceWEB-INF b) extend GenericPortletMETA-INF c) extend AbstractPortletWEB-INF\classes d) extend PortletRendererMETA-INF\classes Option c) is correct. All compiled Java code, not to mention property files and resource bundles, must be places in a package aware subfolder of WEB-INF\classes. The only file typically found in the META-INF directory is the manifest file, which should describe the major and minor version number of your portlet application. Answer 3-5 In the MVC paradigm, a JSP is typically considered to be which MVC component? a) View b) Data c) Controller d) Model Option a) is correct. A JSP is typically responsible for generating output to the client, which represents the view in an MVC, model-view-controller, architecture.
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