58

Most of our team consists of java developers and therefore the whole build / deployment / dependency management system is built on top of maven. We use CI so every build process runs unit test (w. karma and phantomJS for the frontend, and jasmine-node for the backend). I've managed to configure a karma maven plugin for this purpose.

This does not solve the issue of downloading node.js dependencies from package.json on build. I need to deploy my node.js / express app in existing environment, so the perfect scenario would be:

  1. pull from the repo (done automatically with maven build)
  2. npm install (that is - downloading dependencies from node package registry)
  3. running tests

I was trying to find a nodejs package for maven, but to be honest - as a node.js developer I do not feel very confident when it comes to choosing the right tools, since I'm not able to distinguish a bad maven plugin from a decent one.

Maybe using a shell plugin and invoking npm install from the terminal is a better choice?

What's your opinion?

Rafal Pastuszak
  • 3,100
  • 2
  • 29
  • 31

4 Answers4

33

You've got two choices:

As a hacky solution, though still feasible you could as you've mentioned yourself, use something like maven-antrun-plugin to actually execute npm with maven.

All approaches have their pros and cons, but frontend-maven-plugin seems to be the most often used approach - but it assumes that your ci server can download from the internet arbitrary packages, whereas the "hacky" solution should also work, when your ci server has no connection to the internet at all (besides proxying the central maven repo)

sleske
  • 81,358
  • 34
  • 189
  • 227
