use of com.vaadin.flow.server.ExecutionFailedException in project flow by vaadin.
the class BuildFrontendUtil method prepareFrontend.
/**
* Prepares the Frontend
*
* @param adapter
* - the PluginAdapterBase.
* @throws IOException
* - Could not forceMkdir(adapter.generatedFolder());
* @throws ExecutionFailedException
* - While NodeTasks.execute()
* @throws URISyntaxException
* - Could not build an URI from nodeDownloadRoot().
*/
public static void prepareFrontend(PluginAdapterBase adapter) throws IOException, ExecutionFailedException, URISyntaxException {
final URI nodeDownloadRootURI = adapter.nodeDownloadRoot();
FrontendToolsSettings settings = getFrontendToolsSettings(adapter);
FrontendTools tools = new FrontendTools(settings);
tools.validateNodeAndNpmVersion();
try {
FileUtils.forceMkdir(adapter.generatedFolder());
} catch (IOException e) {
throw new IOException("Failed to create folder '" + adapter.generatedFolder() + "'. Verify that you may write to path.", e);
}
File flowResourcesFolder = new File(adapter.npmFolder(), Paths.get(adapter.buildFolder(), DEFAULT_FLOW_RESOURCES_FOLDER).toString());
ClassFinder classFinder = adapter.getClassFinder();
Lookup lookup = adapter.createLookup(classFinder);
NodeTasks.Builder builder = new NodeTasks.Builder(lookup, adapter.npmFolder(), adapter.generatedFolder(), adapter.frontendDirectory(), adapter.buildFolder()).useV14Bootstrap(adapter.isUseDeprecatedV14Bootstrapping()).withFlowResourcesFolder(flowResourcesFolder).createMissingPackageJson(true).enableImportsUpdate(false).enablePackagesUpdate(false).runNpmInstall(false).withNodeVersion(adapter.nodeVersion()).withNodeDownloadRoot(nodeDownloadRootURI).setNodeAutoUpdate(adapter.nodeAutoUpdate()).withHomeNodeExecRequired(adapter.requireHomeNodeExec()).setJavaResourceFolder(adapter.javaResourceFolder()).withProductionMode(adapter.productionMode());
// Copy jar artifact contents in TaskCopyFrontendFiles
builder.copyResources(adapter.getJarFiles());
try {
builder.build().execute();
} catch (ExecutionFailedException exception) {
throw exception;
} catch (Throwable throwable) {
// NOSONAR Intentionally throwable
throw new ExecutionFailedException("Error occured during goal execution: " + throwable.getMessage() + "\n\nPlease run Maven with the -e switch (or Gradle with the --stacktrace switch), to learn the full stack trace.", throwable);
}
}
use of com.vaadin.flow.server.ExecutionFailedException in project flow by vaadin.
the class AbstractTaskClientGenerator method execute.
@Override
public void execute() throws ExecutionFailedException {
if (!shouldGenerate()) {
return;
}
File generatedFile = getGeneratedFile();
try {
String fileContent = getFileContent();
log().debug("writing file '{}'", generatedFile);
FileUtils.forceMkdirParent(generatedFile);
FileUtils.writeStringToFile(generatedFile, fileContent, UTF_8);
} catch (IOException exception) {
String errorMessage = String.format("Error writing '%s'", generatedFile);
throw new ExecutionFailedException(errorMessage, exception);
}
}
use of com.vaadin.flow.server.ExecutionFailedException in project flow by vaadin.
the class TaskRunNpmInstall method runNpmInstall.
/**
* Installs frontend resources (using either pnpm or npm) after
* `package.json` has been updated.
*/
private void runNpmInstall() throws ExecutionFailedException {
// Do possible cleaning before generating any new files.
cleanUp();
long startTime = System.currentTimeMillis();
Logger logger = packageUpdater.log();
if (enablePnpm) {
try {
createPnpmFile(packageUpdater.versionsPath);
} catch (IOException exception) {
throw new ExecutionFailedException("Failed to read frontend version data from vaadin-core " + "and make it available to pnpm for locking transitive dependencies.\n" + "Please report an issue, as a workaround try running project " + "with npm by setting system variable -Dvaadin.pnpm.enable=false", exception);
}
try {
createNpmRcFile();
} catch (IOException exception) {
logger.warn(".npmrc generation failed; pnpm " + "package installation may require manaually passing " + "the --shamefully-hoist flag", exception);
}
}
String baseDir = packageUpdater.npmFolder.getAbsolutePath();
FrontendToolsSettings settings = new FrontendToolsSettings(baseDir, () -> FrontendUtils.getVaadinHomeDirectory().getAbsolutePath());
settings.setNodeDownloadRoot(nodeDownloadRoot);
settings.setForceAlternativeNode(requireHomeNodeExec);
settings.setUseGlobalPnpm(useGlobalPnpm);
settings.setAutoUpdate(autoUpdate);
settings.setNodeVersion(nodeVersion);
FrontendTools tools = new FrontendTools(settings);
List<String> npmExecutable;
List<String> npmInstallCommand;
List<String> postinstallCommand;
try {
if (requireHomeNodeExec) {
tools.forceAlternativeNodeExecutable();
}
if (enablePnpm) {
validateInstalledNpm(tools);
npmExecutable = tools.getPnpmExecutable();
} else {
npmExecutable = tools.getNpmExecutable();
}
npmInstallCommand = new ArrayList<>(npmExecutable);
postinstallCommand = new ArrayList<>(npmExecutable);
// This only works together with "install"
postinstallCommand.remove("--shamefully-hoist=true");
} catch (IllegalStateException exception) {
throw new ExecutionFailedException(exception.getMessage(), exception);
}
npmInstallCommand.add("--ignore-scripts");
npmInstallCommand.add("install");
postinstallCommand.add("run");
postinstallCommand.add("postinstall");
if (logger.isDebugEnabled()) {
logger.debug(commandToString(packageUpdater.npmFolder.getAbsolutePath(), npmInstallCommand));
}
String toolName = enablePnpm ? "pnpm" : "npm";
String commandString = npmInstallCommand.stream().collect(Collectors.joining(" "));
logger.info("using '{}' for frontend package installation", String.join(" ", npmInstallCommand));
// Log a stronger request for patience if package-lock.json is
// missing as "npm install" in this case can take minutes
// https://github.com/vaadin/flow/issues/12825
File packageLockFile = packageUpdater.getPackageLockFile();
if (!enablePnpm && !packageLockFile.exists()) {
packageUpdater.log().warn("package-lock.json is missing from this " + "project. This may cause the npm package installation to " + "take several minutes. It is recommended to keep the " + "package-lock.json file persistently in your project. " + "Please stand by...");
}
Process process = null;
try {
process = runNpmCommand(npmInstallCommand, packageUpdater.npmFolder);
logger.debug("Output of `{}`:", commandString);
StringBuilder toolOutput = new StringBuilder();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream(), StandardCharsets.UTF_8))) {
String stdoutLine;
while ((stdoutLine = reader.readLine()) != null) {
logger.debug(stdoutLine);
toolOutput.append(stdoutLine).append(System.lineSeparator());
}
}
int errorCode = process.waitFor();
if (errorCode != 0) {
// Echo the stdout from pnpm/npm to error level log
logger.error("Command `{}` failed:\n{}", commandString, toolOutput);
logger.error(">>> Dependency ERROR. Check that all required dependencies are " + "deployed in {} repositories.", toolName);
throw new ExecutionFailedException(SharedUtil.capitalize(toolName) + " install has exited with non zero status. " + "Some dependencies are not installed. Check " + toolName + " command output");
} else {
logger.info("Frontend dependencies resolved successfully.");
}
} catch (InterruptedException | IOException e) {
logger.error("Error when running `{} install`", toolName, e);
if (e instanceof InterruptedException) {
// Restore interrupted state
Thread.currentThread().interrupt();
}
throw new ExecutionFailedException("Command '" + toolName + " install' failed to finish", e);
} finally {
if (process != null) {
process.destroyForcibly();
}
}
List<String> postinstallPackages = new ArrayList<>();
postinstallPackages.add("esbuild");
postinstallPackages.add("@vaadin/vaadin-usage-statistics");
postinstallPackages.addAll(additionalPostinstallPackages);
for (String postinstallPackage : postinstallPackages) {
if (postinstallPackage.trim().equals("")) {
continue;
}
// Execute "npm run postinstall" in the desired folders in
// node_modules
File packageFolder = new File(packageUpdater.nodeModulesFolder, postinstallPackage);
if (!packageFolder.exists()) {
continue;
}
logger.debug("Running postinstall for '{}'", postinstallPackage);
try {
process = runNpmCommand(postinstallCommand, packageFolder);
process.waitFor();
} catch (IOException | InterruptedException e) {
if (e instanceof InterruptedException) {
// Restore interrupted state
Thread.currentThread().interrupt();
}
throw new ExecutionFailedException("Error when running postinstall script for '" + postinstallPackage + "'", e);
}
}
lastInstallStats.installTimeMs = System.currentTimeMillis() - startTime;
lastInstallStats.packageManager = enablePnpm ? "pnpm" : "npm";
}
use of com.vaadin.flow.server.ExecutionFailedException in project flow by vaadin.
the class TaskUpdateThemeImport method verifyThemeDirectoryExistence.
private void verifyThemeDirectoryExistence() throws ExecutionFailedException {
String themeName = theme.getName();
String themePath = String.join("/", APPLICATION_THEME_ROOT, themeName);
List<String> appThemePossiblePaths = getAppThemePossiblePaths(themePath);
List<File> existingAppThemeDirectories = appThemePossiblePaths.stream().map(path -> new File(npmFolder, path)).filter(File::exists).collect(Collectors.toList());
if (existingAppThemeDirectories.isEmpty()) {
String errorMessage = "Discovered @Theme annotation with theme " + "name '%s', but could not find the theme directory " + "in the project or available as a jar dependency. " + "Check if you forgot to create the folder under '%s' " + "or have mistyped the theme or folder name for '%s'.";
throw new ExecutionFailedException(String.format(errorMessage, themeName, new File(frontendDirectory, APPLICATION_THEME_ROOT).getPath(), themeName));
}
if (existingAppThemeDirectories.size() >= 2) {
boolean themeFoundInJar = existingAppThemeDirectories.stream().map(File::getPath).anyMatch(path -> path.contains(Paths.get(FrontendUtils.FLOW_NPM_PACKAGE_NAME).toString()));
if (themeFoundInJar) {
String errorMessage = "Theme '%s' should not exist inside a " + "jar and in the project at the same time.%n" + "Extending another theme is possible by adding " + "{ \"parent\": \"your-parent-theme\" } entry to the " + "'theme.json' file inside your theme folder.";
throw new ExecutionFailedException(String.format(errorMessage, themeName));
} else {
String errorMessage = "Discovered Theme folder for theme '%s' " + "in more than one place in the project. Please " + "make sure there is only one theme folder with name " + "'%s' exists in the your project. " + "The recommended place to put the theme folder " + "inside the project is '%s'";
throw new ExecutionFailedException(String.format(errorMessage, themeName, themeName, new File(frontendDirectory, APPLICATION_THEME_ROOT).getPath()));
}
}
}
use of com.vaadin.flow.server.ExecutionFailedException in project flow by vaadin.
the class WebpackHandlerTest method avoidStoringPortOfFailingWebPackDevServer_failWebpackStart_startWebPackSucessfullyAfter.
@Test
public void avoidStoringPortOfFailingWebPackDevServer_failWebpackStart_startWebPackSucessfullyAfter() throws Exception {
handler = startWebpack();
waitForDevServer();
removeDevModeHandlerInstance();
// dev mode handler should fail because of non-existent npm
// folder: it
// means the port number should not have been written
// use non-existent folder for as npmFolder, it should fail the
// validation (which means server instance won't be reused)
WebpackHandler newhHandler = new WebpackHandler(lookup, 0, new File(npmFolder, UUID.randomUUID().toString()), CompletableFuture.completedFuture(null));
VaadinResponse response = Mockito.mock(VaadinResponse.class);
Mockito.when(response.getOutputStream()).thenReturn(new ByteArrayOutputStream());
boolean proceed = true;
Throwable cause = null;
while (proceed) {
try {
proceed = newhHandler.handleRequest(Mockito.mock(VaadinSession.class), Mockito.mock(VaadinRequest.class), response);
} catch (IllegalStateException ise) {
proceed = false;
cause = ise.getCause();
}
}
Assert.assertNotNull(cause);
Assert.assertTrue(cause instanceof ExecutionFailedException);
}
Aggregations