Skip to content

Commit

Permalink
fix: use provided executor for frontend tools (#9553)
Browse files Browse the repository at this point in the history
  • Loading branch information
Denis committed Dec 2, 2020
1 parent ae47abc commit 079c7d2
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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 <code>webpack-dev-server</code>.
* <p>
Expand Down Expand Up @@ -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<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 @@ -665,8 +678,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;
}
Expand Down
Original file line number Diff line number Diff line change
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 @@ -94,11 +95,11 @@
import static com.vaadin.flow.server.Constants.CONNECT_OPEN_API_FILE_TOKEN;
import static com.vaadin.flow.server.Constants.PACKAGE_JSON;
import static com.vaadin.flow.server.InitParameters.SERVLET_PARAMETER_DEVMODE_OPTIMIZE_BUNDLE;
import static com.vaadin.flow.server.frontend.FrontendUtils.DEFAULT_FLOW_RESOURCES_FOLDER;
import static com.vaadin.flow.server.frontend.FrontendUtils.DEFAULT_CONNECT_APPLICATION_PROPERTIES;
import static com.vaadin.flow.server.frontend.FrontendUtils.DEFAULT_CONNECT_GENERATED_TS_DIR;
import static com.vaadin.flow.server.frontend.FrontendUtils.DEFAULT_CONNECT_JAVA_SOURCE_FOLDER;
import static com.vaadin.flow.server.frontend.FrontendUtils.DEFAULT_CONNECT_OPENAPI_JSON_FILE;
import static com.vaadin.flow.server.frontend.FrontendUtils.DEFAULT_FLOW_RESOURCES_FOLDER;
import static com.vaadin.flow.server.frontend.FrontendUtils.DEFAULT_FRONTEND_DIR;
import static com.vaadin.flow.server.frontend.FrontendUtils.DEFAULT_GENERATED_DIR;
import static com.vaadin.flow.server.frontend.FrontendUtils.PARAM_FRONTEND_DIR;
Expand All @@ -117,7 +118,7 @@
NpmPackage.Container.class, JsModule.class, JsModule.Container.class,
CssImport.class, CssImport.Container.class, JavaScript.class,
JavaScript.Container.class, Theme.class, NoTheme.class,
AppShellConfigurator.class,HasErrorParameter.class })
AppShellConfigurator.class, HasErrorParameter.class })
@WebListener
public class DevModeInitializer
implements ClassLoaderAwareServletContainerInitializer, Serializable,
Expand Down Expand Up @@ -268,7 +269,8 @@ public static void initDevModeHandler(Set<Class<?>> classes,
return;
}

String baseDir = config.getStringProperty(FrontendUtils.PROJECT_BASEDIR, null);
String baseDir = config.getStringProperty(FrontendUtils.PROJECT_BASEDIR,
null);
if (baseDir == null) {
baseDir = getBaseDirectoryFallback();
}
Expand Down Expand Up @@ -373,25 +375,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);
}

/**
Expand Down Expand Up @@ -444,12 +444,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
Expand All @@ -465,6 +465,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 079c7d2

Please sign in to comment.