Mike M. created CXF-8041:
----------------------------
Summary: Error resolving relative XSD Schema on Tomcat
Key: CXF-8041
URL: https://issues.apache.org/jira/browse/CXF-8041
Project: CXF
Issue Type: Bug
Components: Core, Transports
Affects Versions: 3.3.1
Reporter: Mike M.
Attachments: cxf-tomcat-resource-resolver.zip
We found an issue in a CXF JAX-WS project when running in WSDL-first mode with
schema-validation enabled on Tomcat. The WSDL references an external XSD schema
using a relative path. The WSDL and XSD are bundled with the application and
are present on the classpath.
Expectation:
The XSD should be resolved successfully and schema validation should work.
Actual behavior:
* The resource lookup runs through CXF {{EndpointReferenceUtils}}'
{{SchemaLSResourceResolver}}. This one runs through multiple strategies for
resolving the imported XSD URL to a resource. One of them (currently around
line 150) is an attempt to ask a {{ResourceManager}} for the URL.
* In a Servlet context, this will be handled by CXF's
{{ServletContextResourceResolver}}. This one (currently starting around line
82) will ask the actual {{ServletContext}} for the URL. While doing so, it will
catch and ignore {{MalformedURLException}}s as documented in the
{{ServletContext}} interface as well as {{URISyntaxException}}s (probably
precautionary).
* Entering Tomcat's implementation: the call will go through Tomcat's
{{ApplicationContext}} and end up in the {{StandardRoot}}'s
{{#validate(String)}} method. Unfortunately, while validating the provided URL,
this one throws {{IllegalArgumentException}}s instead of just returning
{{null}}. In our case, since we resolve the XSD schema relative to the WSDL and
need to go up some levels (../../) from it, Tomcat thinks we're trying to
escape the application context and will trigger the
{{IllegalArgumentException}}.
* Unfortunately though, this exception never gets caught and propagates up the
stack back to CXF's {{SchemaLSResourceResolver#resolveResource}}. This method
had several strategies for resolving resources, remember? The annoying part is:
we didn't even need that particular ServletContext strategy for our XSD, and
one of the other methods (classpath lookup) would have resolved the XSD just
fine, *had the ServletContext lookup not thrown the
{{IllegalArgumentException}}*. That uncaught exception however, breaks the
lookup entirely.
Solution proposal:
I think the least invasive solution would be for
{{ServletContextResourceResolver}} to additionally catch
{{IllegalArgumentException}} when calling {{ServletContext#getResource}}. It
already catches {{URISyntaxException}} even though that one isn't documented by
the {{ServletContext}} API. Catching an exception that basically says "Hey,
this argument isn't valid" would be semantically similar imho.
A more drastic approach would be catching all {{RuntimeException}}s from the
Servlet Container in order to fulfill {{ResourceResolver#resolve}}'s contract,
namely: "@return an instance of the resource or null if the resource cannot be
resolved".
Reproducing the error:
I attached a sample project to this ticket that reproduces the issue. Make sure
to follow the instructions in its README.md.
--
This message was sent by Atlassian JIRA
(v7.6.3#76005)