|
FAQ
History |
|
Search
Feedback |
Examples
The custom tags described in this section demonstrate solutions to two recurring problems in developing JSP applications: minimizing the amount of Java programming in JSP pages and ensuring a common look and feel across applications. In doing so, they illustrate many of the styles of tags discussed in the first part of the chapter.
An Iteration Tag
Constructing page content that is dependent on dynamically generated data often requires the use of flow control scripting statements. By moving the flow control logic to tag handlers, flow control tags reduce the amount of scripting needed in JSP pages.
An iterator tag retrieves objects from a collection stored in a JavaBeans component and assigns them to a scripting variable. The body of the tag retrieves information from the scripting variable. While elements remain in the collection, the
iteratortag causes the body to be reevaluated. To run the example described in this section:Your browser should display the page shown in Figure 5-2.
![]()
Figure 5-2 List of Departments
JSP Page
The
list.jsppage of theiteratorexample uses theiteratortag to step though a collection of department members. First, the collection is retrieved by a name specified as a request parameter. The collection is supplied to the iterator tag which sets the scripting variable namedmemberto each item in the collection. Finally, properties of themembervariable are retrieved withjsp:getPropertystatements for display in a table.<jsp:useBean id="org" class="org.Organization"/> <% String deptName = (String)request.getParameter("deptName"); org.Department dept = org.getDepartment(deptName); %> <head> <title><%= deptName%> Department</title> </head> <body bgcolor="white"> <table border=2 cellspacing=3 cellpadding=3> <tr> <td colspan=3><b><center> <%= deptName%></b></center></td> </tr> <tr> <td width=100><b>Name</b></td> <td width=100><b>Extension</b></td> <td width=100><b>Email</b></td> </tr> <%-- List all department members --%> <tlt:iterator name="member" type="org.Member" group="<%= dept.getMembers()%>"> <tr> <td><jsp:getProperty name="member" property="name"/></td> <td><jsp:getProperty name="member" property="phone"/></td> <td><jsp:getProperty name="member" property="email"/></td> </tr> </tlt:iterator> </table> </body>Upon selecting the Engineering department from the previous page, your browser will display the page in Figure 5-3.
![]()
Figure 5-3 Engineering Department Contact Information
Tag Handler
The
doStartTagmethod first initializes an iterator from a collection provided as a tag attribute. If the iterator contains more elements,doStartTagsets the value of the scripting variable to the next element and then sets the return value toEVAL_BODY_INCLUDEto indicate that the body should be evaluated; otherwise it ends the iteration by returningSKIP_BODY.After the body has been evaluated, the
doAfterBodymethod sets the value of the scripting variable to the next element and returnsEVAL_BODY_AGAINto indicate that the body should be evaluated again. This causes the reexecution ofdoAfterBody. When there are no remaining elements,doAfterBodyterminates the process by returningSKIP_BODY.public int doStartTag() throws JspException, JspException { otherDoStartTagOperations(); if (theBodyShouldBeEvaluated()) { return EVAL_BODY_INCLUDE; } else { return SKIP_BODY; } } public void otherDoStartTagOperations() if(group.size() > 0) iterator = group.iterator(); } public boolean theBodyShouldBeEvaluated() { if (iterator.hasNext()) { pageContext.setAttribute(name, iterator.next()); return true; } else return false; } public int doAfterBody() throws JspException { if (theBodyShouldBeEvaluatedAgain()) { return EVAL_BODY_AGAIN; } else { return SKIP_BODY; } } public boolean theBodyShouldBeEvaluatedAgain() { if (iterator.hasNext()) { pageContext.setAttribute(name, iterator.next()); return true; } else return false; }Tag Extra Info Class
Information about the scripting variable is provided in the
IteratorTEItag extra info class. The name and class of the scripting variable are passed in as thenameandtypetag attributes and used to fill in theVariableInfoconstructor.public VariableInfo[] getVariableInfo(TagData data) { VariableInfo info1 = new VariableInfo( data.getAttributeString("name"), data.getAttributeString("type"), true, VariableInfo.NESTED); VariableInfo [] info = { info1 }; return info; }A Template Tag Library
A template provides a way to separate the common elements that are part of each screen from the elements that change with each screen of an application. Putting all the common elements together into one file makes it easier to maintain and enforce a consistent look and feel in all the screens. It also makes development of individual screens easier because the designer can focus on portions of a screen that are specific to that screen while the template takes care of the common portions.
The template is a JSP page with placeholders for the parts that need to change with each screen. Each of these placeholders is referred to as a parameter of the template. For example, a simple template could include a title parameter for the top of the generated screen and a body parameter to refer to a JSP page for the custom content of the screen.
The template uses a set of nested tags--
definition,screen, andparameter--to define a table of screen definitions and uses aninserttag to insert parameters from a screen definition into a specific application screen.JSP Page
The template for the Duke's Bookstore example,
template.jsp, is shown below. This page includes a JSP page that creates the screen definition and then uses theinserttag to insert parameters from the definition into the application screen.<%@ taglib uri="/template" prefix="tt" %> <%@ page errorPage="errorpage.jsp" %> <%@ include file="screendefinitions.jsp" %><html> <head> <title> <tt:insert definition="bookstore" parameter="title"/> </title> </head> <tt:insert definition="bookstore" parameter="banner"/> <tt:insert definition="bookstore" parameter="body"/> </body> </html>
screendefinitions.jspcreates a screen definition based on a request attributeselectedScreen:<tt:definition name="bookstore" screen="<%= (String)request. getAttribute(\"selectedScreen\") %>"> <tt:screen id="/enter"> <tt:parameter name="title" value="Duke's Bookstore" direct="true"/> <tt:parameter name="banner" value="/banner.jsp" direct="false"/> <tt:parameter name="body" value="/bookstore.jsp" direct="false"/> </tt:screen> <tt:screen id="/catalog"> <tt:parameter name="title" value="<%=messages.getString("TitleBookCatalog")%>" direct="true"/> ... </tt:definition>The template is instantiated by the
Dispatcherservlet.Dispatcherfirst gets the requested screen and stores it as an attribute of the request. This is necessary because when the request is forwarded totemplate.jsp, the request URL doesn't contain the original request (for example,/bookstore3/catalog) but instead reflects the path (/bookstore3/template.jsp) of the forwarded page. Finally, the servlet dispatches the request totemplate.jsp:public class Dispatcher extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) { request.setAttribute("selectedScreen", request.getServletPath()); RequestDispatcher dispatcher = request.getRequestDispatcher("/template.jsp"); if (dispatcher != null) dispatcher.forward(request, response); } public void doPost(HttpServletRequest request, HttpServletResponse response) { request.setAttribute("selectedScreen", request.getServletPath()); RequestDispatcher dispatcher = request.getRequestDispatcher("/template.jsp"); if (dispatcher != null) dispatcher.forward(request, response); } }Tag Handlers
The template tag library contains four tag handlers--
DefinitionTag,ScreenTag,ParameterTag, andInsertTag--that demonstrate the use of cooperating tags.DefinitionTag,ScreenTag, andParameterTagcomprise a set of nested tag handlers that share public and private objects.DefinitionTagcreates a public object nameddefinitionthat is used byInsertTag.In
doStartTag,DefinitionTagcreates a public object namedscreensthat contains a hash table of screen definitions. A screen definition consists of a screen identifier and a set of parameters associated with the screen.public int doStartTag() { HashMap screens = null; screens = (HashMap) pageContext.getAttribute("screens", pageContext.APPLICATION_SCOPE); if (screens == null) pageContext.setAttribute("screens", new HashMap(), pageContext.APPLICATION_SCOPE); return EVAL_BODY_INCLUDE; }The table of screen definitions is filled in by
ScreenTagandParameterTagfrom text provided as attributes to these tags. Table 5-6 shows the contents of the screen definitions hash table for the Duke's Bookstore application.
In
doEndTag,DefinitionTagcreates a public object of classDefinition, selects a screen definition from thescreensobject based on the URL passed in the request, and uses it to initialize theDefinitionobject.public int doEndTag()throws JspTagException { try { Definition definition = new Definition(); HashMap screens = null; ArrayList params = null; TagSupport screen = null; screens = (HashMap) pageContext.getAttribute("screens", pageContext.APPLICATION_SCOPE); if (screens != null) params = (ArrayList) screens.get(screenId); else ... if (params == null) ... Iterator ir = null; if (params != null) ir = params.iterator(); while ((ir != null) && ir.hasNext()) definition.setParam((Parameter) ir.next()); // put the definition in the page context pageContext.setAttribute( definitionName, definition); } catch (Exception ex) { ex.printStackTrace(); } return EVAL_PAGE; }If the URL passed in the request is /
enter, theDefinitioncontains the items shown in Table 5-7:
Table 5-7 Definition for the URL /enter Title Banner BodyDuke's Bookstore/banner.jsp/bookstore.jsp
The screen definition for the URL
/enteris shown in Table 5-8. The definition specifies that the value of theTitleparameter, Duke's Bookstore, should be inserted directly into the output stream, but the values ofBannerandBodyshould be dynamically included.
Table 5-8 Screen Definition for the URL /enter Parameter Name Parameter Value isDirecttitleDuke's Bookstoretruebanner/banner.jspfalsebody/bookstore.jspfalse
InsertTagusesDefinitionto insert parameters of the screen definition into the response. In thedoStartTagmethod, it retrieves the definition object from the page context.public int doStartTag() { // get the definition from the page context definition = (Definition) pageContext. getAttribute(definitionName); // get the parameter if (parameterName != null && definition != null) parameter = (Parameter)definition. getParam(parameterName); if (parameter != null) directInclude = parameter.isDirect(); return SKIP_BODY; }The
doEndTagmethod inserts the parameter value. If the parameter is direct, it is directly inserted into the response; otherwise, the request is sent to the parameter, and the response is dynamically included into the overall response.public int doEndTag()throws JspTagException { try { if (directInclude && parameter != null) pageContext.getOut().print(parameter.getValue()); else { if ((parameter != null) && (parameter.getValue() != null)) pageContext.include(parameter.getValue()); } } catch (Exception ex) { throw new JspTagException(ex.getMessage()); } return EVAL_PAGE; }How Is a Tag Handler Invoked?
The
Taginterface defines the basic protocol between a tag handler and a JSP page's servlet. It defines the life cycle and the methods to be invoked when the start and end tags are encountered.The JSP page's servlet invokes the
setPageContext,setParent, and attribute setting methods before callingdoStartTag. The JSP page's servlet also guarantees thatreleasewill be invoked on the tag handler before the end of the page.Here is a typical tag handler method invocation sequence:
ATag t = new ATag(); t.setPageContext(...); t.setParent(...); t.setAttribute1(value1); t.setAttribute2(value2); t.doStartTag(); t.doEndTag(); t.release();The
BodyTaginterface extendsTagby defining additional methods that let a tag handler access its body. The interface provides three new methods:A typical invocation sequence is:
t.doStartTag(); out = pageContext.pushBody(); t.setBodyContent(out); // perform any initialization needed after body content is set t.doInitBody(); t.doAfterBody(); // whiledoAfterBodyreturnsEVAL_BODY_BUFFEREDwe // iterate body evaluation ... t.doAfterBody(); t.doEndTag(); t.pageContext.popBody(); t.release();
|
FAQ
History |
|
Search
Feedback |
All of the material in The J2EE Tutorial for the Sun ONE Platform is copyright-protected and may not be published in other works without express written permission from Sun Microsystems.