Browse documentation

Version Upgrades

QQQ 4.0 release status, dependency coordinates, breaking changes, and upgrade checks.

QQQ 4.1 release candidate

QQQ 4.1.0-RC.1 pairs with Next 1.0.0-RC.11, served by default. Use the RC quickstart for exact versions, prerequisites and accepted limitations. Import com.kingsrook.qqq:qqq-bom-pom:4.1.0-RC.1 to align framework modules and Next; the optional Material dashboard remains separately versioned. Applications with only the Material jar retain it, and applications with both can select Material using -Dqqq.javalin.frontend=material.

The candidate includes ESB integration and the reviewed framework, authentication and sample changes in its release notes. Trusted Java/SYSTEM Mongo type behavior is preserved. Record-script Test mode still executes explicit writes against live data; the warning and tests do not sandbox Java or external services. Use synthetic test data.

QQQ 4.0 remains the stable release. Each newer published Next RC is paired with a new immutable QQQ 4.1 RC; final general availability is a separate decision. The existing 4.0 migration instructions follow.

4.0 release status

QQQ 4.0.0 is available, with source tagged v4.0.0. Use an exact published version and verify availability in Maven Central.

Release contents

Component4.0 release version or scope
QQQ core4.0.0; 18 coordinates: two POMs and 16 JAR modules
BOMcom.kingsrook.qqq:qqq-bom-pom
QBit build parentcom.kingsrook:qbit-build-parent:2.0.0; imports core 4.0.0
Material Dashboard0.41.0, independently versioned
Sample and starterSource applications for the matching QQQ version
QBit templatesApplication, data, and extension scaffolds

Existing production QBits, qctl, and frontend replacement work are outside this release train. A catalog entry is not proof of 4.0 compatibility. Check each dependency's release notes, POM, and tests.

Breaking changes

  • Javalin packages move from com.kingsrook.qqq.backend.javalin to com.kingsrook.qqq.middleware.javalin.
  • PicoCLI packages move from com.kingsrook.qqq.frontend.picocli to com.kingsrook.qqq.middleware.picocli.
  • Deprecated APIs are removed; update overrides and method calls to their replacement signatures.
  • API-shape cleanups affect context handling, filters, field conversions, backend variants, metadata customizers, route providers, builders, and related utilities.
  • Use the tagged 4.0 migration guide together with the changelog.

    Migration highlights

    The following highlights describe the 4.0.0 release. Consult the tagged source manual for the complete per-API contract and provider limitations.

    Javalin registration

    QQQ 4.0 uses Java 21, Javalin 7.2.3 and Jetty 12.1.13. Register routes and before/after/error handlers during configuration. Move provider registration from acceptJavalinService(Javalin) to acceptJavalinConfig(JavalinConfig), using config.routes. Replace direct config.router.apiBuilder(...) calls with config.routes.apiBuilder(...); EndpointGroup keeps its package and signature.

    For a server-level registration callback, replace a route-registering withJavalinConfigurationCustomizer call with:

    Java
    server.withJavalinConfigCustomizer(config ->
       config.routes.get("/custom/status", ctx -> ctx.result("ready")));

    The older service customizer and acceptJavalinService remain observation hooks; they cannot register Javalin 7 handlers. Preserve authentication and path scopes when moving handlers. Default process-backed routes now supply method as a String such as "GET"; use input.getValueString("method"), not a HandlerType cast. Keep both Jetty core and EE10 dependencies aligned through the release's dependency management.

    Data and application behavior

  • Review joined READ permissions and USER-personalized metadata in the interactive record APIs. Exposing a relationship does not grant record access; hidden fields and password masking still apply. The root table name is reserved and cannot also be a join alias; use distinct aliases for self joins.
  • Preserve association omission versus empty replacement. Check child operation grants and returned errors. Recursive writes do not imply automatic batch rollback or distributed atomicity.
  • USER_ID defaults apply on INSERT/UPDATE, including omitted sparse-update values; reads preserve stored blanks. RDBMS DATE/TIME preserve calendar/wall-clock values, while zone-less DATE_TIME storage uses UTC. Existing timestamp data is not rewritten automatically.
  • Metadata directories must contain valid metadata files only; loading errors fail startup. Use the sample acceptance profile for its browser and packaged-launcher checks.
  • Custom backends must review native write lookup and association discovery contracts. MongoDB write lookups require native ObjectId identities; this does not establish full native String-key CRUD. Query, Count and Aggregate retain provider-specific operators, result types and lifecycle limits.
  • Reporting and process defaults

    Application API process calls and built-in saved-report generation retain their SYSTEM defaults. Permission to run a developer-defined named report can authorize its server-defined sources without granting raw-table READ. Setting ReportInput to USER alone does not uniformly propagate source-access checks into nested count/query inputs; applications can configure query policy with DataSourceQueryInputCustomizer. API asynchronous result ownership is bound independently of process input source.

    Automatic report-source propagation, additional source-permission/privacy checks, and application API process provenance changes are deferred in #448 and #451. Saved-report storage/email fields retain their existing editability; the proposed restriction is deferred in #453. Applications remain responsible for the permissions and configuration they expose.

    Additional rendering-ownership and schedule-management policies (#446, #452), cross-instance API process-cache identity (#449) and scheduled caller-session restoration (#450) remain deferred. These deferred changes are not included in 4.0.

    Saved-report storage and failures

    The correction for #458 finishes and closes the generated temporary file before opening the archive destination. It then copies the completed file through the existing StorageAction.createOutputStream API. Custom storage backends need no new method. A generation failure therefore leaves the prior archive untouched; a later copy or destination-close failure can still change it. Atomic replacement is not guaranteed.

    The proposed atomic storeFile storage API (#459), history-validation and primary-error changes (#460), and preserving COMPLETE after delivery failure (#461) are deferred. A caught delivery failure can mark the render FAILED when its history update succeeds, even if archive bytes were already stored. Cancellation requests do not guarantee that generation or delivery stops; additional report/export cancellation boundaries are deferred in #479. Inspect storage before retrying; a failed status does not prove that no file was stored.

    These highlights do not imply all-provider parity or complete sample feature coverage. The 48 source-coverage groups and separate train.bom coverage group (#627) are deferred beyond 4.0 under #534; the feature ledger continues to report those gaps separately from release acceptance.

    Upgrade workflow

    Create an upgrade branch, import the correct BOM, keep the dashboard version explicit, and inspect mvn dependency:tree for mixed framework versions. Run mvn clean verify, then test your packaged application against the intended database and authentication provider. Verify critical processes, API clients, reports, scheduler work, and denied access in staging.

    Validate the exact release with your application before production adoption. Keep an exact artifact version and a recoverable application/data rollback plan. Changing only a POM version cannot reverse schema or data changes.

    Licensing

    Read the LICENSE, NOTICE, and source headers for the exact artifacts and component versions you use. The website does not override those terms or grant a uniform license to every QBit. See Licensing.

    Powered by qqq