1. Introduction
RESTEasy Vert.x provides integration between RESTEasy and Eclipse Vert.x, bringing Jakarta RESTful Web Services to Vert.x’s reactive, event-driven architecture. The project consists of several modules:
-
resteasy-vertx-embedded-server — An embedded HTTP server using Vert.x Web and the standard
SeBootstrapAPI -
resteasy-vertx-client — A RESTEasy client HTTP engine backed by the Vert.x HTTP client
-
resteasy-vertx-api — Shared API types for managing the
Vertxinstance and configuration -
resteasy-vertx-cdi — CDI integration for automatic dependency injection in Jakarta REST resources
1.1. Version Information
This guide is for RESTEasy Vert.x version 2.0.0.Beta2.
-
For the main RESTEasy documentation, see docs.resteasy.dev.
2. Getting Started
2.1. Maven Dependencies
Add the BOM to your project’s dependency management section to align all RESTEasy Vert.x module versions:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>dev.resteasy.vertx</groupId>
<artifactId>resteasy-vertx-bom</artifactId>
<version>2.0.0.Beta2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
Then add the modules you need:
<dependencies>
<!-- Embedded server -->
<dependency>
<groupId>dev.resteasy.vertx</groupId>
<artifactId>resteasy-vertx-embedded-server</artifactId>
</dependency>
<!-- Client engine -->
<dependency>
<groupId>dev.resteasy.vertx</groupId>
<artifactId>resteasy-vertx-client</artifactId>
</dependency>
<!-- CDI support (optional) -->
<dependency>
<groupId>dev.resteasy.vertx</groupId>
<artifactId>resteasy-vertx-cdi</artifactId>
</dependency>
</dependencies>
2.2. Quick Start
Start an embedded server using the standard Jakarta REST SeBootstrap API:
@ApplicationPath("/api")
public class MyApplication extends Application {
@Override
public Set<Class<?>> getClasses() {
return Set.of(GreetingResource.class);
}
}
SeBootstrap.Configuration config = SeBootstrap.Configuration.builder()
.host("localhost")
.port(8080)
.build();
SeBootstrap.Instance instance = SeBootstrap.start(MyApplication.class, config)
.toCompletableFuture()
.join();
URI uri = instance.configuration().baseUri();
// Server running at http://localhost:8080/api
Create a client to call the running server:
Client client = ClientBuilder.newClient();
String result = client.target("http://localhost:8080/api/greeting")
.request(MediaType.TEXT_PLAIN)
.get(String.class);
client.close();
The Vert.x client engine is automatically discovered via ServiceLoader.
Both client and server share a single managed Vertx instance that is created lazily and shut down automatically.
2.3. Custom Vertx Instance
By default, a Vertx instance is created and managed automatically.
To provide your own Vertx instance (for example, to reuse one from your existing application), implement the VertxFactory interface and register it via ServiceLoader:
public class MyVertxFactory implements VertxFactory {
@Override
public Vertx create() {
return MyApplication.getSharedVertx();
}
}
Register in META-INF/services/dev.resteasy.vertx.spi.VertxFactory:
com.example.MyVertxFactory
3. Embedded Server
The embedded server module integrates RESTEasy with the Vert.x HTTP server and Vert.x Web Router.
It implements the EmbeddedServer interface for SeBootstrap integration and is automatically discovered via ServiceLoader.
3.1. SeBootstrap Usage
The recommended way to start the server is through the standard Jakarta REST SeBootstrap API:
SeBootstrap.Configuration config = SeBootstrap.Configuration.builder()
.host("localhost")
.port(8080)
.rootPath("/api")
.build();
SeBootstrap.Instance instance = SeBootstrap.start(MyApplication.class, config)
.toCompletableFuture()
.join();
// Stop the server
instance.stop().toCompletableFuture().join();
3.2. SSL/TLS
HTTPS is enabled by setting the protocol to "HTTPS" and providing an SSLContext:
SSLContext sslContext = SSLContext.getInstance("TLS");
// ... initialize with KeyManager/TrustManager ...
SeBootstrap.Configuration config = SeBootstrap.Configuration.builder()
.protocol("HTTPS")
.sslContext(sslContext)
.sslClientAuthentication(SSLClientAuthentication.OPTIONAL)
.host("localhost")
.port(8443)
.build();
SeBootstrap.start(MyApplication.class, config);
Client authentication maps to Vert.x ClientAuth values:
-
MANDATORY→ClientAuth.REQUIRED -
OPTIONAL→ClientAuth.REQUEST -
NONE(default) →ClientAuth.NONE
If no SSLContext is provided, SSLContext.getDefault() is used.
3.3. Vert.x Context Injection
The server makes several Vert.x types available via @Context injection:
-
io.vertx.core.Vertx— the shared Vert.x instance -
io.vertx.ext.web.RoutingContext— the routing context for the current request -
io.vertx.ext.web.Router— the Vert.x Web router
@GET
@Path("/info")
@Produces(MediaType.TEXT_PLAIN)
public String info(@Context io.vertx.core.Vertx vertx,
@Context io.vertx.ext.web.RoutingContext routingContext,
@Context io.vertx.ext.web.Router router) {
return "Running on Vert.x";
}
3.4. Async Support
Jakarta REST async responses are fully supported.
The Vertx instance can be injected via @Context to use idiomatic Vert.x async patterns:
@GET
@Path("/async")
@Produces(MediaType.TEXT_PLAIN)
public void asyncGet(@Context Vertx vertx, @Suspended AsyncResponse asyncResponse) {
vertx.executeBlocking(() -> {
// Perform blocking work off the event loop
return "async result";
}).onSuccess(asyncResponse::resume)
.onFailure(asyncResponse::resume);
}
3.5. Custom Router Factory
The server uses a Vert.x Web Router for request handling.
You can customize the router to add Vert.x Web middleware such as CORS handlers, session management, or authentication by providing a RouterFactory.
3.5.1. Via SeBootstrap Configuration
SeBootstrap.Configuration config = SeBootstrap.Configuration.builder()
.property(RouterFactory.PROPERTY, (RouterFactory) vertx -> {
Router router = Router.router(vertx);
router.route().handler(CorsHandler.create());
return router;
})
.build();
SeBootstrap.start(MyApplication.class, config);
3.5.2. Via ServiceLoader
Create a global default factory by implementing RouterFactory and registering it in META-INF/services/dev.resteasy.vertx.server.spi.RouterFactory:
public class MyRouterFactory implements RouterFactory {
@Override
public Router create(Vertx vertx) {
Router router = Router.router(vertx);
router.route().handler(CorsHandler.create());
return router;
}
}
The resolution order is:
-
RouterFactoryset onSeBootstrap.Configurationvia theRouterFactory.PROPERTYproperty -
RouterFactorydiscovered viaServiceLoader -
Default factory that creates a plain
RouterviaRouter.router(Vertx)
4. Client Engine
The client module provides a Vert.x-backed HTTP engine for the RESTEasy client.
It implements AsyncClientHttpEngine and supports both synchronous and asynchronous invocations.
4.1. Auto-Discovery
The Vert.x client engine is automatically discovered via ServiceLoader when the resteasy-vertx-client artifact is on the classpath.
No additional configuration is needed:
Client client = ClientBuilder.newClient();
String result = client.target("http://localhost:8080/api/greeting")
.request(MediaType.TEXT_PLAIN)
.get(String.class);
client.close();
4.2. Features
The Vert.x client engine provides:
-
HTTP/1.1 and HTTP/2 support
-
SSL/TLS (including native SSL engine)
-
Chunked transfer encoding for streaming request bodies
-
Connection pooling
-
Async invocations with
CompletableFuture -
Proxy support
4.3. Async Invocations
The engine supports reactive invocations via CompletionStageRxInvoker:
Client client = ClientBuilder.newClient();
CompletionStage<String> future = client.target("http://localhost:8080/api/greeting")
.request(MediaType.TEXT_PLAIN)
.rx()
.get(String.class);
future.thenAccept(result -> System.out.println("Got: " + result));
4.4. Request Timeout
A per-request timeout can be set using the VertxClientProperties.REQUEST_TIMEOUT property.
The value can be a Duration, a Number (milliseconds), or a string parseable as a long:
Client client = ClientBuilder.newClient();
client.target("http://localhost:8080/api/slow")
.request()
.property(VertxClientProperties.REQUEST_TIMEOUT, Duration.ofSeconds(5))
.get(String.class);
4.5. SSL/TLS
SSL is configured through the standard ClientBuilder API:
SSLContext sslContext = SSLContext.getInstance("TLS");
// ... initialize with KeyManager/TrustManager ...
Client client = ClientBuilder.newBuilder()
.sslContext(sslContext)
.build();
4.6. Configuration via ClientBuilder
When the engine is created via auto-discovery, the VertxClientHttpEngineFactory configures the Vert.x HttpClientOptions automatically from the ClientBuilder settings:
-
Connect timeout
-
Idle timeout
-
Read timeout
-
Proxy settings (HTTP proxy type)
-
SSL context
Client client = ClientBuilder.newBuilder()
.connectTimeout(5, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.build();
4.7. Custom HttpClientOptions
For full control over the Vert.x HTTP client configuration, pass custom HttpClientOptions via the VertxClientProperties.HTTP_CLIENT_OPTIONS property.
When custom HttpClientOptions are provided, standard ClientBuilder settings (timeouts, SSL context, proxy) are not applied.
All configuration must be set directly on the provided options.
|
HttpClientOptions options = new HttpClientOptions()
.setProtocolVersion(HttpVersion.HTTP_2)
.setUseAlpn(true)
.setConnectTimeout(5000)
.setSsl(true);
Client client = ClientBuilder.newBuilder()
.property(VertxClientProperties.HTTP_CLIENT_OPTIONS, options)
.build();
5. CDI Integration
The CDI module enables Jakarta Contexts and Dependency Injection for Jakarta REST resources running on the Vert.x embedded server.
Adding the resteasy-vertx-cdi dependency to the classpath is all that is needed — it is automatically activated via ServiceLoader.
5.1. Dependency
The CDI module requires Weld as the CDI implementation for request context management. Weld is included as a transitive dependency.
<dependency>
<groupId>dev.resteasy.vertx</groupId>
<artifactId>resteasy-vertx-cdi</artifactId>
</dependency>
5.2. Features
When the CDI module is active:
-
Jakarta REST resources are managed as CDI beans with full injection support
-
@ApplicationScoped,@RequestScoped, and other CDI scopes work as expected -
CDI interceptors and decorators are supported
-
Vert.x types are available for injection with
@Inject:-
Vertx—@Singleton, the shared Vert.x instance -
RoutingContext—@RequestScoped, the routing context for the current request -
Router—@RequestScoped, the Vert.x Web router
-
-
The CDI request context is automatically activated and deactivated per HTTP request
-
CDI context is propagated to Vert.x worker threads for
@Suspendedasync processing
5.3. Usage with SeBootstrap
@ApplicationScoped
public class GreetingService {
public String greet(String name) {
return "Hello, " + name + "!";
}
}
@Path("/greeting")
@RequestScoped
public class GreetingResource {
@Inject
GreetingService service;
@Inject
Vertx vertx;
@GET
@Produces(MediaType.TEXT_PLAIN)
public String greet(@QueryParam("name") String name) {
return service.greet(name);
}
}
// Start with SeBootstrap -- CDI container is automatically initialized
SeBootstrap.Instance instance = SeBootstrap.start(MyApplication.class, config)
.toCompletableFuture()
.join();
5.4. CDI Container Lifecycle
The CDI module manages the CDI container automatically:
-
If an existing CDI container is already running (e.g., started by the application or test framework), it is reused
-
If no container is running, a new one is created with bean-defining annotations for
@Path,@Provider, and@ApplicationPath -
The container is shut down when the server stops, but only if it was created by the module
5.5. Standalone Usage
For manual control, the CDI container can be initialized before the server:
// Boot CDI
try (SeContainer container = new Weld().skipShutdownHook().initialize()) {
SeBootstrap.Configuration config = SeBootstrap.Configuration.builder()
.host("localhost")
.port(8080)
.build();
SeBootstrap.Instance server = SeBootstrap.start(GreetingApplication.class, config)
.toCompletableFuture().join();
// ... use the server ...
server.stop().toCompletableFuture().join();
}
5.6. Context Injection
In addition to standard Jakarta REST context types, CDI resources can inject Vert.x types using @Inject:
@Path("/info")
@RequestScoped
public class InfoResource {
@Inject
Vertx vertx;
@Inject
RoutingContext routingContext;
@Inject
Router router;
@Inject
UriInfo uriInfo;
@GET
@Produces(MediaType.TEXT_PLAIN)
public String info() {
return uriInfo.getRequestUri().toString();
}
}
5.7. Running on the Java Module Path
On the class path no extra configuration is required.
On the Java module path, however, injecting the Vert.x RoutingContext and Router types requires additional JVM
options.
RoutingContext and Router are produced as @RequestScoped beans, which is a normal scope, so Weld generates a CDI
client proxy for each of them.
On the module path Weld defines that proxy class into the package of the proxied type — io.vertx.ext.web, which is
owned by the io.vertx.web module.
Two things are needed for this to succeed:
-
the target package must be opened to Weld so it can define the generated class into it, and
-
the target module must read the Weld modules so the generated proxy can link the Weld interfaces it implements.
The following JVM options are required to allow injection of these types into your resources or providers:
--add-opens io.vertx.web/io.vertx.ext.web=weld.core.impl
--add-reads io.vertx.web=weld.core.impl
--add-reads io.vertx.web=weld.api
The Vertx producer is @Singleton, so it is not proxied and requires no additional options.
6. Configuration Reference
6.1. System Properties
Configuration options can be set via system properties or other configuration sources supported by RESTEasy’s Options framework.
| System Property | Type | Default | Description |
|---|---|---|---|
|
|
|
Timeout value for blocking operations such as shutting down the |
|
|
|
Time unit for the timeout value. |
|
|
|
Maximum allowed request body size in bytes.
Requests exceeding this limit are rejected with HTTP 413.
Set to |
6.2. SeBootstrap Configuration Properties
| Property | Type | Description |
|---|---|---|
|
|
Custom |
6.3. Client Configuration Properties
| Property | Type | Description |
|---|---|---|
|
|
Per-request timeout in milliseconds. |
|
|
Custom Vert.x |
6.4. ServiceLoader Extension Points
The following interfaces can be implemented and registered via ServiceLoader to customize behavior:
| Interface | Description |
|---|---|
|
Factory for creating the |
|
Factory for creating the Vert.x Web |
7. Migrating from 1.x to 2.x
RESTEasy Vert.x 2.0 is a major release with significant architectural changes. This guide covers the key changes and how to update your code.
7.1. Package Rename
All packages have been renamed to align with the new group ID dev.resteasy.vertx:
| Old Package | New Package |
|---|---|
|
|
|
|
Update all import statements in your code accordingly.
7.2. Server: SeBootstrap Replaces VertxJaxrsServer
The VertxJaxrsServer class and the deprecated EmbeddedJaxrsServer interface have been removed.
Use the standard Jakarta REST SeBootstrap API instead:
VertxJaxrsServer server = new VertxJaxrsServer();
server.setPort(8080);
server.setRootResourcePath("/api");
server.setSecurityDomain(domain);
ResteasyDeployment deployment = server.getDeployment();
deployment.getRegistry().addPerRequestResource(MyResource.class);
server.start();
SeBootstrap.Configuration config = SeBootstrap.Configuration.builder()
.host("localhost")
.port(8080)
.rootPath("/api")
.build();
SeBootstrap.Instance instance = SeBootstrap.start(MyApplication.class, config)
.toCompletableFuture()
.join();
7.3. Server: Vert.x Web Router
The embedded server now uses a Vert.x Web Router internally.
This adds io.vertx:vertx-web as a required transitive dependency.
You can customize the router to add middleware (CORS, sessions, authentication) by providing a RouterFactory.
See Embedded Server for details.
7.4. Server: Authentication
The SecurityDomain interface is no longer used.
Use Vert.x Web authentication handlers on the Router via a RouterFactory instead:
SecurityDomain domain = new SimpleSecurityDomain(...);
new VertxRequestHandler(vertx, deployment, contextPath, domain);
SeBootstrap.Configuration config = SeBootstrap.Configuration.builder()
.property(RouterFactory.PROPERTY, (RouterFactory) vertx -> {
Router router = Router.router(vertx);
router.route().handler(BasicAuthHandler.create(authProvider));
return router;
})
.build();
SeBootstrap.start(MyApplication.class, config);
7.5. Server: Removed Classes
The following classes have been removed in 2.x:
-
VertxJaxrsServer— replaced bySeBootstrapAPI -
VertxResteasyDeployment— standardResteasyDeploymentImplis used directly -
RequestDispatcher— logic merged into request handler -
VertxContainer— test utility replaced byresteasy-junit-extension/SeBootstrap -
VertxRegistry,VertxResourceFactory— no longer needed
7.6. Client: Custom Vertx Instance
Constructors that accepted a Vertx instance or HttpClient have been removed.
To provide a custom Vertx instance, implement VertxFactory and register it via ServiceLoader:
public class MyVertxFactory implements VertxFactory {
@Override
public Vertx create() {
return Vertx.vertx(new VertxOptions().setWorkerPoolSize(20));
}
}
Register in META-INF/services/dev.resteasy.vertx.spi.VertxFactory.
7.7. Client: Property Constants Moved to VertxClientProperties
Client configuration property constants have been moved from VertxClientHttpEngine to the new VertxClientProperties class.
The request timeout property has also been renamed:
| Old | New |
|---|---|
|
|
A new VertxClientProperties.HTTP_CLIENT_OPTIONS property allows passing custom Vert.x HttpClientOptions via the standard ClientBuilder API without casting to ResteasyClientBuilder.
7.8. Shared Vertx Instance
Both client and server now share a single managed Vertx instance via VertxManager.
The instance is created lazily and shut down automatically.
To customize instance creation, implement VertxFactory as described above.
7.9. Vert.x Upgrade
Vert.x has been upgraded from 4.x/5.0.x to 5.1.x. Netty dependencies are now managed transitively by Vert.x — explicit Netty dependency declarations can be removed.
7.10. CDI Support
A new resteasy-vertx-cdi module provides CDI integration.
See CDI Integration for details.