Skip to content

4.0.0 Deprecations and breaking changes

Julien Viet edited this page Dec 2, 2020 · 124 revisions

Vert.x Core

☑️ EventBus request-response send is removed

The EventBus#send(..., Handler<AsyncResult<Message<T>>>) and Message#reply(..., Handler<AsyncResult<Message<T>>>) methods are revmoed. Such methods raise overloading issues in Vert.x 4 because the version returning a Future<Message<T>> would collide with the fire and forget version.

The request-response messaging pattern should now use the new request and replyAndRequest methods:

// 3.x
eventBus.send("the-address", body, ar -> ...);

// 4.0
eventBus.request("the-address", body, ar -> ...);

Likewise with replies

// 3.x
eventBus.consumer("the-address", message -> {
  message.reply(body, ar -> ...);
});

// 4.0
eventBus.consumer("the-address", message -> {
  message.replyAndRequest(body, ar -> ...);
});

☑️ MessageProducer send methods are removed

https://github.com/eclipse-vertx/vert.x/issues/3005

The MessageProducer interface declares two send methods, these methods are removed. MessageProducer#write(T) should be used instead of MessageProducer#send(T), EventBus#request(String,Object,Handler) should be used instead of MessageProducer#send(T,Handler).

☑️ MessageProducer does not extend anymore the WriteStream interface

https://github.com/eclipse-vertx/vert.x/issues/3389

In Vert.x 3, the MessageProducer interface extends the WriteStream interface and provides limited support for message back-pressure. In practice credit leak might happen leading to a depletion of credits in the producer that won't allow to emit messages.

The MessageConsumer will continue to extend ReadStream and will drop messages when the consumer is paused and the pending message queue is full. This allows to continue supporting the nice integration with Rx generators for building message consuming pipelines.

Point to point message streaming over the event-bus will be introduced in Vert.x 4 to provide a supportable solution to replace this.

☑️ WriteStream write and end methods fluency

WriteStream#write and WriteStream#end methods are not fluent anymore:

  • the callback version now returns void
  • the other now returns a Future<Void

This is a breaking change that removes the fluent write aspect of write streams. Note that the end method accept as parameter a last argument so stream.write(T).end() can actually be stream.end(T)

☑️ NetSocket upgradeToSsl uses Handler<AsyncResult> instead of Handler

https://github.com/eclipse-vertx/vert.x/issues/2962

Currently the NetSocket#upgradeToSsl method uses an Handler completion. The only way to determine whether the upgrade fails is to set an exception handler on the socket which will replace the current handler and complicate the code.

This method should instead use an Handler<AsyncResult>.

☑️ FutureFactory SPI removal

https://github.com/eclipse-vertx/vert.x/issues/3538

Vert.x 4.0 relies more on future and thus make some assumption about the implementation of the futures that would break if no special care is done with the future implementation. As this is a core component of the stack, we prefer in 4.0 to withdraw this SPI.

This is not and end user impacting change

☑️ HttpClient rework

☑️ HttpClient request/response use Handler<AsyncResult> instead of Handler

https://github.com/eclipse-vertx/vert.x/issues/2741

HttpClient request/response methods are using in Vert.x 3 patterns following Handler<HttpClientResponse>. For obvious reasons we want to use instead Handler<AsyncResult<HttpClientResponse>> in Vert.x 4. The WebClient provides already this in Vert.x 3.x and it is the advocated client for high level operations so we don't need to provide replacement for these operations, only to deprecate them.

☑️ Usual methods will send the request

In Vert.x 3.x most HttpClient methods will return an HttpClientRequest that is yet to send. There are a few alternate methods named *Now that will actually send the request on behalf of the user: getNow, optionsNow and headNow.

Vert.x 4 assumes that now the most usual methods behave like the *Now methods and will send the request allowing the user to pass the necessary information to perform the request.

// Get
Future<HttpClientResponse> f1 = client.get(8080, "localhost", "/uri", HttpHeaders.set("foo", "bar"));

// Post with a buffer body
Future<HttpClientResponse> f2 = client.post(8080, "localhost", "/uri", HttpHeaders.set("foo", "bar"), Buffer.buffer("some-data"));

// Post with a streaming body
Future<HttpClientResponse> f3 = client.post(8080, "localhost", "/uri", HttpHeaders.set("foo", "bar"), asyncFile);

☑️ New send method

The new send method is the generic way to send requests, i.e

// Is the same as callling get
Future<HttpClientResponse> f1 = client.send(HttpMethod.GET, 8080, "localhost", "/uri", HttpHeaders.set("foo", "bar"));

☑️ Enhanced request options

Vert.x 3 brought the RequestOptions for creating request data in a fluent manner, these options have been enhanced to carry

  • host
  • port
  • uri
  • ssl
  • headers (new)
  • follow redirect (new)
  • timeout (new)
Future<HttpClientResponse> fut = client.post(
   new RequestOptions()
      .host("example.com")
      .setURI("/resource")
      .addHeader("content-type", "application/json"),
   new JsonObject().put("hello", "world"));

☑️ Request based API

The HttpClient#request methods will create an HttpClientRequest that is yet to send, like in Vert.x 3.x . This allow to perform lower level interactions such as

  • just sending the request headers
  • HTTP/2 specific operations such as setting a push handler, setting stream priority, pings, etc...
  • creating a NetSocket tunnel
  • fine grained write control
  • stream reset
  • handling 100 continue headers manually
client.request(HttpMethod.GET, 8080, "example.com", "/resource", ar -> {
  if (ar.succeeded()) {
    HttpClientRequest request = ar.result();
    request.putHeader("content-type", "application/json")
    request.send(new JsonObject().put("hello", "world"))
      .onSuccess(response -> {
      //
      }).onFailure(err -> {
      //
       });
     }
})

☑️ HttpClient tunnelling with NetSocket

https://github.com/eclipse-vertx/vert.x/issues/3207

The HttpClientResponse#netSocket has some design flaws (it is synchronous and does not report errors). It works correctly in Vert.x 3.x at the expense of a few work around but should not be left as it is.

Instead, the requester should provide a socket handler on the request that will be called when the correct response is received.

// 3.x
client.request(HttpMethod.CONNECT, uri, ar -> {
  if (ar.succeeded()) {
    HttpClientResponse response = ar.result();
    if (response.statusCode() == 200) {
      NetSocket so = response.netSocket();
   }
  }
}).end();

// In 4.0
client.request(HttpMethod.CONNECT, uri, ar1 -> {
  if (ar1.succeeded()) {
    HttpClientRequest request = ar1.result();
    request.netSocket(ar2 -> {
      if (ar2.succeeded()) {
        // Got a response with a 200 status code
        NetSocket so = ar2.result();
        // Go for tunneling
      }
    }).send();
  }  
});

☑️ HttpServer tunnelling with NetSocket

https://github.com/eclipse-vertx/vert.x/issues/3562

The HttpServerRequest#netSocket has some design flaws (it is synchronous).

The API has been made asynchronous and renamed to toNetSocket, the method is back-ported in Vert.x 3.9 and the original netSocket method deprecated.

// 3.x
server.requestHandler(req -> {
  NetSocket ws = req.netSocket();
});

// 4.0
server.requestHandler(req -> {
  Future<NetSocket> fut = req.toNetSocket();
  fut.onSuccess(so -> {
  });
});

☑️ HttpClient WebSocket use Handler<AsyncResult< WebSocket >> instead of Handler / Handler<Throwable)

