Sei sulla pagina 1di 20

Creating JSP 2.

0 Tag Files Page 1 of 20

J2EE & Web Services

Creating JSP 2.0 Tag Files


by Andrei Cioroianu

Learn how to build reusable Web templates and database scripts using JSP, JSTL, and SQL

Download the source code for this article

Tag files are one of the most important new additions to JavaServer Pages (JSP) technology, allowing
Web developers to build libraries of custom tags with the JSP syntax. The JSP tag files are translated
into Java code automatically by the JSP container through the same process that transparently produces
Java Servlets from JSP pages. We could say that tag files hide the complexity of building custom JSP
tag libraries. While such libraries can be reused across Web applications, they offer significant benefits
even when designed for a specific application because custom tags improve the maintainability of the
Web pages. After reading this article, you'll know how to create and use tag files and how to transform
existing page fragments into tag files.

JSP 2.0 has defined three new directives (<%@tag%>, <%@attribute%>, and <%@variable%>) and
two new standard actions (<jsp:invoke> and <jsp:doBody>) that can be used only in tag files. We'll use
them throughout the article, and you'll find out how to take advantage of the more-advanced tag file
features such as "dynamic attributes," "fragment attributes," and "variables named from attributes." Tag
files can be a powerful tool when used together with the JSP Standard Tag Library (JSTL), which
introduced the expression language adopted by JSP 2.0 and many JSP actions, including a set of SQL
tags. We'll use JSTL and the advanced JSP features to build tag files that update and query a database.

Tag Files Overview

JSP 1.x allows Web developers to build Java components (called tag handlers) that are invoked from
JSP pages via custom tags. Tag handlers are like the old Java Servlets because you use lots of println()
calls to generate HTML content and then you have to compile your Java code. The tag files of JSP 2.0
are like the JSP pages, because you use the JSP syntax and then the JSP container takes your JSP tag
files, parses them, generates Java tag handlers, and compiles them automatically. Tag files are invoked
from JSP pages using custom tags matching the <prefix:tagFileName> pattern.

In order to be recognized by the JSP container, tag files must be named using the .tag file extension and
they must be placed in the /WEB-INF/tags directory of your Web application or in a subdirectory
of /WEB-INF/tags. If you adopt this deployment method, you don't have to create any Tag Library
Descriptor (TLD) as you in the case of the JSP libraries implemented with Java tag handlers. You may
also place your tag files in the /META-INF/tags directory of a .jar file, which can be deployed easier,
but in this case you have to create a TLD and you have to repack your tag files after every change.

Tag files and JSP pages use almost the same syntax. The first difference you'll notice is the new <%
@tag%> directive, which is the equivalent of <%@page%>. These two directives have similar
attributes, but the former was designed for tag files while the latter can be used only in JSP pages.
Instead of declaring their attributes and variables in a separate .tld file, tag files use the <%@attribute%
> and <%@variable%> directives. When a tag file is invoked from a JSP page, the custom tag may
have a body (between <prefix:tagFileName> and </prefix:tagFileName>) that can be executed by the
tag file with the <jsp:doBody> action. You'll see how this works in the next section.

Using Tag Files Instead of Page Fragments

In order to have maintainable Web pages, many well-designed JSP 1.x applications use page fragments
that are included with <jsp:include> or <%@include%> in larger pages, which isn't the ideal method
for reusing JSP fragments in Web applications. Unlike the page-inclusion solution, tag files have been

http://www.oracle.com/technology/pub/articles/cioroianu_tagfiles.html?_template=/o... 13/08/2008
Creating JSP 2.0 Tag Files Page 2 of 20

specifically designed for building libraries of reusable page fragments. This section compares the
syntax of the old-fashioned JSP 1.x method with the much better syntax of the JSP 2.0 tag files.

Transforming included pages into tag files. Let's say you have a page named container.jsp that includes
another page named part.jsp with <jsp:include page="part.jsp"/>. Execute the following steps to
transform part.jsp into a tag file.

Step 1: Move the included page.


In the WEB-INF directory of your application, create a subdirectory named tags and move the part.jsp
page into WEB-INF/tags.

Step 2: Rename the included page.


Because the standard tag file extension is .tag, you have to rename part.jsp to part.tag.

Step 3: Edit the tag file.


Open the part.tag file for editing and replace the <%@page%> directive with a similar <%@tag%>
directive. If you get any compilation errors, some other minor changes might be necessary. Use
jspContext instead of pageContext.

Step 4: Declare the tag library.


Insert <%@taglib prefix="tags" tagdir="/technology/WEB-INF/tags"%> at the beginning of
container.jsp.

Step 5: Invoke the tag file.


Replace <jsp:include page="part.jsp"/> with <tags:part/> in container.jsp.

container.jsp (before transformation)

<p> Container Page </p>

<jsp:include page="part.jsp"/>

container.jsp (after transformation)

<%@ taglib prefix="tags" tagdir="/technology/WEB-INF/tags" %>

<p> Container Page </p>

<tags:part/>

part.jsp (before transformation)

<%@ page language="java" %>

<p> Included Page </p>

<%= pageContext.getClass().getName() %>

part.tag (after transformation)

<%@ tag language="java" %>

<p> Invoked tag </p>

<%= jspContext.getClass().getName() %>

Example based on <jsp:include> and <%@include%>. The main page of this example (main.jsp)
includes two page fragments (header.jspf and footer.jspf) using the <%@include%> directive. The
main page also includes another page (content.jsp) using <jsp:include>. The main.jsp page provides

