Friday, 1 August 2008

Java: using XMLBeans to edit web.xml

XMLBeans is a Java API and set of utilities for working with XML. The code that follows demonstrates how to use it to manipulate a J2EE web.xml (version 2.5) document.

Generating Java Beans from a Schema

The XMLBeans scomp tool (schema compiler) is used to generate beans from a schema. It requires a Java compiler to do this. Here is the tool in action:
C:>%XMLBEANS_HOME%\bin\scomp -src .\src_webapp_2_5 -d .\bin_webapp_2_5 -out .\webapp_2_5.jar -javasource 1.5 -compiler %JDK_HOME%\bin\javac.exe -dl http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd
    Time to build schema type system: 10.906 seconds
    Time to generate code: 3.813 seconds
    Time to compile code: 14.765 seconds
    Compiled types to: .\webapp_2_5.jar


Here is a breakdown of the switches used:

SWITCHEXPLANATION
-src .\src_webapp_2_5The directory where source files will be written.
-d .\bin_webapp_2_5The directory where binary files will be written.
-out .\webapp_2_5.jarThe filename for the generated jar file.
-javasource 1.5Directs the tool to generate Java 1.5 code.
-compiler %JDK_HOME%\bin\javac.exeThe Java compiler.
-dlAllows scomp to use the internet to resolve schema dependencies.
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsdThe web.xml 2.5 schema location.


An examination of the generated code will reveal the following:
  • The generated beans have a dependency on the XMLBeans API.
  • Although there is an option to generate the bean sources, it will have missing runtime dependencies (it will lack all the generated files found under .\bin_webapp_2_5\schemaorg_apache_xmlbeans).
  • The source for the top-level bean object is in .\src_webapp_2_5\com\sun\java\xml\ns\javaee\WebAppDocument.java. The package is based on the XML schema namespace and the document object name is based on the top-level element (web-app).


Parsing a web.xml File

Loading a file is trivial. The following prints the file contents to standard out. (Res.WEB_2_5_XML is a static variable pointing to a file.)

    URL web_xml = Res.WEB_2_5_XML;
    WebAppDocument webAppDocument = WebAppDocument.Factory.parse(web_xml);
    System.out.println(webAppDocument);


Adding a Servlet Definition to the web.xml

The following code adds a Servlet and a Servlet mapping to the deployment descriptor (web.xml).

    final String servletName = "FooBarServlet";
    final String displayName = servletName;
    final String description = "A Foo/Bar Servlet";
    final String servletClass = "foo.BarServlet";
    final String urlPattern = "/FooBarServlet/*";
    
    URL web_xml = Res.WEB_2_5_XML;
    WebAppDocument webAppDocument = WebAppDocument.Factory.parse(web_xml);
    
    System.out.println("==BEFORE==");
    System.out.println(webAppDocument);
    System.out.println();
    
    ServletType servlet = webAppDocument.getWebApp().addNewServlet();
    servlet.addNewDescription().setStringValue(description);
    servlet.addNewDisplayName().setStringValue(displayName);
    servlet.addNewServletName().setStringValue(servletName);
    servlet.addNewServletClass().setStringValue(servletClass);
    
    ServletMappingType servletMapping = webAppDocument.getWebApp().addNewServletMapping();
    servletMapping.addNewServletName().setStringValue(servletName);
    servletMapping.addNewUrlPattern().setStringValue(urlPattern);
    
    System.out.println("==AFTER==");
    System.out.println(webAppDocument);
    System.out.println();


When run, the code prints the following to standard out.

==BEFORE==
<web-app xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_1234" version="2.5" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  <display-name>SampleWebApp</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>

==AFTER==
<web-app xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_1234" version="2.5" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  <display-name>SampleWebApp</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
  <servlet>
    <description>A Foo/Bar Servlet</description>
    <display-name>FooBarServlet</display-name>
    <servlet-name>FooBarServlet</servlet-name>
    <servlet-class>foo.BarServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>FooBarServlet</servlet-name>
    <url-pattern>/FooBarServlet/*</url-pattern>
  </servlet-mapping>
</web-app>



End Notes

  • The generated code only works for version 2.5 documents; if you tried to load a web.xml defined by another schema version (2.4) or a DTD (2.3), an exception would be thrown. [XML and determining document versions.]
  • The System.outs above do not emit the <?xml version="1.0" encoding="UTF-8"?> XML signature; developers writing the document to a stream should remember to add it.


Sample Code in Subversion

Repository: http://illegalargumentexception.googlecode.com/svn/trunk/code/java/
License: MIT
Project: xmlbeansDemo

Dev Environment

JRE, JDK and XMLBeans versions.
    C:>java -version
    java version "1.6.0_07"
    Java(TM) SE Runtime Environment (build 1.6.0_07-b06)
    Java HotSpot(TM) Client VM (build 10.0-b23, mixed mode, sharing)

    C:>%JDK_HOME%\bin\javac -version
    javac 1.6.0_05

    C:>%XMLBEANS_HOME%\bin\scomp -version
    Apache Software Foundation, org.apache.xmlbeans.XmlBeans version 2.4.0-r670094
JAVA_HOME, JDK_HOME and XMLBEANS_HOME environment variables have been set. The OS used was Windows XP.

No comments:

Post a Comment

All comments are moderated