JSP - TransformerFactory.newInstance().newTransfor

2019-05-25 21:09发布

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.catalina.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).

标签: java xml jsp xslt
4条回答
对你真心纯属浪费
2楼-- · 2019-05-25 21:50

The input stream is empty.

查看更多
手持菜刀,她持情操
3楼-- · 2019-05-25 21:50

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?

查看更多
SAY GOODBYE
4楼-- · 2019-05-25 22:04

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.

查看更多
混吃等死
5楼-- · 2019-05-25 22:15

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.

查看更多
登录 后发表回答