Skip to content

Migration to v4

v4 is a breaking release built on Spring Boot 4 / Spring Framework 7. This site documents v4 — if you stay on Spring Boot 3, use the latest 3.5.x release and the GitHub wiki.

v3.5.x v4.x
Java 17+ 17+
Spring Boot 3.x 4.x
Jackson 2.x (com.fasterxml.jackson) 3.x (tools.jackson)

Core and databind moved to the tools.jackson.* packages — only the annotations stay at com.fasterxml.jackson.annotation (as intended by Jackson 3). If you registered custom serializers for commons types, port them to the new ValueSerializer / ValueDeserializer base classes.

Error bodies are now problem details delivered as application/problem+json. message was renamed to detail; the new optional members type, title and instance were added. The fields validation map stays as an extension member:

// before (v3)
{ "status": 400, "message": "invalid form", "fields": { "email": ["not empty"] } }
// after (v4)
{
"type": "urn:problem-type:form-error",
"title": "Bad Request",
"status": 400,
"detail": "invalid form",
"fields": { "email": ["not empty"] }
}

Migration aids:

  • Java consumers can keep calling the deprecated getMessage() bridge for a transition period — it delegates to detail.
  • Inbound payloads with the old message key still deserialize (@JsonAlias).
  • Recommendation: also enable spring.mvc.problemdetails.enabled=true so Spring’s own errors (unknown route, 405, malformed JSON) render as problem+json too.

Switched from org.springframework.lang.Nullable to JSpecify (org.jspecify.annotations.Nullable) — in line with Spring Framework 7 itself.

Removed Replacement
BaseRestResource, BaseController plain RestTemplate/HTTP-interface clients + BasicResponseErrorHandler; shared Api interfaces
QueryParamBuilder, QueryParamParser, UrlParts Spring’s UriComponentsBuilder
EntityWithKeyValue, HasKeyValue, HasFirstAndLastName model helpers model your own types
commons-rest-posthog module + @PostHogCapture/@PostHogProperty annotations use the official PostHog Java SDK directly

The old v3 deprecation note on BadRequestExceptionHandler (“will get replaced by javax.ws.rs.BadRequestException”) was dropped — JAX-RS never made sense in a Spring MVC app. BadRequestException stays a first-class citizen for checks bean validation can’t express.

Clients generated with a 4.0.0 milestone before M5 do not compile. The folder layout is unchanged — src/clients, src/hooks and src/model stay where they were — so there is nothing to restructure. Delete the generated output and generate it again.

Both generation routes wrote cross-folder imports one level too deep: ../../model instead of ../model, which pointed outside src/ and resolved to nothing. That default is corrected.

The zip download was broken beyond that. It rendered the templates through its own code path, which never ran the model generator, so src/model/types.ts and src/model/zod-schemas.ts were missing from the archive even though model/index.ts re-exported them. With no generated types to map against, ordinary DTOs came out as Java names — PageableResult<Activity> was emitted as io.rocketbase.commons.dto.PageableResult<io.rocketbase.commons.openapi.sample.dto.Activity>. The endpoint now delegates to generateClientToFileSystem and zips its output, so both routes produce the same files. That also brings useApi into the zip’s clients/index.ts, where the file-system route already had it.

Clients built with generateClientToFileSystem (including StandaloneClientGenerator) were unaffected by that second defect — they always carried their models and resolved type names.

One generated signature changed. React Query v5 infinite hooks for methods that take only paging parameters now accept the filter their queryOptions counterpart always expected:

// before
useInfiniteActivityGetAll(options)
// now
useInfiniteActivityGetAll(filter, options)

This needs an endpoint annotated @InfiniteHook whose only parameter is a Pageable — add any query field of your own and you were already on the correct branch, as useInfiniteActivityFindAll was. A TypeScript error at the call site tells you which hooks, if any, are affected.

  1. Upgrade to Spring Boot 4 first (with your app still on commons-rest 3.5.x it will fail — do both together).
  2. Bump io.rocketbase.commons:* to 4.0.0.
  3. Replace com.fasterxml.jackson.databind/core imports with tools.jackson.*.
  4. Search for getMessage() calls on ErrorResponse — switch to getDetail().
  5. Update API consumers/tests that assert on the old error JSON (message → detail).
  6. Enable spring.mvc.problemdetails.enabled=true.
  7. Regenerate every TypeScript client and adjust paging-only useInfinite* calls (see above).