JaVa
   

Deciding When to Use XML

XML is a core J2EE technology. Due to its use for the standard J2EE deployment descriptors (app.xml, web.xml and ejb-jar.xml) and the proprietary deployment descriptors required by most servers, it's impossible for J2EE developers to avoid using XML. XML technologies can also be used by choice to provide a valuable complement to Java-based J2EE technologies. One of the important enhancements in J2EE 1.3 is that it guarantees that the JAXP 1.1 API is available to J2EE apps (JAXP makes a further move into the core Java libraries in J2SE 1.4). JAXP provides standard support for XML parsing and XSL transformations in J2EE apps. J2EE apps may need to generate and parse XML documents to achieve interoperability with non-J2EE platforms. (However, web services style interoperability can largely conceal the use of XML under the hood; XML may also be used to support client devices and user agents.)

Using XSLT in J2EE apps

Another strong reason to use XML technologies, which applies even within J2EE apps, is to enable the use of XSLT to transform XML data into a wide variety of output formats. This is most valuable in web apps when generating HTML, XHTML or WML, which means that XSLT may be an alternative to web tier view technologies such as JSP. XSLT guru Michael Kay (author of the excellent XSLT Programmer's Reference, Wrox Press) writes that "When I first saw the XSL transformation language, XSLT, I realized that this was going to be the SQL of the web, the high-level data manipulation language that would turn XML from being merely a storage and transmission format for data into an active information source that could be queried and manipulated in a flexible, declarative way". If data is held in the form of XML documents, or can easily be converted to an XML representation, XSLT provides powerful functionality that is superior to Java-based technologies such as JSP in the following areas:

However, XSLT is weaker than Java-based technologies such as JSP in the following areas:

"Deep" Use of XML

To use XSLT, we need XML documents to transform. These don't need to exist as strings or on the file system: they can exist as W3C org.w3c.dom.Node objects before transformation. There is no problem when data naturally exists as XML: for example, if it comes from an XML database, XML content management system or external system that the J2EE app communicates with using XML. While XML databases are not commonly used, the last two of these scenarios are often seen in practice. However, if the data doesn't already exist as XML, but we wish to use XSLT for presentation, we need to decide at what point in our J2EE architecture we will convert data to XML form. We must choose between "deep" use of XML (where data is passed around the app in the form of XML rather than Java objects) and superficial use of XML (in which case XML documents are created only at the boundary of the system; for example immediately before performing an XSLT transform). J2EE and XML Development from Manning () advocates "deep" use of XML. In this approach, XML documents replace Java value objects within the J2EE system, making it easy to use XSLT at the boundaries. Often this data will come from an RDBMS, so we can try to convert query results to XML form. Ronald Bourret maintains an excellent site on this issue at http://www.rpbourret.com/xml/XMLDBLinks.htm. Bourret has also published an article on the subject, at http://www.xml.com/pub/a/2001/05/09/dtdtodbs.html?page=1, which is a useful starting point. There's a choice between doing the mapping work in Java code, inside the J2EE server, and performing it in the database. RDBMS vendors are rushing to provide XML support, and some relational databases, such as Oracle 9i, even allow us to store XML directly in the database. We may also be able to obtain query results in XML. Such approaches aren't portable, as no relevant standards exist yet. Unfortunately, wherever we do the conversion, it will be a non-trivial task. In the next few chapters we'll discuss the "imedance mismatch" between RDBMS schema and Java object model. There is a comparable impedance mismatch between RDBMS schema and XML document, and a similar degree of complexity in trying to bridge it. The trivial examples of RDBMS result set to XML mappings shown in tutorials such as J2EE and XML Development are insufficient for real apps: queries can become extremly complex (and expensive to run) if we try to build a deep XML hierarchy from one or more relational queries. The relational model for data is not hierarchical, and it's difficult to build hierarchies using it. We can run multiple RDBMS queries to produce separate shallow XML documents, hoping to use XSLT to "join" the data on the client-side (XSLT allows nodes to be looked up – in the same or in another document – by ID in an approach analogous to an RDMBS JOIN). However, this is relatively complex to implement in XSLT, and ignores the capabilities of the RDBMS itself. It's only appropriate where a small amount of reference data is concerned. For example, it might be a valid approach where a table of countries is concerned, but inappropriate where a table of invoices is concerned. The difficulty in extracting relational data directly into XML documents is just one of several major problems with "deep" use of XML, which I believe should preclude its use in general:

Important 

I don't advocate "deep" use of XML within J2EE apps. While superficially attractive apps – especially if we wish to use XSLT for presentation – built on internal communication using XSLT are likely to be slower, harder to understand, maintain, and test than apps based on Java objects and sound OO design principles.

Converting Between JavaBeans and XML

When we need to convert data to XML, it's usually a better idea to do so closer to the boundary of the system. If we do so in the web tier itself, immediately before the XSL transform, we can achieve interchangeability of view technology, allowing us to choose between using XSLT and JSP and other solutions, without modifying the entire architecture (we'll talk about how to achieve this important design goal in s 12 and 13). In J2EE apps, data normally exists as JavaBeans before rendering to a client such as a web browser. If we use Java-based technologies such as JSP, we can work with JavaBeans directly. If we need to expose data using XML (for example, to transform it using XSLT) we need to convert the JavaBeans to an XML representation. Fortunately, there is a fairly natural mapping from JavaBeans to XML documents, making this a far less complex problem than converting relational data to XML. There are several approaches to generating XML from a graph of Java objects:

