Search in sources :

Example 1 with ExecutionFailedException

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);
    }
}
Also used : FrontendToolsSettings(com.vaadin.flow.server.frontend.FrontendToolsSettings) ExecutionFailedException(com.vaadin.flow.server.ExecutionFailedException) ClassFinder(com.vaadin.flow.server.frontend.scanner.ClassFinder) ReflectionsClassFinder(com.vaadin.flow.server.scanner.ReflectionsClassFinder) Lookup(com.vaadin.flow.di.Lookup) UncheckedIOException(java.io.UncheckedIOException) IOException(java.io.IOException) URI(java.net.URI) File(java.io.File) NodeTasks(com.vaadin.flow.server.frontend.NodeTasks) FrontendTools(com.vaadin.flow.server.frontend.FrontendTools)

Example 2 with ExecutionFailedException

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);
    }
}
Also used : ExecutionFailedException(com.vaadin.flow.server.ExecutionFailedException) IOException(java.io.IOException) File(java.io.File)

Example 3 with ExecutionFailedException

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";
}
Also used : InputStreamReader(java.io.InputStreamReader) ArrayList(java.util.ArrayList) IOException(java.io.IOException) FrontendUtils.commandToString(com.vaadin.flow.server.frontend.FrontendUtils.commandToString) Logger(org.slf4j.Logger) ExecutionFailedException(com.vaadin.flow.server.ExecutionFailedException) BufferedReader(java.io.BufferedReader) File(java.io.File)

Example 4 with ExecutionFailedException

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()));
        }
    }
}
Also used : ExecutionFailedException(com.vaadin.flow.server.ExecutionFailedException) File(java.io.File)

Example 5 with ExecutionFailedException

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);
}
Also used : VaadinResponse(com.vaadin.flow.server.VaadinResponse) ExecutionFailedException(com.vaadin.flow.server.ExecutionFailedException) ByteArrayOutputStream(java.io.ByteArrayOutputStream) File(java.io.File) AbstractDevModeTest(com.vaadin.base.devserver.startup.AbstractDevModeTest) Test(org.junit.Test)

Aggregations

ExecutionFailedException (com.vaadin.flow.server.ExecutionFailedException)20 File (java.io.File)17 Test (org.junit.Test)10 IOException (java.io.IOException)5 Lookup (com.vaadin.flow.di.Lookup)2 ClassFinder (com.vaadin.flow.server.frontend.scanner.ClassFinder)2 ReflectionsClassFinder (com.vaadin.flow.server.scanner.ReflectionsClassFinder)2 URI (java.net.URI)2 AbstractDevModeTest (com.vaadin.base.devserver.startup.AbstractDevModeTest)1 Template (com.vaadin.flow.internal.Template)1 VaadinResponse (com.vaadin.flow.server.VaadinResponse)1 FallbackChunk (com.vaadin.flow.server.frontend.FallbackChunk)1 FrontendTools (com.vaadin.flow.server.frontend.FrontendTools)1 FrontendToolsSettings (com.vaadin.flow.server.frontend.FrontendToolsSettings)1 FrontendUtils.commandToString (com.vaadin.flow.server.frontend.FrontendUtils.commandToString)1 NodeTasks (com.vaadin.flow.server.frontend.NodeTasks)1 BufferedReader (java.io.BufferedReader)1 ByteArrayOutputStream (java.io.ByteArrayOutputStream)1 InputStreamReader (java.io.InputStreamReader)1 UncheckedIOException (java.io.UncheckedIOException)1