Skip to content

Commit

Permalink
chore: upgrade to Vert.x 4.5.1, fix deprecations
Browse files Browse the repository at this point in the history
  • Loading branch information
kristian committed Jan 12, 2024
1 parent be23b81 commit ea4c3b0
Show file tree
Hide file tree
Showing 7 changed files with 128 additions and 82 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ repositories {

dependencies {
// Framework dependencies
def vertx_version = '4.5.0'
def vertx_version = '4.5.1'
implementation group: 'io.vertx', name: 'vertx-core', version: vertx_version
implementation group: 'io.vertx', name: 'vertx-web', version: vertx_version
implementation group: 'io.vertx', name: 'vertx-web-client', version: vertx_version
Expand Down
125 changes: 77 additions & 48 deletions src/main/java/io/neonbee/NeonBee.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
import java.util.function.Predicate;
import java.util.stream.Collectors;

import javax.annotation.Nullable;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -248,14 +250,16 @@ public static Future<NeonBee> create(NeonBeeOptions options) {
* @return the future to a new NeonBee instance initialized with default options and a new Vert.x instance
*/
public static Future<NeonBee> create(NeonBeeOptions options, NeonBeeConfig config) {
return create((OwnVertxFactory) vertxOptions -> newVertx(vertxOptions, options), options.getClusterManager(),
options, config);
// using the marker interface we signal, that we are responsible of also closing Vert.x if NeonBee shuts down
return create((OwnVertxFactory) (vertxOptions, clusterManager) -> {
return newVertx(vertxOptions, clusterManager, options);
}, options.getClusterManager(), options, config);
}

@VisibleForTesting
@SuppressWarnings({ "PMD.EmptyCatchBlock", "PMD.AvoidCatchingThrowable" })
static Future<NeonBee> create(Function<VertxOptions, Future<Vertx>> vertxFactory,
ClusterManagerFactory clusterManagerFactory, NeonBeeOptions options, NeonBeeConfig config) {
static Future<NeonBee> create(VertxFactory vertxFactory, @Nullable ClusterManagerFactory clusterManagerFactory,
NeonBeeOptions options, NeonBeeConfig config) {
try {
// create the NeonBee working and logging directory (as the only mandatory directory for NeonBee)
Files.createDirectories(options.getLogDirectory());
Expand All @@ -271,52 +275,61 @@ static Future<NeonBee> create(Function<VertxOptions, Future<Vertx>> vertxFactory
vertxOptions.setMetricsOptions(new MicrometerMetricsOptions().setRegistryName(options.getMetricsRegistryName())
.setMicrometerRegistry(compositeMeterRegistry).setEnabled(true));

Future<VertxOptions> loadClusterManager = !options.isClustered() ? succeededFuture(vertxOptions)
: clusterManagerFactory.create(options).map(vertxOptions::setClusterManager);

// create a Vert.x instance (clustered or unclustered)
return loadClusterManager.compose(vertxFactory).compose(vertx -> {
// at this point at any failure that occurs, it is in our responsibility to properly close down the created
// Vert.x instance again. we have to be vigilant the fact that a runtime exception could happen anytime!
Function<Throwable, Future<Void>> closeVertx = throwable -> {
if (!(vertxFactory instanceof OwnVertxFactory)) {
// the Vert.x instance is *not* owned by us, thus don't close it either
LOGGER.error("Failure during bootstrap phase.", throwable); // NOPMD slf4j
return failedFuture(throwable);
}

// the instance has been created, but after initialization some post-initialization
// tasks went wrong, stop Vert.x again. This will also call the close hook and clean up.
LOGGER.error("Failure during bootstrap phase. Shutting down Vert.x instance.", throwable);

// we wait for Vert.x to close, before we propagate the reason why booting failed
return vertx.close().transform(closeResult -> failedFuture(throwable));
};
Future<ClusterManager> loadClusterManager = succeededFuture();
if (options.isClustered()) {
if (clusterManagerFactory == null) {
return failedFuture("Missing a cluster manager factory to create a clustered NeonBee instance");
}

try {
Future<NeonBeeConfig> configFuture;
if (config == null) {
configFuture = loadConfig(vertx, options.getConfigDirectory());
} else {
configFuture = succeededFuture(config);
}
loadClusterManager = clusterManagerFactory.create(options);
}

// create a NeonBee instance, hook registry and close handler
Future<NeonBee> neonBeeFuture = configFuture.map(loadedConfig -> {
return new NeonBee(vertx, options, loadedConfig, compositeMeterRegistry);
// create a Vert.x instance (clustered or unclustered)
return loadClusterManager.compose(clusterManager -> vertxFactory.create(vertxOptions, clusterManager))
.compose(vertx -> {
// from this point onwards, if any failure that occurs it will be our responsibility to properly
// close down the Vert.x instance again (in case it was created by us in the first place). we have
// to be vigilant the fact that a runtime exception could happen anytime!
Function<Throwable, Future<Void>> closeVertx = throwable -> {
if (!(vertxFactory instanceof OwnVertxFactory)) {
// the Vert.x instance is *not* owned by us, thus don't close it either
LOGGER.error("Failure during bootstrap phase.", throwable); // NOPMD slf4j
return failedFuture(throwable);
}

// the instance has been created, but after initialization some post-initialization tasks went
// wrong, stop Vert.x again. This will also call the close hook and clean up
LOGGER.error("Failure during bootstrap phase. Shutting down Vert.x instance.", throwable);

// we wait for Vert.x to close, before we propagate the reason why booting failed
return vertx.close().transform(closeResult -> failedFuture(throwable));
};

try {
Future<NeonBeeConfig> configFuture;
if (config == null) {
configFuture = loadConfig(vertx, options.getConfigDirectory());
} else {
configFuture = succeededFuture(config);
}

// create a NeonBee instance, hook registry and close handler
Future<NeonBee> neonBeeFuture = configFuture.map(loadedConfig -> {
return new NeonBee(vertx, options, loadedConfig, compositeMeterRegistry);
});

// boot NeonBee, on failure close Vert.x
return neonBeeFuture.compose(NeonBee::boot).recover(closeVertx)
.compose(unused -> neonBeeFuture);
} catch (Throwable t) {
// on any exception (e.g. during initialization of NeonBee) don't forget to close Vert.x!
return closeVertx.apply(t).mapEmpty();
}
});

// boot NeonBee, on failure close Vert.x
return neonBeeFuture.compose(NeonBee::boot).recover(closeVertx).compose(unused -> neonBeeFuture);
} catch (Throwable t) {
// on any exception (e.g. during the initialization of a NeonBee object) don't forget to close Vert.x!
return closeVertx.apply(t).mapEmpty();
}
});
}

@VisibleForTesting
static Future<Vertx> newVertx(VertxOptions vertxOptions, NeonBeeOptions options) {
static Future<Vertx> newVertx(VertxOptions vertxOptions, ClusterManager clusterManager, NeonBeeOptions options) {
if (!options.isClustered()) {
return succeededFuture(Vertx.vertx(vertxOptions));
}
Expand All @@ -326,7 +339,9 @@ static Future<Vertx> newVertx(VertxOptions vertxOptions, NeonBeeOptions options)
.ifPresent(currentIp -> vertxOptions.getEventBusOptions().setHost(currentIp));

return applyEncryptionOptions(options, vertxOptions.getEventBusOptions())
.compose(v -> Vertx.clusteredVertx(vertxOptions)).onFailure(throwable -> {
.compose(v -> Vertx.builder().with(vertxOptions)
.withClusterManager(clusterManager).buildClustered())
.onFailure(throwable -> {
LOGGER.error("Failed to start clustered Vert.x", throwable); // NOPMD slf4j
});
}
Expand All @@ -342,8 +357,7 @@ static Future<Void> applyEncryptionOptions(NeonBeeOptions neonBeeOptions, EventB
Optional.ofNullable(neonBeeOptions.getClusterTruststorePassword())
.ifPresent(truststoreOpts::setAliasPassword);

ebo.setSsl(true).setClientAuth(REQUIRED).setPfxKeyCertOptions(keystoreOpts)
.setPfxTrustOptions(truststoreOpts);
ebo.setSsl(true).setClientAuth(REQUIRED).setKeyCertOptions(keystoreOpts).setTrustOptions(truststoreOpts);
return succeededFuture();
} else if (neonBeeOptions.getClusterKeystore() == null && neonBeeOptions.getClusterTruststore() == null) {
return succeededFuture();
Expand Down Expand Up @@ -869,10 +883,25 @@ public boolean isStarted() {
return started.get();
}

/**
* Vert.x factory by NeonBee to create a Vert.x instance.
*/
@FunctionalInterface
public interface VertxFactory {
/**
* Called (exactly once) by NeonBee to create a Vert.x instance to use for initialization afterwards.
*
* @param options The Vert.x options to be used, parameterized according to the options / configuration
* @param clusterManager in case NeonBee is configured to be started clustered, the cluster manager to use
* @return a future to a Vert.x instance
*/
Future<Vertx> create(VertxOptions options, @Nullable ClusterManager clusterManager);
}

/**
* Hidden marker function interface, that indicates to the boot-stage that an own Vert.x instance was created, and
* we must be held responsible to close it again.
*/
@VisibleForTesting
interface OwnVertxFactory extends Function<VertxOptions, Future<Vertx>> {}
interface OwnVertxFactory extends VertxFactory {}
}
8 changes: 8 additions & 0 deletions src/main/java/io/neonbee/config/ServerConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -857,6 +857,7 @@ public ServerConfig setInitialSettings(Http2Settings settings) {
}

@Override
@SuppressWarnings("deprecation") // reason: we have to comply to the interface still
public ServerConfig setJdkSslEngineOptions(JdkSSLEngineOptions sslEngineOptions) {
super.setJdkSslEngineOptions(sslEngineOptions);
return this;
Expand All @@ -869,6 +870,7 @@ public ServerConfig setKeyCertOptions(KeyCertOptions options) {
}

@Override
@SuppressWarnings("deprecation") // reason: we have to comply to the interface still
public ServerConfig setKeyStoreOptions(JksOptions options) {
super.setKeyStoreOptions(options);
return this;
Expand Down Expand Up @@ -911,18 +913,21 @@ public ServerConfig setMaxWebSocketMessageSize(int maxWebSocketMessageSize) {
}

@Override
@SuppressWarnings("deprecation") // reason: we have to comply to the interface still
public ServerConfig setOpenSslEngineOptions(OpenSSLEngineOptions sslEngineOptions) {
super.setOpenSslEngineOptions(sslEngineOptions);
return this;
}

@Override
@SuppressWarnings("deprecation") // reason: we have to comply to the interface still
public ServerConfig setPemKeyCertOptions(PemKeyCertOptions options) {
super.setPemKeyCertOptions(options);
return this;
}

@Override
@SuppressWarnings("deprecation") // reason: we have to comply to the interface still
public ServerConfig setPemTrustOptions(PemTrustOptions options) {
super.setPemTrustOptions(options);
return this;
Expand All @@ -941,12 +946,14 @@ public ServerConfig setPerMessageWebSocketCompressionSupported(boolean supported
}

@Override
@SuppressWarnings("deprecation") // reason: we have to comply to the interface still
public ServerConfig setPfxKeyCertOptions(PfxOptions options) {
super.setPfxKeyCertOptions(options);
return this;
}

@Override
@SuppressWarnings("deprecation") // reason: we have to comply to the interface still
public ServerConfig setPfxTrustOptions(PfxOptions options) {
super.setPfxTrustOptions(options);
return this;
Expand Down Expand Up @@ -1079,6 +1086,7 @@ public ServerConfig setTrustOptions(TrustOptions options) {
}

@Override
@SuppressWarnings("deprecation") // reason: we have to comply to the interface still
public ServerConfig setTrustStoreOptions(JksOptions options) {
super.setTrustStoreOptions(options);
return this;
Expand Down
4 changes: 3 additions & 1 deletion src/test/java/io/neonbee/NeonBeeExtension.java
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,9 @@ private NeonBee createNeonBee(NeonBeeOptions options, NeonBeeInstanceConfigurati
AtomicReference<NeonBee> neonBeeBox = new AtomicReference<>();
AtomicReference<Throwable> errorBox = new AtomicReference<>();

NeonBee.create((NeonBee.OwnVertxFactory) (vertxOptions) -> NeonBee.newVertx(vertxOptions, options),
NeonBee.create(
(NeonBee.OwnVertxFactory) (vertxOptions, clusterManagerInstance) -> NeonBee.newVertx(vertxOptions,
clusterManagerInstance, options),
clusterManager.factory(), options, null).onComplete(ar -> {
if (ar.succeeded()) {
neonBeeBox.set(ar.result());
Expand Down
2 changes: 1 addition & 1 deletion src/test/java/io/neonbee/NeonBeeMockHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ public static Future<NeonBee> createNeonBee(Vertx vertx) {
* @return the mocked NeonBee instance
*/
public static Future<NeonBee> createNeonBee(Vertx vertx, NeonBeeOptions options) {
return NeonBee.create((vertxOptions) -> {
return NeonBee.create((vertxOptions, clusterManager) -> {
if (vertxOptions.getMetricsOptions() != null) {
new VertxMetricsFactoryImpl().metrics(vertxOptions);
}
Expand Down
Loading

0 comments on commit ea4c3b0

Please sign in to comment.