http://www.oracle.com/technology/pub/articles/cioroianu_tagfiles.html?_template=/o... 13/08/2008
Creating JSP 2.0 Tag Files Page 3 of 20

three parameters (a, b, and c) to the included page with the help of the <jsp:param> standard action.
The included content.jsp page outputs the values of the three parameters with ${param.a}, ${param.b},
and ${param.c}.

main.jsp

<%@ include file="header.jspf" %>

<jsp:include page="content.jsp">
<jsp:param name="a" value="1"/>
<jsp:param name="b" value="2"/>
<jsp:param name="c" value="3"/>
</jsp:include>

<%@ include file="footer.jspf" %>

header.jspf

<p> Header </p>

footer.jspf

<p> Footer </p>

content.jsp

<p> Included Content </p>

<p> Parameters - ${param.a}, ${param.b}, ${param.c} </p>

Output

Example based on tag files. The JSP page of this example (main.jsp) uses the <%@taglib%> directive
to declare the library that contains a tag file (wrapper.tag), indicating its prefix (tags) and the directory
where the tag file was created (/WEB-INF/tags). The main.jsp page invokes the wrapper.tag file using
the <tags:wrapper> custom tag, which has three attributes (a, b, and c) and some body content (<p>
Wrapped Content </p>). Note that you may not use any scripting elements between <tags:wrapper>
and </tags:wrapper> in the JSP page. Scripting elements include JSP 1.x declarations (<%!...%>), JSP
1.x expressions (<%=...%>), and scriptlets (<%...%>), which are all supported by JSP 2.0. Note that tag

http://www.oracle.com/technology/pub/articles/cioroianu_tagfiles.html?_template=/o... 13/08/2008
Creating JSP 2.0 Tag Files Page 4 of 20

files may use scripting elements like any regular JSP page. In fact, it would be a good idea to move
your Java code from existing JSP pages into tag files if you don't like building JSP libraries based on
Java tag handlers. This would make your Java scriptlets reusable and your Web pages more readable.
The JSP container does the hard work for you, generating the tag handler classes automatically.

The wrapper.tag file is the replacement of the three included pages from the previous example
(header.jspf, footer.jspf, and content.jsp). The tag file declares three attributes using the <%
@attribute%> directive and outputs a header, a footer, and the values of the attributes (${a}, ${b}, and
${c}). The wrapper.tag file executes the body of <tags:wrapper> from main.jsp with the help of the
new <jsp:doBody> standard action. The tag file decides if and when the body of <tags:wrapper> is
executed. If wrapper.tag doesn't use <jsp:doBody>, the body of <tags:wrapper> is ignored. The tag file
could also use <jsp:doBody> multiple times to execute the body more than once.

main.jsp

<%@ taglib prefix="tags" tagdir="/technology/WEB-INF/tags" %>

<tags:wrapper a="1" b="2" c="3">

<p> Wrapped Content </p>

</tags:wrapper>

wrapper.tag

<%@ tag body-content="scriptless" %>


<%@ attribute name="a" required="true" %>
<%@ attribute name="b" required="true" %>
<%@ attribute name="c" required="true" %>

<p> Header </p>

<jsp:doBody/>

<p> Attributes - ${a}, ${b}, ${c} </p>

<p> Footer </p>

Output

http://www.oracle.com/technology/pub/articles/cioroianu_tagfiles.html?_template=/o... 13/08/2008
Creating JSP 2.0 Tag Files Page 5 of 20

Tag files versus <jsp:include> and <%@include%>. Custom tags invoking tag files have a more
compact syntax than the combination of <jsp:include> and <jsp:param>. Custom tags can also be
nested and indented in a natural way, making the code easy to read. The only thing that might be
perceived as a disadvantage is the restriction that doesn't allow you to use scripting elements in the
body of a custom tag that invokes a tag file. This might actually be a plus, considering that scriptless
Web pages can be maintained more easily. If you have to mix JSP and Java code, you can move the
Java scriptlets into the tag file.

More tag file benefits are offered by the <%@tag%>, <%@attribute%>, and <%@variable%>
directives:

z Attribute declarations make the code of the tag file more readable because you can find out the
names of the attributes by just looking at the tag file's header. In the case of the included pages,
parameters are not declared at the beginning of the page. If you have to use a page developed by
someone else and parameters aren't documented, you might have to analyze the source code of
the entire page.

z By default, all attributes are optional. If an attribute is required, you should specify this with <%
@attribute name="..." required="true"%>. By default, a custom tag invoking a tag file may
contain scriptless JSP code. If the tag file doesn't use <jsp:doBody>, you should specify that the
tag file ignores the body content with <%@tag body-content="empty"%>. This declaration
prevents the accidental use of JSP content between <prefix:tagFileName> and
</prefix:tagFileName>. In this case, the tag file should be invoked with an empty tag like
<prefix:tagFileName/>. By indicating the required attributes and whether the body content is
used or not, you can prevent many frequent errors, reducing the time you spend debugging JSP
pages. Support for such declarations is not provided for the included JSP pages.

z You may also specify the type of an attribute using something like <%@attribute
type="className"%>. The value of the attribute will be converted to the specified type
automatically, and an error occurs if the conversion fails. In the case of an included page, all
parameters are strings and you must code any necessary conversion.

