Migrating from Martini Runtime v2.x to v3.0
Overview
Martini Runtime v3.0 introduces several breaking changes that require manual action when you upgrade from any Martini Runtime v2.x release. You can upgrade directly to v3.0 from any v2.x version — there's no need to be on the latest v2.8.x release first. This guide walks you through every breaking change, in the recommended order, so you can move your packages and deployments to v3.0 without hitting runtime errors.
What You Will Learn
- Whether you need to manually upgrade your JVM to Java 21, depending on how you run Martini
- How to find and replace
javaxnamespace references with theirjakartaequivalents - How to verify custom library JARs remain compatible with Martini Runtime v3.0
- How to resolve Groovy class-version errors after upgrading
- How to migrate expressions from
$gloopOutputand undocumented workaround properties to the$outputexpression variable - How to move development workflows that relied on Swagger 2.0 to OpenAPI v3
When To Use This
Use this guide when you're planning or performing an upgrade of a Martini package, workspace, or deployment from Martini Runtime v2.x to v3.0. Follow it as a pre-upgrade and post-upgrade checklist, whether you manage Martini Runtime yourself or via Lonti Managed Hosting.
Prerequisites
- Administrative access to the Martini Runtime deployment you're upgrading (self-managed, Docker, or Managed Hosting)
- Martini Designer installed and connected to the workspace you're migrating
- A backup or version-controlled copy of your Martini packages, so you can review and revert changes if needed
Suggested Migration Order
Follow these steps in order for a smooth upgrade from v2.x to v3.0. Some steps only apply to specific deployment types, as noted.
- Upgrade the JVM to Java 21 — only required for on-premise or other manually-managed JVM deployments. See Java 21 Requirement and Deployment-Specific Handling.
- Install or upgrade to Martini Runtime v3.0 — direct upgrade is supported from any v2.x release.
- Find and replace
javaxreferences withjakarta, for affected classes only using Martini Designer's search feature. See Updating javax Namespace References to Jakarta. - Test custom or extra library JARs against Martini Runtime v3.0 running on Java 21, and update or replace any that are incompatible. See Verifying Custom Library JAR Compatibility.
- Update workflow expressions that rely on undocumented workaround properties (such as
$context) to use$outputinstead; optionally migrate$gloopOutputusages in services to$outputas well. See Migrating to the $output Expression Variable. - Review REST APIs that relied on Swagger 2.0 for consumption or generation, and migrate them to OpenAPI v3. See Migrating from Swagger 2.0 to OpenAPI v3.
- If you see class-version errors after upgrading, delete
.classfiles in your Martini packages and restart Martini Runtime. See Resolving Groovy Class-Version Errors After Upgrading.
Java 21 Requirement and Deployment-Specific Handling
Martini Runtime v3.0 requires Java 21, up from Java 11 on v2.x releases. Whether you need to take manual action depends on how you run Martini Runtime.
| Deployment type | Manual Java upgrade required? | Details |
|---|---|---|
| Martini Designer v1.8+ | No | Designer v1.8 and later bundles both Martini Runtime v3 and Java 21 automatically. |
| Docker | No | The Martini Runtime v3.0 Docker image already includes Java 21. |
| On-premise / manually-managed JVM | Yes | You must upgrade the host JVM to Java 21 before installing or starting Martini Runtime v3.0. |
Note: Martini Runtime v3.0 will not run correctly on Java 11. If you manage your own JVM, upgrade it to Java 21 before you install or start Martini Runtime v3.0. For exact specifications, see Server Runtime System Requirements.
Updating javax Namespace References to Jakarta
As part of the move to Java 21, Martini Runtime v3.0 adopts the Jakarta EE namespace for classes defined by a
Jakarta EE specification. This does not mean every javax class reference needs to change. Only classes
that belong to a Jakarta EE specification (servlets, mail, activation, and similar enterprise APIs) were renamed
to their jakarta equivalent. Classes that belong to core Java SE — bundled with the JDK itself rather than
defined by a Jakarta EE specification — keep their javax namespace permanently, since Jakarta EE doesn't own
those packages. javax.crypto is a common example: it's part of the Java Cryptography Extension (JCE) in Java
SE, so it has no jakarta.crypto equivalent and must stay as javax.crypto.
This mainly affects fully-qualified Java or Groovy class names wherever they appear in your package content, including:
- Imports and code in Groovy classes
- Scripts
- Expressions
- Object property class-name fields (configuration fields where you enter a class name, such as object property definitions)
The following table shows illustrative examples of classes that do move to jakarta. It isn't an exhaustive
list of every affected class.
| Old (v2.x) | New (v3.0) |
|---|---|
javax.servlet.http.HttpServletRequest |
jakarta.servlet.http.HttpServletRequest |
javax.servlet.http.HttpServletResponse |
jakarta.servlet.http.HttpServletResponse |
javax.activation.DataSource |
jakarta.activation.DataSource |
javax.mail.Message |
jakarta.mail.Message |
javax.mail.Address |
jakarta.mail.Address |
Java SE Packages That Stay Under javax
The javax namespace isn't exclusive to Jakarta EE — Java SE itself has always shipped core JDK APIs under
javax package names. These Java SE APIs were never part of the Jakarta EE rename, so references to them must
stay as javax on Martini Runtime v3.0. Do not replace the following common examples, or any other javax
class that's part of the JDK rather than a Jakarta EE specification:
| Package | Purpose |
|---|---|
javax.crypto |
Java Cryptography Extension (JCE) — ciphers, key generators, and MAC algorithms |
javax.net and javax.net.ssl |
Socket factories and TLS/SSL support |
javax.sql |
Core JDBC extensions, such as DataSource |
javax.naming |
Java Naming and Directory Interface (JNDI) |
javax.management |
Java Management Extensions (JMX) |
javax.xml.parsers, javax.xml.transform, javax.xml.xpath, javax.xml.validation, javax.xml.datatype |
Core JDK XML processing APIs |
javax.swing |
Desktop GUI toolkit |
javax.sound.* |
Audio capture and playback |
javax.imageio |
Image reading and writing |
javax.security.auth |
Java Authentication and Authorization Service (JAAS) |
javax.script |
Scripting engine support (JSR 223) |
Note: This list isn't exhaustive. Before changing an unlisted
javaxreference, confirm that its API appears in the Jakarta EE specifications and that the targetjakartapackage exists. Java SE packages and independent specifications such as JCache may continue to usejavax.
Finding and Replacing javax References in Martini Designer
Use Martini Designer's workspace search to find every javax reference before you replace it. Replacing text
blindly can touch unrelated content, such as comments or unrelated identifiers, that happens to contain javax.,
as well as genuine Java SE classes that must stay under javax.
- Open Martini Designer's text search feature.
- Search your workspace for all occurrences of the literal string
javax.. - Review each match individually. Confirm it's a genuine Jakarta EE class reference — and not a Java SE class
such as
javax.crypto— before changing it. See Java SE Packages That Stay Under javax for common examples to leave unchanged. - Replace confirmed Jakarta EE matches with
jakarta.. - Restart Martini Runtime.
Expected result: After you replace all genuine Jakarta EE javax occurrences and restart Martini Runtime, it
stops throwing classpath or class-not-found errors caused by the removed javax classes, while Java SE classes
such as javax.crypto continue to resolve correctly.
Verifying Custom Library JAR Compatibility
Martini Runtime v3.0 also upgrades several internal, bundled library dependencies as part of the move to Java 21. If you added extra library JARs to your deployment that only worked on Java 11, or that depended on the specific library versions bundled with Martini Runtime v2.x, you may see breaking behavior on v3.0.
There's no exhaustive list of affected libraries, since this depends entirely on what you've added to your own deployment. Test any custom or extra JARs you rely on against Martini Runtime v3.0 running on Java 21, and update or replace any that are incompatible before you rely on them in production.
Migrating to the $output Expression Variable
Martini Runtime v3.0 introduces a consistent global expression variable, $output, exposed everywhere the
invoked step or node's output data model should be accessible in expressions:
- Services: invoke function steps, invoke service steps
- Workflows: invoke function nodes, invoke service nodes, invoke workflow nodes, and workflow database query nodes
$output references the output data model of the invoked step or node — the same data you previously reached
via $gloopOutput (services) or via undocumented workaround properties (workflows).
Backward Compatibility for Services and Workflows
- Services:
$gloopOutputcontinues to work everywhere it already worked, for example$gloopOutput.response.status == 200in invoke function or invoke service step output mappings. It's now deprecated but not removed in v3.0 — there's no forced migration, but new or updated expressions should use$output. - Workflows: there was no officially supported equivalent before v3.0. If you relied on undocumented
workaround properties — for example
$context— to reach step or node output, you must update those expressions to use$outputinstead. The undocumented properties aren't guaranteed to keep working.
The exact set of undocumented workaround properties beyond
$contextisn't formally enumerated. Treat$contextas a representative example, and audit your workflow expressions for any similar undocumented usage.
Migrating $output Usage Step by Step
- Audit your workflow and service expressions for usages of
$gloopOutputand any undocumented workaround properties, such as$context. - In workflows, replace any undocumented workaround property usage with
$output. - In services, leave
$gloopOutputusages as-is if you prefer — they keep working. Migrating them to$outputis optional but recommended, since$gloopOutputis deprecated.
For more on where $output is available, see Invoke Function Node,
Invoke Service Node,
Invoke Workflow Node, and
Database Query Nodes.
Migrating from Swagger 2.0 to OpenAPI v3
Before v3.0, Martini REST APIs automatically generated a Swagger 2.0 schema for each REST API, in addition to other schema formats. You could also consume a Swagger 2.0 schema to generate a Martini REST API, or generate services that called operations from a Swagger 2.0 schema.
In v3.0, Swagger 2.0 support is removed entirely. You can no longer consume a Swagger 2.0 schema, nor generate a Swagger 2.0 schema from an existing Martini REST API.
Martini REST APIs still offer other schema formats, including OpenAPI v3 — the favored, supported format going forward — and a Postman collection. For any development workflow that previously relied on Swagger 2.0, whether for consuming or generating, use the OpenAPI v3 schema as the replacement.
Note: Martini Designer and Martini Runtime don't include a built-in conversion tool for turning an existing Swagger 2.0 schema into OpenAPI v3. If you have a Swagger 2.0 definition you still need to consume, convert it yourself first, for example with third-party Swagger-2.0-to-OpenAPI-v3 conversion tooling, and then consume the resulting OpenAPI v3 schema in Martini.
For more, see OpenAPI Schema in Martini and Consuming a REST API.
Resolving Groovy Class-Version Errors After Upgrading
Martini Runtime normally recompiles Groovy classes automatically when it detects a new Runtime version. If you encounter class-version-related errors after upgrading to v3.0, resolve them as follows:
- Delete all
.classfiles under your Martini packages. - Restart Martini Runtime to force a clean recompile.
Helpful Resources
- Server Runtime System Requirements — Confirm the Java version and other host requirements for self-managed Martini Runtime.
- OpenAPI Schema in Martini — Learn how to generate and publish an OpenAPI v3 schema for your REST APIs.
- Consuming a REST API — Generate services from an OpenAPI v3, Postman Collection, or RAML specification.
- Function Steps — See how
$outputand$gloopOutputare used in service set expressions. - Community Q&A: Martini Community Have a question? Post or search it here.