
io.quarkus.vertx.http.runtime.devmode.VertxHttpHotReplacementSetup Maven / Gradle / Ivy
package io.quarkus.vertx.http.runtime.devmode;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.LogManager;
import io.netty.handler.codec.http.HttpHeaderNames;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.quarkus.dev.ErrorPageGenerators;
import io.quarkus.dev.config.CurrentConfig;
import io.quarkus.dev.console.DevConsoleManager;
import io.quarkus.dev.spi.HotReplacementContext;
import io.quarkus.dev.spi.HotReplacementSetup;
import io.quarkus.vertx.core.runtime.VertxCoreRecorder;
import io.quarkus.vertx.http.runtime.VertxHttpRecorder;
import io.vertx.core.AsyncResult;
import io.vertx.core.Handler;
import io.vertx.core.MultiMap;
import io.vertx.core.Promise;
import io.vertx.core.http.HttpServerResponse;
import io.vertx.core.net.impl.ConnectionBase;
import io.vertx.ext.web.RoutingContext;
public class VertxHttpHotReplacementSetup implements HotReplacementSetup {
private volatile long nextUpdate;
private HotReplacementContext hotReplacementContext;
private static final long HOT_REPLACEMENT_INTERVAL = 2000;
private static final String HEADER_NAME = "x-quarkus-hot-deployment-done";
private static final String CONFIG_FIX = "io.quarkus.vertx-http.devmode.config.fix";
@Override
public void setupHotDeployment(HotReplacementContext context) {
// ensure that Vert.x runs in dev mode, this prevents Vert.x from caching static resources
System.setProperty("vertxweb.environment", "dev");
this.hotReplacementContext = context;
VertxHttpRecorder.setHotReplacement(this::handleHotReplacementRequest, hotReplacementContext);
hotReplacementContext.addPreScanStep(new Runnable() {
@Override
public void run() {
RemoteSyncHandler.doPreScan();
}
});
}
@Override
public void handleFailedInitialStart() {
//remove for vert.x 4.2
//at the moment there is a TCCL error that is normally handled by the log filters
//but if startup fails it may not take effect
//it happens once per thread, so it can completely mess up the console output, and hide the real issue
LogManager.getLogManager().getLogger("io.vertx.core.impl.ContextImpl").setLevel(Level.SEVERE);
VertxHttpRecorder.startServerAfterFailedStart();
}
private static volatile Set openConnections;
public static void handleDevModeRestart() {
if (DevConsoleManager.isDoingHttpInitiatedReload()) {
return;
}
Set cons = VertxHttpHotReplacementSetup.openConnections;
if (cons != null) {
for (ConnectionBase con : cons) {
con.close();
}
}
}
void handleHotReplacementRequest(RoutingContext routingContext) {
if (openConnections == null) {
synchronized (VertxHttpHotReplacementSetup.class) {
if (openConnections == null) {
openConnections = Collections.newSetFromMap(new ConcurrentHashMap<>());
}
}
}
ConnectionBase connectionBase = (ConnectionBase) routingContext.request().connection();
if (openConnections.add(connectionBase)) {
connectionBase.closeFuture().onComplete(new Handler>() {
@Override
public void handle(AsyncResult event) {
openConnections.remove(connectionBase);
}
});
}
if (hotReplacementContext.getDeploymentProblem() != null && routingContext.request().path().endsWith(CONFIG_FIX)) {
routingContext.request().setExpectMultipart(true);
routingContext.request().endHandler(new Handler() {
@Override
public void handle(Void event) {
VertxCoreRecorder.getVertx().get().getOrCreateContext().executeBlocking(new Handler>() {
@Override
public void handle(Promise
© 2015 - 2025 Weber Informatics LLC | Privacy Policy