z The new <%@variable%> directive provides hints to the JSP container that automates tasks such
as the export and synchronization of the JSP variables, which helps the communication between
the invoked tag file and the invoking page. We'll see how this works later in this article. In the
case of the included JSP pages, the interpage communication must be implemented manually,
which usually requires more coding.

z The <%@attribute%> and <%@variable%> directives enable features that are not available in
included JSP pages, such as dynamic attributes collected in a java.util.Map, attributes that
represent JSP fragments, and variables whose names are specified by attributes. The examples of
the next section use these features.

Using the Advanced JSP 2.0 Features

The following examples show how to exploit the true power of the JSP tag files. You'll learn how to
handle dynamic attributes, how to use variables as output parameters, how to use attributes to name
variables, and how to pass JSP fragments to a tag file using attributes. Then, we'll use these advanced
JSP features to build another set of tag files that query and update a database using the JSP expression
language within SQL statements.

Handling dynamic attributes in tag files. This example contains a tag file (dynamicAttr.tag) that accepts
dynamic attributes in addition to several other attributes (listTag, itemTag, and separator) declared with
the <%@attribute> directive. A JSP page (dynamicAttr.jsp) invokes the tag file using the
<demo:dynamicAttr> tag. Declared and dynamic attributes can be mixed because the order of the
attributes doesn't matter.

http://www.oracle.com/technology/pub/articles/cioroianu_tagfiles.html?_template=/o... 13/08/2008
Creating JSP 2.0 Tag Files Page 6 of 20

By default, a tag file accepts only declared attributes. In order to enable the support for dynamic
attributes, the tag file must use <%@tag dynamic-attributes="varName"%>, providing the name of a
variable that will hold all dynamic attributes in a java.util.Map. In our example, this variable was
named attrMap. The dynamicAttr.tag file iterates over the items of attrMap with the <c:forEach>
action of JSTL, getting the name and value of each attribute with ${attr.key} and ${attr.value}.

If you look at the output, you'll observe that the six dynamic attributes (first, second, ... sixth)
are not obtained in the order specified by the <demo:dynamicAttr> tag in dynamicAttr.jsp. This
happens because the java.util.Map implementation controls the order of its items. Therefore, tag files
must be prepared to handle their dynamic attributes in an arbitrary order.

The dynamicAttr.tag file uses the <jsp:element> standard action in order to generate HTML elements
whose names are obtained at runtime. This new JSP 2.0 feature is not related to dynamic attributes, but
we use it in this example to generate an HTML list (listTag is "ul" and itemTag is "li").

dynamicAttr.tag

<%@ tag dynamic-attributes="attrMap" %>


<%@ attribute name="listTag" required="true" %>
<%@ attribute name="itemTag" required="true" %>
<%@ attribute name="separator" required="true" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<p> Dynamic Attributes: </p>


<jsp:element name="${listTag}">
<c:forEach var="attr" items="${attrMap}">
<jsp:element name="${itemTag}">
${attr.key} ${separator} ${attr.value}
</jsp:element>
</c:forEach>
</jsp:element>

dynamicAttr.jsp

<%@ taglib prefix="demo" tagdir="/technology/WEB-INF/tags/demo" %>

<demo:dynamicAttr separator="="
first="1" second="2" third="3"
listTag="ul" itemTag="li"
fourth="4" fifth="5" sixth="6"/>

Output

http://www.oracle.com/technology/pub/articles/cioroianu_tagfiles.html?_template=/o... 13/08/2008
Creating JSP 2.0 Tag Files Page 7 of 20

Exporting variables from a tag file to a JSP page. The <c:set> tag of JSTL allows you to create and
modify variables in any of the four JSP scopes (page, request, session, and application). A JSP page
shares the request, session, and application scopes with the tag files that are invoked from the JSP page.
The page scope, which is the default scope of <c:set>, is not shared. Therefore, you may view the
variables created in the request, session, and application scopes as "global variables," while those
created in the page scope act as "local variables."

Because each tag file has its own page scope, the local variables of the invoking page are not accessible
in the invoked tag file and vice versa. The JSP page may use tag attributes and global variables to pass
parameters to the invoked tag. For each attribute, the JSP container creates a local variable in the page
scope of the tag file, which allows you to get the attribute's value using ${attributeName} constructs.
Therefore, tag attributes act as parameters passed by value, while global variables act as parameters
passed by reference. If the tag file modifies the value of a global variable, the change affects the JSP
page.

A tag file may "export" its local variables to the invoking page using the <%@variable%> directive.
The name of a variable can be specified in the tag file using <%@variable name-given="..."%>, or the
JSP page can provide the variable's name, as we'll see in the varAttr.jsp example. The type of the
variable can be indicated with <%@variable variable-class="..."%>.

After declaring a variable in a tag file with <%@variable%>, you have to set its value with <c:set>.
The JSP container creates another variable with the given name in the JSP page, and this second
variable is initialized with the value of the corresponding variable from the tag file. Changing the value
of the variable from the JSP page does not affect the corresponding variable from the tag file. The JSP
container, however, updates the variable from the JSP page depending on the scope attribute from <%
@variable%>, which can be AT_BEGIN, NESTED, or AT_END.

