9.8 Implementing Database Custom Actions

   

The JSTL database actions are comprehensive enough to support most database scenarios in a production environment; however, on occasion you may need a custom action that gathers data from disparate sources, processes that data, and subsequently specifies it as a parameter to <sql:query> or <sql:update>. For example, in "Database Inserts" on page 399, one JSP page supplies request parameters representing information about a new customer to a second JSP page, and the second JSP page performs a database insert to add the customer to the database. Because both JSP pages were implemented by the same person, the request parameters generated by the first JSP page are exactly what's needed for the second JSP page to add a new customer to the database. Here's a code segment from the second JSP page that shows how those request parameters are used:

 <sql:update var='updateResult'>     INSERT INTO CUSTOMERS VALUES (?, ?, ?, ?, ?, ?)    <sql:param value='${customers.rowsCount+1}'/>    <sql:param value='${  param.name  }'/>    <sql:param value='${  param.phone  }'/>    <sql:param value='${  param.address  }'/>    <sql:param value='${  param.city  }'/>    <sql:param value='${  param.state  }'/> </sql:update> 

But what if the request parameters did not exactly match the SQL parameters needed to create a new customer in the database? For example, if the form in the first JSP page collected the user 's name with two input fields, one for first name and one for last name, the corresponding request parameters would have to be coalesced into one name. That task could be performed by a scriptlet that stores the coalesced name in a scoped variable, or a custom action could perform that task, [17] like this:

[17] In general, custom actions are preferable to scriptlets because custom actions provide a degree of separation between business and presentation logic.

 <html>     ...    <body>       ...  <%@ taglib uri='WEB-INF/core-jstl.tld' prefix='core-jstl'%>  <%-- Perform the database update --%>       <sql:update var='updateResult'>          INSERT INTO CUSTOMERS VALUES (?, ?, ?, ?, ?, ?)          <sql:param value='${customers.rowCount+1}'/>          <%-- The <core-jstl:nameParam> custom action coalesces               the first and last names (which are request               parameters) and passes them to its enclosing               <sql:update> action --%>  <core-jstl:nameParam/>  <sql:param value='${param.phone}'/>          <sql:param value='${param.address}'/>          <sql:param value='${param.city}'/>          <sql:param value='${param.state}'/>       </sql:update>       ...    </body>    ... </html> 

The code fragment listed above uses an application-specific custom action ”<core-jstl:nameParam> ”that coalesces first and last names stored in the request parameters and supplies the coalesced name as a parameter to its enclosing <sql:update>. That custom action behaves just like <sql:param> by sending a parameter to its enclosing <sql:update> action. Let's see how that custom action is implemented.

First, in WEB-INF/core-jstl.tld , we declare the tag library that contains <core-jstl:nameParam>, with a tag library descriptor, which is listed in Listing 9.23.

Listing 9.23 WEB-INF/core-jstl.tld
 <?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE taglib   PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN"   "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> <taglib>   <tlib-version>1.0</tlib-version>   <jsp-version>1.2</jsp-version>   <short-name>app</short-name>   <display-name>application tags</display-name>   <description>     A tag library with an action that passes a parameter to     a query action   </description>   <tag>     <name>nameParam</name>     <tag-class>tags.NameParamTag</tag-class>     <body-content>NONE</body-content>     <description>       Coalesces first and last names obtained from request       parameters, and passes them as an SQL query parameter       to an enclosing tag that implements       javax.servlet.jsp.jstl.sql.SQLExcecutionTag     </description>   </tag> </taglib> 

Second, we implement the action itself, which is listed in Listing 9.24.

Listing 9.24 WEB-INF/classes/tags/NameParamTag.java
 package tags; import javax.servlet.ServletRequest; import javax.servlet.jsp.JspException; import javax.servlet.jsp.tagext.TagSupport;  import javax.servlet.jsp.jstl.sql.SQLExecutionTag;  public class NameParamTag extends TagSupport { _  public int doStartTag() throws JspException {       Class klass =             javax.servlet.jsp.jstl.sql.SQLExecutionTag.class;  SQLExecutionTag ancestor = (SQLExecutionTag)   findAncestorWithClass(this, klass);  if(ancestor != null) {          ServletRequest request = pageContext.getRequest();  ancestor.addSQLParameter(   request.getParameter("firstName") + " " +   request.getParameter("lastName"));  }       else {          throw new JspException("This tag can only be in the " +             "body of a tag that implements " +             "javax.servlet.jsp.jstl.sql.SQLExecutionTag");       }       return SKIP_BODY;    } } 

The tag handlers for <sql:query> and <sql:update> both implement the javax.servlet.jsp.jstl.sql.SQLExecutionTag interface, which defines a single method: addSQLParameter(Object) . The custom action listed above checks to see whether it has an ancestor action that implements that interface; if so, it calls that action's addSQLParameter method, passing it the coalesced name. If the custom action does not have an ancestor that implements SQLExecutionTag , it throws an exception.

   


Core JSTL[c] Mastering the JSP Standard Tag Library
Core JSTL[c] Mastering the JSP Standard Tag Library
ISBN: 131001531
EAN: N/A
Year: 2005
Pages: 124

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