When I refer to XML as a presentation technology, I am referring primarily to the view in an app using a Model-View-Controller (MVC) architecture. Model-View-Controller is a software architecture originally documented as a pattern for traditional client apps (like those created with Swing) but has been widely adopted as an architecture for web apps. In short, an MVC app separates an app into three main areas:


Model

The raw data and business rules of an app


View

The user-visible rendition of the model


Controller

Functionality that receives requests from users, interprets those requests, interacts with the model, and provides the view with any necessary model objects

In more concrete terms, an MVC web app written with Java servlets and JSPs could processes a request in four steps:

  1. A servlet (the controller) receives the request and parses it.
  2. The servlet calls some methods on a data access object (the model).
  3. The servlet passes model data objects to a JSP page for rendering.
  4. The JSP page outputs an HTML page including data from the model objects.

There are a number of Java web MVC frameworks available that provide much of the base code necessary in any web app. Popular examples include Apache Struts (), Spring MVC (), JavaServer Faces (), and Tapestry ().

XML in MVC Web apps

XML can be used in several places in an MVC web app. Most MVC frameworks make heavy use of XML for internal configuration. More interesting for our purposes is where XML is used to contain the data passed between the view and the controller. Instead of the controller passing one or more model objects to the view, the controller constructs an XML representation of the model objects and passes the XML document to the view. In some cases, your app is responsible for delivering XML; the "view" is simply serializing the XML document as the HTTP response. In others, the view is some form of server-side transformation from the controller-supplied XML to a different XML syntax or to HTML. In addition, the use of XML to transfer model data between the controller and the view allows us to move any necessary transformations from the server to users' client apps (usually web browsers). To start, let's simply create a servlet that produces an XML document. contains a simple servlet that creates an XML document containing a list of tutorials. Our model is a List of Map objects. Once it has created a DOM Document object, the servlet outputs the document using the identity transformation technique discussed in .

Example Servlet generating XML document

package javaxml3.ch13;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Result;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Text;
public class BookListXMLServlet extends HttpServlet {
 private DocumentBuilderFactory documentBuilderFactory;
 private TransformerFactory transformerFactory;
 public void init( ) {
 documentBuilderFactory = DocumentBuilderFactory.newInstance( );
 transformerFactory = TransformerFactory.newInstance( );
 }
 private Element newElementFromMap(Map map, String key, Document doc) {
 String text = (String) map.get(key);
 Text textNode = doc.createTextNode(text);
 Element element = doc.createElement(key);
 element.appendChild(textNode);
 return element;
 }
 protected void renderDocument(Document doc, HttpServletRequest request,
 HttpServletResponse response) throws IOException, ServletException {
 // tell the browser we're sending XML
 response.setContentType("text/xml");
 // now do the identity transformation
 try {
 Transformer identity = transformerFactory.newTransformer( );
 // our Result object is a StreamResult wrapping the
 // ServletOutputStream
 Result result = new StreamResult(response.getOutputStream( ));
 identity.transform(new DOMSource(doc), result);
 } catch (TransformerException e) {
 throw new ServletException(
 "Unable to perform identity transformation", e);
 }
 }
 protected void service(HttpServletRequest request,
 HttpServletResponse response) throws ServletException, IOException {
 List tutorialList = BookListFactory.INSTANCE;
 DocumentBuilder docBuilder = null;
 try {
 docBuilder = documentBuilderFactory.newDocumentBuilder( );
 } catch (ParserConfigurationException e) {
 throw new ServletException(
 "Unable to create DocumentBuilderFactory", e);
 }
 // create the DOM document
 Document doc = docBuilder.newDocument( );
 Element tutorials = doc.createElement("books");
 doc.appendChild(books);
 for (Iterator it = tutorialList.iterator( ); it.hasNext( );) {
 Map tutorialMap = (Map) it.next( );
 Element tutorial = doc.createElement("book");
 tutorials.appendChild(book);
 tutorial.appendChild(newElementFromMap(bookMap,
 BookListConstants.TITLE, doc));
 tutorial.appendChild(newElementFromMap(bookMap,
 BookListConstants.AUTHOR, doc));
 tutorial.appendChild(newElementFromMap(bookMap,
 BookListConstants.PUBDATE, doc));
 }
 renderDocument(doc, request, response);
 }
}
class BookListConstants {
 public static final String AUTHOR = "author";
 public static final String PUBDATE = "pubdate";
 public static final String TITLE = "title";
}
class BookListFactory {
 public static final List INSTANCE;
 static {
 List templist = new ArrayList( );
 Map m = new HashMap( );
 m.put(BookListConstants.TITLE, "Ajax Hacks");
 m.put(BookListConstants.AUTHOR, "Bruce W. Perry");
 m.put(BookListConstants.PUBDATE, "March 2006");
 templist.add(m);
 m = new HashMap( );
 m.put(BookListConstants.TITLE, "LDAP System Administration");
 m.put(BookListConstants.AUTHOR, "Gerald Carter");
 m.put(BookListConstants.PUBDATE, "March 2003");
 templist.add(m);
 m = new HashMap( );
 m.put(BookListConstants.TITLE, "Java Servlet Programming");
 m.put(BookListConstants.AUTHOR, "Jason Hunter");
 m.put(BookListConstants.PUBDATE, "April 2001");
 templist.add(m);
 INSTANCE = Collections.unmodifiableList(templist);
 }
 private BookListFactory( ) {
 }
}

