Resolve WSDL schema imports offline via jax-ws-catalog - #82
Conversation
wsdl/WinRM.wsdl references three schemas by absolute URL: - http://schemas.dmtf.org/wbem/wsman/1/dsp8033_1.0.xsd - http://schemas.dmtf.org/wbem/wsman/1/dsp8034_1.0.xsd - http://www.w3.org/2001/xml.xsd Apache CXF fetches each over HTTP at every WinRMService.createInstance() call. On offline / air-gapped / restricted-egress hosts the connect() attempt blocks ~75 s per missing schema (OS TCP timeout) and finally throws: javax.wsdl.WSDLException (at /wsdl:definitions/wsdl:types/xs:schema[1]): faultCode=PARSER_ERROR: Problem parsing 'http://schemas.dmtf.org/wbem/wsman/1/dsp8034_1.0.xsd'.: java.net.ConnectException: Connection timed out dsp8034_1.0.xsd is also transitively imported by the bundled xsd/dsp8033_1.0.xsd, so even when dsp8033 resolves locally a network fetch of dsp8034 is still required without this catalog. Fix: - Ship the three missing schemas under src/main/resources/xsd/. - Add META-INF/jax-ws-catalog.xml — auto-discovered by CXF's OASISCatalogManager — mapping all four absolute URLs (dsp8033, dsp8034, xml.xsd, ws-addr.xsd) to the local classpath copies. - Add CatalogResolutionTest verifying OASISCatalogManager returns a non-network URI for each systemId. After this change WinRMService initialization performs no outbound HTTP to schemas.dmtf.org or www.w3.org, eliminating the offline-fetch timeout and removing a silent runtime dependency on DMTF / W3C servers for every WinRM session.
There was a problem hiding this comment.
Pull request overview
This PR addresses runtime WSDL parsing failures and unwanted outbound HTTP requests by providing a JAX-WS OASIS XML catalog that remaps externally-referenced schema URLs in wsdl/WinRM.wsdl to local, bundled XSD resources on the classpath (fixes #81).
Changes:
- Add
META-INF/jax-ws-catalog.xmlto let Apache CXF resolve imported schemasystemIds to localsrc/main/resources/xsd/*copies. - Bundle missing schema resources (
dsp8034_1.0.xsd,xml.xsd,ws-addr.xsd) required to resolve WSDL/XSD imports offline. - Add a JUnit test to verify CXF catalog resolution returns non-network URIs for the relevant schema URLs.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| src/main/resources/META-INF/jax-ws-catalog.xml | Adds OASIS XML catalog entries mapping external schema URLs to bundled classpath XSDs. |
| src/main/resources/xsd/dsp8034_1.0.xsd | Bundles DMTF WS-Management Addressing schema previously fetched from the network. |
| src/main/resources/xsd/xml.xsd | Bundles W3C XML namespace schema previously fetched from the network. |
| src/main/resources/xsd/ws-addr.xsd | Bundles W3C WS-Addressing schema previously fetched transitively from the network. |
| src/test/java/org/metricshub/winrm/CatalogResolutionTest.java | Adds a unit test to validate CXF’s catalog-based resolution avoids http(s) URLs. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| final Bus bus = BusFactory.getDefaultBus(true); | ||
| final OASISCatalogManager catalog = OASISCatalogManager.getCatalogManager(bus); | ||
| assertNotNull(catalog, "CXF OASISCatalogManager must be available"); | ||
|
|
||
| assertResolvesToClasspath(catalog, "http://schemas.dmtf.org/wbem/wsman/1/dsp8033_1.0.xsd", "dsp8033_1.0.xsd"); | ||
| assertResolvesToClasspath(catalog, "http://schemas.dmtf.org/wbem/wsman/1/dsp8034_1.0.xsd", "dsp8034_1.0.xsd"); | ||
| assertResolvesToClasspath(catalog, "http://www.w3.org/2001/xml.xsd", "xml.xsd"); | ||
| assertResolvesToClasspath(catalog, "http://www.w3.org/2006/03/addressing/ws-addr.xsd", "ws-addr.xsd"); |
There was a problem hiding this comment.
Addressed in 22c4fbb: the test now creates a dedicated Bus via BusFactory.newInstance().createBus() and shuts it down with bus.shutdown(true) in a finally block, so it no longer mutates or leaks the JVM-wide default Bus.
| final String resolved = catalog.resolveSystem(systemId); | ||
| assertNotNull(resolved, "catalog did not resolve " + systemId); | ||
| // Must NOT be a network URL — otherwise CXF will still hit the network at runtime. | ||
| assertFalse( | ||
| resolved.startsWith("http://") || resolved.startsWith("https://"), | ||
| "catalog returned a network URL for " + systemId + " -> " + resolved | ||
| ); | ||
| assertTrue(resolved.endsWith(expectedSuffix), "resolved URI does not end with " + expectedSuffix + ": " + resolved); |
There was a problem hiding this comment.
Addressed in 22c4fbb: assertResolvesToClasspath now opens the resolved URI (new URI(resolved).toURL().openStream()) and asserts it is non-empty, so a mistyped catalog mapping pointing at a missing resource fails the test.
- Use a dedicated CXF Bus and shut it down after the assertions instead of mutating the JVM-wide default Bus (avoids leaking CXF resources and test order-dependence) - Verify each catalog-resolved URI actually exists and is readable, not just well-formed Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Summary
Fixes #81.
wsdl/WinRM.wsdldeclares three externalxs:import schemaLocation="http://..."directives. Without a JAX-WS catalog, Apache CXF resolves them withURL.openStream()at everyWinRMService.createInstance(...)call. On hosts that cannot reachschemas.dmtf.org/www.w3.org, the fetch blocks for ~75 s (OS TCP timeout) andconnect()throwsWSDLException(PARSER_ERROR)caused byConnectException: Connection timed out. On hosts that can reach those domains, an outbound HTTP request happens every WinRM session — silent third-party dependency on DMTF / W3C servers.This PR makes WSDL parsing fully self-contained.
Changes
src/main/resources/META-INF/jax-ws-catalog.xml(new) — OASIS XML catalog auto-discovered by CXF'sOASISCatalogManager. Maps the four absolute URLs referenced (directly or transitively) byWinRM.wsdlto local classpath copies underxsd/:http://schemas.dmtf.org/wbem/wsman/1/dsp8033_1.0.xsd→../xsd/dsp8033_1.0.xsdhttp://schemas.dmtf.org/wbem/wsman/1/dsp8034_1.0.xsd→../xsd/dsp8034_1.0.xsdhttp://www.w3.org/2001/xml.xsd→../xsd/xml.xsdhttp://www.w3.org/2006/03/addressing/ws-addr.xsd→../xsd/ws-addr.xsdsrc/main/resources/xsd/dsp8034_1.0.xsd(new, 7 135 bytes) — WS-Management Addressing XML schema (DMTF DSP8034 v1.0.0, 2010-02-19). The WSDL's<xs:import schemaLocation=".../dsp8034_1.0.xsd"/>previously pointed at an absolute URL with no local fallback; the bundleddsp8033_1.0.xsdalso imports this schema, so a network fetch was required even when dsp8033 resolved locally.src/main/resources/xsd/xml.xsd(new, 8 836 bytes) — W3Cxmlnamespace schema, referenced by both the WSDL and the bundledwsman.xsd.src/main/resources/xsd/ws-addr.xsd(new, 5 574 bytes) — W3C WS-Addressing schema, transitively imported bydsp8033_1.0.xsdandtransfer.xsd.src/test/java/org/metricshub/winrm/CatalogResolutionTest.java(new) — verifies CXF'sOASISCatalogManagerresolves each of the foursystemIds to a non-network URI. Runs in <200 ms, no host required.No Java source files are modified. No public API change.
Why a catalog rather than fixing the WSDL?
Editing the WSDL to use relative
schemaLocationvalues would also work, but:@WebServiceClient(wsdlLocation=...)).Verification
mvn test— all 30 tests pass, including the newCatalogResolutionTest:End-to-end verification (separate downstream codebase that consumes this library): scans against a WinRM target on an offline host that previously failed with
WSDLException(PARSER_ERROR) … dsp8034_1.0.xsd … ConnectExceptionnow succeed without any outbound traffic toschemas.dmtf.orgorwww.w3.org.Schema licensing
xml.xsdandws-addr.xsdare W3C Recommendations under the W3C Document License (BSD-style, attribution required); also explicitly intended for redistribution.Each file retains its original copyright header.
Test plan
mvn testpasses on Linux and Windowsprettier:check,checkstyle:check,pmd:checkpass (no formatting / style violations introduced)CatalogResolutionTestverifies catalog wiring without touching the network or requiring a WinRM hostschemas.dmtf.org) — previously failed in 75 s, now succeeds with WSDL fully parsed from classpath