Issue
I used the Get Started page to create a new Vaadin 14 app, after choosing the Plain Java Servlet option.
The web page successfully downloaded a .zip
file which I unzipped, and opened with IntelliJ Ultimate Edition version 2019.2. I waited a few minutes while Maven did its thing, downloading and reconfiguring the project. Eventually I went to the Maven panel within IntelliJ, and ran the Lifecycle
items clean
and install
.
I received the following error message on the console.
[ERROR] Failed to execute goal com.vaadin:vaadin-maven-plugin:14.0.0:prepare-frontend (default) on project acme: Execution default of goal com.vaadin:vaadin-maven-plugin:14.0.0:prepare-frontend failed:
[ERROR]
[ERROR] ======================================================================================================
[ERROR] Failed to determine 'node' tool.
[ERROR] Please install it either:
[ERROR] - by following the https://nodejs.org/en/download/ guide to install it globally
[ERROR] - or by running the frontend-maven-plugin goal to install it in this project:
[ERROR] $ mvn com.github.eirslett:frontend-maven-plugin:1.7.6:install-node-and-npm -DnodeVersion="v10.16.0"
[ERROR] ======================================================================================================
See discussion on Vaadin Forum.
I filed Ticket # 6262 Configure Maven to automatically install Node.js & npm, suggesting to the Vaadin team that requiring and omitting Node.js & npm is a problem.
Solution
Update: Non-issue in 14.2
Vaadin 14.2 & 16 have been changed to now include automatically the necessary npm tool in a Maven-driven project. No need to manually install Node.js & npm.
To quote this blog post:
Automatic Node.js install
Starting from versions 14.2 and 16, the Node.js install (which includes npm) happens automatically. It is installed to a
.vaadin
folder inside the home folder, and reused from there for all Vaadin projects. As before, Node is only used to build the frontend side of things; it does not run after you deploy for production!
And further improvement: pnpm instead of npm.
Frontend dependency management that just works - pnpm Behind the scenes, npm has been used to manage frontend dependencies since 14.0. Now, we’ve added support for pnpm, which introduces the following benefits:
Shorter build time, compared to npm on your local machine and CI system, because pnpm only downloads packages once and reuses them from a local cache.
No need to delete package.json, lock file or the node_modules folder when updating the Vaadin version in your project.
In 14.2, npm is still used by default, but we encourage you to test pnpm and give us your feedback. Trying pnpm is easy: there is no migration, just enable it by using a configuration property or Maven plugin configuration. You can learn more about pnpm here. Vaadin 16 will use pnpm by default.
I have verified this works well. I have now manually removed the Node.js/npm installation from my Mac.
tl;dr
The Vaadin 14 team expects you to have Node.js and npm tools installed on your computer.
As alternative, Vaadin 14 seems to be working with Node.js/npm being automatically installed within your project (rather than globally on your computer) by the frontend-maven-plugin
tool you can specify in your Maven POM file. See XML snippet below for your POM.
If you would prefer to install Mode/npm globally on your computer, be sure to read the other Answer by Tom Novosad.
Details
As of Vaadin 14, the Vaadin team is switching:
- From HTML Imports, Bower, and WebJars
- To ES6 Modules, npm, and Webpack, with Node.js
…as part of their transition from Polymer 2 to Polymer 3.
See blog post, Bower and npm in Vaadin 14+.
Hopefully, as Vaadin-on-Java users, we need not care about these underlying technical details… but for one thing: Unfortunately, the npm & Node.js tools are required but not bundled within your Vaadin project by default.
You have two solutions:
- Install the tools globally.
- Install within your project.
I prefer the latter. And I prefer to have Maven auto-install them within my project, with less housekeeping for me to do manually.
CAVEAT: I do not know the limitations or ramifications of my node/npm-per-project solution. I barely have any idea of the purpose or nature of either node/npm, and have no idea how Vaadin makes use of them. So use this solution at your own risk. All I can say is that it seems to be working for me.
Add frontend-maven-plugin
to your project
The frontend-maven-plugin
tool can be used by Maven to download and install Node.js with npm within your Vaadin project.
Open the Maven POM file within your Vaadin project.
Add the following block inside the <build> <defaultGoal>jetty:run</defaultGoal> <plugins>
element of that POM.
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
<!-- Use the latest released version:
https://repo1.maven.org/maven2/com/github/eirslett/frontend-maven-plugin/ -->
<version>1.8.0</version>
<executions>
<execution>
<!-- optional: you don't really need execution ids, but it looks nice in your build log. -->
<id>install node and npm</id>
<goals>
<goal>install-node-and-npm</goal>
</goals>
<!-- optional: default phase is "generate-resources" -->
<phase>generate-resources</phase>
</execution>
</executions>
<configuration>
<nodeVersion>v10.16.3</nodeVersion>
<!-- optional: with node version greater than 4.0.0 will use npm provided by node distribution -->
<!-- <npmVersion>2.15.9</npmVersion>-->
<!-- optional: where to download node and npm from. Defaults to https://nodejs.org/dist/ -->
<!-- <downloadRoot>http://myproxy.example.org/nodejs/</downloadRoot>-->
</configuration>
</plugin>
Of course, you can tweak that snippet to use the latest version numbers. Check the Node.js page for the latest versions number.
Notice that we commented-out the npm
item, as that tool is bundled with the latest versions of Node.js.
Remaining steps:
- In the
Maven
panel within IntelliJ, run theLifecycle
items namedclean
andinstall
. Wait a moment as some more items are downloaded and configured. (Notice the item "Installing node version v10.16.3" in your console history.) - In that same panel, in the section
Plugins
>jetty
, run thejetty:run
item. Wait a moment as the Jetty server launches to run your Vaadin app.
On the console you should see something like this (that mysterious Quiet Time
warning is perennial with all releases of Vaadin):
[INFO] Started Jetty Server
[INFO] Using Non-Native Java sun.nio.fs.PollingWatchService
[WARNING] Quiet Time is too low for non-native WatchService [sun.nio.fs.PollingWatchService]: 1000 < 5000 ms (defaulting to 5000 ms)
- Point your web browser to:
http://localhost:8080/
to see the "Click Me" button appear, as your app successfully runs.
This solution came from the project page for the Maven plugin frontend-maven-plugin
. Note that the example POM fragment there is incorrect, failing to wrap the <execution>
tag within a plural <executions>
tag. I filed ticket # 838 there.
You may want to follow this discussion in the Vaadin Forums.
For your reference, here is a complete POM file to compare to yours.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>work.basil.example</groupId>
<artifactId>acme</artifactId>
<name>acme</name>
<version>2.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<maven.compiler.source>13</maven.compiler.source>
<maven.compiler.target>13</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<failOnMissingWebXml>false</failOnMissingWebXml>
<vaadin.version>14.0.5</vaadin.version>
<drivers.downloader.phase>pre-integration-test</drivers.downloader.phase>
</properties>
<repositories>
<repository>
<id>central</id>
<url>https://repo1.maven.org/maven2/</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<!-- Repository used by many Vaadin add-ons -->
<repository>
<id>Vaadin Directory</id>
<url>https://maven.vaadin.com/vaadin-addons</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>central</id>
<url>https://repo1.maven.org/maven2/</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-bom</artifactId>
<type>pom</type>
<scope>import</scope>
<version>${vaadin.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>com.vaadin</groupId>
<!-- Replace artifactId with vaadin-core to use only free components -->
<artifactId>vaadin</artifactId>
<exclusions>
<!-- Webjars are only needed when running in Vaadin 13 compatibility mode -->
<exclusion>
<groupId>com.vaadin.webjar</groupId>
<artifactId>*</artifactId>
</exclusion>
<exclusion>
<groupId>org.webjars.bowergithub.insites</groupId>
<artifactId>*</artifactId>
</exclusion>
<exclusion>
<groupId>org.webjars.bowergithub.polymer</groupId>
<artifactId>*</artifactId>
</exclusion>
<exclusion>
<groupId>org.webjars.bowergithub.polymerelements</groupId>
<artifactId>*</artifactId>
</exclusion>
<exclusion>
<groupId>org.webjars.bowergithub.vaadin</groupId>
<artifactId>*</artifactId>
</exclusion>
<exclusion>
<groupId>org.webjars.bowergithub.webcomponents</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Added to provide logging output as Vaadin uses -->
<!-- the unbound SLF4J no-operation (NOP) logger implementation -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-testbench</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<defaultGoal>jetty:run</defaultGoal>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
</plugin>
<!-- Jetty plugin for easy testing without a server -->
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.4.19.v20190610</version>
<configuration>
<!-- If using IntelliJ IDEA with autocompilation, this
might cause lots of unnecessary compilations in the
background.-->
<scanIntervalSeconds>2</scanIntervalSeconds>
<!-- Use war output directory to get the webpack files -->
<webAppConfig>
<allowDuplicateFragmentNames>true</allowDuplicateFragmentNames>
</webAppConfig>
</configuration>
</plugin>
<!--
Take care of synchronizing java dependencies and imports in
package.json and main.js files.
It also creates webpack.config.js if not exists yet.
-->
<plugin>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-maven-plugin</artifactId>
<version>${vaadin.version}</version>
<executions>
<execution>
<goals>
<goal>prepare-frontend</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
<!-- Use the latest released version:
https://repo1.maven.org/maven2/com/github/eirslett/frontend-maven-plugin/ -->
<version>1.8.0</version>
<executions>
<execution>
<!-- optional: you don't really need execution ids, but it looks nice in your build log. -->
<id>install node and npm</id>
<goals>
<goal>install-node-and-npm</goal>
</goals>
<!-- optional: default phase is "generate-resources" -->
<phase>generate-resources</phase>
</execution>
</executions>
<configuration>
<nodeVersion>v10.16.3</nodeVersion>
<!-- optional: with node version greater than 4.0.0 will use npm provided by node distribution -->
<!-- <npmVersion>2.15.9</npmVersion>-->
<!-- optional: where to download node and npm from. Defaults to https://nodejs.org/dist/ -->
<!-- <downloadRoot>http://myproxy.example.org/nodejs/</downloadRoot>-->
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<!-- Production mode is activated using -Pproduction -->
<id>production</id>
<properties>
<vaadin.productionMode>true</vaadin.productionMode>
</properties>
<dependencies>
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>flow-server-production-mode</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>build-frontend</goal>
</goals>
<phase>compile</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>integration-tests</id>
<build>
<plugins>
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.4.19.v20190610</version>
<configuration>
<scanIntervalSeconds>0</scanIntervalSeconds>
<stopPort>8081</stopPort>
<stopWait>5</stopWait>
<stopKey>${project.artifactId}</stopKey>
</configuration>
<executions>
<execution>
<id>start-jetty</id>
<phase>pre-integration-test</phase>
<goals>
<goal>deploy-war</goal>
</goals>
</execution>
<execution>
<id>stop-jetty</id>
<phase>post-integration-test</phase>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Runs the integration tests (*IT) after the server is started -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>3.0.0-M3</version>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
<configuration>
<trimStackTrace>false</trimStackTrace>
<enableAssertions>true</enableAssertions>
<systemPropertyVariables>
<!-- Pass location of downloaded webdrivers to the tests -->
<webdriver.chrome.driver>${webdriver.chrome.driver}</webdriver.chrome.driver>
</systemPropertyVariables>
</configuration>
</plugin>
<plugin>
<groupId>com.lazerycode.selenium</groupId>
<artifactId>driver-binary-downloader-maven-plugin</artifactId>
<version>1.0.17</version>
<configuration>
<onlyGetDriversForHostOperatingSystem>true
</onlyGetDriversForHostOperatingSystem>
<rootStandaloneServerDirectory>
${project.basedir}/drivers/driver
</rootStandaloneServerDirectory>
<downloadedZipFileDirectory>
${project.basedir}/drivers/driver_zips
</downloadedZipFileDirectory>
<customRepositoryMap>
${project.basedir}/drivers.xml
</customRepositoryMap>
</configuration>
<executions>
<execution>
<!-- use phase "none" to skip download step -->
<phase>${drivers.downloader.phase}</phase>
<goals>
<goal>selenium</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
Answered By - Basil Bourque
Answer Checked By - Gilberto Lyons (JavaFixing Admin)