Christian Ulbrich
  • 3,212
  • 1
  • 23
  • 17
  • 6
    No need to use ant here, maven-exec-plugin is enough to launch npm. – user2189998 Oct 30 '15 at 09:27
  • 3
    Yes maven-exec-plugin is just fine until you will try to deploy you app on a PaaS like Openshift. Being a Java maven application you would normally using an application server jdk based image and these images don't come with node.js installed so no npm command is available. – Sergio Arrighi Jul 05 '17 at 22:04
  • @SergioArrighi https://github.com/eirslett/frontend-maven-plugin will download NodeJS and npm on its own. Of course if you use `exec` something it must be available - this is not NodeJS specific. Having the NodeJS binary in the repo, this would still work - we did exactly that for a customer w/o any problems. – Christian Ulbrich Oct 28 '19 at 01:19
  • The npm-maven-plugin by Mulesoft seems to be discontinued. I edited to mention this. Also note that there is another, apparently unrelated plugin also called npm-maven-plugin - https://github.com/aseovic/npm-maven-plugin . – sleske Apr 16 '20 at 18:05
  • Hello @sleske I'm here again after a while...reading your solution now makes way more sense to me. I'm considering to use it, but my only dubt is how npm/node is supposed to be installed on the target machine? It will work in a local environment where you have npm installed, but how do you run a npm script on remote? I'm talking about CI/CD context in particular. Thanks – funder7 Oct 24 '20 at 16:00
  • @funder7: Please don't ask new questions in comments. There's a "Ask" button for that :-). Also, it's not "my solution" - I only edited it. – sleske Oct 25 '20 at 23:52
  • I don't see the point, why opening a new question when we are talking about possibile solutions? CI/CD are a reality and must be considereded when evaluating diffrent solutions, so...If you don't want to give this information it's not a problem at all. Honestly some time passed and I thought you were the poster of this answer. If @ChristianUlbrich ha nothing against it, I'm interested into this aspect. Thanks – funder7 Oct 26 '20 at 19:21
  • @funder7 Have you read OP's question and the link in my answer? And my comment to @SergioArrighi?: _"github.com/eirslett/frontend-maven-plugin will download NodeJS and npm on its own"_, they will happily work in any CI environment given proper internet access... Just read their documentation... – Christian Ulbrich Oct 27 '20 at 00:04
  • The [Frontend Maven Plugin](https://github.com/eirslett/frontend-maven-plugin) works really nicely, and as of 2023 the author is responsive on the tickets. I just posted [No-Fuss React and JSX with Spring Boot](https://www.garretwilson.com/blog/2023/03/21/no-fuss-react-jsx-with-spring-boot) which gives comprehensive instructions for using the plugin to integrate React JSX transpilation transparently into your existing Maven workflow. The examples in Spring Boot Maven with Thymeleaf, but it would work with any Maven build. – Garret Wilson Mar 22 '23 at 14:27
16

I think you can find the answer in Grunt and the many available plugins.

I'm actually working on a web project where the client-side is made with AngularJS. Nevertheless, I think the deployement process may partially answer to your question :

In your pom.xml, you can do something like that:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-antrun-plugin</artifactId>
    <version>1.5</version>
    <executions>
        <execution>
            <id>exec-gen-sources</id>
            <phase>generate-sources</phase>
            <configuration>
                <target name="Build Web">

                    <exec executable="cmd" dir="${project.basedir}"
                        failonerror="true" osfamily="windows">
                        <arg line="/c npm install" />
                    </exec>

                    <exec executable="cmd" dir="${project.basedir}"
                        failonerror="true" osfamily="windows">
                        <arg line="/c bower install --no-color" />
                    </exec>

                    <exec executable="cmd" dir="${project.basedir}"
                        failonerror="true" osfamily="windows">
                        <arg line="/c grunt release --no-color --force" />
                    </exec>

                </target>
            </configuration>
            <goals>
                <goal>run</goal>
            </goals>
        </execution>
    </executions>
</plugin>
  • First part is the npm install task: downloading of dependencies from node package.

  • Second part is the bower install task: downoading of other dependencies with bower (in my case, AngularJS, but you might not need this part)

  • Third part is the Grunt Release part: launching a Grunt task that includes Karma unit testing.

You can find documentation about Grunt here. There are many available plugins like Karma unit testing.

I hope this helped you.

Pear
  • 470
  • 3
  • 17
  • 1
    Hi, thanks for the answer. In fact, I am using a pretty big (ca 300 lines of code) grunt config. What I wanted to know is if using maven exec along with grunt is a good practice when it comes to maven. – Rafal Pastuszak Jun 14 '13 at 09:35
  • Can you post the pom.xml file with the `` block as well? – Rafal Pastuszak Jun 14 '13 at 11:04
  • 1
    Well, honestely I don't know if it is a good practice, but that is what I do ^^. The pom.xml is more like that : org.apache.maven.plugins maven-antrun-plugin 1.5 – Pear Jun 14 '13 at 11:40
  • 1
    Is this specific to windows? I saw the 'osfamily' on there but I want to be able to run this OS-agnostic -- is that possible? – streetlight Jan 28 '14 at 19:54
  • @BlondCode This post is a bit old, and things are moving pretty fast in the javascript ecosystem ^^ ! IMO The best solution at the moment is the first one listed by Christian Ulbrich. If Grunt doesn't work on your machine, try Gulp (it seems to be winning the contest against Grunt), the maven-frontend-plugin allows you to use it. – Pear Feb 16 '17 at 14:11
  • @Pear My mistake, i was missreading: i was thinking about Gulp not Grunt. So Gulp did not work on my Win7. :D I am totally newby in js world although i have enough experience in java. Thanks for your feedback, it seems a worth to try Grunt as well! Let me see when i am out of time pressure and give you a feedback. :) – BlondCode Feb 22 '17 at 12:34
  • @Pear Finally i succeded with gulp! All my problems were coming from proxy settings and windows symlink permissions (and false setup information from coworker :D). Thanks for all! – BlondCode Feb 24 '17 at 11:47
13

I made npm process work for my AngularJS 2 + Spring Boot application by exec-maven-plugin. I don't use bower and grunt, but think you can make it work by exec-maven-plugin too, after look at the antrun example above from Pear.

Below is my pom.xml example for exec-maven-plugin. My app has package.json and all the AngularJS .ts files are under src/main/resources, so run npm from the path. I run npm install for dependencies and npm run tsc for .ts conversion to .js

pom.xml

        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>exec-maven-plugin</artifactId>
            <executions>
                <execution>
                    <id>exec-npm-install</id>
                    <phase>generate-sources</phase>
                    <configuration>
                        <workingDirectory>${project.basedir}/src/main/resources</workingDirectory>
                        <executable>npm</executable>
                        <arguments>
                            <argument>install</argument>
                        </arguments>
                    </configuration>
                    <goals>
                        <goal>exec</goal>
                    </goals>
                </execution>
                <execution>
                    <id>exec-npm-run-tsc</id>
                    <phase>generate-sources</phase>
                    <configuration>
                        <workingDirectory>${project.basedir}/src/main/resources</workingDirectory>
                        <executable>npm</executable>
                        <arguments>
                            <argument>run</argument>
                            <argument>tsc</argument>
                        </arguments>
                    </configuration>
                    <goals>
                        <goal>exec</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>