contains a web.xml servlet configuration file that maps this servlet to the path /booklist-xml.

Example Simple web.xml file

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="ch13-servlet" version="2.4"
 xmlns="http://java.oracle.com/xml/ns/j2ee"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 <display-name>ch13-servlet</display-name>
 <servlet>
 <servlet-name>BookListXMLServlet</servlet-name>
 <servlet-class>javaxml3.ch13.BookListXMLServlet</servlet-class>
 </servlet>
 <servlet-mapping>
 <servlet-name>BookListXMLServlet</servlet-name>
 <url-pattern>/booklist-xml</url-pattern>
 </servlet-mapping>
</web-app>

Once we've created a web app containing this servlet class and configuration file, we can view the results in a browser, as seen in .

XML output from a servlet

Java ScreenShot

We didn't have to use a servlet to build this document. A page using JSP or another template language (such as Velocity) could build the same document. Instead of the servlet from , we could have a much simpler servlet such as and then do the XML creation in a JSP such as the one seen in .

Example Much simpler tutorial list servlet

package javaxml3.ch13;
import java.io.IOException;
import java.util.List;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class BookListXMLJSPServlet extends HttpServlet {
 protected void service(HttpServletRequest request,
 HttpServletResponse response) throws ServletException, IOException {
 List tutorialList = BookListFactory.INSTANCE;
 request.setAttribute("bookList", tutorialList);
 RequestDispatcher dispatcher = getServletContext( )
 .getRequestDispatcher("/booklist1.jsp");
 dispatcher.include(request, response);
 }
}

Example Rendering XML with JSP tags

<?xml version="1.0" encoding="UTF-8" ?>
<%@ page contentType="text/xml"%>
<%@ taglib prefix="c" uri="http://java.oracle.com/jsp/jstl/core"%>
<books>
<c:forEach items="${bookList}" var="book">
 <book>
 <title>${book.title}</title>
 <author>${book.author}</author>
 <pubdate>${book.pubdate}</pubdate>
 </book>
</c:forEach>
</books>
Java Warning Note that the XML declaration is placed at the top of the JSP page, above the directives. This is because the XML declaration must be the first thing in an XML document.

However, when we generate XML with a JSP such as , we are now able to produce an XML document that is not well-formed. Because the servlet in creates its document with DOM, there's no way a document that's not well-formed would be produced (except in case of a bug in the XML libraries). But with this method of creating a document with JSP, there is nothing to prevent you from accidentally creating a document with mismatched end tags such as:

<?xml version="1.0" encoding="UTF-8" ?>
<books>
 <book>
 <title>Ajax Hacks</title>
 <author>Bruce W. Perry</pubdate>
 <pubdate>March 2006</author>
 </book>
</books>

Or any of a variety of other well-formedness issues. Nevertheless, creating the document this way with JSP is bound to be faster and consume far less memory, since intermediate DOM objects are not created.