Learn Logo
Home    |    www.ExamScam.com    |    Leave Us A Message    |    SCJA Java Certification Site    |    Free Mock Cert Exams    |    Free Multimedia Tutorials   

pulpJavaNetwork


Support this site!
(And bill it to your boss)

Buy it now on Amazon!



Search Now:
Google

 

jsps, forms, and linking back to a portlet

 

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 API 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 makup generation.

 

‘Gotchas’ when Deferring to a JSP from a Portlet

CaSe SenSItiVe Names and Deceptive JSP Paths

JSP Deferment and Multiple Markup Support

Creating Basic HTML Forms for User Input

Referencing the Originating Portlet

The Challenge of Linking Back to a Portlet

The PortletURI Object

Required Custom Tags for Portlet Based JSPs

The taglib Directive and the <portletAPI:init/> Tag

Grabbing Form Input From Within a Portlet

Multiple Portlets and Handling Form Data

Encoding Form Data with encodeNamespace( )

A Quick Look at Some Portlet Custom Tags

Our Input Form with Portlet Custom Tags


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, it certainly isn’t a best practice.

We have been spoiled so far with portlets that are relatively light on html. However, for proper markup generation, portlets 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 dynamic.

While the concept of delegating to a JSP for view generation is relatively simple and straight forward, the code required to do this with a portlet is actually a little bit intimidating. To forward to a JSP named welcome.jsp, the code in your doView() method would look like this:

 

getPortletConfig().getContext().include("welcome.jsp", request, response);

 

