15.5 A Tool Application

Java Servlet Programming, 2nd Edition > 15. WebMacro > 15.5 A Tool Application

 
< BACKCONTINUE >

15.5 A Tool Application

To conclude our discussion of WebMacro, let's look at how we would rewrite the tool application from the previous chapter using WebMacro now instead of Tea. It's easiest to understand if we look at the template first, shown in Example 15-9.

Example 15-9. The Tool Application WebMacro Template
## toolview.wm #set $Response.ContentType = "text/html" #set $title = "Tool Listing" #set $deck = "A list of content creation tools" #set $desc = "Without tools, people are nothing more than animals.  And \               pretty weak ones at that.  Here's a list of servlet-based \               content creation tools you can use so you won't be a servlet \               weakling." #parse "header.wm" ## Define a value to be read by the servlet #param $defaultState = "LIVE" #foreach $tool in $tools {   <HR SIZE=2 ALIGN=LEFT>   <H3>   $tool.Name   #if ($tool.isNewWithin(45)) {     <FONT COLOR=#FF0000><B> (New!) </B></FONT>   }    #else {     #if ($tool.isUpdatedWithin(45)) {       <FONT COLOR=#ff0000><B> (Updated!) </B></FONT>     }   }    </H3>   <A HREF="$tool.HomeURL">$tool.HomeURL</A><BR>   $tool.Comments } #parse "footer.wm"

The beginning of this template assigns values for the page's title, deck, and description (using \ characters as line continuators for the description). These variables are used within the parsed header.wm template to create the page structure surrounding the core tools list. The variables are also visible within the footer.wm template parsed at the bottom of the template, although the footer doesn't make use of them. The header and footer templates are shown in Example 15-10 and Example 15-11, respectively.

The toolview.wm template uses the #param directive to define LIVE as a constant value for the template parameter defaultState, allowing the servlet calling this template to know the default tool state this page should display.

Then the template uses a #foreach directive to iterate over the tools list the servlet passed in. The tools variable may be an array, Iterator, Enumeration, or an object like Vector or List with either an iterator( ) or elements( ) method the template doesn't care. For each tool entry, the template prints its name, whether it's new or updated, its URL, and finally the comments about the tool. The template invokes the isNewWithin(int) and isUpdatedWithin(int) methods to determine if the content should count as new or updated. The template could access $tool.CreatedAgeInDays and $tool.ModifiedAgeInDays, however it would need the support of the MathTool context tool from Example 15-5 to perform the less-than comparison.

Example 15-10. The header.wm File
## header.wm <HTML><HEAD><TITLE>$title</TITLE></HEAD> <BODY BGCOLOR="#FFFFFF" BACKGROUND="/images/background.gif"       LINK="#003333" ALINK="#669999" VLINK="#333333"> <IMG src="/books/1/318/1/html/2//images/banner.gif" WIDTH=600 HEIGHT=87 BORDER=0><BR> <TABLE> <TR> <TD WIDTH=125 ROWS=10 VALIGN=TOP>  <BR><BR><BR>  <FONT FACE="Arial,Helvetica" SIZE="+1" COLOR="#FF0000">  <A HREF="/index.html">Home</A><BR>  <A HREF="/hosting.html">Hosting</A><BR>  <A HREF="/engines.html">Engines</A><BR>  </FONT> </TD> <TD WIDTH=475>   <TABLE CELLPADDING=5><TR><TD WIDTH=600 BGCOLOR="#006699" VALIGN=TOP>   <B><FONT FACE="Arial,Helvetica" SIZE="+2">   $title   </FONT></B>   </TD></TR></TABLE>   <B><FONT FACE="Arial,Helvetica" SIZE="+1" COLOR="#003366">   $deck   </FONT></B><P>   <P>   <FONT FACE="Arial,Helvetica">   $desc
Example 15-11. The footer.wm File
## footer.wm  </FONT> </TD> </TR> <TR> <TD></TD> <TD WIDTH=475 ALIGN=CENTER COLSPAN=3> <HR> <FONT FACE="Arial,Helvetica"> <A HREF="/index.html">Home</A>&nbsp;&nbsp; <A HREF="/hosting.html">Hosting</A>&nbsp;&nbsp; <A HREF="/engines.html">Engines</A>&nbsp;&nbsp;<P> </FONT> <TABLE WIDTH=100%> <TR> <TD WIDTH=260 ALIGN=LEFT VALIGN=TOP> <FONT FACE="Arial,Helvetica"> <A HREF="/copyright.html">Copyright</A> &copy; 2000 Jason Hunter<BR> All Rights Reserved.</TD> <TD WIDTH=5></FONT></TD> <TD WIDTH=230 ALIGN=RIGHT VALIGN=TOP> <FONT FACE="Arial,Helvetica"> Contact: <A HREF="mailto:webmaster@servlets.com">webmaster@servlets.com</a> </FONT></TD> </TR> </TABLE> </TD> </TR> </TABLE> </BODY> </HTML>

