The Java EE 5 Tutorial

Chapter 6 JavaServer Pages Documents

A JSP document is a JSP page written in XML syntax as opposed to the standard syntax described in Chapter 5, JavaServer Pages Technology. Because it is written in XML syntax, a JSP document is also an XML document and therefore gives you all the benefits offered by the XML standard:

In addition to these benefits, the XML syntax gives the JSP page author less complexity and more flexibility. For example, a page author can use any XML document as a JSP document. Also, elements in XML syntax can be used in JSP pages written in standard syntax, allowing a gradual transition from JSP pages to JSP documents.

This chapter gives you details on the benefits of JSP documents and uses a simple example to show you how easy it is to create a JSP document.

You can also write tag files in XML syntax. This chapter covers only JSP documents. Writing tag files in XML syntax will be addressed in a future release of the tutorial.

The Example JSP Document

This chapter uses the Duke’s Bookstore application, version bookstore5, and the books application to demonstrate how to write JSP pages in XML syntax. The JSP pages of the bookstore5 application use the JSTL XML tags (see XML Tag Library) to manipulate the book data from an XML stream. The books application contains the JSP document books.jspx, which accesses the book data from the database and converts it into the XML stream. The bookstore5 application accesses this XML stream to get the book data.

These applications show how easy it is to generate XML data and stream it between web applications. The books application can be considered the application hosted by the book warehouse’s server. The bookstore5 application can be considered the application hosted by the book retailer’s server. In this way, the customer of the bookstore web site sees the list of books currently available, according to the warehouse’s database.

The source for the Duke’s Bookstore application is located in the tut-install/javaeetutorial5/examples/web/bookstore5/ directory, which is created when you unzip the tutorial bundle (see Chapter 2, Using the Tutorial Examples).

    To deploy the books application using NetBeans IDE, follow these steps:

  1. Perform all the operations described in Accessing Databases from Web Applications.

  2. In NetBeans IDE, select File->Open Project.

  3. In the Open Project dialog, navigate to:


    tut-install/javaeetutorial5/examples/web/
  4. Select the books folder.

  5. Select the Open as Main Project check box and the Open Required Projects check box.

  6. Click Open Project.

  7. In the Projects tab, right-click the books project, and select Undeploy and Deploy.

    To deploy the books application using the Ant utility, follow these steps:

  1. In a terminal window, go to tut-install/javaeetutorial5/examples/web/books/.

  2. Type ant build. This target will spawn any necessary compilations, copy files to the tut-install/javaeetutorial5/examples/web/books/build/ directory, build a WAR file, and copy the WAR file to the tut-install/javaeetutorial5/examples/web/books/dist/ directory.

  3. To deploy the application, type ant deploy.

    To deploy and run the bookstore5 application using NetBeans IDE, follow these steps:

  1. Perform all the operations described in Accessing Databases from Web Applications.

  2. In NetBeans IDE, select File->Open Project.

  3. In the Open Project dialog, navigate to:


    tut-install/javaeetutorial5/examples/web/
    
  4. Select the bookstore5 folder.

  5. Select the Open as Main Project check box and the Open Required Projects check box.

  6. Click Open Project.

  7. In the Projects tab, right-click the bookstore5 project, and select Undeploy and Deploy.

  8. To run the applications, open the bookstore URL http://localhost:8080/bookstore5/books/bookstore.

    To deploy and run the application using Ant, follow these steps:

  1. In a terminal window, go to tut-install/javaeetutorial5/examples/web/bookstore5/.

  2. Type ant. This command will spawn any necessary compilations, copy files to the tut-install/javaeetutorial5/examples/web/bookstore5/build/ directory, and create a WAR file and copy it to the tut-install/javaeetutorial5/examples/web/bookstore5/dist/ directory.

  3. Start the Application Server.

  4. Perform all the operations described in Creating a Data Source in the Application Server.

  5. To deploy the example, type ant deploy. The deploy target outputs a URL for running the application. Ignore this URL, and instead use the one shown in the next step.

  6. To run the applications, open the bookstore URL http://localhost:8080/bookstore5/books/bookstore.

To learn how to configure the bookstore5 example, refer to the web.xml file, which includes the following configurations:

To learn how to configure the books example, refer to the web.xml file, which includes the following configurations:

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 6–1 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.

Table 6–1 Standard Syntax Versus XML Syntax

Syntax Elements 

Standard Syntax 

XML Syntax 

Comments 

<%--.. --%>

<!-- .. -->

Declarations 

<%! ..%>

<jsp:declaration> .. </jsp:declaration>

Directives 

<%@ include .. %>

<jsp:directive.include .. />

<%@ page .. %>

<jsp:directive.page .. />

<%@ taglib .. %>

xmlns:prefix="tag library URL"

Expressions 

<%= ..%>

<jsp:expression> .. </jsp:expression>

Scriptlets 

<% ..%>

<jsp:scriptlet> .. </jsp:scriptlet>

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:

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 and jsp: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 a taglib directive:

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

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:

...
xmlns:c="http://java.sun.com/jsp/jstl/core"
...

The value that identifies the location of the tag library can take three forms:

The URN of the form urn:jsptld:path points to one tag library packaged with the application:

xmlns:u="urn:jsptld:/WEB-INF/tlds/my.tld"

The URN of the form urn:jsptagdir:path must start with /WEB-INF/tags/ and identifies tag extensions (implemented as tag files) installed in the /WEB-INF/tags/ directory or a subdirectory of it:

xmlns:u="urn:jsptagdir:/WEB-INF/tags/mytaglibs/"

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 the xmlns attributes in the root element, books:

