Search code examples
javaspring-bootherokuvaadin

Cannot deploy Vaadin Java Spring App to Heroku


I try to deploy a vaadin App to Heroku. I found several questions which are solved by specifing the Java Version. So i did this as well and the Java App seems to be detected:

-----> Java app detected
-----> Installing JDK 11... done
-----> Installing Maven 3.6.2... done
-----> Executing Maven
       $ mvn -DskipTests clean dependency:list install

Several things get installed, but at the end i got following error:

[ERROR] Failed to execute goal com.vaadin:vaadin-maven-plugin:14.1.27:prepare-frontend (default) on project networker: 
       [ERROR] 
       [ERROR] ======================================================================================================
       [ERROR] Vaadin requires node.js & npm to be installed. Please install the latest LTS version of node.js (with npm) either by:
       [ERROR]   1) following the https://nodejs.org/en/download/ guide to install it globally. This is the recommended way.
       [ERROR]   2) running the following 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="v12.14.0" 
       [ERROR] 
       [ERROR] Note that in case you don't install it globally, you'll need to install it again for another Vaadin project.
       [ERROR] In case you have just installed node.js globally, it was not discovered, so you need to restart your system to get the path variables updated.
       [ERROR] ======================================================================================================
       [ERROR] -> [Help 1]
       [ERROR] 
       [ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
       [ERROR] Re-run Maven using the -X switch to enable full debug logging.
       [ERROR] 
       [ERROR] For more information about the errors and possible solutions, please read the following articles:
       [ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException !     ERROR: Failed to build app with Maven
       We're sorry this build is failing! If you can't find the issue in application code,
       please submit a ticket so we can help: https://help.heroku.com/  !     Push rejected, failed to compile Java app.  !     Push failed

Someone has an idea how to handle this error?

This is my poml.xlm:

<?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>de.essling.networker</groupId>
    <artifactId>networker</artifactId>
    <name>networker</name>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <properties>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>11</java.version>
        <vaadin.version>14.1.27</vaadin.version>

        <drivers.dir>${project.basedir}/drivers</drivers.dir>
        <drivers.downloader.phase>pre-integration-test</drivers.downloader.phase>
    </properties>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.0.RELEASE</version>
    </parent>

    <repositories>
        <!-- The order of definitions matters. Explicitly defining central here to make sure it has the highest priority. -->

        <!-- Main Maven repository -->
        <repository>
            <id>central</id>
            <url>https://repo.maven.apache.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>
        <!-- Main Maven repository -->
        <pluginRepository>
            <id>central</id>
            <url>https://repo.maven.apache.org/maven2</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </pluginRepository>
    </pluginRepositories>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>com.vaadin</groupId>
                <artifactId>vaadin-bom</artifactId>
                <version>${vaadin.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </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>
        <dependency>
            <groupId>com.vaadin</groupId>
            <artifactId>vaadin-spring-boot-starter</artifactId>
            <exclusions>
                <!-- Excluding so that webjars are not included. -->
                <exclusion>
                    <groupId>com.vaadin</groupId>
                    <artifactId>vaadin-core</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>com.vaadin</groupId>
            <artifactId>vaadin-testbench</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <defaultGoal>spring-boot:run</defaultGoal>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <!-- Clean build and startup time for Vaadin apps sometimes may exceed
                     the default Spring Boot's 30sec timeout.  -->
                <configuration>
                    <wait>500</wait>
                    <maxAttempts>240</maxAttempts>
                </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>
        </plugins>
    </build>

    <profiles>

        <profile>
            <id>npm</id>
            <build>
                <plugins>
                    <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.9.1</version>
                        <executions>
                            <execution>
                                <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>v12.13.0</nodeVersion>
                        </configuration>
                    </plugin>
                </plugins>
            </build>
        </profile>

        <profile>
            <!-- Production mode is activated using - Production -->
            <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>org.springframework.boot</groupId>
                        <artifactId>spring-boot-maven-plugin</artifactId>
                        <configuration>
                            <jvmArguments>-Dvaadin.productionMode</jvmArguments>
                        </configuration>
                    </plugin>
                    <plugin>
                        <groupId>com.vaadin</groupId>
                        <artifactId>vaadin-maven-plugin</artifactId>
                        <version>${vaadin.version}</version>
                        <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.springframework.boot</groupId>
                        <artifactId>spring-boot-maven-plugin</artifactId>
                        <executions>
                            <execution>
                                <id>start-spring-boot</id>
                                <phase>pre-integration-test</phase>
                                <goals>
                                    <goal>start</goal>
                                </goals>
                            </execution>
                            <execution>
                                <id>stop-spring-boot</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>
                        <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>

UDPATE:

I've got following node error:

-----> Node.js app detected

-----> Creating runtime environment

       NPM_CONFIG_LOGLEVEL=error
       NODE_ENV=production
       NODE_MODULES_CACHE=true
       NODE_VERBOSE=false

-----> Installing binaries
       engines.node (package.json):  >=14.2.0
       engines.npm (package.json):   unspecified (use default)

       Resolving node version >=14.2.0...
       Downloading and installing node 14.2.0...
       Using default npm version: 6.14.4

-----> Installing dependencies
       Installing node modules
       npm ERR! code ENOENT
       npm ERR! syscall open
       npm ERR! path /tmp/build_80d39ca15258361b79fcfee6c11fad8c/node_modules/@vaadin/flow-deps/package.json
       npm ERR! errno -2
       npm ERR! enoent ENOENT: no such file or directory, open '/tmp/build_80d39ca15258361b79fcfee6c11fad8c/node_modules/@vaadin/flow-deps/package.json'
       npm ERR! enoent This is related to npm not being able to find a file.
       npm ERR! enoent 

       npm ERR! A complete log of this run can be found in:
       npm ERR!     /tmp/npmcache.1OllU/_logs/2020-05-11T13_48_17_942Z-debug.log
-----> Build failed

       We're sorry this build is failing! You can troubleshoot common issues here:
       https://devcenter.heroku.com/articles/troubleshooting-node-deploys

       Some possible problems:

       - Dangerous semver range (>) in engines.node
         https://devcenter.heroku.com/articles/nodejs-support#specifying-a-node-js-version

       Love,
       Heroku

 !     Push rejected, failed to compile Node.js app.
 !     Push failed

The Problem seems to be this one:

"@vaadin/flow-deps": "./target/frontend"

Without this line i can deploy the app. Just can't start it then, because vaadin is missing of course.

{
  "name": "no-name",
  "license": "UNLICENSED",
  "dependencies": {
    "@polymer/polymer": "3.2.0",
    "@webcomponents/webcomponentsjs": "^2.2.10",
    "@vaadin/flow-deps": "./target/frontend"
  },
  "devDependencies": {
    "webpack": "4.42.0",
    "webpack-cli": "3.3.10",
    "webpack-dev-server": "3.9.0",
    "webpack-babel-multi-target-plugin": "2.3.3",
    "copy-webpack-plugin": "5.1.0",
    "webpack-merge": "4.2.2",
    "raw-loader": "3.0.0",
    "compression-webpack-plugin": "3.0.1",
    "terser": "4.6.7"
  },
  "engines": {
    "node": "14.X"
  },
  "vaadinAppPackageHash": "Main dependencies updated, force install"
}

Solution

  • You need the node binary in order to webpack Vaadin 14 client code into WAR javascript bundle. Please see https://github.com/mvysny/vaadin14-embedded-jetty#heroku-integration on how to get that done. In short, you need a custom Maven settings.xml file for Heroku with two profiles, production and heroku; triggering heroku profile will enable com.github.eirslett:frontend-maven-plugin which will install node for you.

    Alternatively you can try Vaadin 14.2.0.beta1 which is able to download node automatically if it's missing. That being said, you still need the custom settings.xml file to at least enable the production mode.