我正在使用CXF提供基于WSDL的Web服务。 CxfServlet在嵌入式Tomcat中运行,而我的wsdl和xsd文件位于类路径中的JAR中。
XSD文件中的导入使用相对路径,例如./../../some.xsd
Web服务已部署并正常运行。
但是,如果尝试启用架构验证,则会收到以下异常:
java.lang.IllegalArgumentException: The resource path [/./../../some.xsd] has been normalized to [null] which is not valid
at org.apache.catalina.webresources.StandardRoot.validate(StandardRoot.java:265)
at org.apache.catalina.webresources.StandardRoot.getResource(StandardRoot.java:212)
at org.apache.catalina.webresources.StandardRoot.getResource(StandardRoot.java:206)
at org.apache.catalina.core.ApplicationContext.getResource(ApplicationContext.java:529)
at org.apache.catalina.core.ApplicationContextFacade.getResource(ApplicationContextFacade.java:201)
at org.apache.cxf.transport.servlet.ServletContextResourceResolver.resolve(ServletContextResourceResolver.java:82)
at org.apache.cxf.resource.DefaultResourceManager.findResource(DefaultResourceManager.java:120)
at org.apache.cxf.resource.DefaultResourceManager.resolveResource(DefaultResourceManager.java:58)
at org.apache.cxf.ws.addressing.EndpointReferenceUtils$SchemaLSResourceResolver.resolveResource(EndpointReferenceUtils.java:150)
at com.sun.org.apache.xerces.internal.util.DOMEntityResolverWrapper.resolveEntity(DOMEntityResolverWrapper.java:117)
at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.resolveEntity(XMLEntityManager.java:1081)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaLoader.resolveDocument(XMLSchemaLoader.java:654)
at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.resolveSchema(XSDHandler.java:2058)
at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.constructTrees(XSDHandler.java:1014)
at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.constructTrees(XSDHandler.java:1126)
at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.constructTrees(XSDHandler.java:1126)
at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.constructTrees(XSDHandler.java:1126)
at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.parseSchema(XSDHandler.java:625)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaLoader.loadSchema(XMLSchemaLoader.java:610)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaLoader.loadGrammar(XMLSchemaLoader.java:569)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaLoader.loadGrammar(XMLSchemaLoader.java:535)
at com.sun.org.apache.xerces.internal.jaxp.validation.XMLSchemaFactory.newSchema(XMLSchemaFactory.java:254)
at org.apache.cxf.ws.addressing.EndpointReferenceUtils.createSchema(EndpointReferenceUtils.java:622)
at org.apache.cxf.ws.addressing.EndpointReferenceUtils.getSchema(EndpointReferenceUtils.java:668)
at org.apache.cxf.interceptor.AbstractInDatabindingInterceptor.setDataReaderValidation(AbstractInDatabindingInterceptor.java:116)
at org.apache.cxf.interceptor.AbstractInDatabindingInterceptor.getDataReader(AbstractInDatabindingInterceptor.java:90)
at org.apache.cxf.interceptor.AbstractInDatabindingInterceptor.getDataReader(AbstractInDatabindingInterceptor.java:95)
at org.apache.cxf.wsdl.interceptors.DocLiteralInInterceptor.handleMessage(DocLiteralInInterceptor.java:92)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308)
at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121)
at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:267)
at org.apache.cxf.transport.servlet.ServletController.invokeDestination(ServletController.java:234)
at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:208)
at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:160)
at org.apache.cxf.transport.servlet.CXFNonSpringServlet.invoke(CXFNonSpringServlet.java:216)
at org.apache.cxf.transport.servlet.AbstractHTTPServlet.handleRequest(AbstractHTTPServlet.java:301)
at org.apache.cxf.transport.servlet.AbstractHTTPServlet.doPost(AbstractHTTPServlet.java:220)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:707)
...
我调试了CXF代码,并得到以下发现:
DefaultResourceManager
具有ServletContextResourceResolver
作为顶部条目,由CXFNonSpringServlet
添加。ServletContextResourceResolver
使用Catalina ApplicationContext.getResource(String path)
方法,该方法又期望path
以/
开头。它将添加此斜杠并引发StandardRoot.validate()
上面列出的异常。DefaultResourceManager
并被EndpointReferenceUtils.createSchema()
方法捕获。即ResourceResolver
中列出的其他ClasspathResolver
个对象(尤其是DefaultResourceManager
)中的任何一个都不用于将XSD加载到类路径之外。如何实现XSD验证运行?
有什么方法可以更改ResourceResolver
的顺序?
已编辑
EndpointReferenceUtils.SchemaLSResourceResolver
类可以很好地解析URL(即newId
包含相对于XSD文件的所需URL)。
但是,它不使用它,因为它无法捕获ResourceManager
引发的异常。ServletContextResourceResolver
如果无法解析XSD并且不应引发异常,则应返回null
。答案 0 :(得分:0)
对于其他可能会陷入困境的人:我能够遵循@Joem的分析,将其进一步发展,并设法在CXF方面获得针对此问题的修复程序。它应该从CXF 3.3.3开始运行(在撰写本文时尚未发布)。