27 Upgrade
Use this guide to upgrade a Helidon 4 application to Helidon 27.
Before You Start
- Upgrade to latest Helidon 4.5.x release.
- Build and test with JDK 27.
- Remove deprecation warnings in your Helidon 4 build.
- Inventory dependencies that start with
io.helidon.microprofile,io.helidon.jersey,io.helidon.lra, andio.helidon.integrations. - Check whether each
io.helidon.integrationsdependency has a replacement in the Helidon Extensions repository.
MicroProfile
MicroProfile support has been decoupled from Helidon and now releases independently from Helidon MicroProfile. MicroProfile support is not available for Helidon 27 at this time.
If your application uses Helidon MP, CDI, JAX-RS, or MicroProfile specification APIs, keep that application on Helidon 4.5.x until the independent MicroProfile release is available. Do not upgrade those workloads to Helidon 27 unless you are also replacing the MP programming model with Helidon Core APIs.
Java
Helidon 27 requires Java 27.
Update:
- Maven and Gradle toolchains
- CI images
- Runtime container images
- Native image builds
maven-compiler-pluginor Gradle Java language settings
Dependencies
Import the Helidon 27 BOM to update Helidon dependencies to the same version. Then remove dependencies for modules that are no longer present:
helidon-mphelidon-microprofile*helidon-jersey*helidon-lra*helidon-integrations*helidon-tracing-providers-jaegerhelidon-tracing-providers-zipkinhelidon-tracing-providers-opentracinghelidon-tracing-exporter-jaegerhelidon-metrics-prometheushelidon-corshelidon-http-media-gsonhelidon-security-abac-policy-elhelidon-security-providers-google-loginhelidon-security-providers-config-vaulthelidon-webserver-service-common
Use these replacements where applicable:
- CORS:
io.helidon.webserver:helidon-webserver-cors - Metrics endpoint:
helidon-webserver-observe-metrics - Tracing:
helidon-tracing-providers-opentelemetry - Former integrations: use the matching Helidon Extensions release when one is available
For Gson media support and the removed security providers, follow the migration steps
under JSON and Security. Applications using
helidon-webserver-service-common must also update their service implementations
as described under WebServer. Existing SE messaging applications
must migrate their API usage and connector dependencies as described under
Messaging.
Extensions
Helidon 27 no longer releases the former io.helidon.integrations artifacts
from the Helidon repository. Supported integrations are moving to independent
releases from Helidon Extensions.
Import the extension-specific BOM and replace the old coordinates with the new extension coordinates. Each extension is versioned independently.
For most replacement artifacts, apply this rule:
- In the group ID, replace
io.helidon.integrationswithio.helidon.extensions. - In the artifact ID, replace
helidon-integrationswithhelidon-extensions.
For example:
<dependency>
<groupId>io.helidon.extensions.neo4j</groupId>
<artifactId>helidon-extensions-neo4j</artifactId>
</dependency>
The exceptions are:
| Integration | Replacement rule |
|---|---|
| Eureka discovery | Use io.helidon.extensions.eureka:helidon-extensions-eureka-discovery when you need only the Eureka discovery provider. |
| OCI | Add v3 to the group ID and artifact ID. For example, use io.helidon.extensions.oci.v3:helidon-extensions-oci-v3. |
| Vault | Replace vault with hashicorp.vault in the group ID and hashicorp-vault in the artifact ID. For example, use io.helidon.extensions.hashicorp.vault:helidon-extensions-hashicorp-vault. |
Extensions are released on independent schedules. All extensions might not be available initially, but they will be released over time and new extensions will be added.
Helidon Core APIs
Most Helidon Core APIs remain compatible with Helidon 4.5.x code. The most common source changes are from deprecated APIs that were removed in Helidon 27.
Make these changes before upgrading:
- Replace
Header.value()withHeader.get(). - Replace
HostValidatorwithio.helidon.common.uri.UriValidator. - Replace common config bridge usage with
io.helidon.config.Config. - Replace static metrics helper calls with injected
MeterRegistryor, in imperative application code,Services.get(MeterRegistry.class). - Replace static metrics factory calls with injected
MetricsFactoryor, in imperative application code,Services.get(MetricsFactory.class). - Replace tracing global accessors with injected
Traceror, in imperative application code,Services.get(Tracer.class). - Replace direct builder constructors with static
builder()orcreate(...)methods.
After upgrading to Helidon 27, replace old TLS reload APIs that accept Tls with
TlsMaterial. TlsMaterial is new in Helidon 27 and is not available in Helidon 4.x.
Service Registry
@Service.Provider is removed. Replace it with a service scope annotation,
such as @Service.Singleton or @Service.PerLookup, that preserves the intended
lifetime of the service. A class with an @Service.Inject constructor is also
discovered as a service; without an explicit scope it uses @Service.PerLookup.
See Defining Services.
Services created by the registry must obtain dependencies through injection.
Do not replace a static metrics or tracing accessor inside a registry-created
service with Services.get(...). If that service needs programmatic lookup,
inject ServiceRegistry and use that instance. This restriction applies during
construction, lifecycle callbacks, and normal service methods.
Config
Update providers and mapping code to use io.helidon.config.Config, not
io.helidon.common.config.Config.
Config.global(Config) and io.helidon.common.config.GlobalConfig are removed.
For imperative application bootstrap, replace:
Config.global(config);
with:
Services.set(Config.class, config);
Register the configuration before any service resolves it. Config.global()
now returns the Config from the current service registry. If the application
uses a custom registry, register the configuration with that registry. Inside
registry-created services, inject Config instead of using either global
accessor. These registration changes can be made while still on Helidon 4.5.x.
JSON
Gson Media Support
Gson media support moves to Helidon Extensions, with a release planned after
Helidon 27. Replace io.helidon.http.media:helidon-http-media-gson with
io.helidon.extensions.gson:helidon-extensions-gson-media when that extension
release is available. Update explicit GsonSupport imports to
io.helidon.extensions.gson.media.GsonSupport.
See the Gson extension documentation
for the extension version, configuration, and registration details.
JWT and JWK JSON-P APIs
The deprecated JWT and JWK overloads using jakarta.json are removed. Replace
them with the APIs using io.helidon.json before upgrading; the replacements
are available in Helidon 4.5.x.
| Helidon 4 API | Replacement |
|---|---|
Jwt.headerClaim(name) | Jwt.headerClaimValue(name) |
Jwt.payloadClaim(name) | Jwt.payloadClaimValue(name) |
Jwt.payloadClaims() | Jwt.payloadClaimsJson() |
Jwt.headerJson() | Jwt.headerJsonObject() |
Jwt.payloadJson() | Jwt.payloadJsonObject() |
Jwk.create(jakarta.json.JsonObject) | Jwk.create(io.helidon.json.JsonObject) |
Update imports and code that reads or constructs the JSON values returned or
accepted by these methods. The Helidon and Jakarta JSON types are distinct;
they cannot be cast to each other. This change does not remove the separate
helidon-http-media-jsonp and helidon-http-media-jsonb modules.
WebServer
If you use Unix domain sockets, move the socket path from bind-address to
bindings.uds.socket.
Example:
server:
bindings:
tcp:
enabled: false
uds:
socket: "/var/run/my-service.sock"
required: true
Use connectionOptions() instead of removed listener connection config helpers.
Use maxConnections() instead of maxTcpConnections().
The helidon-webserver-service-common module and its RestServiceSettings,
FeatureSupport, and HelidonFeatureSupport APIs are removed. Implement custom
services directly with HttpService and custom HTTP features with HttpFeature,
preserving their route and context-path configuration. Move service-specific
CORS setup to the WebServer CorsFeature or its cors configuration. See
CORS.
HTTP Method Case Sensitivity
Helidon 27 preserves HTTP method text exactly and matches method selectors case-sensitively, with temporary compatibility for the security configuration listed below.
Before upgrading, enable case-sensitive wire parsing on every Helidon 4.5.x listener and test the application with its actual clients:
server:
case-sensitive-methods: true
In Helidon 4.5.x this option affects only inbound HTTP/1.1 and HTTP/2 wire
parsing; configured method selectors retain the 4.x compatibility
normalization. At the same time, replace lowercase or mixed-case built-in method
names such as get with their standard uppercase form such as GET in all
configuration.
This prepares those selectors for the case-sensitive behavior in Helidon 27.
Update at least the following:
- WebServer security path
methods - security provider outbound target
methods - HTTP signature
sign-headersmethod entries and signing outbound targets - automatic metrics path
methodsand tracing pathmethods - WebClient metric
methods - CORS
allow-methods
To ease migration, Helidon 27 temporarily retains compatibility when loading
WebServer security path methods, security provider outbound target methods,
and inbound or outbound HTTP signature sign-headers method selectors from
configuration. A non-uppercase known method matches both the exact configured
token and its uppercase form. For example, get matches get and GET, but
does not match Get; PoSt matches PoSt and POST, but does not match post.
The known methods are GET, POST, QUERY, PUT, DELETE, HEAD, PATCH,
OPTIONS, TRACE, and CONNECT. An already uppercase method matches only
that token, and a custom method such as Follow remains exact.
For HTTP signature sign-headers, an explicit uppercase entry overrides any
generated compatibility entry regardless of configuration order. Without an
explicit uppercase entry, the last configured case variant supplies the signed
headers for their shared uppercase entry. Security path method lists ignore
duplicates; absent or empty lists continue to match all methods.
Loading a non-uppercase known method in these security settings logs a warning. This compatibility will be removed in a future major version, when all method selectors will match only their exact configured token. Use uppercase names now for standard methods.
This compatibility applies only to the security configuration listed above.
Programmatic builder selectors, runtime HTTP method parsing, and selectors in
other modules remain case-sensitive. A programmatic selector for get matches
only the distinct lowercase method get, not GET. OpenTelemetry server
metrics and spans classify only exact known method names; case variants are
reported as _OTHER, and spans preserve the received token in
http.request.method_original.
Method.createCaseSensitive(String) is retained as an alias for compatibility
with Helidon 4 and is deprecated for removal. Use Method.create(String) on
Helidon 27; both methods preserve the exact method text.
The HTTP signatures provider continues to implement the legacy
draft-cavage-http-signatures-03 (request-target) canonicalization, which
lowercases the method before signing. That signed component therefore does not
distinguish method case. The temporary compatibility for security configuration
does not change this canonicalization.
Messaging
Helidon 4 SE messaging used MicroProfile Reactive Messaging types and Reactive
Streams. Helidon 27 replaces that implementation under the same
io.helidon.messaging:helidon-messaging coordinates. Existing SE messaging
applications require source and configuration changes; updating the dependency
version alone is insufficient.
After upgrading the messaging dependency:
- Replace
Messaging.builder()andChanneltopology construction withMessagingGraph.builder()and the graph's named channels. Start and close the resultingMessagingGraphas part of the application's lifecycle. - Replace
Emitter.create(...)with an emitter obtained from the graph or injected for a named channel. ReplaceEmitter.send(...)withemit(...). The new call completes synchronously when the required outputs have completed; it does not return aCompletionStage. Adapt asynchronous completion callbacks and error handling accordingly. - Replace MicroProfile
Messagevalues withio.helidon.messaging.Message. UseMessage.create(...)instead ofMessage.of(...), andentity()instead ofgetPayload(). The new message has noack()ornack()callbacks. Handlers must finish their delivery work before returning and throw on failure; transport acknowledgement is the connector's responsibility. - Replace
mp.messaging.*configuration with themessagingconfiguration model. Declare named connector instances undermessaging.connector, each with atype, then reference an instance name frommessaging.incoming.<channel>.connectorormessaging.outgoing.<channel>.connector. This requires adapting the connector configuration, not only renaming the top-level key. - When loading graph configuration programmatically, pass the
messagingsubtree:.config(rootConfig.get("messaging")). - Replace old
helidon-messaging-*connector artifacts with compatible connectors from Helidon Extensions. Select a connector release built for the new messaging API and follow that release's dependency and configuration documentation; the old connectors are not binary-compatible replacements.
For imperative topologies, replace .listener(...) with .payloadSink(...)
and the payload-mapping .processor(...) overload with .payloadProcessor(...).
Topologies using .publisher(...), .subscriber(...), or the reactive
.processor(...) overloads must also be rewritten. The graph no longer accepts
Reactive Streams publishers, subscribers, or processors:
- Rewrite publishers as
java.util.stream.Streamsources registered with.payloadSource(...)or.messageSource(...), or produce messages through a graph emitter. - Rewrite subscribers as synchronous consumers registered with
.payloadSink(...)or.messageSink(...). - Rewrite reactive processors as synchronous per-item mappings registered with
.payloadProcessor(...)or.messageProcessor(...).
Adapt reactive operators and asynchronous completion to these synchronous contracts; these changes require more than renaming the builder methods.
Custom connectors must implement the new messaging connector and channel SPI. Review retry handling: outputs that completed before a later output failed are not rolled back, so retrying a delivery can repeat their effects.
See the Messaging API and configuration documentation for graph construction, delivery handling, and connector configuration. If a required compatible connector is not yet available, keep that application on Helidon 4.5.x until the connector migration can be completed.
Metrics
Helidon 27 uses Micrometer-backed metrics for Helidon Core. The old Prometheus Java client integration is removed.
Change code as follows:
- Inject or look up
MeterRegistry. - Use meter tags instead of scopes.
- Use
/observe/metricsas the canonical metrics endpoint. - Treat
/observe/metrics/application,/observe/metrics/base, and/observe/metrics/vendoras compatibility paths only. - Look up
gc.timeas aGauge. - Replace
metrics.rest-request-enabledwithmetrics.rest-request.enabled. - Remove
metrics.gc-time-type.
metrics.scoping no longer controls meter registration or output, and the
scope query parameter is ignored. The legacy scope-specific endpoint paths
return the same unscoped metrics as /observe/metrics. Applications that used
scope settings to disable meters or select exported data must replace those
rules and update their scrape configuration; retaining the old settings can
expose meters that were previously excluded. Use ordinary meter tags for
classification and implement the corresponding selection in the metrics
integration. See Metrics Scopes
for the customization and formatter APIs.
Tracing
Use OpenTelemetry. Remove Jaeger, Zipkin, and OpenTracing Helidon provider dependencies.
Also remove io.helidon.tracing:helidon-tracing-exporter-jaeger if the
application uses the Helidon Jaeger gRPC exporter. It is removed independently
of the Jaeger tracing provider. Configure an OpenTelemetry exporter and update
the collector endpoint and protocol to match the selected exporter.
Prefer OTLP export. OpenTelemetry Java 1.65 no longer publishes the Zipkin exporter.
If imperative application bootstrap owns the OpenTelemetry instance, register it before any tracer lookup:
Services.set(OpenTelemetry.class, openTelemetry);
Then inject Tracer into registry-created services. Imperative application
code can use:
Tracer tracer = Services.get(Tracer.class);
Security
HTTP Digest authentication is removed. Replace it with OIDC, HTTP Basic, header assertion, or HTTP signatures.
If you use JWT Provider, plan extra validation. It is retained but is no longer evolved.
The following providers are also removed. Migrate any application that depends on them before upgrading:
| Removed provider | Required application change |
|---|---|
ABAC policy EL (helidon-security-abac-policy-el) | Replace EL policy evaluation with an application-supplied PolicyExecutor or equivalent authorization logic that preserves the existing rules. The policy validator API remains available, but its former EL executor does not. |
Google Login (helidon-security-providers-google-login) | Replace GoogleTokenProvider and its google-login provider configuration with a supported authentication provider, such as OIDC, and adapt token validation and identity mapping. |
Config Vault (helidon-security-providers-config-vault) | Replace the config-vault provider with the HashiCorp Vault extension's secrets and encryption providers, or an application-specific implementation. Update provider configuration and API usage as described below. |
The HashiCorp Vault extension provides KV1, KV2, and Cubbyhole security providers
for secrets, and a Transit security provider for encryption. See the
Vault extension documentation
for dependencies and setup. Migrating from ConfigVaultProvider requires
moving config-backed secrets to Vault and updating secret paths and key
configuration. Migrate existing encrypted data before removing the old
provider; the extension uses Vault's keys and ciphertext format.
DB Client
If your application has a JPMS descriptor and uses Hikari DB client metrics, change:
requires helidon.dbclient.metrics.hikari;
to:
requires io.helidon.dbclient.metrics.hikari;
Maven coordinates and Java packages are unchanged.
Other API Changes
Review these additional changes before upgrading:
- WebClient: deprecated compatibility methods are removed from connection, DNS, and HTTP client configuration APIs.
- Fault Tolerance: deprecated helpers such as
FaultTolerance.config(io.helidon.common.config.Config),executor(Supplier<? extends ExecutorService>),toDelayedRunnable(...), andtoDelayedCallable(...)are removed. - Fault Tolerance: if both
delay-factorand absolutejitterare configured, Helidon 27 applies the delay factor first and then jitter. Earlier releases ignoredjitterin that case. - gRPC: deprecated helper APIs such as
CollectingObserverandResponseHelperare removed. - GraphQL:
@GraphQl.Subscriptionis deprecated. Subscription execution is reserved for future use and is ignored. - Feature metadata: top-level
Aot,Feature,Incubating, andPreviewannotations are removed. Use nested annotations inio.helidon.common.features.api.Features.
Deprecated APIs
Helidon 27 still contains deprecated APIs that compile but should not be used in new code. Treat these as upgrade cleanup items:
- Metrics scopes and scope-aware registry methods
- Static metrics factory and lifecycle methods
- Static meter builders and factory methods
- Tracing global accessors and wrapper aliases
- TLS reload methods that accept
Tls - Security and DB client direct builder constructors
- Old time-unit overloads in reactive, file watcher, and health APIs
- Old config date and time mappers for
Date,Calendar,TimeZone, and related types SecurityContext.atzChecked()- HTTP/1 split receive and send logging accessors
BufferData.asInputStream()HeaderNames.TSV_NAMEandHeaderNames.TSV
Compile with deprecation warnings enabled and replace these APIs before relying on them for long-lived Helidon 27 code.
Third-Party Libraries
Review direct use of these managed libraries:
| Library | Helidon 4.5.x | Helidon 27 | Compatibility notes |
|---|---|---|---|
| HikariCP | 5.0.1 | 7.1.0 | Validate pool behavior and metrics. HikariCP 6 changed some connection eviction and metrics behavior. |
| Micrometer | 1.15.12 | 1.17.1 | Prometheus duplicate meter names are stricter. Duplicate time series errors now use the Prometheus Java client exception type. |
| Micrometer Prometheus | 1.15.2 | 1.17.1 | Review custom Prometheus naming conventions and any direct Prometheus Java client usage. |
| OpenTelemetry | 1.62.0 | 1.65.0 | Zipkin exporter publishing stopped in OpenTelemetry Java 1.65. Prometheus reader constructors and some SPI property names changed in earlier 1.63 and 1.64 releases. |
| OpenTelemetry semantic conventions | 1.37.0 | 1.43.0 | Review code that uses semantic convention constants directly. |
| Protobuf | 4.31.1 | 4.36.0 | Regenerate gRPC or protobuf classes with a matching protoc version if your build pins code generation. |
| ASM | 9.8 | 9.10.1 | Usually build-time only. Recheck custom bytecode tooling. |
Regenerate protobuf or gRPC classes if your build pins protoc or generated
sources. Review custom Prometheus meter names for duplicate effective names.
Review code that uses OpenTelemetry alpha, incubating, or SPI APIs directly.
GraalVM Native Image
The native-image Maven profile in example application poms has been removed. Considering using
the jlink-image profile which now supports the JDK AOT Cache.
Final Checks
- Run with JDK 27.
- Run tests with deprecation warnings enabled.
- Check startup logs for missing service providers.
- Check
/observe/healthand/observe/metrics. - Check tracing export in your collector.
- Check container and custom Java runtime image builds.