Skip to content

Commit

Permalink
fix: use provided executor for frontend tools (#9553)
Browse files Browse the repository at this point in the history
fixes vaadin/spring#691
# Conflicts:
#	flow-server/src/main/java/com/vaadin/flow/server/DevModeHandler.java
#	flow-server/src/main/java/com/vaadin/flow/server/startup/DevModeInitializer.java
  • Loading branch information
Denis committed Dec 3, 2020
1 parent adebce2 commit 5480e98
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 39 deletions.
Expand Up @@ -15,17 +15,9 @@
*/
package com.vaadin.flow.server;

import static com.vaadin.flow.server.InitParameters.SERVLET_PARAMETER_DEVMODE_WEBPACK_ERROR_PATTERN;
import static com.vaadin.flow.server.InitParameters.SERVLET_PARAMETER_DEVMODE_WEBPACK_OPTIONS;
import static com.vaadin.flow.server.InitParameters.SERVLET_PARAMETER_DEVMODE_WEBPACK_SUCCESS_PATTERN;
import static com.vaadin.flow.server.InitParameters.SERVLET_PARAMETER_DEVMODE_WEBPACK_TIMEOUT;
import static com.vaadin.flow.server.frontend.FrontendUtils.GREEN;
import static com.vaadin.flow.server.frontend.FrontendUtils.RED;
import static com.vaadin.flow.server.frontend.FrontendUtils.YELLOW;
import static com.vaadin.flow.server.frontend.FrontendUtils.commandToString;
import static com.vaadin.flow.server.frontend.FrontendUtils.console;
import static java.net.HttpURLConnection.HTTP_NOT_FOUND;
import static java.net.HttpURLConnection.HTTP_OK;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import java.io.BufferedReader;
import java.io.File;
Expand All @@ -44,15 +36,13 @@
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.regex.Pattern;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
Expand All @@ -65,6 +55,18 @@
import com.vaadin.flow.server.frontend.FrontendTools;
import com.vaadin.flow.server.frontend.FrontendUtils;

import static com.vaadin.flow.server.InitParameters.SERVLET_PARAMETER_DEVMODE_WEBPACK_ERROR_PATTERN;
import static com.vaadin.flow.server.InitParameters.SERVLET_PARAMETER_DEVMODE_WEBPACK_OPTIONS;
import static com.vaadin.flow.server.InitParameters.SERVLET_PARAMETER_DEVMODE_WEBPACK_SUCCESS_PATTERN;
import static com.vaadin.flow.server.InitParameters.SERVLET_PARAMETER_DEVMODE_WEBPACK_TIMEOUT;
import static com.vaadin.flow.server.frontend.FrontendUtils.GREEN;
import static com.vaadin.flow.server.frontend.FrontendUtils.RED;
import static com.vaadin.flow.server.frontend.FrontendUtils.YELLOW;
import static com.vaadin.flow.server.frontend.FrontendUtils.commandToString;
import static com.vaadin.flow.server.frontend.FrontendUtils.console;
import static java.net.HttpURLConnection.HTTP_NOT_FOUND;
import static java.net.HttpURLConnection.HTTP_OK;

/**
* Handles getting resources from <code>webpack-dev-server</code>.
* <p>
Expand Down Expand Up @@ -134,12 +136,23 @@ private DevModeHandler(DeploymentConfiguration config, int runningPort,
port = runningPort;
reuseDevServer = config.reuseDevServer();

devServerStartFuture = waitFor.whenCompleteAsync((value, exception) -> {
// Check whether executor is provided by the caller (framework)
Object service = config.getInitParameters().get(Executor.class);

BiConsumer<Void, ? super Throwable> action = (value, exception) -> {
// this will throw an exception if an exception has been thrown by
// the waitFor task
waitFor.getNow(null);
runOnFutureComplete(config);
});
};

if (service instanceof Executor) {
// if there is an executor use it to run the task
devServerStartFuture = waitFor.whenCompleteAsync(action,
(Executor) service);
} else {
devServerStartFuture = waitFor.whenCompleteAsync(action);
}
}

/**
Expand Down Expand Up @@ -648,8 +661,10 @@ private boolean doStartWebpack(DeploymentConfiguration config,
getLogger().info(LOG_END, ms);
saveRunningDevServerPort();
return true;
} catch (IOException | InterruptedException e) {
} catch (IOException e) {
getLogger().error("Failed to start the webpack process", e);
} catch (InterruptedException e) {
getLogger().debug("Webpack process start has been interrupted", e);
}
return false;
}
Expand Down
Expand Up @@ -45,6 +45,7 @@
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.concurrent.Executor;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
Expand Down Expand Up @@ -320,8 +321,8 @@ public static void initDevModeHandler(Set<Class<?>> classes,
.enableImportsUpdate(true).runNpmInstall(true)
.populateTokenFileData(tokenFileData)
.withEmbeddableWebComponents(true).enablePnpm(enablePnpm)
.withHomeNodeExecRequired(useHomeNodeExec)
.build().execute();
.withHomeNodeExecRequired(useHomeNodeExec).build()
.execute();

FallbackChunk chunk = FrontendUtils
.readFallbackChunk(tokenFileData);
Expand All @@ -345,25 +346,23 @@ public static void initDevModeHandler(Set<Class<?>> classes,
.withEmbeddableWebComponents(true).enablePnpm(enablePnpm)
.withHomeNodeExecRequired(useHomeNodeExec).build();

CompletableFuture<Void> runNodeTasks = CompletableFuture
.runAsync(() -> {
try {
tasks.execute();

FallbackChunk chunk = FrontendUtils
.readFallbackChunk(tokenFileData);
if (chunk != null) {
vaadinContext.setAttribute(chunk);
}
} catch (ExecutionFailedException exception) {
log().debug(
"Could not initialize dev mode handler. One of the node tasks failed",
exception);
throw new CompletionException(exception);
}
});

DevModeHandler.start(config, builder.npmFolder, runNodeTasks);
// Check whether executor is provided by the caller (framework)
Object service = config.getInitParameters().get(Executor.class);

Runnable runnable = () -> runNodeTasks(vaadinContext, tokenFileData,
tasks);

CompletableFuture<Void> nodeTasksFuture;
if (service instanceof Executor) {
// if there is an executor use it to run the task
nodeTasksFuture = CompletableFuture.runAsync(runnable,
(Executor) service);
} else {
nodeTasksFuture = CompletableFuture.runAsync(runnable);

}

DevModeHandler.start(config, builder.npmFolder, nodeTasksFuture);
}

private static Logger log() {
Expand Down Expand Up @@ -422,6 +421,24 @@ static Set<File> getFrontendLocationsFromClassloader(
return frontendFiles;
}

private static void runNodeTasks(VaadinContext vaadinContext,
JsonObject tokenFileData, NodeTasks tasks) {
try {
tasks.execute();

FallbackChunk chunk = FrontendUtils
.readFallbackChunk(tokenFileData);
if (chunk != null) {
vaadinContext.setAttribute(chunk);
}
} catch (ExecutionFailedException exception) {
log().debug(
"Could not initialize dev mode handler. One of the node tasks failed",
exception);
throw new CompletionException(exception);
}
}

private static Set<File> getFrontendLocationsFromClassloader(
ClassLoader classLoader, String resourcesFolder)
throws ServletException {
Expand Down

0 comments on commit 5480e98

Please sign in to comment.