Migrating to RESTEasy Reactive
Migrating from RESTEasy Classic to RESTEasy Reactive is straightforward in most cases, however there are a few cases that require some attention. This document provides a list of issues users attempting the migration should be aware of.
The reference documentation of RESTEasy Reactive can be found here. |
Server
The server part of RESTEasy Reactive (quarkus-resteasy-reactive
and its
dependencies) provide an implementation of the Jakarta REST specification,
but leverage Quarkus' build time processing and the unified I/O model
provided by Vert.x.
Dependencies
The following table matches the legacy RESTEasy dependencies with the new RESTEasy Reactive ones.
Legacy |
RESTEasy Reactive |
|
|
|
|
|
|
|
|
|
|
The quarkus-resteasy-mutiny does not have a corresponding dependency, as
RESTEasy Reactive provides Mutiny integration out of the box.
|
Annotations
RESTEasy Reactive does not support the various custom annotation under the
org.jboss.resteasy.annotations
package.
The following table matches the legacy RESTEasy annotations with the new RESTEasy Reactive ones.
Legacy |
RESTEasy Reactive |
Comments |
|
|
This annotation is not necessary when the path part matches the method parameter name |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The previous table does not include the
org.jboss.resteasy.annotations.Form annotation because there is no
RESTEasy Reactive specific replacement for it. Users are instead encouraged
to use the Jakarta REST standard jakarta.ws.rs.BeanParam annotation which
is supported on both the server and the client.
|
Jakarta REST providers
Although RESTEasy Reactive provides the same spec compliant behavior as RESTEasy Classic does, it does not include the same exact provider implementations at runtime.
The most common case where the difference in providers might result in
different behavior, is the included jakarta.ws.rs.ext.ExceptionMapper
implementations. To see what classes are included in the application, launch
the application in dev mode and navigate to
http://localhost:8080/q/dev-ui/io.quarkus.quarkus-resteasy-reactive/exception-mappers.
Service Loading
RESTEasy Classic supports determining providers at build time using Java’s Service Loader. In order to ensure that all providers are determined at build time, RESTEasy Reactive does not support this feature. Instead, users that have providers in application dependencies are encouraged to index those dependencies using one of the methods described in the Bean Discovery section of the CDI guide.
Multipart support
HTTP Multipart support in RESTEasy Reactive does not reuse the same types or annotations as RESTEasy Classic and thus users are encouraged to read this part of the reference documentation.
Users migrating multipart resources to RESTEasy Reactive should be aware of
the configuration parameter quarkus.http.limits.max-form-attribute-size ,
as this poses an upper limit to the size of each part. Any request with a
part size exceeding this configuration value will result in HTTP status code
413.
|
Default media types
Quarkus uses smart defaults when determining the media type of Jakarta REST
methods in order to simplify common use cases. The difference between
quarkus-resteasy-reactive
and quarkus-resteasy
is the use of
text/plain
as the default media type instead of text/html
when the
method returns a String
.
Servlets
RESTEasy Reactive does not support servlets. If your project depends on
servlets you have to migrate them. A servlet-based JAX-RS implementation
must support injections of these types with the @Context
annotation:
ServletConfig
, ServletContext
, HttpServletRequest
and
HttpServletResponse
. Since RESTEasy Reactive is not servlet-based these
injections will not work.
It is not always obvious that this will fail especially if you depend on an
extension like quarkus-undertow
which supplies the interfaces. For
example, if you write this you could compile it but get an exception on
calling it:
@Path("/reactive")
public class ReactiveResource {
@Context
HttpServletRequest httpServletRequest;
@GET
@Produces(MediaType.TEXT_PLAIN)
public String servletContextPath() {
String contextPath = httpServletRequest.getContextPath();
return "My context path is: " + contextPath;
}
}
The same is true for your third-party libraries. If they happen to depend on servlets you need to find a migration path for them.
Log authentication and authorization failures
The RESTEasy Reactive endpoint security checks are performed before CDI interceptors are invoked. The safest approach to log Quarkus Security authentication exceptions is to ensure that proactive authentication is enabled and to use Vert.x HTTP route failure handlers. For more information, see the Customize authentication exception responses section of the Proactive authentication guide.
Client
The Reactive REST Client (quarkus-rest-client-reactive
and its
dependencies) replace the legacy quarkus-rest-client
but leverage Quarkus'
build time processing and the unified I/O model provided by Vert.x.
Dependencies
The following table matches the legacy REST Client dependencies with the new Reactive REST Client ones.
Legacy |
RESTEasy Reactive |
|
|
|
|
|
|
|
|
Keycloak admin client
When using quarkus-rest-client
, users can use the
quarkus-keycloak-admin-client
to administer the target Keycloak instance
by leveraging the rest client.
When using quarkus-rest-client-reactive
however, users must use
quarkus-keycloak-admin-client-reactive
to access the same functionality
and use the reactive REST Client.
OIDC
When using quarkus-rest-client
, users can use the
quarkus-oidc-client-filter
extensions to acquire and refresh access tokens
from OpenID Connect and OAuth 2.0 compliant Authorization Servers.
When using quarkus-rest-client-reactive
however, users must use
quarkus-oidc-client-filter-reactive
to access the same functionality.
Similarly, quarkus-oidc-token-propagation
allows user of the legacy REST
to propagate the current Bearer
or Authorization Code Flow
access
tokens.
When using quarkus-rest-client-reactive
however, users must use
quarkus-oidc-token-propagation-reactive
to access the same functionality.
Custom extensions
This is an advanced section that only needs to be read by users who have developed custom extensions that depend on Jakarta REST and / or REST Client functionality.
Dependencies
A first concern is whether custom extensions should depend on RESTEasy Reactive explicitly, or alternatively support both RESTEasy flavors and leave it to the user to decide. If the extension is some general purpose extension, it probably makes sense to choose the latter option, while the former option is easiest to adopt when the custom extension is used by a specific set of users / applications.
When opting for supporting both extensions, the deployment module of the
custom extension will usually depend on the SPI modules -
quarkus-jaxrs-spi-deployment
, quarkus-resteasy-common-spi
,
quarkus-resteasy-reactive-spi-deployment
, while the runtime modules will
have optional
dependencies on the runtime modules of both RESTEasy
flavors.
A couple good examples of how Quarkus uses this strategy to support both RESTEasy flavors in the core repository can be seen [here](https://github.com/quarkusio/quarkus/pull/21089) and [here](https://github.com/quarkusio/quarkus/pull/20874).
In general, it should not be needed to have two different versions of the custom extension to support both flavors. Such a choice is only strictly necessary if it is desired for the extension consumers (i.e. Quarkus applications) to not have to select a RESTEasy version themselves.
Resource and Provider discovery
Custom extensions that contain Jakarta REST Resources, Providers or REST
Client interfaces in their runtime modules and depend on Jandex indexing for
their discovery (for example because they have an empty META-INF/beans.xml
file) don’t have to perform any additional setup to make these discoverable
by RESTEasy Reactive.
Provider registration via Build Items
Extensions that register providers via build items use the
io.quarkus.resteasy.common.spi.ResteasyJaxrsProviderBuildItem
build item
in RESTEasy Classic. With RESTEasy Reactive however, extensions need to use
specific build items, such as
io.quarkus.resteasy.reactive.spi.MessageBodyWriterBuildItem
and
io.quarkus.resteasy.reactive.spi.MessageBodyWriterBuildItem
.