If scope is AT_END, the variable from the JSP page is initialized with the value of the tag file variable
after the execution of the tag file. If scope is AT_BEGIN, the variable from the JSP page is updated
before <jsp:doBody>, before each <jsp:invoke>, and at the end of the tag file's execution. If scope is
NESTED, the JSP variable is updated only before <jsp:doBody> and before each <jsp:invoke> with the
value of the tag file variable. After the execution of the tag file, in the NESTED case, the JSP variable
is restored to the value it had before the invocation of the tag file.

For a better understanding of how variables work, let's use them in an example that is made of a tag file
(varScope.tag), a JSP page (varScope.jsp), and several fragments (varScopeRow.tagf,

http://www.oracle.com/technology/pub/articles/cioroianu_tagfiles.html?_template=/o... 13/08/2008
Creating JSP 2.0 Tag Files Page 8 of 20

varScopeHeader.jspf, varScopeFooter.jspf, and varScopeRow.jspf). The fragments are used only to


create an HTML table. We have to use <%@include%> in this example to separate the logic from the
presentation while studying the tag file variables. Using tag files for presentation is the best solution in
most situations, but in this case the additional tag files would interfere with the variable "exporting"
mechanisms that we want to study.

The tag file uses a "global" variable (GV), an undeclared "local" variable (LV), and three variables (BV,
NV, and EV) declared with <%@variable%>. The varScope.tag file initializes these variables with "TAG
A", then it uses <jsp:doBody>, and finally it changes the values of all variables to the "TAG B" string.
The varScope.jsp page initializes its own set of variables with "JSP A" and then invokes the tag file
with <demo:varScope>, changing the values of the variables to "JSP B" within the body of
<demo:varScope>. The resulting output is included after the source code.

varScope.tag

<%@ variable name-given="BV" scope="AT_BEGIN" %>


<%@ variable name-given="NV" scope="NESTED" %>
<%@ variable name-given="EV" scope="AT_END" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<c:set var="tagPhase" value="TAG: at begin"/>


<%@ include file="varScopeRow.tagf" %>

<c:set var="GV" value="TAG A" scope="request"/>


<c:set var="LV" value="TAG A"/>
<c:set var="BV" value="TAG A"/>
<c:set var="NV" value="TAG A"/>
<c:set var="EV" value="TAG A"/>

<c:set var="tagPhase" value="TAG: before doBody"/>


<%@ include file="varScopeRow.tagf" %>

<jsp:doBody/>

<c:set var="tagPhase" value="TAG: after doBody"/>


<%@ include file="varScopeRow.tagf" %>

<c:set var="GV" value="TAG B" scope="request"/>


<c:set var="LV" value="TAG B"/>
<c:set var="BV" value="TAG B"/>
<c:set var="NV" value="TAG B"/>
<c:set var="EV" value="TAG B"/>

<c:set var="tagPhase" value="TAG: at end"/>


<%@ include file="varScopeRow.tagf" %>

varScopeRow.tagf

<tr>
<td width="25%">${tagPhase}</td>
<c:set var="allEqual" value=
"${LV == GV and LV == BV and LV == NV and LV == EV}"/>
<c:if test="${allEqual}">
<td align="center" width="75%" colspan="5">
<i> ${LV != null ? LV : "null"} </i>
</td>
</c:if>
<c:if test="${!allEqual}">
<td align="center" width="15%">
${GV != null ? GV : "null"}
</td>
<td align="center" width="15%">
${LV != null ? LV : "null"}
</td>

http://www.oracle.com/technology/pub/articles/cioroianu_tagfiles.html?_template=/o... 13/08/2008
Creating JSP 2.0 Tag Files Page 9 of 20

<td align="center" width="15%">


${BV != null ? BV : "null"}
</td>
<td align="center" width="15%">
${NV != null ? NV : "null"}
</td>
<td align="center" width="15%">
${EV != null ? EV : "null"}
</td>
</c:if>
</tr>

varScope.jsp

<%@ taglib prefix="demo" tagdir="/technology/WEB-INF/tags/demo" %>


<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<%@ include file="varScopeHeader.jspf" %>

<c:set var="GV" value="JSP A" scope="request"/>


<c:set var="LV" value="JSP A"/>
<c:set var="BV" value="JSP A"/>
<c:set var="NV" value="JSP A"/>
<c:set var="EV" value="JSP A"/>

<c:set var="jspPhase" value="JSP: before start tag"/>


<%@ include file="varScopeRow.jspf" %>

<demo:varScope>

<c:set var="jspPhase" value="JSP: after start tag"/>


<%@ include file="varScopeRow.jspf" %>

<c:set var="GV" value="JSP B" scope="request"/>


<c:set var="LV" value="JSP B"/>
<c:set var="BV" value="JSP B"/>
<c:set var="NV" value="JSP B"/>
<c:set var="EV" value="JSP B"/>

<c:set var="jspPhase" value="JSP: before end tag"/>


<%@ include file="varScopeRow.jspf" %>

</demo:varScope>

<c:set var="jspPhase" value="JSP: after end tag"/>


<%@ include file="varScopeRow.jspf" %>

<%@ include file="varScopeFooter.jspf" %>

varScopeHeader.jspf

<table border="1">

<tr>
<th width="25%">

</th>
<th align="center" width="15%">
GV<br>Global Var<br>in Request<br>Scope
</th>
<th align="center" width="15%">
LV<br>Local Var<br>Not<br>Declared
</th>
<th align="center" width="15%">
BV<br>Tag Var<br>Scope:<br>AT_BEGIN
</th>