https://github.com/eclipse-vertx/vert.x/issues/2954

HttpClient WebSocket methods are using in Vert.x 3 patterns following Handler<WebSocket>/Handler<Throwable>. For obvious reasons we want to use instead Handler<AsyncResult< WebSocket >> in Vert.x 4. These new methods are named webSocket(...). The number of overloaded methods has also been reduced using WebSocketConnectOptions.

☑️ HTTP server WebSocket upgrade improvements

https://github.com/eclipse-vertx/vert.x/issues/3564

The HttpServerRequest#upgrade has some design flaws (it is synchronous).

The API has been made asynchronous and renamed to toWebSocket, the method is back-ported in Vert.x 3.9 and the original upgrade method deprecated.

// 3.x
server.requestHandler(req -> {
  WebSocket ws = req.upgrade();
});

// 4.0
server.requestHandler(req -> {
  Future<WebSocket> fut = req.toWebSocket();
  fut.onSuccess(ws -> {
  });
});

☑️ HttpClient max WebSocket config

https://github.com/eclipse-vertx/vert.x/issues/3681

The max number of WebSocket is defined by the HTTP client pool size (HttpClientOptions#maxPoolSize). In Vert.x 4 there is no pooling of WebSocket TCP connections (since those are closed after usage) and they use a different pool than HTTP connections used for request/response. Both use maxPoolSize.

Vert.x 4 comes with a new maxWebSockets setting with a default of 50 per endpoint instead of 4.

// 3.x
options.setMaxPoolSize(30); // At most 30 WebSocket per endpoint

// 4.0
options.setMaxWebSockets(30); // At most 30 WebSocket per endpoint

☑️ Remove HTTP client request connection handler

The HttpClientRequest#connectionHandler is removed in Vert.x 4.

Application can instead rely on the HttpClient#connectionHandler to achieve the same:

// 3.x
client.request().connectionHandler(conn -> {
  // Do something with connection
}).end();

// 4.0
client.connectionHandler(conn -> {
  // Do something with connection
});

☑️ HTTP/1.x incorrect client version handling

https://github.com/eclipse-vertx/vert.x/issues/3525

Invalid HTTP/1.x version is handling in HttpServerRequest#version() that will send a 501 status response and close the connection when called. Sending the appropriate response is performed as a side effect of checking the HTTP version which means it is done only if the application will check the HTTP version.

Now this is performed before the request is dispatched to server handler and the application will always get a valid version instead an exception.

☑️ HttpHeaders enhancement

The HttpHeaders defines a bunch of useful HTTP header related constants. This is now an interface allowing to create MultiMap instances more easily:

// 3.x
MultiMap headers = MultiMap.caseInsensitiveMultiMap();

// 4.0
MultiMap headers = HttpHeaders.headers();

// 4.0
MultiMap headers = HttpHeaders.set("content-type", "application.data");

☑️ CaseInsensitiveHeaders made internal

https://github.com/eclipse-vertx/vert.x/issues/3269

The CaseInsensitiveHeaders implementation of MultiMap is deprecated in Vert.x 3.x and moved in the io.vertx.core.http.impl.headers package in Vert.x 4. This class does not expose more than the MultiMap contract.

// 3.x
CaseInsensitiveHeaders headers = new CaseInsensitiveHeaders();

// 4.0
MultiMap multiMap = MultiMap#caseInsensitiveMultiMap();

// Or use
MultiMap headers = HttpHeaders.headers();

☑️ Remove pooled buffer option

https://github.com/eclipse-vertx/vert.x/issues/2746

Vert.x provides the option on TCPSSLOptions to configure the usage of pooled buffers. This option has no effect whatsoever and has marked as deprecated in 3.6. We should simply remove it from Vert.x. This option might be overridden by TCPSSLOptions sub classes in other modules of the stack, so the stack should be checked and provide corresponding PR along with this one.

☑️ Future setHandler method pruning

https://github.com/eclipse-vertx/vert.x/issues/3329

Vert.x supports multiple handler per future in 4.0. The setHandler method does convey the meaning that a single handler per future can be set and unset and the onComplete, onSuccess, onFailure methods shall be used instead.

The setHandler method usage must be replaced by the onComplete method, e.g

// Before
Future<String> fut = getSomeFuture();
fut.setHandler(ar -> ...);

// After
Future<String> fut = getSomeFuture();
fut.onComplete(ar -> ...);

Vert.x 3.9 deprecates setHandler.

☑️ Future completer method pruning

https://github.com/eclipse-vertx/vert.x/issues/2869

The Future#completer() method is deprecated since Future<T> extends Handler<AsyncResult<T>> for some time now (and the default implementation actually returns this).

☑️ Remove multithreaded worker verticles

See https://github.com/eclipse-vertx/vert.x/issues/2431

MultiThreaded worker verticles are an extension to worker verticles. Like with usual worker verticles, events are handled on worker pool threads. But they can be executed by different threads concurrently, which means the verticle must manage its own state to be visible between threads.

There are many parts of Vert.x which simply doesn't support them. For example, you can't create an HTTP server on a MT worker verticle.

Also, we have seen many new users, in particular those experienced with Spring or Java EE, starting directly with MT worker verticles and adding as many threads as possible with the impression it would help get the best performance results. But this is really counter-productive.

In 3.6.0 we deprecate the usage of multi-threader worker verticles and we document how to replace them. The feature will is dropped in Vert.x 4.

☑️ Log4j 1 removal

See https://github.com/eclipse-vertx/vert.x/issues/3502

Using Log4j 1 is still possible using SLF4J.

☑️ Deprecate logging API

See https://github.com/eclipse-vertx/vert.x/issues/2774

The Vert.x logging API is public and advertised in the docs. Besides, there are a couple of issues as it supports parameterised logging methods without standardising on a message format (it delegates this to the logging backend so messages are not portable).

Therefore, we regularly get questions/bug reports about this, which increases the maintenance effort. Also, it's not good to provide a non-working feature only to cause users' disappointment.

Considering it's not a programming toolkit responsibility to provide yet another logging API, the Vert.x loggers shall be deprecated and, in a later major version made internal.

☑️ Remove options clone methods

See https://github.com/eclipse-vertx/vert.x/issues/2833 and https://github.com/eclipse-vertx/vert.x/issues/2839

KeyCertOptions#clone(), TrustOptions#clone() and SSLEngineOptions#clone() methods are deprecated in 3.7 and are replaced by KeyCertOptions#copy(), TrustOptions#copy() and SSLEngineOptions#copy()` methods in 4.0.

☑️ Remove TrustOptions toJson method

The TrustOptions interface defines a toJson() method, this method is used mainly by some unit tests and there is no purpose for TrustOptions to define such method.

☑️ Remove equals/hashCode method from options

See https://github.com/eclipse-vertx/vert.x/issues/2840

There is no deprecation in 3.x, users should simply not use it.

☑️ Remove deprecated Metrics#isEnabled() method

See https://github.com/eclipse-vertx/vert.x/issues/2845

This is an internal SPI method.

☑️ Remove deprecated NetServerOptions#isClientAuthRequired()

See https://github.com/eclipse-vertx/vert.x/issues/2846

The 3.x version will point to the new method to use instead.

☑️ Remove deprecated VertxOptions#fileResolverCachingEnabled

See https://github.com/eclipse-vertx/vert.x/issues/2847

The 3.x version will point to the new method to use instead.

☑️ Encapsulate Jackson

Methods carrying Jackson types are removed from the common Json API. These elements are deprecated in Vert.x 3 with replacements.

  • Json#mapper field replaced by DatabindCodec#mapper() method
  • Json#prettyMapper field replaced by DatabindCodec#prettyMapper() method
  • Json#decodeValue(Buffer, TypeReference<T>) method replaced by JacksonCodec#decodeValue(Buffer, TypeReference)
  • Json#decodeValue(String, TypeReference<T>) method replaced by JacksonCodec#decodeValue(String, TypeReference)

When using Jackson't TypeReference

// 3.x
List<Foo> foo1 = Json.decodeValue(json, new TypeReference<List<Foo>>() {});

// 4.0
List<Foo> foo2 = io.vertx.core.json.jackson.JacksonCodec.decodeValue(json, new TypeReference<List<Foo>>() {});

Referencing an ObjectMapper:

// 3.x
ObjectMapper maper = Json.mapper;

// 4.0
mapper = io.vertx.core.json.jackson.DatabindCodec.mapper();

Setting an ObjectMapper:

// 3.x
Json.mapper = someMapper;

// 4.0
// You cannot write anymore the mapper instance instead you should use your own static mapper
// or configure the Databind#mapper() instance

Remove cluster reply address

https://github.com/eclipse-vertx/vert.x/issues/2704

TODO

There are still references in the code and docs to the event bus reply address. But it's actually only used now to provide the origin server ID.

☑️ Change JsonObject/JsonArray base64 encoder to base64url

https://github.com/eclipse-vertx/vert.x/pull/3123

Vert.x JSON types implement RFC-7493, however the implementation was incorrect as it used plain Base64 while the RFC mandates base64url.

In order to ease the migration/interop with other services a utility method is added to Json to convert from base64url to plain base64:

// get a base64 string as with Vert.x 3
String base64url = someJsonObject.getString("base64encodedElement")
String base64 = Json.toBase64(base64url);

☑️ Isolated deployment for Java 8

https://github.com/eclipse-vertx/vert.x/issues/3274

Vert.x has provided isolated class loading support in Vert.x 3 . This option cannot be properly supported above Java 8 due to the evolution of the Java runtime. In Vert.x 4 we continue provides a best effort support of this option for Java 8.

This relies on Multi-Release Jar support supporting this support for Java version < 11 exclusively. The DeploymentOptions class for Java >= 11 does not provide anymore the class loading related fields and the class loader manager implementation is a no-op implementation.

☑️ VerticleFactory simplification

Currently the VerticleFactory provides a synchronous contract for instantiating a Verticle. We are changing this contract to become asynchronous and provide instead a Callable<Verticle> instead of a single instance, allowing the deployment phase to call this method once and later on invoke the returned callable many times for creating instances.

// 3.x
Verticle createVerticle(String verticleName, ClassLoader classLoader) throws Exception;

// 4.0
void createVerticle(String verticleName, ClassLoader classLoader, Promise<Callable<Verticle>> promise);

Existing factories can be rewritten by completing or failing the promise with a callable which can be called several times:

// 3.x
return new MyVerticle();

// 4.0
promise.complete(() -> new MyVerticle());

When the factory needs to block, it shall use Vertx#executeBlocking to achieve it and resolve the promise when it obtains the blocking code result (e.g a java.lang.Class) and infers verticle instances from it.

The VerticleFactory has also been simplified to remove the initial resolution of a identifier as the factory can simply perform a nested deployment instead.

NOTE: this change is not for mainstream applications, rather for integration.

☑️ Context close hook made internal

The io.vertx.core.Context interfaces defines addCloseHook and removeCloseHook methods which are used internally by Vert.x to be aware of verticle undeployment. Those methods have been removed from this interface in favor of being now an internal mechanism on the ContextInternal interface.

☑️ Context affinity for non Vert.x thread

https://github.com/eclipse-vertx/vert.x/issues/3430

The Vertx#getOrCreateContext() returns a new context each time it is called from a non Vert.x thread. In Vert.x 4 a single context is created for each non Vert.x thread.

// Passes for Vert.x 4 but not for Vert.x 3
new Thread(() -> {
  assertSame(vertx.getOrCreateContext(), vertx.getOrCreateContext());
}).start();

This is not a breaking changed and user code shall not be affected by this. However in some situations there can be code that were implicitly relying on this effect, e.g it a few tests in Vert.x stack were doing

for (int i = 0;i < n;i++) {
  vertx.executeBlocking(block, hander);
}

Such code expects the n blocks to run concurrently and it does in Vert.x 3 as each executeBlocking is called on a different context. To achieve the same in Vert.x 4, the code needs to be changed to

for (int i = 0;i < n;i++) {
  vertx.executeBlocking(block, false, hander);
}

☑️ WebSocket spelling fixes

https://github.com/eclipse-vertx/vert.x/issues/3235

Vert.x 3.x provides an inconsistent naming concerning for WebSocket, it is often spelled as Websocket. We should address this in Vert.x 4 whenever possible and provide deprecation for incorrect names.

In 4.0, the following were renamed (and deprecated in 3.x):

  • HttpServerOptions properties
    • spelling fixes, e.g getMaxWebsocketFrameSize renamed to getMaxWebSocketFrameSize
    • the fixed sub-protocols uses now List<String> instead of a coma separated string
  • HttpClientOptions properties spelling fixes, e.g getMaxWebsocketFrameSize renamed to getMaxWebSocketFrameSize
  • HttpServer handlers: websocketHandler, websocketStream
  • WebsocketRejectedException is removed, instead the UpgradeRejectedException should be used

☑️ HttpMethod is an interface

https://github.com/eclipse-vertx/vert.x/issues/3246

In Vert.x 2 and 3, the HttpMethod is declared as an enum. This limits the extensibility of HTTP and prevents modelling other HTTP methods with this type unless using HttpMethod#OTHER in addition with the rawMethod attribute on HttpServerRequest and HttpClientRequest.

In Vert.x 4 we turned this enum into an interface in Vert.x 4.

If you are using the enum in a switch block we can recommend doing

// 3.x
switch (method) {
  case GET:
    ...
    break;
  case OTHER:
    String s = request.getRawMethod();
    if (s.equals("PROPFIND") {
      ...
    } else ...
}

// 4.0
switch (method.name()) {
  case "GET":
    ...
    break;
  case "PROPFIND";
    ...
    break;
}

// or

// 4.0
HttpMethod PROPFIND = HttpMethod.valueOf("PROPFIND");

if (method == HttpMethod.GET) {
  ...
} else if (method.equals(PROPFIND)) {
  ...
} else {
  ...
}

If you are using HttpMethod#OTHER you can migrate with:

// 3.x
client.request(HttpMethod.OTHER, ...).setRawName("PROPFIND");

// 4.0
client.request(HttpMethod.valueOf("PROPFIND"), ...);

Removed the Starter class

The Starter class has been removed in 4.0. It was deprecated for quite a few versions already.

To start Vert.x apps without writing your own main, you can use the io.vertx.core.Launcher class instead.

Clustered flag removed from VertxOptions and EventBusOptions

In 3.x, the options to build Vert.x provide a clustered boolean with the following behavior:

  • calling vertx(options) with clustered set to false builds a non clustered instance
  • calling vertx(options) with clustered set to true throws an IllegalArgumentException
  • calling clusteredVertx(options) with clustered set to true builds a clustered instance
  • calling clusteredVertx(options) with clustered set to false does set clustered to true and then builds a clustered instance

Given this behaviour, the usefulness of this setting is very low and instead it is removed in Vert.x 4.

Vert.x Auth

☑️ Internal module "vertx-jwt"

The module vertx-jwt not to confuse with vertx-auth-jwt has been merged with vertx-auth-common and shall not exist on 4.0.0. This module included utilities to parse and handle JOSE keys and signatures. In order to simplify the JPMS work this module is removed and all it's public API is now available on vertx-auth-common.

Note that since this was a internal module, the code now lives under the impl package so signal that, still, this is mostly to be used internally.

☑️ Deprecation and removals (common)

  • AbstractUser - All user objects are now constructed by the User.createUser() factory
  • AuthOptions - This was a hack for Shell
  • PubSecKeyOptions - Now extracts the kind of key from the PEM data, so all getters and setters: publicKey, 'secretKey, symmetric, certificateare not use. Just set thebuffer` setter with the PEM data.
  • User the methods isAuthorized is deprecated (authorization should be performed by the AuthorizationProvider
  • User the methods clearCache is deprecated (use user.authorizations().clear())
  • User the internal method setAuthProvider has no effect and will be removed
  • impl.AuthProviderInternal is to be removed (hack for Shell and Web)

☑️ Deprecation and removals (jdbc)

  • JDBCHashStrategy is deprecated for the standard PHC alternative from common
  • JDBCAuthOptions is deprecated and replaced by the Authorization and Authentication Options.

☑️ Deprecation and removals (oauth2)

  • Accesstoken is deprecated for the standard ``User` alternative from common
  • KeycloakHelper is deprecated as it overlaps with User and is not secure.
  • OAuth2Auth#decodeToken deprecated, just use #authenticate()
  • OAuth2Auth#introspectToken deprecated, just use #authenticate()
  • OAuth2Auth#getFlowType() deprecated (was an internal API that can be reached from the options)
  • OAuth2Auth#loadJWK() deprecated (use the jwkSet() as it's the official name from the spec)
  • Oauth2ClientOptions#isUseAuthorizationHeader() not used anymore, this data is inferred from the config
  • Oauth2ClientOptions#scopeSeparator() not used anymore, this configuration is AuthorizationProvider specific.
  • OAuth2RBAC replaced by the new AuthorizationProvider
  • Oauth2Response deprecated as it a legacy way to fetch HTTP resource before WebClient existed.

☑️ Deprecation and removals (shiro)

The whole module is deprecated due to the blocking API and limitations. Users should upgrade to the new modules:

  • PropertyFileAuthentication - for property authentication using the same file format
  • LDAPAuthentication - for LDAP using the stock JDK API

☑️ Deprecation and removals (jwt)

  • JWT#<ctor>(Keystore, char[]) All keys are now managed by JWK.
  • JWTOptions deprecated scopes and scopeDelimiter as they are Authorization config.

Vert.x gRPC

☑️ Remove usage of Vert.x gRPC Java Compiler

https://github.com/vert-x3/vertx-grpc/issues/37

In Vert.x 3.x, Vert.x provides its own compiled gRPC stubs for Vert.x API. This leads to maintain a fork of the grpc compiler which cannot be trivially achieved by anyone. It is agreed in Vert.x 4 to drop this.

Vert.x Rx

☑️ Remove legacy XYZObservable method in RxJava 1 API

https://github.com/vert-x3/vertx-rx/issues/113

These methods have been deprecated since rx prefixed version exist and should not be used normally. These methods are simply removed in Vert.x 4. In addition these methods were present on modules created before the introduction of rx prefixes, other modules don't carry it.

Remove deprecated onComplete callback in WriteStream / Subscriber adapters

https://github.com/vert-x3/vertx-rx/issues/218

The onComplete callback might be invoked while there are outstanding writes in the underlying WriteStream.

Two callbacks have been added, that will be invoked after WriteStream#end signals its completion.

WriteStreamSubscriber<Buffer> subscriber = writeStream.toSubscriber();

// Removed
subscriber.onComplete(() -> {
    // Invoked after writeStream#end is invoked, even if operation is not completed yet
});

// After
subscriber.onWriteStreamEnd(() -> {
    // Invoked after writeStream#end is invoked and completes successfully
});
subscriber.onWriteStreamError(() -> {
    // Invoked after writeStream#end is invoked and fails
});

Dropwizard Metrics

☑️ JSON options: remove backward compatibility for monitoredServerUris, monitoredClientUris and monitoredClientEndpoints

https://github.com/vert-x3/vertx-dropwizard-metrics/issues/87

In 3.3, monitoredServerUris, monitoredClientUris and monitoredClientEndpoints have been renamed to monitoredHttpServerUris, monitoredHttpClientUris and monitoredHttpClientEndpoints, respectively.

In the JSON to options constructor, there is code to support the old options format. It shall be removed now.

☑️ TCP bytes read/written become counters

In Vert.x 3.x, the bytes-written and bytes-read metrics are logged as histograms for sockets. Since Vert.x 4 they are now counter reporting the amount of data exchanged.

Micrometer Metrics

☑️ TCP bytes read/written become counters, new distribution summaries for HTTP bytes

In Vert.x 3.x, the Net's _bytesSent and _bytesReceived metrics are logged as distribution summaries for sockets. Since Vert.x 4 they are now counter reporting the amount of data exchanged. The equivalent distribution summaries are introduced at the HTTP level, allowing to account for request or response sizes (named request_bytes and response_bytes).

☑️ Full review of metric names

All metric names have been reviewed, and several have been changed, to get closer to common naming conventions. In particular, the "camelCase" style has been dropped in favor of backend-dependent styles, like "snake_case" for Prometheus. Here is the full list of the changes, in Prometheus format:

  • *_connections is renamed to *_active_connections (in Net client and server, HTTP client and server)
  • *_bytesReceived is renamed to *_bytes_read (in Datagram, Net client and server, HTTP client and server)
  • *_bytesSent is renamed to *_bytes_written (in Datagram, Net client and server, HTTP client and server)
  • vertx_http_client_queue_delay_seconds is renamed to vertx_http_client_queue_time_seconds
  • vertx_http_client_queue_size is renamed to vertx_http_client_queue_pending
  • *_requests is renamed to *_active_requests (in HTTP client and server)
  • *_requestCount_total is renamed to *_requests_total (in HTTP client and server)
  • *_responseTime_seconds is renamed to *_response_time_seconds (in HTTP client and server)
  • *_responseCount_total is renamed to *_responses_total (in HTTP client and server)
  • *_wsConnections is renamed to *_active_ws_connections (in HTTP client and server)
  • vertx_http_server_requestResetCount_total is renamed to vertx_http_server_request_resets_total
  • vertx_eventbus_bytesWritten is renamed to vertx_eventbus_bytes_written
  • vertx_eventbus_bytesRead is renamed to vertx_eventbus_bytes_read
  • vertx_eventbus_replyFailures is renamed to vertx_eventbus_reply_failures
  • vertx_pool_queue_delay_seconds is renamed to vertx_pool_queue_time_seconds
  • vertx_pool_queue_size is renamed to vertx_pool_queue_pending
  • vertx_pool_inUse is renamed to vertx_pool_in_use

Vert.x Web

☑️ All file system access over vert.x core, no need for class loaders

https://github.com/vert-x3/vertx-web/pull/1713

This means that FaviconHandler and ErrorHandler now require a vertx instance object to be passed to the create methods.

// before 3.x
FaviconHandler.create();
ErrorHandler.create();

// on 4.0.0
FaviconHandler.create(vertx);
ErrorHandler.create(vertx);

☑️ Merged the functionality of SessionHandler and UserSessionHandler

https://github.com/vert-x3/vertx-web/issues/1093

When working with session users always need to provide 2 handlers. The code is too fine grained and a common source of confusion for users. For this reason, the 2 handlers will be merged into a single SessionHandler.

☑️ Removed the deprecated cookie API

https://github.com/vert-x3/vertx-web/issues/1337

The vertx-core module introduced in 3.8.1 a cookie API borrowed from vertx-web. The vertx-web cookie support is deprecated in 3.8.1 and removed in 4.0.

☑️ Removed the deprecated Locale

https://github.com/vert-x3/vertx-web/pull/1385

☑️ Removed the deprecated RoutingContext::accept

https://github.com/vert-x3/vertx-web/pull/1385

This was a deprecated and duplicate method for handle

☑️ Fixed typpo on API Router::mountSubRouter returns Route

https://github.com/vert-x3/vertx-web/pull/1605

Previously this was a deviation of the API by returning Router. All methods on Router return Route, this way users can still be able to mount, unmount, add failure handlers.

☑️ Removed the deprecated JWTAuthHandler exclude factory

`JWTAuthHandler.create(jwtAuth, "/excluded/path") deprecation was removed. This API had several limitation in terms of exclusions and had several flaws on error handling. The same functionality can be achieved by:

// 3.x
router
   // protect everything but "/excluded/path"
   .route().handler(JWTAuthHandler(jwtAuth, "/excluded/path")

// 4.0
router
   .route("/excluded/path").handler(/* public access to "/excluded/path" */)
   // protect everything
   .route().handler(JWTAuthHandler(jwtAuth)

☑️ Removed the deprecated StaticHandler.create(String, ClassLoader)

https://github.com/vert-x3/vertx-web/pull/1402

This was a required factory for OSGi environments, as OSGi is dropped from the modules this isnt't needed anymore. The alternative solution for users of this factory is to add the resources either to the application classpath or serve resources from the file system.

☑️ Deprecated SessionHandler.setAuthProvider(AuthProvider)

https://github.com/vert-x3/vertx-web/pull/1406

This deprecation which replaces the method: setAuthProvider with addAuthProvider allows multiple providers to be present in the application and session objects can now be matched and correctly linked. This is usefull when multiple providers are available, for example and application that supports WebAuthN and OAuth2.

☑️ Oauth2 Handler now requires vertx as constructor argument

The reason was that Oauth2 handler wasn't using the state of the Oauth2 protocol correctly which would mean that it could be vulnerable to replay attacks. The vertx argument allows us to use the secure non blocking random number generator to generate nonces avoid secure applications against this.

☑️ Renamed Prune BridgeOptions

https://github.com/vert-x3/vertx-web/issues/1499

The default SockJS bridge options have been renamed to SockJSBridgeOptions and now extend the common bridge options. This avoid duplicate code across modules and ensures a common behavior across bridges.

SockJSSocket: event bus writeHandler is disabled by default

https://github.com/vert-x3/vertx-web/issues/1221

SockJSSocket no longer registers a clustered event bus consumer by default. In order to write to the socket over the event bus, you must now enable this behavior in SockJSHandlerOptions:

Router router = Router.router(vertx);

SockJSHandlerOptions options = new SockJSHandlerOptions()
  .setRegisterWriteHandler(true); // enable the event bus consumer registration

SockJSHandler sockJSHandler = SockJSHandler.create(vertx, options);

router.mountSubRouter("/myapp", sockJSHandler.socketHandler(sockJSSocket -> {

  // Retrieve the writeHandlerID and store it (e.g. in a local map)
  String writeHandlerID = sockJSSocket.writeHandlerID();

}));

When enabled, the event bus consumer is now local only by default but this is configurable too:

SockJSHandlerOptions options = new SockJSHandlerOptions()
  .setRegisterWriteHandler(true) // enable the event bus consumer registration
  .setLocalWriteHandler(false) // register a clustered event bus consumer

Template engines

Template engines allow accessing the underlying engine/config object using:

engine.unwrap();

The returned type is engine specific and can be seen on the javadoc of the engine factory interface.

This also means that engines that were exposing configurations have those methods deprecated in favour of the common unwrap() api:

// Before (3.x)
HandlebarsTemplateEngine.getHandlerbars()
HandlebarsTemplateEngine.getResolvers()
HandlebarsTemplateEngine.setResolvers()
// After (4.0)
HandlebarsTemplateEngine.unwrap()
// from the handlebars object returned it is possible
// to get/set the resolvers too

// Before (3.x)
JadeTemplateEngine.getJadeConfiguration()
// After (4.0)
JadeTemplateEngine.unwrap()

// Before (3.x)
ThymeleafTemplateEngine.getThymeleafTemplateEngine()
ThymeleafTemplateEngine.setMode()
// After (4.0)
ThymeleafTemplateEngine.unwrap()
// mode is accessible by getting the loader from the engine

Vert.x Web Client.js

The vertx-web-client.js file isn't published to maven central anymore. Users should use the new location on NPM: @vertx/eventbus-bridge-client.js

Vert.x Kafka Client

☑️ Remove deprecated AdminUtils

https://github.com/vert-x3/vertx-kafka-client/commit/3ac632fc32d4bb6464633c13ca3615d34b513be4

The AdminUtils class, for doing administrative operations on a Kafka cluster, was removed. The new KafkaAdminClient class should be used for that.

https://github.com/vert-x3/vertx-kafka-client/pull/122

Vert.x Mail Client

☑️ MailAttachment is now an API interface and not anymore a data object

In order to allow mail attachment streaming we converted the MailAttachment data object to be an API object instead which will allow the streaming implementation.

https://github.com/vert-x3/vertx-mail-client/pull/110

☑️ MailConfig extends NetClientOptions

MailConfig extends NetClientOptions now to support proxy setting in the underline NetClient. This will lead to the following breaks:

  • This will lead to different output Json format regarding to the trusted keystore part, it can read the old Json format configuration.
  • The hashCode() and equals() methods take consideration of fields in the super class.

https://github.com/vert-x3/vertx-mail-client/pull/122

Creating a non shared client

MailClient#createNonShared method was deprecated in 3.8.x and is now removed. Use MailClient#create instead.

☑️ Vert.x Redis Client

The new API io.vertx.redis.client.Redis replaced the old one. The new API is connection oriented and supports all modern feature of Redis. In order to use an API similar to the old one an helper class: RedisAPI is available to expose all known commands as methods.

Removed deprecated term "slave" (following redis documentation) with "replica" on the API:

// Before (3.x)
Redis.createClient(
      rule.vertx(),
      new RedisOptions()
        .setType(RedisClientType.SENTINEL)
        .addConnectionString("redis://localhost:5000")
        .setMasterName("sentinel7000")
        .setRole(RedisRole.SLAVE));
// After (4.0)
Redis.createClient(
      rule.vertx(),
      new RedisOptions()
        .setType(RedisClientType.SENTINEL)
        .addConnectionString("redis://localhost:5000")
        .setMasterName("sentinel7000")
        .setRole(RedisRole.REPLICA));

And on the RedisOptions:

// Before (3.9)
options.setUseSlaves(RedisSlaves);
// After (4.0)
options.setUseReplicas(RedisReplicas);

Vert.x MQTT

☑️ Fluent methods

A few fluent methods return now Future instead of being fluent, e.g:

// 3.x
client
   .publish("hello", Buffer.buffer("hello"), MqttQoS.EXACTLY_ONCE, false, false)
   .publish("hello", Buffer.buffer("hello"), MqttQoS.AT_LEAST_ONCE, false, false);

// 4.0
client.publish("hello", Buffer.buffer("hello"), MqttQoS.EXACTLY_ONCE, false, false);
client.publish("hello", Buffer.buffer("hello"), MqttQoS.AT_LEAST_ONCE, false, false);

☑️ Removed deprecated methods

https://github.com/vert-x3/vertx-mqtt/issues/180

A few methods deprecated in Vert.x 3 have been removed

On MqttWill

// 3.x
System.out.println(will.willMessage());
System.out.println(will.willTopic());
System.out.println(will.willQos());

// 4.0
System.out.println(will.getWillMessage());
System.out.println(will.getWillTopic());
System.out.println(will.getWillQos());

On MqttAuth

// 3.x
System.out.println(auth.username());
System.out.println(auth.password());

// 4.0
System.out.println(auth.getUsername());
System.out.println(auth.getPassword());

On MqttClientOptions

// 3.x
options.setKeepAliveTimeSeconds(4);

// 4.0
options.setKeepAliveInterval(4);

☑️ MqttWill message is now a buffer

MqttWill data object will get and set a string message, these methods are deprecated in Vert.x 3 in favor of getWillMessageBytes and setWillMessageBytes.

In Vert.x 4, those methods are not deprecated anymore and instead will return a buffer.

☑️ Vert.x Kafka Client

https://github.com/vert-x3/vertx-kafka-client/issues/145

The flush operations are declared with Handler<Void> argument instead of Handler<AsyncResult<Void>>. They have been changed to the correct type. In practice the user code will work equally well and will get an async result instead of null value.

☑️ Vert.x Circuit Breaker

https://github.com/vert-x3/vertx-circuit-breaker/issues/36

executeCommandXXX methods are renamed executeXXX for futurization purpose. In the 3.x branch we deprecate these methods and we add the new methods as deprecation replacements. These methods are removed in Vert.x 4 because of the renaming.

// 3.x
breaker.executeCommand(promise -> ..., res -> ...);

// 4.0
breaker.execute(promise -> ..., res -> ...);

☑️ Vert.x AMQP Client

https://github.com/vert-x3/vertx-amqp-client/issues/21

Currently the client declares a few methods that takes an Handler<AmqpMessage> as parameter, this handler is then set on a ReadStream<AmqpMessage>. Such methods raise issues with futurisation as the futurised form has the same erased signature than other methods, e.g

Future<AmqpReceiver> createReceiver(String, Handler<AmqpMessage>);
void createReceiver(String, Handler<AsyncResult<AmqpReceiver>>);

Such methods are removed in Vert.x 4 and are deprecated in 3.x

Vert.x Auth

☑️ OAuth2Auth#createKeycloak is removed

The factory method was removed as it was deprecated for long time. To configure Keycloak users should now use the provider factory:

io.vertx.ext.auth.oauth2.providers.KeycloakAuth this provider will allow configuring the provider similar to the old factory: KeycloakAuth#create(vertx, JsonObject) as well as other mechanisms such as OpenID Discovery.

☑️ OAuth2Auth#create(Vertx, OAuth2FlowType, OAuth2ClientOptions) is removed

The factory method was removed as it was deprecated for long time. The flow type is configurable on the OAuth2ClientOptions options object so this factory introduced confusion. User should use:

OAuth2Auth.create(vertx, new OAuth2ClientOptions().setFlow(YOUR_DESIRED_FLOW));

☑️ OAuth2Auth#create(Vertx, OAuth2FlowType) is removed

The factory method was removed as it was deprecated for long time. The flow type is configurable on the OAuth2ClientOptions options object so this factory introduced confusion. User should use:

OAuth2Auth.create(vertx, new OAuth2ClientOptions().setFlow(YOUR_DESIRED_FLOW));

☑️ io.vertx.ext.auth.jwt.JWTOptions is removed

This data object was deprecated as it was yet another way to define JWT options, it was replaced by io.vertx.ext.jwt.JWTOptions with the same structure as this allows JWT options to be shared with other providers.

☑️ io.vertx.ext.auth.oauth2.AccessToken#refreshToken is removed

Refresh tokens are vendor specific and are not guaranteed to be JWTs therefore cannot be decoded/verified. Access is still possible using:

accessToken.opaqueRefreshToken()

Which returns the raw String instead of the json object.

☑️ io.vertx.ext.auth.User#isAuthorised is removed

The deprecated method was replaced by the z variant as it makes it easier to reason with AuthZ

user.isAuthorized("some-permission", hander);

☑️ SecretOptions is removed

This option is duplicate of PubSecKeyOptions in order to keep just 1 API to achieve the same result the option class was removed and users are expected to update their code to:

// 3.x
new SecretOptions()
        .setType("HS256")
        .setSecret("notasecret")

// 4.0
new PubSecKeyOptions()
        .setAlgorithm("HS256")
        .setSecretKey("notasecret")

☑️ Vert.x Service Discovery

The creation of ServiceDiscovery passing an Handler<ServiceDiscovery> is removed.

The methods

  • ServiceDiscovery#registerServiceImporter
  • ServiceDiscovery#registerServiceExporter

are not fluent anymore since now they return Future<Void> instead.

☑️ Vert.x Service Config

https://github.com/vert-x3/vertx-config/issues/97

The instance method of ConfigRetriever (and deprecated in 3.x)

// deprecated
Future<JsonObject> fut = ConfigRetriever. getConfigAsFuture(retriever);

// instead use in 4
fut = retriever.getConfig();

☑️ Vert.x Mongo Client

https://github.com/vert-x3/vertx-mongo-client/issues/204

The following methods have been deprecated for a long time in 3.x and removed in Vert.x 4

  • update(String collection, JsonObject query, JsonObject update, Handler<AsyncResult<Void>> resultHandler) instead use updateCollection
  • updateWithOptions(String collection, JsonObject query, JsonObject update, UpdateOptions options, Handler<AsyncResult<Void>> resultHandler) instead use updateCollectionWithOptions
  • replace(String collection, JsonObject query, JsonObject replace, Handler<AsyncResult<Void>> resultHandler) instead use replaceDocuments
  • replaceWithOptions(String collection, JsonObject query, JsonObject replace, UpdateOptions options, Handler<AsyncResult<Void>> resultHandler) instead use replaceDocumentsWithOptions
  • remove(String collection, JsonObject query, Handler<AsyncResult<Void>> resultHandler) instead use removeDocuments
  • removeWithOptions(String collection, JsonObject query, WriteOption writeOption, Handler<AsyncResult<Void>> resultHandler) instead use removeDocumentsWithOptions
  • removeOne(String collection, JsonObject query, Handler<AsyncResult<Void>> resultHandler) instead use removeDocument
  • removeOneWithOptions(String collection, JsonObject query, WriteOption writeOption, Handler<AsyncResult<Void>> resultHandler) instead use removeDocumentsWithOptions

e.g

// 3.x
mongoClient.update(collection, new JsonObject().put("_id", docIdToBeUpdated), new JsonObject().put("$set", new JsonObject().put("foo", "fooed")), ar -> ... });

// 4.0
mongoClient.updateCollection(collection, new JsonObject().put("_id", docIdToBeUpdated), new JsonObject().put("$set", new JsonObject().put("foo", "fooed")), ar -> ...});

Creating a non shared client

MongoClient#createNonShared method was deprecated in 3.8.x and is now removed. Use MongoClient#create instead.

☑️ Vert.x Stomp

StompClientConnection frame based methods should use an async result

https://github.com/vert-x3/vertx-stomp/issues/58

Currently StompClientConnection has a bunch of methods consuming a Handler<Frame> as receipt handler, such signatures don't handle failures and needs to be changed to use Handler<AsyncResult<Frame>> instead.

// 3.x
connection.send("/queue", Buffer.buffer("Hello"), frame -> ...);

// 4.0
connection.send("/queue", Buffer.buffer("Hello"), res -> {
  if (res.succeeded()) {
    Frame frame = res.result();
    ...
  } else {
    ...
  }
});

StompClientConnection subscribe method should return an async id instead of a frame

https://github.com/vert-x3/vertx-stomp/issues/59

StompClientConnection has its subscribe method that returns the subscription id. Since we are futurizing the client, such method will instead return a Future of the result and thus we need before to have the subscribe method to use a receipt handler of the id instead of the frame.

Handler<Frame> handler = frame -> System.out.println("Just received a frame from /queue : " + frame);

// 3.x
String id = connection.subscribe("/queue", handler);

// 4.0
connection.subscribe("/queue", handler, res -> {
  if (res.succeeded()) {
    String id = res.results();
  } else {
    // Failure
  }
});

☑️ Vert.x RabbitMQ Client

The client has been reworked in Vert.x 4 to use RabbitMQ types instead of wrappers or JsonObject for these types

Use void async result type instead of JsonObject in ack/nack

// 3.x
client.ack(tag, true, res -> {
  if (res.succeeded()) {
    JsonObject o = res.result()
    // o was actually null
  }
});

// 4.0
client.ack(tag, true, res -> {
  if (res.succeeded()) {
    Void v = res.result()
  }
});

Basic get uses RabbitMQ message instead JSON object

// 3.x
client.basicGet("my.queue", true, res -> {
  if (res.succeeded()) {
    JsonObject msg = res.results();
    ...
  }
  ...
});

// 4.0
client.basicGet("my.queue", true, res -> {
  if (res.succeeded()) {
    RabbitMQMessage msg = res.results();
    ...
  }
  ...
});

Rabbit MQ message use RabbitMQ properties and envelope instead of wrappers

// 3.x
client.basicConsumer("my.queue", ar -> {
  if (ar.succeeded()) {
    RabbitMQConsumer consumer = ar.result();
    consumer.handler(msg -> {
      io.vertx.rabbitmq.BasicProperties props = msg.properties();
      io.vertx.rabbitmq.Envelope envelope = msg.envelope();
    });
  }
});

// 4.0
client.basicConsumer("my.queue", ar -> {
  if (ar.succeeded()) {
    RabbitMQConsumer consumer = ar.result();
    consumer.handler(msg -> {
      com.rabbitmq.client.BasicProperties props = msg.properties();
      com.rabbitmq.clientEnvelope envelope = msg.envelope();
    });
  }
});

Basic publish should use RabbitMQ properties and buffer instead of JSON Object

// 3.x
JsonObject message = new JsonObject().put("body", "Hello RabbitMQ, from Vert.x !");
message.put("priority", priority);
client.basicPublish("", "my.queue", message, pubResult -> ...);

// 4.0
Buffer message = Buffer.buffer("Hello RabbitMQ, from Vert.x !");
BasicProperties props, new AMQP.BasicProperties.Builder().priority(priority).build();
client.basicPublish("", "my.queue", props, message, pubResult -> ...);

client queue declaration method provides Rabbit MQ async result instead of JSON object

// 3.x
client.queueDeclare("my.queue", true, true, ar -> {
  if (ar.succeeded()) {
    JsonObject res = ar.result();
  }
  ...
});

// 4.0
client.queueDeclare("my.queue", true, true, ar -> {
  if (ar.succeeded()) {
    AMQP.Queue.DeclareOk res = ar.result();
  }
  ...
});

client queue delete method provides Rabbit MQ async result instead of JSON object

// 3.x
client.queueDelete("my.queue", ar -> {
  if (ar.succeeded()) {
    JsonObject res = ar.result();
  }
  ...
});

// 4.0
client.queueDelete("my.queue", ar -> {
  if (ar.succeeded()) {
    AMQP.Queue.DeleteOk res = ar.result();
  }
  ...
});

Reconnect options renamed

The RabbitMQOptions#setConnectionRetries and RabbitMQOptions#setConnectionRetryDelay have been renamed to setReconnectAttempts and setReconnectInterval since now RabbitMQOptions extends NetClientOptions and inherit from them

// 3.x
options.setConnectionRetries(10).setConnectionRetryDelay(500);

// 4.0
options.setReconnectAttempts(10).setReconnectInterval(500);

☑️ Vert.x Web - GraphQL

Polyglot support

The current tech preview API has been changed to be supported on polyglot environments:

  • UploadScalar is now a factory, use UploadScalar.create()
  • VertxBatchLoader is now a factory, use: io.vertx.ext.web.handler.graphql.dataloader.VertxBatchLoader.create()
  • VertxDataFetcher is now a factory, use: io.vertx.ext.web.handler.graphql.schema.VertxDataFetcher.create()
  • VertxPropertyDataFetcher is now a factory, use: io.vertx.ext.web.handler.graphql.schema.VertxPropertyDataFetcher.create()

Dependency on BodyHandler

Graphql used to handle post data on its own. The implementation was limited and did not cover reroute, multipart uploads and was susceptible to DDoS attacks. For this reason it is required to have BodyHandler on the route for non GET or WS requests.

Vert.x Codegen

Standardize on templateFilename and filename attribute names

In codegen.json files, it was possible to use either templateFilename or templateFileName attribute names, even if the former was the only one documented. Same goes with filename and fileName

Vert.x 4.0 will no longer supports alternative attribute names and standardizes on templateFilename and filename.

Deprecated processor options removal

Removed the support for codeGenerators (replaced by codegen.generators) and outputDirectory (replaced by codegen.output). Those are internal changes for code generators mainly and most users should not be affected.

Vert.x JDBC Client

Vert.x SQL common merged in JDBC client

https://github.com/vert-x3/vertx-sql-common/issues/69

The io.vertx:vertx-sql-common module is now part of io.vertx:vertx-jdbc-client.

Creating a non shared client

JDBCClient#createNonShared method was deprecated in 3.8.x and is now removed. Use JDBCClient#create instead.

Vert.x Cassandra Client

Creating a non shared client

CassandraClient#createNonShared methods were deprecated in 3.8.x and are now removed. Use CassandraClient#create instead.

DataStax driver version change

Major DataStax driver version has been changed from 3 to 4.

Migration requires import and usage changes when querying:

// vertx 3.x
import com.datastax.driver.core.SimpleStatement;

SimpleStatement statement =
  new SimpleStatement("SELECT release_version FROM system.local");
cassandraClient.execute(statement, ar -> ... );

// vertx 4.x+
import com.datastax.oss.driver.api.core.cql.SimpleStatement;

SimpleStatement statement =
  SimpleStatement.newInstance("SELECT release_version FROM system.local");
cassandraClient.execute(statement, ar -> ... );

There are also changes needed when creating the client:

// Vert.x Cassandra Client 3.x:
import com.datastax.driver.core.Cluster;
import io.vertx.cassandra.CassandraClientOptions;

new CassandraClientOptions(Cluster.builder());

// Vert.x Cassandra Client 4.x:
import com.datastax.oss.driver.api.core.CqlSession;
import com.datastax.oss.driver.api.core.CqlSessionBuilder;
import io.vertx.cassandra.CassandraClientOptions;

new CassandraClientOptions(CqlSession.builder());

Methods setPort, getContactPoints and setContactPoints were removed. Instead, addContactPoint is expected to be used:

// Vert.x Cassandra Client 3.x:
import io.vertx.cassandra.CassandraClient;
import io.vertx.cassandra.CassandraClientOptions;
CassandraClientOptions options = new CassandraClientOptions()
  .setContactPoints(List.of("node1.address", "node2.address", "node3.address"))
  .setPort(9142)
  .setKeyspace("my_keyspace");
CassandraClient client = CassandraClient.create(vertx, options); 

// Vert.x Cassandra Client 4.x:
import io.vertx.cassandra.CassandraClient;
import io.vertx.cassandra.CassandraClientOptions;
CassandraClientOptions options = new CassandraClientOptions()
  .addContactPoint("node1.address", 9142)
  .addContactPoint("node2.address", 9142)
  .addContactPoint("node3.address", 9142)
  .setKeyspace("my_keyspace");
CassandraClient client = CassandraClient.create(vertx, options);  

Mappers are not supported anymore

Such constructions as this one:

@Table(keyspace = "test", name = "names")
public class MappedClass {
  @PartitionKey
  private String name;
   ...
}

are no longer possible.

Vert.x Lang Kotlin

☑️ Removal of script compiler

https://github.com/vert-x3/vertx-lang-kotlin/issues/166

Vert.x 3 provides a Kotlin Script compiler based on Kotlin Compiler API. The API often breaks and creates friction for upgrading Kotlin versions. This is removed in Vert.x 4.0.

☑️ Deprecate generated coroutine extension methods

https://github.com/vert-x3/vertx-lang-kotlin/issues/174

Vert.x 3 generates extension suspending extension methods, e.g get(Handler<AsyncResult<Result>> generates getAwait() extension method. Vert.x 4 provides a future based model and the Vert.x Future has an await() extension methods that does the same.

// vert.x 3
var result = getSomethingAwait();

result = getSomething().await();

☑️ Removed 3.x deprecated methods

https://github.com/vert-x3/vertx-lang-kotlin/issues/140

JsonArray(...) and JsonObject(...) function have been removed instead jsonObjectOf(...) and jsonArrayOf(...) should be used.

// Before
val json = JsonObject("name" to "Julien")

// After
val json = jsonObjectOf("name" to "Julien")

Likewise data object generated functions named after the data object name have been removed, instead the XyzOf function should be used.

// Before
val account = Account(id = 1, name = "name")

// After
val account = accountOf(id = 1, name = "name")

Vert.x JUnit5

Split the core implementation and extensions

Due to a dependency cycle in the Vert.x stack, the core has been rewritten around a service provider interface for parameter injection.

While this is largely transparent in terms of API, you need to be aware that:

  1. the Vertx parameter should be placed before any parameter that requires it for creation, such as when injecting a WebClient,
  2. the vertx-junit5 module now only offers APIs for the Vert.x core module (vertx-core),
  3. the reactiverse-junit5-extensions module now hosts extensions that offer extra parameter types like WebClient,
  4. the RxJava 1 and 2 bindings are now offered as vertx-junit5-rx-java and vertx-junit5-rx-java2 modules in the vertx-junit5-extensions repository.

Deprecation of succeeding() and failing() in VertxTestContext

This is to improve ergonomics, see https://github.com/vert-x3/vertx-junit5/pull/80, you should now use succeedingThenComplete() and failingThenComplete().

Cluster Managers

In Vert.x 4, the clustering SPI has been redesigned. In particular, the subscription data model has changed in an incompatible way. As a consequence, Vert.x 3 nodes and Vert.x 4 nodes cannot be put together in the same cluster.

This applies to all the supported cluster managers: vertx-hazelcast, vertx-infinispan, vertx-zookeeper and vertx-ignite.

Vert.x application code is not impacted though, as the EventBus and SharedData APIs remain the same.

Hazelcast cluster manager

If a custom configuration is provided:

  • add the __vertx.nodeInfo map
  <map name="__vertx.nodeInfo">
    <backup-count>1</backup-count>
  </map>

Infinispan cluster manager

This cluster manager is now based on Infinispan 11.

If a custom configuration is provided:

  • change the __vertx.subs cache type to replicated instead of distributed
  • add the replicated __vertx.nodeInfo cache
  <cache-container default-cache="distributed-cache">
    <distributed-cache name="distributed-cache"/>
    <replicated-cache name="__vertx.subs"/>
    <replicated-cache name="__vertx.haInfo"/>
    <replicated-cache name="__vertx.nodeInfo"/>
    <distributed-cache-configuration name="__vertx.distributed.cache.configuration"/>
  </cache-container>

If you run a Vert.x cluster on Kubernetes/Openshift, the infinispan-cloud JAR is no longer needed and shall be removed from the dependencies section of your build file. The configuration files bundled in this JAR are now included in the infinispan-core JAR.

Ignite cluster manager

If a custom configuration is provided:

  • change all __vertx.* caches types to replicated
  • add the EVT_CACHE_OBJECT_PUT type to listened events
  <property name="cacheConfiguration">
    <list>
      <bean class="org.apache.ignite.configuration.CacheConfiguration">
        <property name="name" value="__vertx.*"/>
        <property name="cacheMode" value="REPLICATED"/>
        <property name="readFromBackup" value="false"/>
        <property name="atomicityMode" value="ATOMIC"/>
        <property name="writeSynchronizationMode" value="FULL_SYNC"/>
      </bean>
      <bean class="org.apache.ignite.configuration.CacheConfiguration">
        <property name="name" value="*"/>
        <property name="cacheMode" value="PARTITIONED"/>
        <property name="backups" value="1"/>
        <property name="readFromBackup" value="false"/>
        <property name="atomicityMode" value="ATOMIC"/>
        <property name="writeSynchronizationMode" value="FULL_SYNC"/>
      </bean>
    </list>
  </property>

  <property name="includeEventTypes">
    <list>
      <util:constant static-field="org.apache.ignite.events.EventType.EVT_CACHE_OBJECT_PUT"/>
      <util:constant static-field="org.apache.ignite.events.EventType.EVT_CACHE_OBJECT_REMOVED"/>
    </list>
  </property>

Vert.x Sync

The vertx-sync module has been deprecated due to the Quasar project being effectively abandoned.

In the future we are interested in coming with a programming model abstraction based on top of Project Loom.

See https://github.com/vert-x3/vertx-sync/pull/40

Vert.x Stack

NPM Client

The NPM client has been removed from the stack, users should use the new package @vertx/eventbus-bridge-client.js

# Before
npm install --save vertx3-eventbus-client
# After (4.0.0)
npm install --save @vertx/eventbus-bridge-client.js

The version of the new module will only be bumped on major changes or bug fixes, so there is no need to update the dependency on every vertx release.

Clone this wiki locally