Creating a JSP Document
A JSP document is an XML document and therefore must comply with the XML standard. Fundamentally, this means that a JSP document must be well formed, meaning that each start tag must have a corresponding end tag and that the document must have only one root element. In addition, JSP elements included in the JSP document must comply with the XML syntax.
Much of the standard JSP syntax is already XML-compliant, including all the standard actions. Those elements that are not compliant are summarized in Table 13-2 along with the equivalent elements in XML syntax. As you can see, JSP documents are not much different from JSP pages. If you know standard JSP syntax, you will find it easy to convert your current JSP pages to XML syntax and to create new JSP documents.
To illustrate how simple it is to transition from standard syntax to XML syntax, let's convert a simple JSP page to a JSP document. The standard syntax version is as follows:
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %> <html> <head><title>Hello</title></head> <body bgcolor="white"> <img src="duke.waving.gif"> <h2>My name is Duke. What is yours?</h2> <form method="get"> <input type="text" name="username" size="25"> <p></p> <input type="submit" value="Submit"> <input type="reset" value="Reset"> </form> <jsp:useBean id="userNameBean" class="hello.UserNameBean" scope="request"/> <jsp:setProperty name="userNameBean" property="name" value="${param.username}" /> <c:if test="${fn:length(userNameBean.name) > 0}" > <%@include file="response.jsp" %> </c:if> </body> </html>Here is the same page in XML syntax:
<html xmlns:c="http://java.sun.com/jsp/jstl/core" xmlns:fn="http://java.sun.com/jsp/jstl/functions" > <head><title>Hello</title></head> <body bgcolor="white" /> <img src="duke.waving.gif" /> <h2>My name is Duke. What is yours?</h2> <form method="get"> <input type="text" name="username" size="25" /> <p></p> <input type="submit" value="Submit" /> <input type="reset" value="Reset" /> </form> <jsp:useBean id="userNameBean" class="hello.UserNameBean" scope="request"/> <jsp:setProperty name="userNameBean" property="name" value="${param.username}" /> <c:if test="${fn:length(userNameBean.name) gt 0}" > <jsp:directive.include="response.jsp" /> </c:if> </body> </html>As you can see, a number of constructs that are legal in standard syntax have been changed to comply with XML syntax:
- The
taglib
directives have been removed. Tag libraries are now declared using XML namespaces, as shown in thehtml
element.- The
img
andinput
tags did not have matching end tags and have been made XML-compliant by the addition of a / to the start tag.- The > symbol in the EL expression has been replaced with
gt
.- The
include
directive has been changed to the XML-compliantjsp:directive.include
tag.With only these few small changes, when you save the file with a
.jspx
extension, this page is a JSP document.Using the example described in The Example JSP Document, the rest of this chapter gives you more details on how to transition from standard syntax to XML syntax. It explains how to use XML namespaces to declare tag libraries, include directives, and create static and dynamic content in your JSP documents. It also describes
jsp:root
andjsp:output
, two elements that are used exclusively in JSP documents.Declaring Tag Libraries
This section explains how to use XML namespaces to declare tag libraries.
In standard syntax, the
taglib
directive declares tag libraries used in a JSP page. Here is an example of ataglib
directive:This syntax is not allowed in JSP documents. To declare a tag library in a JSP document, you use the
xmlns
attribute, which is used to declare namespaces according to the XML standard:The value that identifies the location of the tag library can take three forms:
- A plain URI that is a unique identifier for the tag library. The container tries to match it against any
<taglib-uri>
elements in the application'sweb.xml
file or the<uri>
element of tag library descriptors (TLDs) in JAR files inWEB-INF/lib
or TLDs underWEB-INF
.- A URN of the form
urn:jsptld:path
.- A URN of the form
urn:jsptagdir:path
.The URN of the form
urn:jsptld:path
points to one tag library packaged with the application:The URN of the form
urn:jsptagdir:path
must start with/WEB-INF/tags/
and identifies tag extensions (implemented as tag files) installed in theWEB-INF/tags/
directory or a subdirectory of it:You can include the
xmlns
attribute in any element in your JSP document, just as you can in an XML document. This capability has many advantages:The
books.jspx
page declares the tag libraries it uses with thexmlns
attributes in the root element,books
:In this way, all elements within the
books
element have access to these tag libraries.As an alternative, you can scope the namespaces:
<books> ... <jsp:useBean xmlns:jsp="http://java.sun.com/JSP/Page" id="bookDB" class="database.BookDB" scope="page"> <jsp:setProperty name="bookDB" property="database" value="${bookDBAO}" /> </jsp:useBean> <c:forEach xmlns:c="http://java.sun.com/jsp/jstl/core" var="book" begin="0" items="${bookDB.books}"> ... </c:forEach> </books>In this way, the tag library referenced by the
jsp
prefix is available only to thejsp:useBean
element and its subelements. Similarly, the tag library referenced by thec
prefix is only available to thec:forEach
element.Scoping the namespaces also allows you to override the prefix. For example, in another part of the page, you could bind the
c
prefix to a different namespace or tag library. In contrast, thejsp
prefix must always be bound to the JSP namespace:http://java.sun.com/JSP/Page
.Including Directives in a JSP Document
Directives are elements that relay messages to the JSP container and affect how it compiles the JSP page. The directives themselves do not appear in the XML output.
There are three directives:
include
,page
, andtaglib
. Thetaglib
directive is covered in the preceding section.The
jsp:directive.page
element defines a number of page-dependent properties and communicates these to the JSP container. This element must be a child of the root element. Its syntax isThe
page_directive_attr_list
is the same list of attributes that the<@ page ...>
directive has. These are described in Chapter 12. All the attributes are optional. Except for theimport
andpageEncoding
attributes, there can be only one instance of each attribute in an element, but an element can contain more than one attribute.An example of a page directive is one that tells the JSP container to load an error page when it throws an exception. You can add this error page directive to the
books.jspx
page:<books xmlns:jsp="http://java.sun.com/JSP/Page"> <jsp:directive.page errorPage="errorpage.jsp" /> ... </books>If there is an error when you try to execute the page (perhaps when you want to see the XML output of
books.jspx
), the error page is accessed.The
jsp:directive.include
element is used to insert the text contained in another file--either static content or another JSP page--into the including JSP document. You can place this element anywhere in a document. Its syntax is:The XML view of a JSP document does not contain
jsp:directive.include
elements; rather the included file is expanded in place. This is done to simplify validation.Suppose that you want to use an
include
directive to add a JSP document containing magazine data inside the JSP document containing the books data. To do this, you can add the followinginclude
directive tobooks.jspx
, assuming thatmagazines.jspx
generates the magazine XML data.<jsp:root version="2.0" > <books ...> ... </books> <jsp:directive.include file="magazine.jspx" /> </jsp:root>Note that
jsp:root
is required because otherwisebooks.jspx
would have two root elements:<books>
and<magazines>
. The output generated frombooks.jspx
will be a sequence of XML documents: one with<books>
and the other with<magazines>
as its root element.The output of this example will not be well-formed XML because of the two root elements, so the client might refuse to process it. However, it is still a legal JSP document.
In addition to including JSP documents in JSP documents, you can also include JSP pages written in standard syntax in JSP documents, and you can include JSP documents in JSP pages written in standard syntax. The container detects the page you are including and parses it as either a standard syntax JSP page or a JSP document and then places it into the XML view for validation.
Creating Static and Dynamic Content
This section explains how to represent static text and dynamic content in a JSP document. You can represent static text in a JSP document using uninterpreted XML tags or the
jsp:text
element. Thejsp:text
element passes its content through to the output.If you use
jsp:text
, all whitespace is preserved. For example, consider this example using XML tags:The output generated from this XML has all whitespace removed:
If you wrap the example XML with a
<jsp:text>
tag, all whitespace is preserved. The whitespace characters are#x20
,#x9
,#xD
,and#xA
.You can also use
jsp:text
to output static data that is not well formed. The${counter}
expression in the following example would be illegal in a JSP document if it were not wrapped in ajsp:text
tag.This example will output
The
jsp:text
tag must not contain any other elements. Therefore, if you need to nest a tag insidejsp:text
, you must wrap the tag insideCDATA
.You also need to use
CDATA
if you need to output some elements that are not well-formed. The following example requiresCDATA
wrappers around theblockquote
start and end tags because theblockquote
element is not well formed. This is because theblockquote
element overlaps with other elements in the example.<c:forEach var="i" begin="1" end="${x}"> <![CDATA[<blockquote>]]> </c:forEach> ... <c:forEach var="i" begin="1" end="${x}"> <![CDATA[</blockquote>]]> </c:forEach>
Just like JSP pages, JSP documents can generate dynamic content using expressions language (EL) expressions, scripting elements, standard actions, and custom tags. The
books.jspx
document uses EL expressions and custom tags to generate the XML book data.As shown in this snippet from
books.jspx
, thec:forEach
JSTL tag iterates through the list of books and generates the XML data stream. The EL expressions access the JavaBeans component, which in turn retrieves the data from the database:<c:forEach var="book" begin="0" items="${bookDB.books}"> <book id="${book.bookId}" > <surname>${book.surname}</surname> <firstname>${book.firstName}</firstname> <title>${book.title}</title> <price>${book.price}</price> <year>${book.year}</year> <description>${book.description}</description> <inventory>${book.inventory}</inventory> </book> </c:forEach>When using the expression language in your JSP documents, you must substitute alternative notation for some of the operators so that they will not be interpreted as XML markup. Table 13-3 enumerates the more common operators and their alternative syntax in JSP documents.
Table 13-3 EL Operators and JSP Document-Compliant Alternative Notation EL Operator JSP Document Notation<
lt
>
gt
<=
le
>=
ge
!=
ne
You can also use EL expressions with
jsp:element
to generate tags dynamically rather than hardcode them. This example could be used to generate an HTML header tag with alang
attribute:<jsp:element name="${content.headerName}" xmlns:jsp="http://java.sun.com/JSP/Page"> <jsp:attribute name="lang">${content.lang}</jsp:attribute> <jsp:body>${content.body}</jsp:body> </jsp:element>The
name
attribute identifies the generated tag's name. Thejsp:attribute
tag generates thelang
attribute. The body of thejsp:attribute
tag identifies the value of thelang
attribute. Thejsp:body
tag generates the body of the tag. The output of this examplejsp:element
could beAs shown in Table 13-2, scripting elements (described in Chapter 16) are represented as XML elements when they appear in a JSP document. The only exception is a scriptlet expression used to specify a request-time attribute value. Instead of using
<%=expr %>
, a JSP document uses%= expr %
to represent a request-time attribute value.The three scripting elements are declarations, scriptlets, and expressions.
A
jsp:declaration
element declares a scripting language construct that is available to other scripting elements. Ajsp:declaration
element has no attributes and its body is the declaration itself. Its syntax isA
jsp:scriptlet
element contains a Java program fragment called a scriptlet. This element has no attributes, and its body is the program fragment that constitutes the scriptlet. Its syntax isThe
jsp:expression
element inserts the value of a scripting language expression, converted into a string, into the data stream returned to the client. Ajsp:expression
element has no attributes and its body is the expression. Its syntax isUsing the jsp:root Element
The
jsp:root
element represents the root element of a JSP document. Ajsp:root
element is not required for JSP documents. You can specify your own root element, enabling you to use any XML document as a JSP document. The root element of thebooks.jspx
example JSP document isbooks
.Although the
jsp:root
element is not required, it is still useful in these cases:
- When you want to identify the document as a JSP document to the JSP container without having to add any configuration attributes to the deployment descriptor or name the document with a
.jspx
extension- When you want to generate--from a single JSP document--more than one XML document or XML content mixed with non-XML content
The
version
attribute is the only required attribute of thejsp:root
element. It specifies the JSP specification version that the JSP document is using.The
jsp:root
element can also includexmlns
attributes for specifying tag libraries used by the other elements in the page.The
books.jspx
page does not need ajsp:root
element and therefore doesn't include one. However, suppose that you want to generate two XML documents frombooks.jspx
: one that lists books and another that lists magazines (assuming magazines are in the database). This example is similar to the one in the section Including Directives in a JSP Document. To do this, you can use thisjsp:root
element:<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.0" > <books>...</books> <magazines>...</magazines> </jsp:root>Notice in this example that
jsp:root
defines the JSP namespace because both thebooks
and themagazines
elements use the elements defined in this namespace.Using the jsp:output Element
The
jsp:output
element specifies the XML declaration or the document type declaration in the request output of the JSP document. For more information on the XML declaration, see The XML Prolog. For more information on the document type declaration, see Referencing the DTD.The XML declaration and document type declaration that are declared by the
jsp:output
element are not interpreted by the JSP container. Instead, the container simply directs them to the request output.To illustrate this, here is an example of specifying a document type declaration with
jsp:output
:The resulting output is:
Specifying the document type declaration in the
jsp:output
element will not cause the JSP container to validate the JSP document against thebooks.dtd
.If you want the JSP document to be validated against the DTD, you must manually include the document type declaration within the JSP document, just as you would with any XML document.
Table 13-4 shows all the
jsp:output
attributes. They are all optional, but some attributes depend on other attributes occurring in the samejsp:output
element, as shown in the table. The rest of this section explains more about usingjsp:output
to generate an XML declaration and a document type declaration.
Generating XML Declarations
Here is an example of an XML declaration:
This declaration is the default XML declaration. It means that if the JSP container is generating an XML declaration, this is what the JSP container will include in the output of your JSP document.
Neither a JSP document nor its request output is required to have an XML declaration. In fact, if the JSP document is not producing XML output then it shouldn't have an XML declaration.
The JSP container will not include the XML declaration in the output when either of the following is true:
The JSP container will include the XML declaration in the output when either of the following is true:
The
books.jspx
JSP document does not include ajsp:root
action nor ajsp:output
. Therefore, the default XML declaration is generated in the output.Generating a Document Type Declaration
A document type declaration (DTD) defines the structural rules for the XML document in which the document type declaration occurs. XML documents are not required to have a DTD associated with them. In fact, the
books
example does not include one.This section shows you how to use the
jsp:output
element to add a document type declaration to the XML output ofbooks.jspx
. It also shows you how to enter the document type declaration manually intobooks.jspx
so that the JSP container will interpret it and validate the document against the DTD.As shown in Table 13-4, the
jsp:output
element has three attributes that you use to generate the document type declaration:
doctype-root-element
: Indicates the root element of the XML documentdoctype-system
: Indicates the URI reference to the DTDdoctype-public
: A more flexible way to reference the DTD. This identifier gives more information about the DTD without giving a specific location. A public identifier resolves to the same actual document on any system even though the location of that document on each system may vary. See the XML 1.0 specification for more information.The rules for using the attributes are as follows:
This syntax notation summarizes these rules:
<jsp:output (omit-xmldeclaration= "yes"|"no"|"true"|"false"){doctypeDecl} /> doctypeDecl:= (doctype-root-element="rootElement
" doctype-public="PublicLiteral
" doctype-system="SystemLiteral
") | (doctype-root-element="rootElement
" doctype-system="SystemLiteral
")Suppose that you want to reference a DTD, called
books.DTD
, from the output of thebooks.jspx
page. The DTD would look like this:<!ELEMENT books (book+) > <!ELEMENT book (surname, firstname, title, price, year, description, inventory) > <!ATTLIST book id CDATA #REQUIRED > <!ELEMENT surname (#PCDATA) > <!ELEMENT firstname (#PCDATA) > <!ELEMENT title (#PCDATA) > <!ELEMENT price (#PCDATA) > <!ELEMENT year (#PCDATA) > <!ELEMENT description (#PCDATA) > <!ELEMENT inventory (#PCDATA) >To add a document type declaration that references the DTD to the XML request output generated from
books.jspx
, include thisjsp:output
element inbooks.jspx
:With this
jsp:output
action, the JSP container generates this document type declaration in the request output:The
jsp:output
need not be located before the root element of the document. The JSP container will automatically place the resulting document type declaration before the start of the output of the JSP document.Note that the JSP container will not interpret anything provided by
jsp:output
. This means that the JSP container will not validate the XML document against the DTD. It only generates the document type declaration in the XML request output. To see the XML output, runhttp://localhost:8080/books/books.jspx
in your browser after you have updatedbooks.WAR
withbooks.DTD
and thejsp:output
element. When using some browsers, you might need to view the source of the page to actually see the output.Directing the document type declaration to output without interpreting it is useful in situations when another system receiving the output expects to see it. For example, two companies that do business via a web service might use a standard DTD, against which any XML content exchanged between the companies is validated by the consumer of the content. The document type declaration tells the consumer what DTD to use to validate the XML data that it receives.
For the JSP container to validate
books.jspx
againstbook.DTD
, you must manually include the document type declaration in thebooks.jspx
file rather than usejsp:output
. However, you must add definitions for all tags in your DTD, including definitions for standard elements and custom tags, such asjsp:useBean
andc:forEach
. You also must ensure that the DTD is located in the<J2EE_HOME>/
domains/domain1/config/
directory so that the JSP container will validate the JSP document against the DTD.