Skip to content

Build and validate SIRI 2.1 on JDK 24+ despite the JDK built-in XML catalog - #39

Merged
vpaturet merged 1 commit into
masterfrom
fix/jdk24-builtin-xml-catalog
Oct 12, 2026
Merged

vpaturet merged 1 commit into
masterfrom
fix/jdk24-builtin-xml-catalog

Conversation

@vpaturet

@vpaturet vpaturet commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor

Problem

The project does not build on JDK 24 or newer, and SiriValidator cannot validate SIRI 2.1 documents on those JDKs either.

JDK 22 introduced a built-in XML catalog in java.xml (JDK-8306055), and JDK 24 added the W3C DTDs and XSDs to it (JDK-8344800). One of its rules is a suffix match that rewrites every schema location ending in XMLSchema.xsd to the JDK's own copy of the XML Schema schema-for-schemas:

<systemSuffix systemIdSuffix="XMLSchema.xsd" uri="schema10/XMLSchema.xsd"/>

The SIRI 2.1 standard ships the W3C xml-namespace schema as xml/2009/01/XMLSchema.xsd, imported from siri_utility/siri_types.xsd. On JDK 24+ that file is shadowed, xml:lang is no longer declared, and loading the schema fails:

src-import.3.1: The namespace attribute, 'http://www.w3.org/XML/1998/namespace', of an <import> element
information item must be identical to the targetNamespace attribute, 'http://www.w3.org/2001/XMLSchema' ...
src-resolve: Cannot resolve the name 'xml:lang' to a(n) 'attribute declaration' component.

The XSDs are part of the standard and are left untouched. Upstream SIRI-CEN uses the same file name.

Changes

Build

  • pom.xml: pass a user catalog (src/main/xjc/siri-2.1-catalog.xml) to XJC through the cxf-xjc-plugin catalog option for the SIRI 2.1 xsdOption. A user catalog takes precedence over the JDK built-in one, so the import resolves to the bundled file.
  • Bump maven-compiler-plugin 3.8.0 → 3.16.0, using <release>11</release> instead of source/target. The bytecode target is unchanged.
  • Bump cxf-xjc-plugin 4.0.0 → 4.2.0.

Runtime

  • New RelativeSchemaResourceResolver, set on the SchemaFactory in SiriValidator. It resolves schema imports relative to their base URI (file or jar URLs) without consulting catalogs. Without it, SIRI 2.1 validation throws on JDK 24+ for consumers of the published jar. This affects the released 2.0.6 as well.
  • The resolver returns an LSInput that carries only the resolved system id; it opens no stream itself. Xerces opens the document, and only if it has not already traversed it, so nothing is leaked for the many schemas that are included or imported more than once.
  • Xerces skips its accessExternalSchema check for any location a resource resolver has resolved: the resolver is the access policy. The resolver therefore only resolves file: and jar: locations, which keeps it inside the bundled schema tree, and returns null for anything else so that Xerces applies its own access check and catalog. The bundled XSDs contain no absolute schema locations outside documentation text, so this path is never taken today.
  • The resolver keeps the deprecated URL(URL, String) constructor on purpose: jar: URIs are opaque, so URI.resolve() returns the relative reference unchanged instead of resolving it. A comment in the code records this.
  • SiriValidator previously rebuilt the whole SIRI schema set (86 XSD files) on every validate() call. Schema is immutable and thread-safe, so one compiled Schema per version is now built lazily through ConcurrentHashMap.computeIfAbsent and reused, as already done for the JAXB contexts. Cache hits take no lock, and a failed build is not cached so a later call retries.

Verification

Run Result
mvn clean install on JDK 25 success, 14 tests pass
mvn clean install on JDK 11 success, 14 tests pass
Validating SIRI 2.0 and 2.1 fixtures on JDK 25 with the schemas loaded from inside the OTP shaded jar (otp-shaded-2.11.0-SNAPSHOT.jar, which bundles siri-java-model 2.0.6), with this PR's two validator classes placed ahead of the jar 2.1 fixtures valid; 2.0 fixture reports the same content errors as 2.0.6

Before the resolver change, SiriXmlTest failed on JDK 25 with the catalog error above, which is how the runtime problem was found. The bundled 2.0.6 fails the same way in the OTP jar run.

