<?xml version='1.0' encoding='utf-8'?>
<?xml-stylesheet href="/style/browser.xsl" type="text/xsl"?>
<essay xmlns="http://docbook.org/ns/docbook"
       xmlns:xlink="http://www.w3.org/1999/xlink"
       xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'
       xmlns:dc='http://purl.org/dc/elements/1.1/'
       xmlns:dcterms="http://purl.org/dc/terms/"
       xmlns:gal='http://norman.walsh.name/rdf/gallery#'
       xmlns:foaf="http://xmlns.com/foaf/0.1/"
       xml:lang="en"
       version='5.0'>
<info>
<title>All your resolvers are belong to us</title>
<volumenum>10</volumenum>
<issuenum>12</issuenum>
<pubdate>2007-02-14T07:43:35-05:00</pubdate>
<date>$Date: 2007-04-25 07:53:59 -0400 (Wed, 25 Apr 2007) $</date>
<author><personname>
<firstname>Norman</firstname><surname>Walsh</surname>
</personname></author>
<copyright><year>2007</year><holder>Norman Walsh</holder></copyright>
<abstract>
<para>Making resolvers easier for users.</para>
</abstract>
</info>

<para xml:id='p1'>In addition to the
<link xlink:href="http://norman.walsh.name/2007/02/09/resolvers">API proliferation
problem</link> I mentioned the other day, resolvers have another
significant shortcoming: they're designed for programmers. That's a
problem because, by and large, it isn't the programmers who need them,
it's the legions of users out there wanting to make applications do the
right thing.
</para>

<para xml:id='p2'>This point was driven home quite forcefully the other day
after an internal presentation I gave about the new resolver code.
<link xlink:href="http://weblogs.java.net/blog/spericas/"><personname>
<firstname>Santiago</firstname><surname role="suppress">Pericas-Geersten</surname>
</personname></link> said, roughly, “that looks great, I'd love to use
it” but when I began to explain how he could, he interrupted with “no, no,
I don't want to have to set anything up, I don't want a properties file, it
should just work.”</para>

<para xml:id='p3'>This is, in fact, manifestly the case. End users, the ones stuck
with applications that need resolvers, can't usually tinker with the
code involved.</para>

<para xml:id='p4'>We kicked around some ideas about how this might be
accomplished. Eventually we came up with a plan and I have now
implemented that plan. It's not a perfect plan because it does require a little
bit of setup work and it does, in at least one case, break the
rules.</para>

<para xml:id='p5'>On the other hand, it's a good plan because it should work with any
Java application.</para>

<section xml:id="theplan">
<title>The plan</title>

<para xml:id='p6'>The plan is this: using the standard <wikipedia>JAXP</wikipedia>
factory finder mechanisms,
inject a special set of parser classes into the application. These classes
behave exactly like the standard JAXP 1.4 parsers except that they always
use a resolver.</para>

<para xml:id='p7'>It turns out that this works quite well. If you instantiate the
resolver versions of the <classname>SAXParserFactory</classname>,
<classname>XMLInputFactory</classname>, and
<classname>DocumentBuilderFactory</classname> then:</para>

<itemizedlist>
<listitem>
<para xml:id='p8'>The <wikipedia page="Document_Object_Model">DOM</wikipedia>
<classname>LSResourceResolver</classname> will fallback to the
XML catalog resolver code,</para>
</listitem>
<listitem>
<para xml:id='p9'>the <wikipedia>StAX</wikipedia>
<classname>XMLResolver</classname> will fallback to the
XML catalog resolver code,</para>
</listitem>
<listitem>
<para xml:id='p10'>the <wikipedia page="Simple_API_for_XML">SAX</wikipedia>
<classname>EntityResolver2</classname> will fallback to the
XML catalog resolver code, and</para>
</listitem>
<listitem>
<para xml:id='p11'>the SAX <classname>EntityResolver</classname> will always use the
XML catalog resolver code.</para>
<para xml:id='p12'>This is where the rules are broken. Because there's no way for the
SAX <classname>EntityResolver</classname> to indicate that it didn't succeed,
I never let the application specify one. Any attempt to do so is ignored
and the XML catalog resolver is always used.</para>
</listitem>
<listitem>
<para xml:id='p13'>The <classname>NamespaceResolver</classname> isn't actually used by anyone
yet, so there's no hook for it in the platform. Any application that uses it
will be using the XML catalog resolver code, at least for now.</para>
</listitem>
</itemizedlist>

</section>
<section xml:id="thecatch">
<title>The catch</title>

