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.
The XSD should be resolved successfully and schema validation should work.
- 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.
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.