DekGenius.com
Previous Section  < Day Day Up >  Next Section

10.3 The User Interface (JSP)

The user interface is fairly straightforward. Instead of just dumping our results to the console or creating an XML document of the results (as in the web service implementation from Chapter 9), this time we need to write a JSP that iterates over the results and displays them as hyperlinks in a table.

The original jPetStore search feature used a PagedListHolder for its results because it displayed the image associated with each returned product in the table. Since the images were arbitrary in size, jPetStore didn't want to display too many entries on a given page since it might result in a lot of vertical scrolling. Our results consist of a hyperlink to the returned URL and the relative rank of the given result; therefore, we'll use a simple table to display our results.

Again, we are faced with the rewrite-or-replace question. Just like last time, we have three questions to consider:

  1. Do we have access to the original source? We must, since JSPs are just text files in both development and deployment mode.

  2. Will we ever want to reuse the existing service? We do, but in this case, a JSP is so easy to recreate that it won't make much difference.

  3. Does the current version implement some standard interface? Not as such, since JSPs are just mixes of static HTML and dynamic content.

Because of the rather trivial nature of the changes and because JSPs are easily edited in place (no compilation necessary), we'll just repurpose the existing SearchProducts.jsp file. This strategy saves us from having to change any more configuration settings:

<%@ include file="IncludeTop.jsp" %>

<table align="left" bgcolor="#008800" border="0" cellspacing="2" cellpadding="2">
<tr>
    <td bgcolor="#FFFF88">
    <a href="<c:url value="/shop/index.do"/>">
       <b><font color="BLACK" size="2"> &lt;&lt; Main Menu</font></b>
    </a>
    </td>
</tr>
</table>
<table align="center" bgcolor="#008800" border="0" cellspacing="2" 
    cellpadding="3">
  
    <tr bgcolor="#CCCCCC">  <td><b>URL</b></td>  <td><b>Rank</b></td> </tr>
    <c:forEach var="page" items="${hits}">
          <tr bgcolor="#FFFF88">
          <td><a href="<c:out value="${page.url}"/>">
                <c:out value="${page.url}"/></a>
          </td>
          <td>
              <c:out value="${page.score}"/>
        </td>
          </tr>
    </c:forEach>
</table>

<%@ include file="IncludeBottom.jsp" %>

The JSP files in the application have a standard header and footer defined in IncludeTop.jsp and IncludeBottom.jsp. All we have to do is render the results in between the include directives. Start by creating a JSP-style forEach loop, with an enumerator called page pointing at each member of the HashMap called "hits." For each hit, we render a table row containing the URL (the value of which is both the text to display and the HREF to point it to) and the relative rank of the hit. JSP handles hooking up the variables and properties using reflection. However, when implementing this page, we come across the first (and only) reason to change some of the original Spider code.

10.3.1 Changes to the Original Code to Fit the JSP

JSP reflects on fields to hook up properties to <out> display tags instead of getters and setters. Unfortunately, our original implementation of HitBean marked all of its data private and only exposed getters and setters (normally, the appropriate strategy). Since we now have to have the fields exposed directly, we need to make a simple change to the Spider. The original class started with these declarations:

final String url;
final String title;
final float score;

It now has to become:

public final String url;
public final String title;
public final float score;

10.3.2 What if We Don't Have the Spider Source?

It is instructive to examine what happens when we aren't the original authors of either the application we are extending (jPetStore) or the service we are integrating (Simple Spider). If we don't have access to the source code of either project, we can still make the extension we've been working on. For the jPetStore, all we did was modify a configuration file and a JSP (which we always have the source for) and add a new class.

If we don't have access to the original source for the HitBean class, how can we make it work with the JSP? The answer is simple: write a wrapper class that exposes the correct properties (or just use the already exposed web service interface):

public class HitBeanWrapper {
    private HitBean _hitbean;
    public String url;
    public String title;
    public float score;

    public HitBeanWrapper(HitBean hitbean)
    {
        _hitbean = hitbean;
        url = hitbean.getUrl( );
        title = hitbean.getTitle( );
        score = hitbean.getScore( );
    }
    public String getScoreAsString( ) {
            return _hitbean.getScoreAsString( );
    }
}

This requires a change to the handleRequest method of the SearchPagesController, as well:

HashMap hits = new HashMap(qb.getResults( ).length);
for(int i =0;i<qb.getResults( ).length;i++)
{
      hits.put("hits", new HitBeanWrapper(qb.getResults( )[i]));
}
return new ModelAndView("SearchProducts", hits);

That's it. We've edited the Spider all we need to in order to incorporate it into the jPetStore application.

10.3.3 Principles in Action

  • Keep it simple: display the URL to result pages instead of complex rendering of product information; use simple table output instead of PagedListHolder (the need for it was gone)

  • Choose the right tools: table, not PagedListHolder; JSP

  • Do one thing, and do it well: JSP focuses on display of output, not search intricacies

  • Strive for transparency: HitBean exposes simple data properties; use a wrapper for HitBean if the source is not available

  • Allow for extension: none

    Previous Section  < Day Day Up >  Next Section