[ 
https://issues.apache.org/jira/browse/CXF-8041?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Mike M. updated CXF-8041:
-------------------------
    Description: 
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.

  was:
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.


> 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.
>            Priority: Major
>         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)

Reply via email to