<books
    xmlns:jsp="http://java.sun.com/JSP/Page"
    xmlns:c="http://java.sun.com/jsp/jstl/core"
>

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 the jsp:useBean element and its subelements. Similarly, the tag library referenced by the c prefix is only available to the c: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, the jsp prefix must always be bound to http://java.sun.com/JSP/Page, the JSP namespace.

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, and taglib. The taglib 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 is

<jsp:directive.page page-directive-attr-list />

The page-directive-attr-list is the same list of attributes that the <@ page ...> directive has. These are described in Chapter 5, JavaServer Pages Technology. All the attributes are optional. Except for the import and pageEncoding 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:

<jsp:directive.include file="relativeURLspec" />

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 following include directive to books.jspx, assuming that magazines.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 otherwise books.jspx would have two root elements: <books> and <magazines>. The output generated from books.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. The jsp:text element passes its content through to the output.

If you use jsp:text, all white space is preserved. For example, consider this example using XML tags:

<books>
    <book>
        Web Servers for Fun and Profit
    </book>
</books>

The output generated from this XML has all white space removed:

<books><book>
        Web Servers for Fun and Profit
</book></books>

If you wrap the example XML with a <jsp:text> tag, all white space is preserved. The white space 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 a jsp:text tag.

<c:forEach var="counter" begin="1" end="${3}">
    <jsp:text>${counter}</jsp:text>
</c:forEach>

This example will output


123

The jsp:text tag must not contain any other elements. Therefore, if you need to nest a tag inside jsp:text, you must wrap the tag inside CDATA.

You also need to use CDATA if you need to output some elements that are not well-formed. The following example requires CDATA wrappers around the blockquote start and end tags because the blockquote element is not well formed. This is because the blockquote 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, the c: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 6–2 enumerates the more common operators and their alternative syntax in JSP documents.

Table 6–2 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 hard code them. This example could be used to generate an HTML header tag with a lang 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. The jsp:attribute tag generates the lang attribute. The body of the jsp:attribute tag identifies the value of the lang attribute. The jsp:body tag generates the body of the tag. The output of this example jsp:element could be

<h1 lang="fr">Heading in French</h1>

As shown in Table 6–1, scripting elements (described in Chapter 9, Scripting in JSP Pages) 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. A jsp:declaration element has no attributes and its body is the declaration itself. Its syntax is

<jsp:declaration> declaration goes here </jsp:declaration>

A 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 is

<jsp:scriptlet> code fragment goes here </jsp:scriptlet>

The jsp:expression element inserts the value of a scripting language expression, converted into a string, into the data stream returned to the client. A jsp:expression element has no attributes and its body is the expression. Its syntax is

<jsp:expression> expression goes here </jsp:expression>

Using the jsp:root Element

The jsp:root element represents the root element of a JSP document. A jsp: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 the books.jspx example JSP document is books.

Although the jsp:root element is not required, it is still useful in these cases:

The version attribute is the only required attribute of the jsp:root element. It specifies the JSP specification version that the JSP document is using.

The jsp:root element can also include xmlns attributes for specifying tag libraries used by the other elements in the page.

The books.jspx page does not need a jsp:root element and therefore doesn’t include one. However, suppose that you want to generate two XML documents from books.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 this jsp: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 the books and the magazines 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.

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:

<jsp:output doctype-root-element="books"
                    doctype-system="books.dtd" />

The resulting output is:

<!DOCTYPE books SYSTEM "books.dtd" >

Specifying the document type declaration in the jsp:output element will not cause the JSP container to validate the JSP document against the books.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 6–3 shows all the jsp:output attributes. They are all optional, but some attributes depend on other attributes occurring in the same jsp:output element, as shown in the table. The rest of this section explains more about using jsp:output to generate an XML declaration and a document type declaration.

Table 6–3 jsp:output Attributes

Attribute 

What It Specifies 

omit-xml-declaration

A value of true or yes omits the XML declaration. A value of false or no generates an XML declaration.

doctype-root-element

Indicates the root element of the XML document in the DOCTYPE. Can be specified only if doctype-system is specified.

doctype-system

Specifies that a DOCTYPE is generated in output and gives the SYSTEM literal.

doctype-public

Specifies the value for the Public ID of the generated DOCTYPE. Can be specified only if doctype-system is specified.

Generating XML Declarations

Here is an example of an XML declaration:

<?xml version="1.0" encoding="UTF-8" ?>

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 a jsp:root action nor a jsp: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 of books.jspx. It also shows you how to enter the document type declaration manually into books.jspx so that the JSP container will interpret it and validate the document against the DTD.

As shown in Table 6–3, the jsp:output element has three attributes that you use to generate the document type declaration:

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 the books.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 this jsp:output element in books.jspx:

<jsp:output doctype-root-element="books"
         doctype-system="books.DTD" />

With this jsp:output action, the JSP container generates this document type declaration in the request output:

<!DOCTYPE books SYSTEM "books.DTD" />

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, run http://localhost:8080/books/books.jspx in your browser after you have updated books.WAR with books.DTD and the jsp: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 by means of 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 against book.DTD, you must manually include the document type declaration in the books.jspx file rather than use jsp:output. However, you must add definitions for all tags in your DTD, including definitions for standard elements and custom tags, such as jsp:useBean and c:forEach. You also must ensure that the DTD is located in the domain-dir/config/ directory so that the JSP container will validate the JSP document against the DTD.

Identifying the JSP Document to the Container

A JSP document must be identified as such to the web container so that the container interprets it as an XML document. There are three ways to do this: