我需要修改一个有多个命名空间的xml文档。我的代码在我的本地机器上运行没有问题,但是当我将它部署到IBM Websphere应用程序服务器时,我遇到了java.lang.IncompatibleClassChangeError。
我正在使用xercesImpl-2.8.1.jar和xalan-2.7.0.jar。 是什么导致了这个错误,我该如何解决?或者,是否有其他方法可以使用命名空间支持修改xml文档?
代码:
System.setProperty("javax.xml.parsers.DocumentBuilderFactory", "org.apache.xerces.jaxp.DocumentBuilderFactoryImpl");
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
DocumentBuilder db = dbf.newDocumentBuilder();
org.w3c.dom.Document doc = db.parse(new java.io.FileInputStream("c:/test.xml"));
System.setProperty("javax.xml.xpath.XPathFactory", "org.apache.xpath.jaxp.XPathFactoryImpl");
XPathFactory xf = XPathFactory.newInstance();
XPath xpath = xf.newXPath();
xpath.setNamespaceContext(new MyNamespaceContext());
// get the node for editing
String xpathExpr = ...
org.w3c.dom.Node n = (org.w3c.dom.Node)xpath.compile(xpathExpr).evaluate(doc, XPathConstants.NODE); // IncompatibleClassChangeError here
异常堆栈跟踪:
java.lang.IncompatibleClassChangeError
at org.apache.xpath.jaxp.JAXPPrefixResolver.getNamespaceForPrefix(JAXPPrefixResolver.java:45)
at org.apache.xpath.compiler.Lexer.mapNSTokens(Lexer.java:587)
at org.apache.xpath.compiler.Lexer.tokenize(Lexer.java:265)
at org.apache.xpath.compiler.Lexer.tokenize(Lexer.java:96)
at org.apache.xpath.compiler.XPathParser.initXPath(XPathParser.java:110)
at org.apache.xpath.XPath.<init>(XPath.java:176)
at org.apache.xpath.XPath.<init>(XPath.java:264)
at org.apache.xpath.jaxp.XPathImpl.compile(XPathImpl.java:394)
at com.ibm._jsp._xml._jspService(_xml.java:94)
at com.ibm.ws.jsp.runtime.HttpJspBase.service(HttpJspBase.java:87)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:856)
at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1146)
at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:592)
at com.ibm.ws.wswebcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:525)
at com.ibm.wsspi.webcontainer.servlet.GenericServletWrapper.handleRequest(GenericServletWrapper.java:122)
at com.ibm.ws.jsp.webcontainerext.AbstractJSPExtensionServletWrapper.handleRequest(AbstractJSPExtensionServletWrapper.java:232)
at com.ibm.ws.webcontainer.webapp.WebApp.handleRequest(WebApp.java:3548)
at com.ibm.ws.webcontainer.webapp.WebGroup.handleRequest(WebGroup.java:269)
at com.ibm.ws.webcontainer.WebContainer.handleRequest(WebContainer.java:831)
at com.ibm.ws.wswebcontainer.WebContainer.handleRequest(WebContainer.java:1478)
at com.ibm.ws.webcontainer.channel.WCChannelLink.ready(WCChannelLink.java:133)
at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleDiscrimination(HttpInboundLink.java:458)
at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleNewInformation(HttpInboundLink.java:387)
at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.ready(HttpInboundLink.java:267)
at com.ibm.ws.ssl.channel.impl.SSLConnectionLink.determineNextChannel(SSLConnectionLink.java:1037)
at com.ibm.ws.ssl.channel.impl.SSLConnectionLink$MyReadCompletedCallback.complete(SSLConnectionLink.java:644)
at com.ibm.ws.ssl.channel.impl.SSLReadServiceContext$SSLReadCompletedCallback.complete(SSLReadServiceContext.java:1818)
at com.ibm.ws.tcp.channel.impl.AioReadCompletionListener.futureCompleted(AioReadCompletionListener.java:165)
at com.ibm.io.async.AbstractAsyncFuture.invokeCallback(AbstractAsyncFuture.java:217)
at com.ibm.io.async.AsyncChannelFuture.fireCompletionActions(AsyncChannelFuture.java:161)
at com.ibm.io.async.AsyncFuture.completed(AsyncFuture.java:136)
at com.ibm.io.async.ResultHandler.complete(ResultHandler.java:196)
at com.ibm.io.async.ResultHandler.runEventProcessingLoop(ResultHandler.java:751)
at com.ibm.io.async.ResultHandler$2.run(ResultHandler.java:881)
at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1497)
答案 0 :(得分:2)
我通常的经验法则是IncompatibleClassChangeError意味着编译器在编译时看到的某个类的版本与在运行时加载的同一个类的版本不兼容。堆栈跟踪显示XPath引擎正在对NamespaceResolver进行回调,因此应该集中调查。
答案 1 :(得分:0)
我的猜测是websphere在共享类路径中有另一个版本的xerces或xalan的副本,并且您的应用程序最终使用不同版本的混合。我首先尝试找出websphere使用的版本以及您的应用程序是否适用。
如果您使用的是Java 6,您还可以尝试使用newInstance方法获取类名和类加载器并传递您的webapps context classloader。
答案 2 :(得分:0)
我设法解决了这个问题。这是因为从xml-apis.jar加载了一个类文件(javax.xml.namespace.NamespaceContext
),我也在使用它。
javax.xml.namespace.NamespaceContext
是xml-apis.jar和JRE中的接口。在JRE版本的类中,接口方法都标记为'abstract',但在xml-apis.jar的版本中,接口方法不是抽象的。我相信这会导致二进制兼容性问题导致我遇到的错误。
所以解决我的问题,我改变了我的类加载器配置,在应用程序类加载器之前使用父类加载器,以便使用来自JRE的javax.xml.namespace.NamespaceContext
。