Stubborn Contract 0.2.0 is released and on Maven Central. Pin the stubborn-contract-dependencies BOM once and every module lines up.
Highlights
The consumer BOM no longer overrides Spring Boot
stubborn-contract-dependencies now manages only Stubborn Contract’s own artifacts, plus
the libraries Spring Boot does not manage — WireMock and REST Assured. Everything else
(Netty, Tomcat, Artemis, ZooKeeper, FreeMarker, httpclient5, icu4j, plexus-utils …) is left
to whichever platform BOM you import.
Before this release the BOM also carried the version pins Stubborn uses for its own CVE
gate. Those pins are correct on the day they are cut and wrong a month later: imported
ahead of spring-boot-dependencies they silently replaced Boot’s managed versions, so a
consumer on a newer Boot patch could be quietly downgraded by us — with Boot 4.1 that meant
a spring-boot-starter-jetty application failing to start. The pins have moved into
Stubborn’s own reactor, where they still gate our build and no longer leak into yours.
Fixes stubborn-sh/stubborn#142.
One deliberate exception: Jetty
Correction, added after this post went out. What this section originally said — that there was no version to pin because no
ee10release works against Jetty core 12.1 — is wrong. Jetty 12.1.x does publish theee10modules, andwiremock-jetty12:3.13.2runs on them. 0.2.1 fixes this properly. The rest of this section describes what 0.2.0 shipped and how to work around it if you are staying on 0.2.0.The failure was never a 12.0-only API in WireMock. It was version skew.
spring-boot-dependenciesimportsjetty-bomandjetty-ee11-bom, so Boot manages Jetty core and the Jakarta EE 11 layer but notorg.eclipse.jetty.ee10, which is the servlet layerwiremock-jetty12is built against. With nothing managing it,ee10resolved to the 12.0.30 thatwiremock-jetty12declares while Boot pulled the core to 12.1.x — and theEnvironment.ensurecall comes fromjetty-ee10-servlet’s ownServletContextHandlerstatic initializer, not from WireMock, so anee10on the core’s line resolves it. Pinning everything to 12.0 cured the skew by dragging the core down, which is exactly what brokespring-boot-starter-jettyapplications.Thanks to @mhalbritter, who tried the
ee10import and showed it works (stubborn-sh/stubborn#142).
wiremock-jetty12:3.13.2 is built against Jetty’s ee10 servlet layer, which Boot does not
manage. Left unmanaged it resolves to 12.0.30, a minor line below the 12.1.x core Boot
manages, and the stub server dies on:
NoSuchMethodError: org.eclipse.jetty.util.component.Environment.ensure(java.lang.String)
WireMock’s shaded standalone distribution was tried as the way out and does not work — it relocates Handlebars, so Stubborn’s own response-template helpers cannot register with it.
So this release’s BOM manages Jetty 12.0.x, and only Jetty. The consequence, stated
plainly: if you import the 0.2.0 BOM, a spring-boot-starter-jetty application runs on
Jetty 12.0.x rather than Boot’s 12.1.x, and may not start at all — Boot’s own ee11 layer
stays at 12.1.x on top of that 12.0.x core.
If you are on 0.2.0, do not exclude the org.eclipse.jetty entries (the original advice
here, now withdrawn — that leaves the stub server on a split classpath). Instead let Boot
keep its Jetty and bring ee10 up to meet it, by importing this ahead of the Stubborn
BOM:
<dependency>
<groupId>org.eclipse.jetty.ee10</groupId>
<artifactId>jetty-ee10-bom</artifactId>
<version>${jetty.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
${jetty.version} comes from spring-boot-starter-parent, so it follows Boot rather than
freezing a version. From 0.2.1 this is unnecessary — the BOM manages ee10 at Boot’s
Jetty line itself and leaves the core alone.
Upgrading from 0.1.x
If you relied on the BOM to pin a third-party library, pin it yourself — or let your platform BOM do it. Import order no longer matters for anything except Stubborn’s own modules, WireMock, REST Assured and Jetty.
The case most likely to bite: Spring Cloud Stream. Spring Cloud ships its own release
train, so spring-boot-dependencies does not manage spring-cloud-stream and this BOM
deliberately no longer does either. If you declare it without a version, import the train
yourself:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2025.1.2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
Dependency updates
- Handlebars (
com.github.jknack:handlebars) 4.5.4 → 4.5.5, which carries a path-traversal fix in its classpath template loader (GHSA-pvrx-3g7m-fpgv) - REST Assured 6.0.1 → 6.2.0
- Tomcat 11.0.26 → 11.0.27
- Quarkus
quarkus-test-common3.38.1 → 3.40.1
A note on the changelog below: #244 added a
stubborn-contract-starter-stub-runner-standalonestarter and #246 removed it again before this release. It relocated Handlebars, which stopped Stubborn’s own response-template helpers from registering. It is not part of 0.2.0 — don’t go looking for it on Central.
Use it
Pin the BOM once and every Stubborn Contract module lines up:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>sh.stubborn</groupId>
<artifactId>stubborn-contract-dependencies</artifactId>
<version>0.2.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
All libraries are on Maven Central.
Standalone stub runner
Prefer running the stub runner as a server? Download
stubborn-contract-stub-runner-app-0.2.0-exec.jar below (SHA-256 alongside) and run:
java -jar stubborn-contract-stub-runner-app-0.2.0-exec.jar
This executable jar is published here rather than to Maven Central.
What’s Changed
- build(deps): bump org.apache.maven.plugins:maven-plugin-plugin from 3.15.2 to 3.16.0 by @dependabot[bot] in https://github.com/stubborn-sh/stubborn-contract/pull/239
- build(deps): bump actions/upload-artifact from 7.0.1 to 7.0.2 by @dependabot[bot] in https://github.com/stubborn-sh/stubborn-contract/pull/238
- build(deps-dev): bump org.apache.maven.plugins:maven-failsafe-plugin from 3.5.6 to 3.6.0 by @dependabot[bot] in https://github.com/stubborn-sh/stubborn-contract/pull/237
- build(deps): bump the rest-assured group across 1 directory with 2 updates by @dependabot[bot] in https://github.com/stubborn-sh/stubborn-contract/pull/236
- build: stop managing Spring Boot’s versions from the consumer BOM by @marcingrzejszczak in https://github.com/stubborn-sh/stubborn-contract/pull/243
- build: add a standalone stub runner starter, and repurpose the Jetty one onto it by @marcingrzejszczak in https://github.com/stubborn-sh/stubborn-contract/pull/244
- build(deps): bump tomcat.version from 11.0.26 to 11.0.27 by @dependabot[bot] in https://github.com/stubborn-sh/stubborn-contract/pull/240
- build(deps): bump io.quarkus:quarkus-test-common from 3.38.1 to 3.40.1 by @dependabot[bot] in https://github.com/stubborn-sh/stubborn-contract/pull/241
- build(deps): bump actions/setup-java from 6.0.1 to 6.1.0 by @dependabot[bot] in https://github.com/stubborn-sh/stubborn-contract/pull/242
- build: clear the OWASP gate on the handlebars.js vendored in handlebars.java by @marcingrzejszczak in https://github.com/stubborn-sh/stubborn-contract/pull/245
- build: restore the Jetty pin in the consumer BOM, and drop the shaded stub runner by @marcingrzejszczak in https://github.com/stubborn-sh/stubborn-contract/pull/246
Full Changelog: https://github.com/stubborn-sh/stubborn-contract/compare/v0.1.3…v0.2.0