http://www.oracle.com/technology/pub/articles/cioroianu_tagfiles.html?_template=/o... 13/08/2008
Creating JSP 2.0 Tag Files Page 10 of 20

<th align="center" width="15%">


NV<br>Tag Var<br>Scope:<br>NESTED
</th>
<th align="center" width="15%">
EV<br>Tag Var<br>Scope:<br>AT_END
</th>
</tr>

varScopeFooter.jspf

</table>

varScopeRow.jspf

<tr>
<td width="25%">${jspPhase}</td>
<c:set var="allEqual" value=
"${LV == GV and LV == BV and LV == NV and LV == EV}"/>
<c:if test="${allEqual}">
<td align="center" width="75%" colspan="5">
<i> ${LV != null ? LV : "null"} </i>
</td>
</c:if>
<c:if test="${!allEqual}">
<td align="center" width="15%">
${GV != null ? GV : "null"}
</td>
<td align="center" width="15%">
${LV != null ? LV : "null"}
</td>
<td align="center" width="15%">
${BV != null ? BV : "null"}
</td>
<td align="center" width="15%">
${NV != null ? NV : "null"}
</td>
<td align="center" width="15%">
${EV != null ? EV : "null"}
</td>
</c:if>
</tr>

Output

http://www.oracle.com/technology/pub/articles/cioroianu_tagfiles.html?_template=/o... 13/08/2008
Creating JSP 2.0 Tag Files Page 11 of 20

Using attributes to provide names for variables. The previous example showed how to use variables
whose names are given by the tag file. The following example has a tag file (varAttr.tag) that creates a
variable whose name is provided by a JSP page (varAttr.jsp) as the value of a tag attribute (v). In order
to be able to operate with the variable, the tag file defines an alias (a) using <%@variable name-from-
attribute="v" ... alias="a" ...%>.

The varAttr.tag file sets the value of the variable with <c:set var="a" value="..."/>, outputs the
variable's name with ${v}, and outputs the variable's value with ${a}. The varAttr.jsp page invokes the
tag file with <demo:varAttr v="x"/> and works with the variable named x. Note that the JSP container
creates the x variable automatically, setting it to the value of a, which is 123.

varAttr.tag

<%@ attribute name="v" required="true" %>


<%@ variable name-from-attribute="v"
variable-class="java.lang.Long"
alias="a" scope="AT_END" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<c:set var="a" value="${123}"/>

<p> TAG: ${v} = ${a} </p>

varAttr.jsp

<%@ taglib prefix="demo" tagdir="/technology/WEB-INF/tags/demo" %>

<demo:varAttr v="x"/>

<p> JSP: x = ${x} </p>

http://www.oracle.com/technology/pub/articles/cioroianu_tagfiles.html?_template=/o... 13/08/2008
Creating JSP 2.0 Tag Files Page 12 of 20

Output

Invoking JSP fragments from tag files. You've learned so far that tag files support two attribute types:
simple declared attributes and dynamic attributes. There is a third type called fragment attributes. The
JSP page of this example (fragmentAttr.jsp) invokes a tag file (fragmentAttr.tag) with
<demo:fragmentAttr>, providing two simple attributes (attr1 and attr2) and a fragment attribute
(template). All three attributes are declared in the tag file with <%@attribute%>, but only template
is declared as a fragment attribute with fragment="true".

The fragmentAttr.jsp page uses the <jsp:attribute> and <jsp:body> standard actions to define the two
JSP fragments that are invoked from the tag file with <jsp:invoke> and <jsp:doBody>, respectively. In
addition, the tag file declares a nested variable (data) with <%@variable%>. The value of the variable
is set by the tag file with <c:set>, and the two JSP fragments output the variable's value with ${data}.

fragmentAttr.tag

<%@ attribute name="template" fragment="true" %>


<%@ attribute name="attr1" %>
<%@ attribute name="attr2" %>
<%@ variable name-given="data" scope="NESTED" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<c:set var="data" value="${attr1}"/>


<jsp:invoke fragment="template"/>

<c:set var="data" value="${attr1} - ${attr2}"/>


<jsp:doBody/>

<c:set var="data" value="${attr2}"/>


<jsp:invoke fragment="template"/>

<c:set var="data" value="${attr2} - ${attr1}"/>


<jsp:doBody/>

fragmentAttr.jsp

<%@ taglib prefix="demo" tagdir="/technology/WEB-INF/tags/demo" %>

<demo:fragmentAttr attr1="value1" attr2="value2">


<jsp:attribute name="template">
<p> Template: ${data} </p>
</jsp:attribute>
<jsp:body>
<p> Body Content: ${data} </p>
</jsp:body>

http://www.oracle.com/technology/pub/articles/cioroianu_tagfiles.html?_template=/o... 13/08/2008
Creating JSP 2.0 Tag Files Page 13 of 20

</demo:fragmentAttr>

Output

Using Tag Files to Update and Query Databases

When developing complex enterprise applications, many prefer to use the Enterprise JavaBeans (EJB)
technology, letting the application server manage the object persistence. Others might prefer to use the
Java Database Connectivity (JDBC) standard API in order to optimize the database access manually.
These solutions might not be suitable in the case of a simple database-backed Web site that just needs
to be prototyped as fast as possible using JSPs. A tag library providing database access features can be
the best solution if you just need to query and update a simple database.

JSTL has a set of simple SQL tags that we'll use in the following examples. Instead of invoking the
JSTL SQL tags directly from your pages, it's a good idea to separate the presentation from the database
access scripts using tag files. This separation allows you to switch easily to another database
connectivity solution, at a later time, in order to increase the performance and scalability of your
application.

JSTL is not the only tag library providing database access features. Oracle Application Development
Framework (ADF) offers a JSP library called Business Components Data Tags that contains a more
advanced set of database-related JSP tags. Note that the set of ADF features is much broader, making
Oracle ADF suitable for simple and complex applications. Oracle ADF is bundled together with
JDeveloper 10g, which has visual design tools for ADF.

The following six examples create a table, insert three rows, update a row, delete another row, perform
a couple of queries, and drop the table. Everything is done with generic tag files that don't depend on
the table's structure.

Step 1: Create table. The JSP page of this example (create.jsp) invokes a tag file (create.tag) to create a
table whose structure is provided as the body of the <db:create> custom tag. The table attribute
specifies the name of the table (People). After creating the table, the JSP page outputs a message
notifying the user that the operation was completed:

<db:create table="People">
userID INTEGER,
name VARCHAR2(60),

http://www.oracle.com/technology/pub/articles/cioroianu_tagfiles.html?_template=/o... 13/08/2008
Creating JSP 2.0 Tag Files Page 14 of 20

email VARCHAR2(60)
</db:create>

<p> Table created. </p>

The create.tag file includes a tag fragment (init.tagf) that sets a javax.sql.DataSource variable named
tags_db_dataSource within the application scope with the help of the <sql:setDataSource> tag of
JSTL. The variable is created only if it doesn't already exist and is used in the tag file with the
<sql:update> tag of JSTL, which executes the SQL statement from its body. The create.tag file builds
the CREATE TABLE statement dynamically, getting the table's name with ${table} and inserting the
table's structure with <jsp:doBody>:

<sql:update dataSource="${tags_db_dataSource}">
CREATE TABLE ${table} ( <jsp:doBody/> )
</sql:update>

In order to run the examples, you'll have to configure a datasource named dbtags. A reference to this
resource is declared in the Web application's descriptor (web.xml):

<resource-ref>
<res-ref-name>jdbc/dbtags</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>

The init.tagf fragment gets the path to the resource from an initialization parameter that is defined in
web.xml too:

<context-param>
<param-name>tags_db_dataSource</param-name>
<param-value>jdbc/dbtags</param-value>
</context-param>

If you want to use another datasource, you just have to replace dbtags with the name of your
datasource in the web.xml file.

init.tagf

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>


<%@ taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql" %>

<c:if test="${applicationScope.tags_db_dataSource == null}">


<sql:setDataSource
dataSource="${initParam.tags_db_dataSource}"
var="tags_db_dataSource" scope="application"/>
</c:if>

create.tag

<%@ tag body-content="scriptless" %>


<%@ attribute name="table" required="true" %>
<%@ include file="init.tagf" %>

<sql:update dataSource="${tags_db_dataSource}">
CREATE TABLE ${table} ( <jsp:doBody/> )
</sql:update>

create.jsp

<%@ taglib prefix="db" tagdir="/technology/WEB-INF/tags/db" %>

<db:create table="People">

http://www.oracle.com/technology/pub/articles/cioroianu_tagfiles.html?_template=/o... 13/08/2008
Creating JSP 2.0 Tag Files Page 15 of 20

userID INTEGER,
name VARCHAR2(60),
email VARCHAR2(60)
</db:create>

<p> Table created. </p>

Step 2: Insert. Once you have a table, you can insert one row at a time using the <db:insert> tag, which
invokes a tag file (insert.tag) with the following syntax:

<db:insert table="..." column1="value1" column2="value2" .../>

An example JSP page (insert.jsp) uses <db:insert> to insert three rows into the People table. At each
invocation, the tag file builds and executes an SQL statement using the following syntax:

INSERT INTO table (column1, column2, ...) VALUES (value1, value2, ...)

The column names and values are specified as dynamic attributes so that <db:insert> can be used with
any table, no matter how its columns are named. The tag file uses <c:forEach> to iterate over the
entries of a java.util.Map instance (columnAttr) holding the dynamic attributes of <db:insert>. The
name of each dynamic attribute represents a column name and is obtained with ${v_entry.key}. The tag
file gets the values that must be inserted into the table with ${v_entry.value}.

Within the body of <sql:update>, the tag file builds a list of column names (v_columnNames) and
another list containing parameter markers (v_paramMarkers). The <sql:param> tag of JSTL cooperates
with <sql:update> transmitting the values of the SQL parameters. After the <c:forEach> loop, which
produces no output, the tag file generates the SQL statement with

INSERT INTO ${table} (${v_columnNames}) VALUES (${v_paramMarkers})

When the tag file is invoked by insert.jsp, the <sql:update> tag evaluates its body obtaining

INSERT INTO People (userID, name, email) VALUES (?, ?, ?)

Then, <sql:update> executes the above SQL statement using the JDBC API and passing the parameter
values that were transmitted by <sql:param>. Note that the columns and their corresponding values
may appear in a different order because they are retrieved from a java.util.Map instance. Therefore, we
have to make sure that the SQL statement does not rely on the order of the columns.

insert.tag

<%@ tag body-content="empty" dynamic-attributes="columnAttr" %>


<%@ attribute name="table" required="true" %>
<%@ include file="init.tagf" %>

<c:set var="v_columnNames" value=""/>


