CXF:使用JAR文件中的XSD并使用相对导入的模式验证

时间:2018-09-21 13:27:56

标签: java cxf

我正在使用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代码,并得到以下发现:

  1. DefaultResourceManager具有ServletContextResourceResolver作为顶部条目,由CXFNonSpringServlet添加。
  2. ServletContextResourceResolver使用Catalina ApplicationContext.getResource(String path)方法,该方法又期望path/开头。它将添加此斜杠并引发StandardRoot.validate()上面列出的异常。
  3. 此异常通过DefaultResourceManager并被EndpointReferenceUtils.createSchema()方法捕获。即ResourceResolver中列出的其他ClasspathResolver个对象(尤其是DefaultResourceManager)中的任何一个都不用于将XSD加载到类路径之外。

如何实现XSD验证运行? 有什么方法可以更改ResourceResolver的顺序?

已编辑

  • EndpointReferenceUtils.SchemaLSResourceResolver类可以很好地解析URL(即newId包含相对于XSD文件的所需URL)。 但是,它不使用它,因为它无法捕获ResourceManager引发的异常。
  • 我不想仅使用绝对路径作为解析程序错误的解决方法。从我的角度来看,ServletContextResourceResolver如果无法解析XSD并且不应引发异常,则应返回null

1 个答案:

答案 0 :(得分:0)

对于其他可能会陷入困境的人:我能够遵循@Joem的分析,将其进一步发展,并设法在CXF方面获得针对此问题的修复程序。它应该从CXF 3.3.3开始运行(在撰写本文时尚未发布)。

请参阅:https://issues.apache.org/jira/browse/CXF-8041