I may have discovered a bug in jakarta-taglibs-standard-1.1.2. The JSP code <x:transform doc="${onlineevents_archiveDoc}" xslt="${onlineevents_archiveXSLT}"> <x:param name="order" value="${order}" /> </x:transform> is very occasionally causing a NullPointerException, with the following stack trace: java.lang.NullPointerException *** org.apache.taglibs.standard.tag.common.xml.TransformSupport.addParameter(TransformSupport.java:221) *** org.apache.taglibs.standard.tag.common.xml.ParamSupport.doEndTag(ParamSupport.java:74) *** org.apache.jsp.onlineevents.archive.default_jsp._jspx_meth_x_param_0(default_jsp.java:546) *** org.apache.jsp.onlineevents.archive.default_jsp._jspx_meth_x_transform_0(default_jsp.java:515) *** org.apache.jsp.onlineevents.archive.default_jsp._jspService(default_jsp.java:206) *** org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:97) *** javax.servlet.http.HttpServlet.service(HttpServlet.java:802) *** org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:332) *** org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:314) *** org.apache.jasper.servlet.JspServlet.service(JspServlet.java:264) *** javax.servlet.http.HttpServlet.service(HttpServlet.java:802) *** org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:252) *** org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173) *** org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213) *** org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:178) *** org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:126) *** org.apache.catalina.cluster.tcp.ReplicationValve.invoke(ReplicationValve.java:346) *** org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105) *** org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:107) *** org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:148) *** org.apache.coyote.ajp.AjpAprProcessor.process(AjpAprProcessor.java:425) *** org.apache.coyote.ajp.AjpAprProtocol$AjpConnectionHandler.process(AjpAprProtocol.java:452) *** org.apache.tomcat.util.net.AprEndpoint$Worker.run(AprEndpoint.java:1285) *** java.lang.Thread.run(Thread.java:595) Looking at the source of TransformSupport, I see the offending method is: public void addParameter(String name, Object value) { t.setParameter(name, value); } implying that instance variable 't' (of type javax.xml.transform.Transformer) is set to null - which suggests some kind of weird bug where it is either overwritten or not initialised properly. I'm a bit stuck as I can't reproduce this myself; it seems to be occurring at random several times a day on my production site. I had thought it was a concurrency issue and have tried wrapping the call to <x:transform> in a synchronized block, just in case, but it hasn't made any noticeable difference. The server information is: Tomcat 5.5.17 JVM: Sun 1.5.0_07-b03 OS: SunOS 5.9 Arch: sparc
Make sure that ${order} does not evaluate to null. Transformer.setParameter should throw an NPE if the parameter value is null.
(In reply to comment #1) > Make sure that ${order} does not evaluate to null. Transformer.setParameter > should throw an NPE if the parameter value is null. Yes, but the first entry in the stack trace is TransformSupport.addParameter, so doesn't that imply that t is null? Anyway I will add a check of ${order} to eliminate the possibility that it evaluates to null. Rob
OK, the same NPE has occurred, and this time ${order} is definitely not null <% if (pageContext.findAttribute("order")==null) throw new Exception("order==null"); %><x:transform doc="${onlineevents_archiveDoc}" xslt="${onlineevents_archiveXSLT}"> <x:param name="order" value="${order}" /> </x:transform> Rob
(In reply to comment #3) Yeah, I skimmed too quickly. Actually, it looks like ParamSupport.doEndTag would never allow it to be null anyway. I'm having a hard time seeing how the Transformer in TransformSupport could be null though. It's set every time via doStartTag and TransformFactory.newTransformer(Source) is supposed to guarantee a non-null return value...
Feels like a Sherlock Holmes mystery :) Nothing unsets t, so either it's being set to null, or it's not being set in the first place. The latter either because doStartTag is not being called, or because doStartTag is not reaching the 't = ...' line. 1) TransformerFactory breaking contract and returning null. 2) Container breaking contract and not calling doStartTag. 3) doStartTag throwing an Exception which is quietly caught. As nothing unsets t, I don't think concurrency would be at play, unless it's a bug relating to (2) above. I can't see anything in the Tomcat release notes post 5.5.17 about doStartTag. Only suggestion I have is to put tracing into the JSTL classes and try to hunt down which it seems to be.
I faced exactly the same issue... then going to previous JSTL releases, and running the same x:transform, with the same XML & XSL files. The exception was different: javax.xml.transform.TransformerConfigurationException: Impossible de compiler la feuille de style at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl.newTemplates(Unknown Source) at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl.newTransformer(Unknown Source) .... The pb was the malformed XSL file... there was a BOM responsible for bad SAX parsing, after a file edition. What I am sure is 't' can be null if SAX failed to parse the XSL file (don't know if it is the same behavior with bad XML doc parsing), because when I updated my jstl.jar and standard.jar to last 1.1 release afterwards, the previous exception java.lang.NullPointerException org.apache.taglibs.standard.tag.common.xml.TransformSupport.addParameter(TransformSupport.java:221). went back. I hope it helps, Nicolas
Resolving as I can't see how the code could be NPE'ing there and we needed more info to get any further.