A
Alan Krueger
Greetings,
I've been able to cache Transformer objects in a Tomcat-based servlet
application to avoid unnecessary Transformer rebuilding, except for
certain ones on certain machines. I'm running Tomcat 4.1.27 under
Eclipse 2.1.0 using the Sysdeo Tomcat plugin using j2re1.4.1_02 under
Windows 2000 SP4.
I've digested this down to a small (albeit convoluted) sample that
exhibits the behavior reliably on my development workstation.
Accessing this servlet more than once (hitting reload in the browser)
causes a NullPointerException to be thrown from within the Transformer
object.
Any help in figuring out what we're doing wrong, or what could be
causing this exception, would be greatly appreciated.
Thanks,
Alan Krueger
---begin TestReuseTransformerServlet.java---
import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Text;
public class TestReuseTransformerServlet extends HttpServlet
{
public void init( ServletConfig config ) throws ServletException
{
try
{
myTestTransformer = TransformerFactory.newInstance()
.newTransformer( new StreamSource(
config.getServletContext().getRealPath( "test.xslt" ) )
);
}
catch ( TransformerConfigurationException e )
{
throw new ServletException( "Transformer exception: "
+ e.getMessage(), e );
}
}
public void service( ServletRequest request, ServletResponse
response )
throws ServletException, IOException
{
try
{
Document document = DocumentBuilderFactory.newInstance()
.newDocumentBuilder().newDocument();
Element element = document.createElement( "input" );
document.appendChild( element );
Text text = document.createTextNode( "one" );
element.appendChild( text );
myTestTransformer.transform(
new DOMSource( document ),
new StreamResult( response.getOutputStream() ) );
}
catch ( ParserConfigurationException e )
{
throw new ServletException( "Parser config exception: "
+ e.getMessage(), e );
}
catch ( FactoryConfigurationError e )
{
throw new ServletException( "Factory config exception: "
+ e.getMessage(), e );
}
catch ( TransformerException e )
{
throw new ServletException( "Transformer exception: "
+ e.getMessage(), e );
}
}
Transformer myTestTransformer;
}
---end TestReuseTransformerServlet.java---
---begin test.xslt---
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:variable name="foo">
<xsl:value-of select="/input"/>
</xsl:variable>
<xsl:variable name="otherPath" select="concat( 'test_', $foo,
'.xml')"/>
<xsl:variable name="otherPage" select="document($otherPath)"/>
<xsl:template match="/">
<foo>
<xsl:value-of select="$otherPage/foo/foo[@id='id']/foo[@id='id']"/>
</foo>
</xsl:template>
</xsl:stylesheet>
---end test.xslt---
---begin test_one.xml---
<foo>
<foo id="id">
<foo id="id">one</foo>
</foo>
</foo>
---end test_one.xml---
The exception I get is the following: (nothing snipped because I
wasn't sure what would be significant)
java.lang.NullPointerException
at org.apache.xpath.axes.AxesWalker.setRoot(Unknown Source)
at org.apache.xpath.axes.WalkingIteratorSorted.setRoot(Unknown
Source)
at org.apache.xpath.axes.LocPathIterator.execute(Unknown Source)
at org.apache.xpath.Expression.executeCharsToContentHandler(Unknown
Source)
at org.apache.xalan.templates.ElemValueOf.execute(Unknown Source)
at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(Unknown
Source)
at org.apache.xalan.templates.ElemLiteralResult.execute(Unknown
Source)
at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(Unknown
Source)
at org.apache.xalan.transformer.TransformerImpl.applyTemplateToNode(Unknown
Source)
at org.apache.xalan.transformer.TransformerImpl.transformNode(Unknown
Source)
at org.apache.xalan.transformer.TransformerImpl.transform(Unknown
Source)
at org.apache.xalan.transformer.TransformerImpl.transform(Unknown
Source)
at org.apache.xalan.transformer.TransformerImpl.transform(Unknown
Source)
at TestReuseTransformerServlet.service(TestReuseTransformerServlet.java:51)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:247)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:256)
at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)
at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)
at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)
at org.apache.catalina.core.StandardContext.invoke(StandardContext.java:2416)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:180)
at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643)
at org.apache.catalina.valves.ErrorDispatcherValve.invoke(ErrorDispatcherValve.java:171)
at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:641)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:172)
at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:641)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)
at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:174)
at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)
at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)
at org.apache.coyote.tomcat4.CoyoteAdapter.service(CoyoteAdapter.java:223)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:601)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.processConnection(Http11Protocol.java:392)
at org.apache.tomcat.util.net.TcpWorkerThread.runIt(PoolTcpEndpoint.java:565)
at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:619)
at java.lang.Thread.run(Unknown Source)
I've been able to cache Transformer objects in a Tomcat-based servlet
application to avoid unnecessary Transformer rebuilding, except for
certain ones on certain machines. I'm running Tomcat 4.1.27 under
Eclipse 2.1.0 using the Sysdeo Tomcat plugin using j2re1.4.1_02 under
Windows 2000 SP4.
I've digested this down to a small (albeit convoluted) sample that
exhibits the behavior reliably on my development workstation.
Accessing this servlet more than once (hitting reload in the browser)
causes a NullPointerException to be thrown from within the Transformer
object.
Any help in figuring out what we're doing wrong, or what could be
causing this exception, would be greatly appreciated.
Thanks,
Alan Krueger
---begin TestReuseTransformerServlet.java---
import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Text;
public class TestReuseTransformerServlet extends HttpServlet
{
public void init( ServletConfig config ) throws ServletException
{
try
{
myTestTransformer = TransformerFactory.newInstance()
.newTransformer( new StreamSource(
config.getServletContext().getRealPath( "test.xslt" ) )
);
}
catch ( TransformerConfigurationException e )
{
throw new ServletException( "Transformer exception: "
+ e.getMessage(), e );
}
}
public void service( ServletRequest request, ServletResponse
response )
throws ServletException, IOException
{
try
{
Document document = DocumentBuilderFactory.newInstance()
.newDocumentBuilder().newDocument();
Element element = document.createElement( "input" );
document.appendChild( element );
Text text = document.createTextNode( "one" );
element.appendChild( text );
myTestTransformer.transform(
new DOMSource( document ),
new StreamResult( response.getOutputStream() ) );
}
catch ( ParserConfigurationException e )
{
throw new ServletException( "Parser config exception: "
+ e.getMessage(), e );
}
catch ( FactoryConfigurationError e )
{
throw new ServletException( "Factory config exception: "
+ e.getMessage(), e );
}
catch ( TransformerException e )
{
throw new ServletException( "Transformer exception: "
+ e.getMessage(), e );
}
}
Transformer myTestTransformer;
}
---end TestReuseTransformerServlet.java---
---begin test.xslt---
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:variable name="foo">
<xsl:value-of select="/input"/>
</xsl:variable>
<xsl:variable name="otherPath" select="concat( 'test_', $foo,
'.xml')"/>
<xsl:variable name="otherPage" select="document($otherPath)"/>
<xsl:template match="/">
<foo>
<xsl:value-of select="$otherPage/foo/foo[@id='id']/foo[@id='id']"/>
</foo>
</xsl:template>
</xsl:stylesheet>
---end test.xslt---
---begin test_one.xml---
<foo>
<foo id="id">
<foo id="id">one</foo>
</foo>
</foo>
---end test_one.xml---
The exception I get is the following: (nothing snipped because I
wasn't sure what would be significant)
java.lang.NullPointerException
at org.apache.xpath.axes.AxesWalker.setRoot(Unknown Source)
at org.apache.xpath.axes.WalkingIteratorSorted.setRoot(Unknown
Source)
at org.apache.xpath.axes.LocPathIterator.execute(Unknown Source)
at org.apache.xpath.Expression.executeCharsToContentHandler(Unknown
Source)
at org.apache.xalan.templates.ElemValueOf.execute(Unknown Source)
at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(Unknown
Source)
at org.apache.xalan.templates.ElemLiteralResult.execute(Unknown
Source)
at org.apache.xalan.transformer.TransformerImpl.executeChildTemplates(Unknown
Source)
at org.apache.xalan.transformer.TransformerImpl.applyTemplateToNode(Unknown
Source)
at org.apache.xalan.transformer.TransformerImpl.transformNode(Unknown
Source)
at org.apache.xalan.transformer.TransformerImpl.transform(Unknown
Source)
at org.apache.xalan.transformer.TransformerImpl.transform(Unknown
Source)
at org.apache.xalan.transformer.TransformerImpl.transform(Unknown
Source)
at TestReuseTransformerServlet.service(TestReuseTransformerServlet.java:51)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:247)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:256)
at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)
at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)
at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)
at org.apache.catalina.core.StandardContext.invoke(StandardContext.java:2416)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:180)
at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643)
at org.apache.catalina.valves.ErrorDispatcherValve.invoke(ErrorDispatcherValve.java:171)
at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:641)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:172)
at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:641)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)
at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:174)
at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)
at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)
at org.apache.coyote.tomcat4.CoyoteAdapter.service(CoyoteAdapter.java:223)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:601)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.processConnection(Http11Protocol.java:392)
at org.apache.tomcat.util.net.TcpWorkerThread.runIt(PoolTcpEndpoint.java:565)
at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:619)
at java.lang.Thread.run(Unknown Source)