One little hack on this is running maven build on eclipse with Windows or Mac. It perfectly fine on eclipse with linux or even also fine on Windows command window though. When run build on eclipse with Windows, it fail to understand npm and complain about not find the file. Weird thing is npm is working fine on Windows command window. So solving the hack I create npm.bat file under system path. In my case nodejs and npm are installed under C:\Program File\nodejs. After putting this batch file. everything works fine.

npm.bat

@echo off
set arg1=%1
set arg2=%2
C:\Progra~1\nodejs\npm.cmd %arg1% %arg2%

For Mac, I got same issue on eclipse. The thing is nodejs and npm are installed under /usr/local/bin. So to solve the issue, I make symbolic link /usr/local/bin/node and /usr/local/bin/npm to under /user/bin. However /usr/bin is protected in security policy, I done that after booting from recovery disk

Steve Park
  • 1,979
  • 27
  • 33
5

Since 2015, there is an alternative to the frontend-maven-plugin mentioned in Christian Ulbrich's excellent answer:

https://github.com/aseovic/npm-maven-plugin

Usage

Basically, all you have to do to use it is to put it into your POM as usual (and use "extensions:true"):

<build>
  <plugins>
    <plugin>
      <groupId>com.seovic.maven.plugins</groupId>
      <artifactId>npm-maven-plugin</artifactId>
      <version>1.0.4</version>
      <extensions>true</extensions>
    </plugin>
  [...]
  </plugins>
</build>

The plugin will then automatically bind to the Maven lifecycle. Then, you can put a script into your package.json, such as:

"scripts": 
  {
    "package": "npm pack",
  [...]
  }

and the npm script "package" will run automatically as part of the Maven build lifecycle phase "package".

Compared to frontend-maven-plugin

Just like frontend-maven-plugin, it will run npm scripts inside a maven project. There are two important differences:

  • frontend-maven-plugin will (and must) download and install npm itself. npm-maven-plugin uses (and requires) an installed version of npm.
  • frontend-maven-plugin requires you to describe every npm invocation in the POM (as an "execution" section). In contrast, npm-maven-plugin simply extends the Maven build lifecycle to automatically execute an npm script with the same name for each lifecycle phase (clean, install etc.). That means there is no npm-specific configuration in the POM - it's all taken from package.json.

Personally, I prefer the npm-maven-plugin's approach because it requires less configuration in the POM - POMs have a tendency to get bloated, and everything to counter that helps. Also, putting the npm invocations into package.json feels more natural and allows reusing them when invoking npm directly.

Admittedly, even with the frontend-maven-plugin you can [and probably should] define all npm invocations as scripts in package.json, and invoke these scripts from the POM, but there is still the temptation to put them directly into the POM.

Ritesh
  • 7,472
  • 2
  • 39
  • 43
sleske
  • 81,358
  • 34
  • 189
  • 227
  • Yep, npm-maven-plugin is easy to use, but is 5 years old, it doesn't mean it's a bad choice, but what if something changes and then you cannot use it anymore? Also with classic plugin & profiles you can run different npm scripts depending on the situation. On the other side, you need to create npm scripts to couple npm and maven, adding scripts to the ones already present. Yes, maven is pretty redundant. But...who cares as soon as you can configure as you need to? It works fine, highly configurable... I'm missing something? please tell me, I'm not very experienced! – funder7 May 26 '20 at 18:34
  • @Funder: Sorry, I'm not quite sure what you want to say. Consider asking a new question :-). – sleske May 26 '20 at 19:51
  • Sorry I was thinking out loud, I gaved a quick look to the npm-maven-plugin, and it did not seem the best solution (for me)! Correct me if I'm wrong, but in order to use it, you need to create a new npm script for each maven build phase. It's an interesting solution, but it couples npm with maven. :-) – funder7 May 27 '20 at 14:38
  • 1
    @Funder: Yes, you need to create a script per Maven build phase (not for all, just those you need). As to coupling: There's always coupling involved, you can only choose where to put it (into the POM, or into package.json). – sleske May 28 '20 at 08:57