JSP - TransformerFactory.newInstance().newTransformer(xsl) returning null?
The java API guarantees that it will never return a null - but for me, it is!
http://download.oracle.com/javase/6/docs/api/javax/xml/transform/TransformerFactory.html#newTransformer(javax.xml.transform.Source)
Relevant code:
xml = new StreamSource(new URL(mondialURL).openStream());
xsl = new StreamSource(new File("/REMOVED/countriesnofilter.xsl"));
result = new StreamResult(new PrintWriter(out));
transformer = TransformerFactory.newInstance().newTransformer(xsl);
transformer.transform(xml, result);
Since xml, xsl and result were made something using new, they -must- contain not null, so it must be transformer that's becoming null. Why is this happening and how can I fix it?
Throws this:
org.apache.jasper.JasperException: Exception in JSP: /dca/ass2/a.jsp:46
43: result = new StreamResult(new PrintWriter(out));
44:
45: transformer = TransformerFactory.newInstance().newTransformer(xsl);
46: transformer.transform(xml, result);
47:
48: %>
49: <INPUT TYPE="SUBMIT" VALUE="Get one country">
Stacktrace:
org.apache.jasper.servlet.JspServletWrapper.handleJspException(JspServletWrapper.java:451)
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:373)
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:329)
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:265)
javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
sun.reflect.GeneratedMethodAccessor50.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
java.lang.reflect.Method.invoke(Method.java:597)
org.apache.catalina.security.SecurityUtil$1.run(SecurityUtil.java:244)
java.security.AccessController.doPrivileged(Native Method)
javax.security.auth.Subject.doAsPrivileged(Subject.java:517)
org.apache.catalina.security.SecurityUtil.execute(SecurityUtil.java:276)
org.apache.catalina.security.SecurityUtil.doAsPrivilege(SecurityUtil.java:162)
root cause
java.lang.NullPointerException
org.apache.jsp.dca.ass2.a_jsp._jspService(a_jsp.java:104)
org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:98)
javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:331)
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:329)
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:265)
javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
sun.reflect.GeneratedMethodAccessor50.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
java.lang.reflect.Method.invoke(Method.java:597)
org.apache.catalina.security.SecurityUtil$1.run(SecurityUtil.java:244)
java.security.AccessController.doPrivileged(Native Method)
javax.security.auth.Subject.doAsPrivileged(Subject.java:517)
org.apache.catalina.security.SecurityUtil.execute(SecurityUtil.java:276)
org.apache.cata开发者_开发百科lina.security.SecurityUtil.doAsPrivilege(SecurityUtil.java:162)
EDIT: It is DEFINITELY the case that the transformer is null somehow. Watch:
org.apache.jasper.JasperException: Exception in JSP: /dca/ass2/a.jsp:49
46:
47: xml.getInputStream();
48: xsl.getInputStream();
49: transformer.reset();
50:
51: //transformer.transform(xml, result);
52:
And it's a null pointer exception again. If it was because xml was null then it would have thrown an NPE at 47.
EDIT2: If I change newTransformer(xsl) to newTransformer() it works, so it's a problem in newTransformer(xsl).
I ran into the same problem, when some of my tests went wrong, after having added a new dependency to the project. Wondering how could this return null when its API says it's impossible, I revised it again:
"Obtain a new instance of a TransformerFactory. This static method creates a new factory instance This method uses the following ordered lookup procedure to determine the TransformerFactory implementation class to load: Use the javax.xml.transform.TransformerFactory system property. ... [lookup order] ... Once an application has obtained a reference to a TransformerFactory it can use the factory to configure and obtain transformer instances."
So, I had a look at TransformerFactory API, too, and it says:
"The system property that determines which Factory implementation to create is named "javax.xml.transform.TransformerFactory". This property names a concrete subclass of the TransformerFactory abstract class. If the property is not defined, a platform default is be used."
As I mentioned, the problem started when I added a new dependency to the project: another project that processes XML documents/signatures. I deleted the dependency, ran the test (that failed with the dependency added) and retrieved the specific class of the TransformerFactory. I added the dependency back and ran the test again: it was a different class now. So, as I supposed, the lookup procedure was instantiating a wrong TransformerFactory implementation, finding it in the added jar.
I didn't want to fix it adding another system property, so I changed the code like that:
private static final String TRANSFORMER_FACTORY_CLASS = "com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl";
TransformerFactory factory = TransformerFactory.newInstance(TRANSFORMER_FACTORY_CLASS, null);
//null for default ClassLoader
and everything worked fine.
This question's answer seems to indicate this will happen when the XSL is invalid, which would explain what I'm currently running into.
In our specific case, an XML editor that was used silently inserted an invisible character in the first position of the file. Printing the first few bytes of the file showed this. Using a more powerful editor, we removed the offending bytes from the file and all was well.
The input stream is empty.
Check whether xml is null/empty before passing it it. I think you'll find it's empty.
e.g. is new StreamSource(new URL(mondialURL).openStream())
returning null or and empty object?
精彩评论