diff --git a/flow-server/src/main/java/com/vaadin/flow/server/DevModeHandler.java b/flow-server/src/main/java/com/vaadin/flow/server/DevModeHandler.java
index 99c5e67440b..2eecdbd3517 100644
--- a/flow-server/src/main/java/com/vaadin/flow/server/DevModeHandler.java
+++ b/flow-server/src/main/java/com/vaadin/flow/server/DevModeHandler.java
@@ -15,18 +15,9 @@
*/
package com.vaadin.flow.server;
-import static com.vaadin.flow.server.Constants.VAADIN_MAPPING;
-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.commandToString;
-import static com.vaadin.flow.server.frontend.FrontendUtils.console;
-import static java.lang.String.format;
-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.File;
import java.io.IOException;
@@ -44,14 +35,12 @@
import java.util.UUID;
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.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;
@@ -64,6 +53,19 @@
import com.vaadin.flow.server.frontend.FrontendTools;
import com.vaadin.flow.server.frontend.FrontendUtils;
+import static com.vaadin.flow.server.Constants.VAADIN_MAPPING;
+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.commandToString;
+import static com.vaadin.flow.server.frontend.FrontendUtils.console;
+import static java.lang.String.format;
+import static java.net.HttpURLConnection.HTTP_NOT_FOUND;
+import static java.net.HttpURLConnection.HTTP_OK;
+
/**
* Handles getting resources from webpack-dev-server
.
*
@@ -142,12 +144,23 @@ private DevModeHandler(DeploymentConfiguration config, int runningPort,
reuseDevServer = config.reuseDevServer();
devServerPortFile = getDevServerPortFile(npmFolder);
- devServerStartFuture = waitFor.whenCompleteAsync((value, exception) -> {
+ // Check whether executor is provided by the caller (framework)
+ Object service = config.getInitParameters().get(Executor.class);
+
+ BiConsumer 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);
+ }
}
@@ -653,9 +666,10 @@ private boolean doStartWebpack(DeploymentConfiguration config,
long ms = (System.nanoTime() - start) / 1000000;
getLogger().info(LOG_END, ms);
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;
}
diff --git a/flow-server/src/main/java/com/vaadin/flow/server/startup/DevModeInitializer.java b/flow-server/src/main/java/com/vaadin/flow/server/startup/DevModeInitializer.java
index 5dfeefa7a7c..f80f618e9f8 100644
--- a/flow-server/src/main/java/com/vaadin/flow/server/startup/DevModeInitializer.java
+++ b/flow-server/src/main/java/com/vaadin/flow/server/startup/DevModeInitializer.java
@@ -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;
@@ -267,7 +268,8 @@ public static void initDevModeHandler(Set> classes,
return;
}
- String baseDir = config.getStringProperty(FrontendUtils.PROJECT_BASEDIR, null);
+ String baseDir = config.getStringProperty(FrontendUtils.PROJECT_BASEDIR,
+ null);
if (baseDir == null) {
baseDir = getBaseDirectoryFallback();
}
@@ -372,25 +374,23 @@ public static void initDevModeHandler(Set> classes,
.withEmbeddableWebComponents(true).enablePnpm(enablePnpm)
.withHomeNodeExecRequired(useHomeNodeExec).build();
- CompletableFuture 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 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);
}
/**
@@ -443,12 +443,12 @@ private static String getBaseDirectoryFallback() {
+ "Directory '%s' does not look like a Maven or "
+ "Gradle project. Ensure that you have run the "
+ "prepare-frontend Maven goal, which generates "
- +"'flow-build-info.json', prior to deploying your "
+ + "'flow-build-info.json', prior to deploying your "
+ "application",
path.toString()));
}
}
-
+
/*
* This method returns all folders of jar files having files in the
* META-INF/resources/frontend folder. We don't use URLClassLoader because
@@ -464,6 +464,24 @@ static Set 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 getFrontendLocationsFromClassloader(
ClassLoader classLoader, String resourcesFolder)
throws ServletException {