<para xml:id='p14'>There is a catch. You knew there would be a catch, didn't you?
The catch is that I constructed these specialty factories by stealing code
from the JAXP 1.4 implementation. But I didn't want to steal <emphasis>all</emphasis>
the code, so the result <emphasis>depends on</emphasis> JAXP 1.4.</para>

<para xml:id='p15'>In practice, this means that you'll need to be running at least
<link xlink:href="http://java.sun.com/javase/">Java 6</link> or
using the standalone
<link xlink:href="http://jaxp.dev.java.net/">JAXP 1.4</link> code developed
in the <wikipedia>GlassFish</wikipedia> Community.</para>

</section>
<section xml:id="howto">
<title>Making it work</title>

<para xml:id='p16'>To try out this new feature, you do need to do a few things (sorry,
Santiago, <wikipedia page="Tanstaafl">TANSTAAFL</wikipedia>):</para>

<orderedlist>
<listitem>
<para xml:id='p17'>Make sure that you're using JAXP 1.4, either because you're
using Java 6 or because you've got the JAXP 1.4 jar files in one of your
<property>java.endorsed.dirs</property>.</para>
</listitem>
<listitem>
<para xml:id='p18'><link xlink:href="https://xmlresolver.dev.java.net/servlets/ProjectDocumentList?folderID=6890&amp;expandFolder=6890&amp;folderID=6847">Download</link>
both the <citetitle>XML Resolver</citetitle> and the
<citetitle>XML Resolver JAXP 1.4 Factories</citetitle> from the
<link xlink:href="http://xmlresolver.dev.java.net/">XMLResolver project</link>.
</para>
</listitem>
<listitem>
<para xml:id='p19'>Put both of those jar files on your class path.</para>
</listitem>
<listitem>
<para xml:id='p20'>Run your Java application with the following system property settings:</para>
<screen>javax.xml.parsers.SAXParserFactory=org.xmlresolver.sunjaxp.jaxp.SAXParserFactoryImpl
javax.xml.stream.XMLInputFactory=org.xmlresolver.sunxml.stream.XMLInputFactoryImpl
javax.xml.parsers.DocumentBuilderFactory=org.xmlresolver.sunjaxp.jaxp.DocumentBuilderFactoryImpl</screen>
</listitem>
</orderedlist>

<para xml:id='p21'>I haven't setup a special factory for the Transformer yet, so you'll still
have to tell your application which URI Resolver to use if you're using XSLT.
(I might fix that as well, depending on just how many classes I have to copy to
make that work.)</para>

<para xml:id='p22'>Naturally, I don't expect these alternate factories to have any consequences
except improved resolver support. If you do have trouble, please let me know.
</para>

</section>

<section xml:id="changes">
<title>Other Changes</title>

<para xml:id='p23'>The other significant change I made was to enable caching by
default. This means that you don't need to have a properties file,
there are sensible defaults for all of the properties including the
cache. The cache directory defaults to
<filename>.xmlresolver/cache</filename> in your home directory. Of
course, you can still override all the defaults with property
settings.
</para>

<para xml:id='p24'>If you only care about the updated resolver and don't want to try
the factories trick, you only need the <citetitle>XML Resolver</citetitle> jar file;
you can ignore the <citetitle>XML Resolver JAXP 1.4 Factories</citetitle>.
</para>

</section>

<section xml:id="debugging">
<title>Debugging</title>

<para xml:id='p25'>The resolver uses the 
<package xlink:href="http://java.sun.com/javase/6/docs/api/java/util/logging/package-summary.html">java.util.logging</package> framework.
By default, it only logs those few messages of priority “info” or higher to
the console.</para>

<para xml:id='p26'>If you want more details, specify the <property>verbosity</property> property
(either in a properties file or as a system property,
<property>xml.catalog.verbosity</property>). A setting of “fine” or even “finer”
will give much more information about what the resolver is doing.</para>

<para xml:id='p27'>Note that the Java console logger will only print messages of priority
“info” or higher too, so if you want to see the finer messages, you also have
to tell <emphasis>the logger</emphasis> to allow them through. I use</para>

<screen>java.util.logging.config.file="<link xlink:href="examples/logging.properties">/home/ndw/java/logging.properties</link>"</screen>

<para xml:id='p28'>Setting this information in two places is confusing and I'll probably unify
it all into the logging framework for the next release.</para>

<para xml:id='p29'>It all works for me, but I've been hacking pretty hard.
Feedback of any sort is always welcome.</para>
</section>

</essay>
