我们的一个Web应用程序,它已经在我们的生产环境中运行了很长时间,最近在出现大量事务时遇到了一个奇怪的错误。我们无法弄清楚问题的根本原因究竟是什么,但我们在之前的版本WebSphere 6中发现了一些与应用服务器使用的Xalan版本中的错误相关的类似问题。我们的应用服务器实际上是WebSphere 7,它应该已经修复了,除了它不再使用Xalan。我们的应用程序也没有嵌入Xalan jar。 要修复它,我们只需重新启动应用程序本身。 一个重要的注意事项是文档正在被缓存(docs.get(tableName))并重用以执行XPath评估。我们这样做是为了避免每次解析文档的成本。
应用代码
Document doc = null;
try {
doc = docs.get(tableName);
if (doc == null)
return null;
XPathFactory xFactory = XPathFactory.newInstance();
XPath xpath = xFactory.newXPath();
XPathExpression expr = xpath.compile(toUpper(xPathQuery));
Object result = expr.evaluate(doc, XPathConstants.NODESET);
return (NodeList) result;
} catch (XPathExpressionException e) {
logger.error("Error executing XPath", e);
}
错误堆栈在这里
javax.xml.transform.TransformerException: Unknown error in XPath.
at java.lang.Throwable.<init>(Throwable.java:67)
at javax.xml.transform.TransformerException.<init>(Unknown Source)
at org.apache.xpath.XPath.execute(Unknown Source)
at org.apache.xpath.jaxp.XPathExpressionImpl.evaluate(Unknown Source)
Caused by: java.lang.NullPointerException
at org.apache.xerces.dom.ElementNSImpl.getPrefix(Unknown Source)
at org.apache.xml.dtm.ref.dom2dtm.DOM2DTM.processNamespacesAndAttributes(Unknown Source)
at org.apache.xml.dtm.ref.dom2dtm.DOM2DTM.nextNode(Unknown Source)
at org.apache.xml.dtm.ref.DTMDefaultBase._nextsib(Unknown Source)
at org.apache.xml.dtm.ref.DTMDefaultBase.getNextSibling(Unknown Source)
at org.apache.xml.dtm.ref.DTMDefaultBaseTraversers$ChildTraverser.next(Unknown Source)
at org.apache.xpath.axes.AxesWalker.getNextNode(Unknown Source)
at org.apache.xpath.axes.AxesWalker.nextNode(Unknown Source)
at org.apache.xpath.axes.WalkingIterator.nextNode(Unknown Source)
at org.apache.xpath.axes.NodeSequence.nextNode(Unknown Source)
at org.apache.xpath.axes.NodeSequence.runTo(Unknown Source)
at org.apache.xpath.axes.NodeSequence.setRoot(Unknown Source)
at org.apache.xpath.axes.LocPathIterator.execute(Unknown Source)
... 16 more
这就是我提到的类似问题。 http://www-01.ibm.com/support/docview.wss?uid=swg1PK42574
Thakns。
答案 0 :(得分:1)
许多人没有意识到DOM不是线程安全的(即使你只是在做读取)。如果要缓存DOM对象,请确保同步对它的所有访问。
坦率地说,这使DOM不适合这种应用程序。我知道我有偏见,但我建议切换到Saxon,它的原生树实现不仅比DOM快得多,而且还是线程安全的。一位用户最近发布了关于在进行此切换时获得100倍性能提升的推文。