The second and fourth approaches are usually best. I've used the last three approaches successfully in several projects. The fourth approach – "domification" using reflection – is most attractive, as it minimizes the amount and complexity of code written by app developers. While the use of reflection will incur a small performance overhead, it will probably be smaller than the overhead of transforming the XML. One major benefit of the use of reflection is that it will ensure that XML-generation code is always up to date; there will be no need to modify bloated XML-generation classes when objects change. We won't need to write verbose XML-generation code either; the domification library will hide the details of XML document creation. If domification is done on the fly, only the object properties actually needed by a stylesheet will be invoked at runtime, meaning that some of the overhead can be avoided. There are a few things we need to consider before relying on domification:

There are several published libraries for converting Java objects to XML. My favorite is the Domify open source project (http://domify.sf.net/). Domify was originally part of the Maverick MVC web framework but was split into a separate project in December 2001. It's a tiny library (only eight classes) and is very easy to use. Other, more sophisticated, but more complex, products include Castor (http://castor.exolab.org/xml-framework.html), which "can marshal almost any ‘bean-like’ Java Object to and from XML". See http://www.rpbourret.com/xml/XMLDataBinding.htm for a directory of several XML-Java conversion products. Domify uses the on-the-fly approach to XML node creation, with lazy loading. Nodes in the logical DOM tree that are never accessed, by XSLT or other user code are never created. Once created, nodes are cached, so subsequent accesses will be faster. To use Domify, it's first necessary to create an object of class org.infohazard.domify.DOMAdapter. Once a DOMAdapter has been created, its adapt (Object, String) method can be used to domify objects. A DOMAdapter object is thread-safe, hence can be used repeatedly (however, DOMAdapter objects are cheap to instantiate so there's no problem in creating many objects). The entire process looks like this:

 DOMAdapter domAdapter = new DOMAdapter();
 Node node = domAdapter.adapt(javaBean, "nameOfRootElement");


The adapt() method throws an unchecked exception if the transformation fails: most likely, because an invoked getter method threw an exception. As this is not recoverable, and should not happen when traversing a web tier model, this is a reasonable approach (as discussed in ). Domify doesn't check for cyclic references, so we must ensure that beans to be domified don't have any (again, this is not usually a problem with Java bean models in web apps). To illustrate how Domify works, let's take a simple bean and look at the XML document Domify generates from it. The following simple bean has four properties, of String, int, Collection, and Map type respectively, which are highlighted in the listing below, along with methods allowing data to be added:

 public class Person {
 private int age;
 private String name;
 private List hobbies = new LinkedList();
 private Map family = new HashMap();
 public Person (String name, int age) {
 this.age = age;
 this.name = name;
 }
 public void addHobby (String name) {
 hobbies.add (name);
 }
 public void addFamilyMember (String relation, String name) {
 family.put (relation, name);
 }


 public int getAge() {
 return age;
 }
 public String getName() {
 return name;
 }
 public Collection getHobbies() {
 return hobbies;
 }
 public Map getFamily() {
 return family;
 }


 }


I've omitted the no-arg constructor and property setters for brevity. Let's construct a simple bean:

 Person p = new Person ("Kerry", 35) ;
 p.addHobby ("skiing") ;
 p.addHobby ("cycling") ;
 p.addFamilyMember ("husband", "Rod") ;
 p.addFamilyMember ("son" , "Tristan") ;


Domify will automatically expose the four bean properties. Each node is created only on demand, and cached thereafter in case it is required again in the same XML operation. The following illustrates the complete XML document. Note the treatment of the Collection and Map properties (highlighted):

<?xml version="1.0" encoding="UTF-8"?>
<person>
 <name>Kerry</name>
 <age>35</age>
 <hobbies>
 <item type="java.lang.String">skiing</item>
 <item type="java.lang.String">cycling</item>
 </hobbies>
 </family>
 <item key="son" type="java.lang.String">Tristan</item>
 <item key="husband" type="java.lang.String">Rod</item>
 </family> 
</person>



It's easy to write an XSLT stylesheet to format this data as desired. This approach is very simple, yet powerful. The Maverick MVC web app framework demonstrates its effectiveness. Converting in the opposite direction – from XML representation to JavaBean – is also relatively straightforward, and is a widely used approach for getting app configuration out of Java code. Many apps and frameworks use XML documents to provide long-term persistence for JavaBeans, such as JBoss's jboss.jcml XML configuration file, which uses XML to configure JMX MBeans. Each bean property is usually represented as an XML element, with an attribute value holding the property name. The generic framework we'll describe in this tutorial and use for our sample app also uses this approach. Most app objects will be JavaBeans, their properties and relationships held outside Java code in XML documents. This is discussed in detail in .

J2SE 1.4 introduces "Long Term JavaBeans Persistence" to standardize such functionality, although it is too early to tell how widely this standardization will be accepted. In Java 1.4, the java.beans API is extended to read and write a bean as an XML representation of its property values. As this tutorial is concerned with the J2EE 1.3 platform, which is based on J2SE 1.3, it's assumed that this new API isn't available. However, its introduction indicates the importance of Java beans to XML mapping.

J2EE and XML in the Future

J2EE will become still more closely integrated with XML – even besides web services support. Important forthcoming enhancements include Java Architecture for XML Binding (JAXB), which automates the mapping between Java objects and XML documents by providing tools to generate Java classes from XML DTDs or schemas. The generated classes can efficiently handle XML parsing and formatting, simplifying code that uses them and offering the potential of much better performance than is available with traditional XML parsing or Java-to-XML converters such as Domify. The JAXB homepage is at http://java.oracle.com/xml/jaxb/index.html. The JAXB specification is presently in draft, and should be complete by the end of 2002.

Important 

XML is a core J2EE technology. XSLT is a viable alternative to JSP as a view technology in J2EE apps if it simplifies presentation logic, and when data already exists as XML or can efficiently be converted to XML form.

I don't favor "deep" use of XML within a J2EE architecture. XML documents are loosely typed and cumbersome to access and manipulate in J2EE apps.

XML in the Sample app

There's no reason to use XML deep within the sample app's architecture. However, it is reasonable to consider the option of using XSLT as a view technology. A key business requirement is the ability to "rebrand" the app by modifying the presentation without revising the workflow. XML and XSLT provides an excellent way of doing this, although we can also achieve it with JSP and other view technologies, so long as we use an MVC approach in the web tier. We may want to retain the option of using XML and XSLT to generate web content, but have no reason to tie ourselves to using XML. This suggests that we should create our data models as JavaBeans, and use a package such as Domify to convert them to XML documents if needed. The volume of user-specific data to be converted and styled (in reservation objects, for example) is modest, so the performance overhead of this approach should not be a problem. Where reference data (such as performance dates) is concerned, we may want to cache converted documents, as more data is involved and more pages are concerned.

It would be difficult to justify using XML and XSLT in Phase 1 except as a strategic choice, or unless practical considerations suggested it (such as the availability of strong XSLT skills but no JSP skills). JSP, will prove simpler and quicker to generate the screens described in the initial requirements. However, XSLT might well come into its own in the future (for example, it would be well suited to sort reference data in the web tier). In we will discuss XSLT as a view technology in detail, along with a demonstration of how it could be used in the sample app without changing the app's overall architecture.

JaVa
   
Comments