Performance (schemas from the OTP jar, 200 timed calls after 50 warm-up calls, median per validate() call)

Document 2.0.6 on JDK 11 2.0.6 on JDK 25 PR on JDK 11 PR on JDK 25
et-2_1.xml (19 KB) 38.1 ms fails 1.6 ms 1.4 ms
vm-2_1.xml (3 KB) 39.6 ms fails 1.4 ms 1.2 ms
et.xml (19 KB, SIRI 2.0) 35.2 ms 41.3 ms 1.6 ms 1.5 ms

The first call still takes about 1.5 s to compile the schema set, now once per version per JVM instead of on every call. Open file descriptors stayed flat over the 250 validations in every configuration.

Notes

  • CI still builds on Java 11 and is unaffected. The plugin bumps are compatible with JDK 11.
  • jdk.xml.jdkcatalog.resolve cannot be used as a workaround: it only governs what happens when the built-in catalog fails to resolve, and does not disable it. See the java.xml module summary, section "JDK built-in Catalog".

@vpaturet vpaturet changed the title fix: build and validate SIRI 2.1 on JDK 24+ despite the JDK built-in XML catalog Build and validate SIRI 2.1 on JDK 24+ despite the JDK built-in XML catalog Oct 12, 2026
@vpaturet
vpaturet marked this pull request as ready for review October 12, 2026 09:01
@vpaturet
vpaturet requested a review from lassetyr October 12, 2026 09:01
@vpaturet
vpaturet marked this pull request as draft October 12, 2026 09:07
@vpaturet
vpaturet removed the request for review from lassetyr October 12, 2026 09:08
@vpaturet
vpaturet force-pushed the fix/jdk24-builtin-xml-catalog branch from d3a99e9 to 57ed676 Compare October 12, 2026 09:26
…XML catalog

JDK 22 introduced a built-in XML catalog in java.xml (JDK-8306055), and
JDK 24 added the W3C DTDs and XSDs to it (JDK-8344800). One of its rules is
a suffix match that rewrites every schema location ending in "XMLSchema.xsd"
to the JDK's own copy of the XML Schema schema-for-schemas. The SIRI 2.1
standard ships the W3C xml namespace schema as xml/2009/01/XMLSchema.xsd,
so on JDK 24+ that file is shadowed and loading the schema fails with
"Cannot resolve the name 'xml:lang'". The XSDs are part of the standard and
are left untouched.

Build: pass a user catalog (src/main/xjc/siri-2.1-catalog.xml) to XJC via the
cxf-xjc-plugin catalog option, so the location resolves to the bundled file.
Also bump maven-compiler-plugin to 3.16.0 with <release>11</release> and
cxf-xjc-plugin to 4.2.0.

Runtime: SiriValidator now sets a RelativeSchemaResourceResolver on the
SchemaFactory that resolves schema imports relative to their base URI without
consulting catalogs. The resolver returns an LSInput that carries only the
resolved system id; Xerces opens the stream itself, only for the documents it
has not already traversed, so nothing is leaked for schemas that are included
or imported more than once. Xerces skips its accessExternalSchema check for
locations a resource resolver has resolved, so the resolver only resolves
file: and jar: locations, which keeps it inside the bundled schema tree, and
leaves anything else to Xerces' own access check and catalog. It keeps the
deprecated URL(URL, String) constructor on purpose: jar: URIs are opaque, so
URI.resolve() cannot resolve relative references against them.

SiriValidator previously rebuilt the whole SIRI schema set on every validate()
call. Schema is immutable and thread-safe, so one compiled Schema per version
is now built lazily via ConcurrentHashMap.computeIfAbsent and reused, as
already done for the JAXB contexts. Cache hits take no lock, and a failed
build is not cached so a later call retries.

Verified with mvn clean install on JDK 25 and JDK 11, and by validating
SIRI 2.0 and 2.1 documents on JDK 25 with schemas loaded from inside the
OTP shaded jar.
@vpaturet
vpaturet force-pushed the fix/jdk24-builtin-xml-catalog branch from 57ed676 to a5e8992 Compare October 12, 2026 10:04
@vpaturet
vpaturet marked this pull request as ready for review October 12, 2026 10:06
@vpaturet
vpaturet merged commit 94e321c into master Oct 12, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant