0

I have created a web app that uses the Saxon library for XSLT transformations. This application works well when the web application is deployed on Tomcat using its own name (equal to the name of the subdirectory in the webapps directory). But now I have changed server.xml to use this web application as the root application and now it cannot load the Saxon library.

I think this has something to do with the class loader. I've used the class loader to find configuration files which also broke down when I made this application the tomcat root application. I was able to load the config files using the ServletContext, so that problem was solved.

But now I get the following error:

Caused by: javax.xml.transform.TransformerFactoryConfigurationError: Provider net.sf.saxon.TransformerFactoryImpl not found

which was called using:

TransformerFactory tf = TransformerFactory.newInstance("net.sf.saxon.TransformerFactoryImpl",null);

The changes I made to server.xml (I've added the <Context> element):

  <Host name="localhost"  appBase="webapps"
        unpackWARs="true" autoDeploy="true">

    <!-- SingleSignOn valve, share authentication between web applications
         Documentation at: /docs/config/valve.html -->
    <!--
    <Valve className="org.apache.catalina.authenticator.SingleSignOn" />
    -->

    <!-- Access log processes all example.
         Documentation at: /docs/config/valve.html
         Note: The pattern used is equivalent to using pattern="common" -->
    <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
           prefix="localhost_access_log." suffix=".txt"
           pattern="%h %l %u %t &quot;%r&quot; %s %b" />
    <Context docBase="foodvoc-pipelines" path="/" reloadable="true"/> 
  </Host>

It seems that tomcat cannot find the SAXON library when the TransformerFactory is created using the class name in the newInstance method.

Can I add a directory (the lib directory in the web app) to the classpath programmatically? Or should I add the SAXON library to another directory (which?) that is used by tomcat in its classpath? Can I create a Saxon TransformerFactory directly (without class loaders)? Or is my configuration to make this application the root application wrong?

Dieudonné
  • 543
  • 1
  • 4
  • 16
  • Where is the SAXON library originally located ? In the web-inf/lib of your web application ? – ramp Jan 28 '15 at 14:17
  • Yes, at webapps/foodvoc-pipelines/WEB-INF/lib/ together with a bunch of other libraries which it is able to find. – Dieudonné Jan 28 '15 at 14:30

1 Answers1

0

I was able to get this working by adding the lib directory in the tomcat webapp programatically to the class loader.

To be honest, I'm not really happy with the solution, but it works...

The path has to be added statically as described in the answer to this question. This is a static method in my FoodVocApplication class.

private static void addPath(File file) throws NoSuchMethodException, MalformedURLException, InvocationTargetException, IllegalAccessException {
    URI u = file.toURI();
    ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
    Class<URLClassLoader> urlclass = URLClassLoader.class;
    Method method = urlclass.getDeclaredMethod("addURL", new Class[]{URL.class});
    method.setAccessible(true);
    method.invoke(classLoader, new Object[]{u.toURL()});
}

This method can then be called during initialisation by:

FoodVocApplication.addPath(new File(webInff, "lib"));

where webInff is a File object pointing to the WEB-INF directory in the webapp.

Community
  • 1
  • 1
Dieudonné
  • 543
  • 1
  • 4
  • 16