Figure ?-? A Sample Java Server Page (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.

 

<%@ taglib uri="/WEB-INF/tld/portlet.tld" prefix="portletAPI" %>

<portletAPI:init />

<B>Welcome to this simple JSP<B>

<BR>We did some snooping on you.

<BR>This is what we learned about your browser:

 

<I> <%=portletRequest.getHeader("user-agent") %> </I>

<BR>And we know what language you speak, it's:

<I> <%=portletRequest.getLocale().getDisplayLanguage ( ) %> </I>

 

Generating this amount of html using a PrintWriter inside of athe doView method of a portlet would be insane. This is the type of html generation we like to defer to a JSP file. After all, generating html is what JSP files do best.


‘Gotchas’ when Deferring to a JSP from a Portlet

There are indubitably a few ‘gotchas’ you must be aware of before you defer to a Java Server Page (JSP). Pay careful attention here: we are going to show you how to avoid the frustrating task of trying to figure you why your JSPs aren’t displaying properly.

CaSe SenSItiVe Names and Deceptive JSP Paths

First and foremost, the name of a JSP file is case sensitive. Make sure you spell the name correctly, and make sure the case in the ‘include’ method call of the portlet matches the case of the actual name of the JSP. For the sake of simplicity, name your jsp and html files using all lower case letters, rather than an undecipherable mish-mash of upper and lower case letters.

Secondly, the location of the jsp file you reference in your portlet is not relative to the root of the web module (the ‘Web Content’ folder). With typical Servlet based applications, the location of an included or ‘forwarded to’ file is relative to the root of the web module, but this is not necessarliy the case with portlet applications.

 

//the welcome.jsp file is deceptively NOT in the root of the web module

getPortletConfig().getContext().include("welcome.jsp", request, response);

 

In our example, the welcome.jsp is actually in the \html subdirectory of the web module root. If you place your welcome.jsp file directly under the root, you will get a “This portlet is unavailable” message when you try to run the portlet. That’s never a good thing.

Furthermore, if a path is given to the jsp file in the include, the html directory is implied after the path, and before the name of the jsp. So, if the path in the include was:

include(“common/jsp/welcome.jsp”, request, response);

then your web module would need a folder named:

common/jsp/html/welcome.jsp

As you can see, the html comes after the folder path, and before the name of the jsp file to which you are delegating.

 


JSP Deferment and Multiple Markup Support

So, why is it that despite telling the portal to look for a jsp in the root of the web module, that it actually looks in a subfolder named html?

Well, it’s all due to the fact that the portal dynamically matches the jsp to which you are calling to the preferred markup language of the client.

If the client device has a preferred markup language of html, then the portal will look for a matching JSP in the html subfolder off of the root of the web module. If the client device prefers wml, then the portal will look for a matching JSP file in the wml subdirectory off of the root of the web module.

By matching the preferred markup language of the client to a subfolder with a matching name, dynamically supporting multiple markup languages is as simple as placing markup specific JSP pages in the appropriate directory. It’s coyote super-genious, really, although it can sometime throw you off when you’re trying to get a simple portlet that includes a JSP working properly.

 

Figure ?-? Actual Location of Included JSP Files

When the doView method defers to a JSP, the JSP file must be placed in a folder named according to the markup language generated by the JSP; in this case, html.

 

public void doView (PortletRequest request, PortletResponse response)

                                                             throws PortletException, IOException {

     getPortletConfig().getContext().include("welcome.jsp", request, response);

}

 


Creating Basic HTML Forms for User Input

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 takes input from a user would be a fine application of your programming talents.

To grab input from a user, we 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 ?-?:

 

Figure ?-? Using html Forms for User Input

Web based forms are used to grab input from the user. This form expects a user to type a number between one and ten  into the textfield and click the Guess!! button.

 

Referencing the Originating Portlet

Using html forms to obtain input from a user is nothing new to a web developer, but using forms in the portal presents a few unique challenges.

One challenge is figuring out how to reference back our originating portlet. 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 what web page it will appear on?

The other challenge is making sure that the data submitted on our form goes to our portlet, and our portlet only. We don’t want any other portlets on the portlet page using data submitted from our portlet’s form.

Fortunately for us though, those clever sausages who put together the portlet API have addressed these very challenges.


The Challenge of Linking Back to a Portlet

When a user clicks submit on a form, there must be an object sitting on the server this is ready to process that 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 attribute of the form; Unfortunately, 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 creatively named NumberGuessServlet, that would respond to the submission of the form and extract the users 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 appear.

 

Figure ?-?

We don’t know the name of the page a portlet  may appear on at runtime. This makes hardcoding 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>

 

Notice how the action attribute of the form element in figure ?-? points to a question mark. Typcially, this would point to a Servlet or a CGI script that handles the submission of a form. How can we direct to submission of the form back to our portlet?


The PortletURI 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, which hopefully  includes the portlet with which we are trying to communicate.

So, how do we make a new request to the portal to have our portlet, and the portal page it is associated, re-invoked? The answer is to have the PortletResponse create a PortletURI object, which essentially represents a link back to the current portal page, and all of the portlets that appear on it.

response.createURI(); //generates a link back to the current portal page

To create a link back to a portlet from within an html form, we need to configure that action attribute of our form. This can be done using a JSP expression:

< FORM   ACTION = ”<%= portletResponse.createURI( ) %>”>

Unfortunately, out of the box, this line of code will not compile. A taglib directive, along with a <portletAPI:init/> custom tag must be added to make everything cosher. Figure ?-? deomontrates creating a PortletURI object, while including the taglib directive, and the portletAPI:init custom tag.

 

Figure ?-?

To create a link back to the page a portlet appears on, the createURI() method of the PortletResponse can be used. Notice the required custom tag and taglib directive.

 

<%@ taglib uri="/WEB-INF/tld/portlet.tld" prefix="portletAPI" %>

<portletAPI:init />

<FORM   ACTION=” <%= portletResponse.createURI( ) %>  >

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>

 


Required Custom Tags for Portlet Based JSPs

While all JSPs understand that the word response used inside of an expression or a scriptlet is a reference to the HttsServletResponse 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.

The taglib Directive and the <portletAPI:init/> Tag

To get the Java compiler to understand that when we say ‘portletResponse’ in our JSPs, that we are referring to the PortletResponse object, we need to add two lines to the top of our Java Server Page:

1.  <%@ taglib uri="/WEB-INF/tld/portlet.tld" prefix="portletAPI" %>
2.  <portletAPI:init />

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 portletAPI custom tag library.

The second line, <portletAPI:init/> is an actual portletAPI custom tag in action. The sole purpose of the portletAPI:init tag is to expose three important portlet API objects:

>>>  The PortletRequest object, named portletRequest
>>> The PortletRepsonse object, named portletResponse
>>> The PortletConfig object: portletConfig


With local access to the portletRequest, portletResponse, and portletConfig objects, you have access to all of the other important portlet API objects, including the PortletSession, PortletContext, PortletURI and others.

With the taglib directive, and the portletAPI:init tag, any expression that uses objects defined in the portlet API will compile and run successfully.


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 of the request object, and provide the name of that textfield. - in this case the name is ‘number’. The input of the user will be returned to as a String.

Again, anything you want to know about the user, which includes what the user typed into a give textfield, is obtained through the PortletRequest object.

 

Figure ?-?  Code used to grab user input from a textfield named ‘number’.

 

package com.pulpjava.numberguesser;

import org.apache.jetspeed.portlet.*;  import java.io.*;

 

public class NumberGuesserPortlet extends PortletAdapter {

  public void doView(PortletRequest request, PortletResponse response)

                                              throws PortletException, IOException {

    //generate a magic number

    String magicNumber = "" +( System.currentTimeMillis() % 9 + 1);

    //if the user submitted the form, find out what number they guessed

    String guess = request.getParameter("number");

 

    //if there is no guess, show the input form to the user

    if (guess==null){

      getPortletConfig().getContext().include("numberform.jsp", request, response);

    }else {

      PrintWriter out = response.getWriter();

      //if there is text input from the users, tell them if they got the magic number

      if (guess.equals(magicNumber)){

        out.print("You gessed it!");

    }else {

      out.print("You guessed wrong.");

    }

      out.print("<BR><BR>The magic number was "+magicNumber);

    }

  }

}

Data Clashes on the Portal Server

With our funky custom tags, and the clever use of the PortletURI object, our NumberGuesserPortlet works pretty darn good, but there is a pesky little problem buried in the JSP.

Our portlet uses the request.getParameter(“number”) method call to figure out what the user typed into the textfield named ‘number’. But remember, our Portlet isn’t the only portlet on the page. What if another portlet also uses a form, with a textfield called ‘number’? That other portlet would get access to our portlet’s number, and that isn’t good.

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 of shares a user wants to sell. That same page might also have a SpousalBenefitsPortlets that needs to know the number of wives or husbands a user has (Utah residents only). If each of those portlets makes a request.getParameter(“number”) call in their doView method , each one will get the number that was typed into the form of the NumberGuesserPortlet.

When a portal page is rendered, the doView method of every portlet on the page is invoked, not just that one portlet with which you might currently be interacting.

 


Encoding Form Data with encodeNamespace( )

To ensure that form data being sent from our portlet doesn’t get confused with the form data of another portlet, the PortletResponse object gives us a special method called encodeNamespace(String). If we use the encodeNamespace method on the field names in our form, no other portlet on the portal page that gets rendered back to the client will have access to our data.

All form elements should be encoded using the encodeNamespace(String) method of the response.

 

 

Figure ?-?

To ensure form data is only sent back to the intended portlet, the encodeNamespace method of the PortletResponse object needs to be used.

 

<%@ taglib uri="/WEB-INF/tld/portlet.tld" prefix="portletAPI" %>

<portletAPI:init />

 

<FORM action="<%=portletResponse.createURI()%>">

 

I'm thinking of a number between 1 and 10.

<BR><BR><I>What is it?</I>

 

<INPUT name= "<%=portletResponse.encodeNamespace("number")%>"

                                                                              type="text"  size="10" />

 

<INPUT name= "<%=portletResponse.encodeNamespace("SUBMIT")%>"

                                                                 value="Guess!!" type="submit" />

 

</FORM>

 

 

 


A Quick Look at Some Portlet Custom Tags

Since creating return URIs, and encoding form variables are such common tasks in our JSP files, the Portlet API provides a couple of handy-dandy custom tags that make these tasks just a little bit easier.

Comparatively, it is much slicker to use the <potletAPI:createURI/> custom tag to spit out a link back the the current portal page, than it is to use the corresponding scriptlet.

With a JSP Expression:
            <FORM action=
”<%=portletResponse.createURI() %>”  >

With a Custom Tag:    
            <FORM action=
"< portletAPI:createURI />"  >

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.

With a JSP: Expression:
          name=" <%=portletResponse.encodeNamespace("number")%> "

With a portletAPI Custom Tag:
          name=" <portletAPI:encodeNamespace value="number"/> "

There are fifteen custom tags defined by the portlet tag library descriptor (tld). We will explore these tags in more detail as we encounter them.

Table ?-?  

Tags Defined by the Portlet Custom Tag Library

createURI

dataAttribute

if

URIAction

createReturnURI

dataLoop

init

URIParameter

encodeURI

settingaAttribute

log

client

encodeNamespace

settingsLoop

text

 

 

Our Input Form with Portlet Custom Tags

 

Figure ?-?

Custom 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 a JSP the is loaded with innumerable custom tags really is..

 

<%@ taglib uri="/WEB-INF/tld/portlet.tld" prefix="portletAPI" %>

<portletAPI:init />

 

<FORM action="<portletAPI:createURI/>">

I'm thinking of a number between 1 and 10.<BR><BR><I>What is it?</I>

<INPUT name="<portletAPI:encodeNamespace value="number"/>"

                                                                                type="text"  size="10" >

<INPUT name="<portletAPI:encodeNamespace value="submit"/>" 

                                                                  type="submit" value="Guess!!"  >

</FORM>

 

 

Figure ?-? Using html Forms for User Input

While special custom tags are used to design portlal JSP pages, the end user has no knowledge of the behind the scenes implementation.

 

 

Home    |    www.ExamScam.com    |    Leave Us A Message    |    SCJA Java Certification Site    |    Free Mock Cert Exams    |    Free Multimedia Tutorials   
sbs
eXTReMe Tracker