Tuesday 2 December 2014

Integrating Javascript into a Maven build

I've recently set up a few Javascript components into a Java web application and I though that sharing my experiences would be helpful, so here goes!

Project Structure

I decided to follow maven conventions and use the src/[main|test]/[language] conventions, and to have all the project definition files (package.json, bower.json, gulpfile.js) in the project root. I soon found myself wanting to split up the gulp tasks into groups, so I added a gulp/ folder, resulting in a structure like this:

webapp-module
`--- bower_components/ : runtime and test JS dependencies
`--- node_modules/ : build dependencies
`--- gulp/ : JS build tasks
`--- src/
    `--- main/js : main javascript files
    `--- test/js : test javascript files
`--- bower.json : runtime and test dependency configuration
`--- package.json : npm configuration, including build dependencies
`--- karma.conf.js : test framework configuration
`--- gulpfile.js : root build file
`--- pom.xml : normal maven project configuration (packaging=war)
`--- target/gulp/ : output directory for JS files

Project Configuration

In the POM, I added an entry for target/gulp as a project resource

<build>
...
  <resources>
    <resource>
      <directory>${project.build.directory}/gulp</directory>
    </resource>
  </resources>
...
</build>

In addition, I used the maven-exec-plugin to include it by default in the build:

<plugins>
...
  <plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>exec-maven-plugin</artifactId>
    <configuration>
      <executable>gulp</executable>
      <arguments>
        <argument>check</argument>
        <argument>build</argument>
      </arguments>
    </configuration>
    <executions>
      <execution>
        <id>build-javascript</id>
        <phase>generate-resources</phase>
        <goals>
          <goal>exec</goal>
        </goals>
      </execution>
    </executions>
  </plugin>
...
</plugins>

This of course requires node & npm to be installed and on the path, and for the gulp module (and in our configuration, bower too) to be globally installed. Therefore on a clean checkout, a developer would run:

npm install -g gulp bower
npm install

They would then be free to mvn package or whatever lifecycle they chose (after generate-resources) and the javascript would be checked and built according to the gulp check and build tasks.

Next Steps

In my next post I'll share some of the structure of the gulp tasks, so you can get a feel for what processes are used to build the javascript into the target/gulp folder.