<c:set var="v_paramMarkers" value=""/>
<c:set var="v_separator" value=""/>
<sql:update dataSource="${tags_db_dataSource}">
<c:forEach var="v_entry" items="${columnAttr}">
<sql:param value="${v_entry.value}"/>
<c:set var="v_columnNames"
value="${v_columnNames}${v_separator}${v_entry.key}"/>
<c:set var="v_paramMarkers"
value="${v_paramMarkers}${v_separator}${'?'}"/>
<c:set var="v_separator" value=", "/>
</c:forEach>
INSERT INTO ${table} (${v_columnNames})
VALUES (${v_paramMarkers})
</sql:update>

http://www.oracle.com/technology/pub/articles/cioroianu_tagfiles.html?_template=/o... 13/08/2008
Creating JSP 2.0 Tag Files Page 16 of 20

insert.jsp

<%@ taglib prefix="db" tagdir="/technology/WEB-INF/tags/db" %>

<db:insert table="People" userID="1" name="John Smith"


email="JohnSmith@company.com" />

<db:insert table="People" userID="2" name="Mark Johnson"


email="MarkJohnson@company.com" />

<db:insert table="People" userID="3" name="Bill Davis"


email="BillDavis@company.com" />

<p> Rows inserted. </p>

Step 3: Update. The update.jsp page uses <db:update> to change the email value of one of the rows
inserted with insert.jsp. The update.tag file is similar to insert.tag, but this time the <sql:update> tag of
JSTL is used to execute an UPDATE statement:

UPDATE table SET column1=value1, column2=value2, ... WHERE ...

The columns and their values are specified as dynamic attributes using the following syntax:

<db:update table="..." column1="value1" column2="value2" ...


where="..."/>

The tag file uses the dynamic attributes to build a list (v_setList) containing column=? constructs.
The column values are transmitted to <sql:update> with the help of <sql:param> as in the previous
example. Then, update.tag generates the SQL statements with

UPDATE ${table} SET ${v_setList} WHERE ${where}

When the tag file is invoked by update.jsp, the <sql:update> tag evaluates its body obtaining

UPDATE People SET email=? WHERE userID=2

Unlike the <db:insert> tag that may be used to insert only one row at a time, the <db:update> tag can be
used to update multiple rows with a single invocation.

update.tag

<%@ tag body-content="empty" dynamic-attributes="columnAttr" %>


Resources
<%@ attribute name="table" required="true" %>
<%@ attribute name="where" required="false" %>
<%@ include file="init.tagf" %> Use the following resources
to test the examples and
<c:set var="v_setList" value=""/> learn more about the JSP
<c:set var="v_separator" value=""/> 2.0 tag files and about the
<sql:update dataSource="${tags_db_dataSource}">
<c:forEach var="v_entry" items="${columnAttr}"> JSTL Core and SQL tags.
<sql:param value="${v_entry.value}"/>
<c:set var="v_setList" Download the Source Code
value="${v_setList}${v_separator}${v_entry.key}=?"/>
The tagfiles_src.zip file
<c:set var="v_separator" value=", "/> contains the examples of
</c:forEach>
UPDATE ${table} SET ${v_setList}
this article. In order to run
<c:if test="${!empty where}"> WHERE ${where} </c:if> them, you need J2SE, a
</sql:update> J2EE 1.4 application server,
JSTL 1.1, and a database
update.jsp server.

http://www.oracle.com/technology/pub/articles/cioroianu_tagfiles.html?_template=/o... 13/08/2008
Creating JSP 2.0 Tag Files Page 17 of 20

<%@ taglib prefix="db" tagdir="/technology/WEB-INF/tags/db" %>

<db:update table="People" Download OC4J 10g


email="markj@company.com" where="userID=2"/> Oracle Application Server
Containers for J2EE 10g
<p> Row updated. </p> fully implement the J2EE
1.4 specs, which include
Step 4: Delete. The following tag file (delete.tag) can be used to delete JSP 2.0. You may use OC4J
one or more rows, as in the delete.jsp page. 10g (10.0.3) to test the
examples. It works with all
delete.tag major database servers,
including—of course—
<%@ tag body-content="empty" %> Oracle Database.
<%@ attribute name="table" required="true" %>
<%@ attribute name="where" required="false" %>
<%@ include file="init.tagf" %> Download JSTL 1.1
Before deploying the
<sql:update dataSource="${tags_db_dataSource}"> examples, download JSTL
DELETE FROM ${table} and copy jstl.jar and
<c:if test="${!empty where}"> WHERE ${where} </c:if> standard.jar into the WEB-
</sql:update>
INF/lib directory of the
Web application. Also,
delete.jsp don't forget to configure the
dbtags datasource and make
<%@ taglib prefix="db" tagdir="/technology/WEB-INF/tags/db" %>
sure that the proper
<db:delete table="People" where="userID=1"/> database driver is available.

<p> Row deleted. </p> Read the JSP 2.0