The code for the Tool class remains the same as for the Tea application, although with WebMacro the bean accessor methods aren't necessary and the isNewWithin(int) and isUpdatedWithin(int) are visible from the template. The code for the ToolServlet class is listed in Example 15-12.

Example 15-12. The Servlet Driving the Tool Application
import org.webmacro.*; import org.webmacro.servlet.*; import org.webmacro.util.*; import java.io.*; import java.sql.*; import java.util.*; import javax.servlet.*; public class ToolServlet extends WMServlet {   private Log log;   private Tool[] tools;   public void start() throws ServletException {     // Load the tool data in our init for simplicity     String toolsFile = getInitParameter("toolsFile"); // from web.xml     if (toolsFile == null) {       throw new ServletException(         "A tools data file must be specified as the toolsFile init parameter");     }     log = new Log(getServletName(), "Tool example debugging log");     log.debug("Loading tools from " + toolsFile);     try {       tools = Tool.loadTools(toolsFile);       if (tools.length == 0) {         log.warning("No tools found in " + toolsFile);       }       else {         log.info(tools.length + " tools found in " + toolsFile);       }     }     catch (Exception e) {       log.error(e);       throw new ServletException(e);     }   }   // Creating a context provides functions accessible from the templates.   public Template handle(WebContext context) throws HandlerException {     // You often pass on the request, response, and application even if     // not all the objects are used, since they may be used later     try {       Template view = getTemplate("toolview.wm");       String state = context.getRequest().getParameter("state");       if (state == null) {         state = (String)view.getParam("defaultState");       }       if (state == null) {         context.put("tools", getTools());        }       else {         context.put("tools", getTools(state));       }       return view;     }     catch (WebMacroException e) {       log.exception(e);       throw new HandlerException(e.getMessage());     }     catch (IOException e) {       log.exception(e);       throw new HandlerException(e.getMessage());     }   }   public Tool[] getTools() {     return tools;   }   public Tool[] getTools(String state) {     List list = new LinkedList();     for (int i = 0; i < tools.length; i++) {       if (tools[i].getStateFlag().equalsIgnoreCase(state)) {         list.add(tools[i]);       }     }     return (Tool[]) list.toArray(new Tool[0]);   } }

The servlet extends WMServlet and thus defines a start( ) method instead of init( ) and a handle( ) method instead of doGet( ) and doPost( ). The start( ) method retrieves the init parameter toolsFile and loads the tool data from the file using Tool.loadTools(toolsFile). The method also creates a Log instance and uses it to report on its progress writing info, debug, warning, and error messages.

The handle( ) method loads the toolview.wm template, then reads the request's state parameter to determine tools of which state to display. If no such parameter exists, the servlet uses the default value specified within the template itself. The servlet then places into the WebContext the appropriate tools list under the variable name tools and returns the template. Any exception thrown is logged and passed on as a HandlerException.

The getTools( ) methods at the end of the servlet are only supporting methods. They aren't accessible by the template, although they could be made visible by including a lookup object containing these methods within the context. Then a template could do its own handling of the state parameter:

    #set $state = $Form.state;     #if (!state) {       #set $tools = $lookup.getTools("live")     }     #else {       #set $tools = $lookup.getTools($state)     }

Whether you prefer this pull approach or the push model presented earlier is mostly a matter of taste. WebMacro tends to encourage the push model, and Tea tends to encourage the pull model; yet both can easily support either model.

You can use the com.oreilly.servlet.CacheHttpServlet class from Chapter 3, to cache the output and improve the performance of templates. The technique works best for templates whose output takes a significant time to produce but changes only rarely, such as templates that display database results. To take advantage of the caching you need to write your servlet to extend CacheHttpServlet (you'll have to avoid the convenience of WMServlet and handle templates manually) and implement getLastModified( ) . If the data comes from a database, the getLastModified( ) method can return the time the database was last updated (as notes in a context-wide variable by the servlet doing the update) or, if the update time can't be determined, the method can simply return the current time modulo some value so updates occur on regular intervals. If the data comes from a file, the method can return the time the datafile was last updated (perhaps checking only every once in a while for efficiency).


Last updated on 3/20/2003
Java Servlet Programming, 2nd Edition, © 2001 O'Reilly

< BACKCONTINUE >


Java servlet programming
Java Servlet Programming (Java Series)
ISBN: 0596000405
EAN: 2147483647
Year: 2000
Pages: 223

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net