Specification
Step 5: Select. The next tag file (select.tag) uses the <sql:query> tag of The JSP 2.0 specification
JSTL to execute SELECT statements. The syntax of <db:select> is has an entire chapter
included below: dedicated to tag files ("Part
I: Chapter JSP.8 Tag
<db:select var="row" table="..." columns="..." Files"). The new standard
where="..." groupBy="..." having="..." orderBy="..."> actions introduced by JSP
process the result of the query, one row at a time
2.0 are described in another
chapter ("Part I: Chapter
</db:select> JSP.5 Standard Actions").

The <db:select> tag builds and executes the following SQL statement, Read the JSTL 1.1
whose clauses are specified as the attributes of the tag. Specification
The JSTL specification
SELECT columns FROM table WHERE ... describes the <c:set>,
GROUP BY ... HAVING ... ORDER BY ... <c:if>, <c:forEach>,
<sql:setDataSource>,
When <db:select> appears in a JSP page, its body is invoked for each <sql:query>, <sql:update>,
row with the <jsp:doBody> action form select.tag. The JSP page gets and <sql:param> tags used
the row data from a java.util.Map created by the tag file with JSTL. For in the examples of this
example, the values of the current row can be obtained with JSP article.
constructs like ${row.userID}, ${row.name}, and ${row.email},
assuming that the JSP page invokes the tag file specifying that the Related Articles and
variable holding the data should be named row: Downloads

<db:select var="row" table="People" columns="*"> How-To: Add a Custom


${row.userID} ... ${row.name} ... ${row.email} JSP Tag Library to
</db:select>
JDeveloper 10g
The select.jsp page invokes the tag file twice. First it uses <db:select>
Oracle JDeveloper 10g
to iterate over the relational table's rows generating an HTML table, and

http://www.oracle.com/technology/pub/articles/cioroianu_tagfiles.html?_template=/o... 13/08/2008
Creating JSP 2.0 Tag Files Page 18 of 20

then the JSP page uses <db:select> to count the rows of the People
JSP Sample Code
table.
Tutorial: Understanding the
select.tag
New Features of JSP 2.0,
<%@ tag body-content="scriptless" %>
"Tag Files" module
<%@ attribute name="var" required="true" %>
<%@ variable name-from-attribute="var"
alias="v_row" scope="NESTED" %>
<%@ attribute name="table" required="true" %>
<%@ attribute name="columns" required="false" %>
<%@ attribute name="where" required="false" %>
<%@ attribute name="groupBy" required="false" %>
<%@ attribute name="having" required="false" %>
<%@ attribute name="orderBy" required="false" %>
<%@ include file="init.tagf" %>

<sql:query dataSource="${tags_db_dataSource}" var="v_result">


SELECT ${empty columns ? "*" : columns} FROM ${table}
<c:if test="${!empty where}"> WHERE ${where} </c:if>
<c:if test="${!empty groupBy}"> GROUP BY ${groupBy} </c:if>
<c:if test="${!empty having}"> HAVING ${having} </c:if>
<c:if test="${!empty orderBy}"> ORDER BY ${orderBy} </c:if>
</sql:query>

<c:forEach var="v_row" items="${v_result.rows}">


<jsp:doBody/>
</c:forEach>

select.jsp

<%@ taglib prefix="db" tagdir="/technology/WEB-INF/tags/db" %>


<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<table border="2" cellspacing="1" cellpadding="3">


<tr>
<th> User ID </th>
<th> Name </th>
<th> Email </th>
</tr>
<db:select var="row" table="People" orderBy="name">
<tr>
<td> ${row.userID} </td>
<td> ${row.name} </td>
<td> ${row.email} </td>
</tr>
</db:select>
</table>

<db:select var="c" table="People" columns="count(*) as n">


<p> ${c.n} people. </p>
</db:select>

Output

http://www.oracle.com/technology/pub/articles/cioroianu_tagfiles.html?_template=/o... 13/08/2008
Creating JSP 2.0 Tag Files Page 19 of 20

Step 6: Drop table. If you want to execute again the JSP examples, you have to drop the table with the
drop.jsp page that uses the drop.tag file.

drop.tag

<%@ tag body-content="scriptless" %>


<%@ attribute name="table" required="true" %>
<%@ include file="init.tagf" %>

<sql:update dataSource="${tags_db_dataSource}">
DROP TABLE ${table}
</sql:update>

drop.jsp

<%@ taglib prefix="db" tagdir="/technology/WEB-INF/tags/db" %>

<db:drop table="People"/>

<p> Table dropped. </p>

Conclusion

Tag files are the easy-to-use solution that Web developers need in order to build custom tag libraries.
The transition from Java tag handlers to JSP tag files is similar to the transition from Servlets to JSP
that happened several years ago. When developing Java Web applications, most of the dynamic content
is now generated with JSP, but Servlets are still used as an underlying technology for JSPs and there
are cases when Servlets are preferred instead of JSP. Similarly, Java tag handlers are still needed as an
underlying technology for tag files and for building sophisticated tag libraries such as JSTL. Most tag
libraries, however, will be built using tag files because they simplify the development process.

Andrei Cioroianu (devtools@devsphere.com) is the founder of Devsphere (www.devsphere.com), a


provider of Java frameworks, XML consulting, and Web development services. Andrei Cioroianu has
written many Java articles published by ONJava, JavaWorld, and Java Developer's Journal. He also
coauthored the books Java XML Programmer's Reference and Professional Java XML (both from
Wrox Press).

http://www.oracle.com/technology/pub/articles/cioroianu_tagfiles.html?_template=/o... 13/08/2008
Creating JSP 2.0 Tag Files Page 20 of 20

Please rate this document:

Excellent Good Average Below Average Poor

Rate and View Results

Send us your comments

http://www.oracle.com/technology/pub/articles/cioroianu_tagfiles.html?_template=/o... 13/08/2008

Potrebbero piacerti anche