Building your Front End with Maven: Simple Resources

Share this article

Building your Front End with Maven: Simple Resources

Every time you are developing a web application, you will invariably have a number of static resources that you desire to serve up to the end user. These static files come in a number of different forms – HTML, CSS, LESS, SCSS, Javascript, Plain Text, Markdown, Asciidoc, etc. – and have a number of challenges to best incorporate into your web application for the easiest development process. This article aims to show some simple techniques using Maven plugins to streamline the development and incorporation of these static resources into your application.

Serving up Static Resources

It is assumed that you are already able to serve up static resources from your web application. Generally, whichever framework you are using to build your application has standard ways of supporting this – Spring, for example – uses the mvc:resources tag. Additionally, assuming you are using a Servlet Container such as Tomcat, it is often the case that you can serve anything up that appears in the src/main/webapp directory without any extra configuration at all. It is important that you know where in the resulting WAR file your static files need to end up, as this will be used repeatedly throughout the examples given in this article.

Plain, Unmanipulated Files

The absolute simplest form of static resources that can be included are ones that require absolutely no manipulation. These are files that you write and are then included into the webapp as-is. Including these is really simple. All you need to do is put the files into either src/main/webapp or src/main/resources as appropriate for where you want them to appear. Files included in src/main/webapp will be copied into the root of your WAR file, whereas files included in src/main/resources will be copied into target/classes, which then ends up on the classpath of your webapp.

Templated Files

Sometimes you find that you want to have some plain files, but include in them expanded properties taken from the Maven build. For example, the version number of the artifact is a common one that might be included.

This is achievable using standard Maven plugins that are already used as part of your build – the Maven Resources Plugin and the Maven WAR Plugin – so let’s have a look at them.

Maven Resources Plugin

Without any additional configuration at all, the Maven Resources Plugin is already used to copy the src/main/resources directory into the resultant JAR or WAR file. (Note, the Maven Resources Plugin is also used for the src/test/resources directory, and everything that is mentioned here is equally applicable to that).

By default, it will not do filtering, though, so some extra configuration is needed to support this. Filtering is the act of substituting special placeholders in your static resources with the correct values at the time the resources are copied into your webapp.

Configuring filtering of your resources is a simple case of adding the following configuration to your pom.xml file:

<build>
    <resources>
        <resource>
            <directory>src/main/filteredResources</directory>
            <filtering>true</filtering>
        </resource>
    </resources>
</build>

This block has two effects:

  • Adds a new directory from which resources will be copied – in this case we used src/main/filteredResources
  • Enable filtering for all resources in this directory

It is recommended that you keep your filtered resources separate if possible, so that you don’t accidentally perform filtering on files you don’t mean to do so. For example, Spring Context files often contain properties to be expanded that use the exact same syntax, but that you do not wish to be expanded by this process.

Filtering is then achieved by adding special placeholders into your files. These placeholders all start ${ and end }. Between the braces is the property name that you wish to substitute into the file. Say, for example, you have a file src/main/filteredResources/details.txt that contains the following:

Group ID: ${project.groupId}
Artifact ID: ${project.artifactId}
Version: ${project.version}

Then, upon copying into the built webapp, this will be automatically expanded with the group ID, artifact ID and version of the project currently being built.

The properties that can be used here are anything available to the Maven Reactor. These include the default Maven properties, additional ones defined in the POM file, and system properties provided on the command line.

Maven WAR Plugin

The Maven WAR Plugin is slightly less integrated into the build process, so configuring it needs to use the standard mechanism for configuring plugins.

Again, by default this will not do any filtering. As before, you probably want to be selective about the files that are chosen for filtering, so as to not interfere too much with other sources. If you wish to use a similar setup to before, where you have one entire directory for filtered resources and one for unfiltered ones, then the following configuration will work.

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-war-plugin</artifactId>
            <configuration>
                <webResources>
                    <resource>
                        <directory>src/main/filteredWebapp</directory>
                        <filtering>true</filtering>
                    </resource>
                    <resource>
                        <directory>src/main/webapp</directory>
                        <filtering>false</filtering>
                    </resource>
                </webResources>
            </configuration>
        </plugin>
    </plugins>
</build>

As before, we now have two directories from which files will be included into the WAR file. The files in src/main/webapp will be included as-is, whilst the files in src/main/filteredWebapp will be filtered as they are copied across.

Alternatively, you may want to keep all of the files together, and selectively filter only a small subset of them. This can be achieved as follows:

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-war-plugin</artifactId>
            <configuration>
                <webResources>
                    <resource>
                        <directory>src/main/webapp</directory>
                        <filtering>true</filtering>
                        <includes>
                            <include>version.html</include>
                        </includes>
                    </resource>
                    <resource>
                        <directory>src/main/webapp</directory>
                        <filtering>false</filtering>
                        <excludes>
                            <exclude>version.html</exclude>
                        </excludes>
                    </resource>
                </webResources>
            </configuration>
        </plugin>
    </plugins>
</build>

This version keeps all of the files in src/main/webapp, and selectively filters only the specified files – in this case version.html. This makes it easier to keep track of which files are in use, but the downside is that the list of filtered files needs to be specified twice – once to include in the filtered set of files and once to be excluded from the non-filtered set. This is an unfortunate side effect of the need to use different resource tags to represent filtered and unfiltered resources.

Using Maven to process your project's resources

CSS Files

Any webapp will invariably need to include Cascading Stylesheet (CSS) files to describe the styling of the page. These CSS files can be built in a variety of ways, ranging from hand-crafted and included as simple resources – as described above – to using a CSS preprocessor such as LESS or SASS.

LESS

LESS files can be supported by use of the LESS Maven Plugin. LESS is implemented as a Javascript application, and the LESS Maven Plugin incorporates this into the build by executing the Javascript inside of the JVM running the build. This plugin is slightly simpler and lighter weight than the SASS one, but LESS is also a slightly simpler preprocessor with less features. If you’ve never used a CSS preprocessor before it is a good place to start, though.

Configuring the build to automatically build LESS files into CSS files can be done as follows:

<build>
    <plugins>
        <plugin>
            <groupId>org.lesscss</groupId>
            <artifactId>lesscss-maven-plugin</artifactId>
            <version>1.7.0.1.1</version>
            <configuration>
                <sourceDirectory>
                    ${project.basedir}/src/main/less
                </sourceDirectory>
                <outputDirectory>
                    ${project.build.directory}/${project.build.finalName}/css
                </outputDirectory>
            </configuration>
            <executions>
                <execution>
                    <id>compile-less</id>
                    <phase>generate-resources</phase>
                    <goals>
                        <goal>compile</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

This configuration will compile every *.less file in the src/main/less directory, and place the resulting CSS files in the css directory of the webapp, exactly the same as if the CSS files themselves had been put into src/main/webapp/css. If you wish to include the files on the classpath – as if they had been written in src/main/resources then simply change outputDirectory to use classes instead of ${project.build.finalName}.

SCSS

SCSS files can be supported by use of the SASS Maven Plugin. SASS is implemented as a Ruby application, and the SASS Maven Plugin incorporates this into the build by executing the Ruby code using the JRuby bindings for Java. This makes the process slightly more complicated than the LESS plugin but the complexity is mostly handled by the Maven plugin and is not something the user needs to care about.

Configuring the build to automatically build SCSS files into CSS files can be done as follows:

<build>
    <plugins>
        <plugin>
            <groupId>nl.geodienstencentrum.maven</groupId>
            <artifactId>sass-maven-plugin</artifactId>
            <version>2.23</version>
            <executions>
                <execution>
                    <id>lint</id>
                    <phase>validate</phase>
                    <goals>
                        <goal>scss-lint</goal>
                    </goals>
                </execution>
                <execution>
                    <id>build</id>
                    <phase>generate-resources</phase>
                    <goals>
                        <goal>update-stylesheets</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <sassSourceDirectory>
                    ${project.basedir}/src/main/scss
                </sassSourceDirectory>
                <destination>
                    ${project.build.directory}/${project.build.finalName}/css
                </destination>
            </configuration>
        </plugin>
    </plugins>
</build>

This configuration will compile every *.scss file in the src/main/scss directory, and place the resulting CSS files in the css directory of the webapp, exactly the same as if the CSS files themselves had been put into src/main/webapp/css. If you wish to include the files on the classpath – as if they had been writtein in src/main/resources then simply change destination to use classes instead of ${project.build.finalName}.

Note that one feature the SASS plugin gives over the LESS plugin is support for linting of the stylesheets. This is configured above to execute in an earlier phase and will ensure that the SCSS files are syntactically valid. This can be very useful to ensure that the build is going to be valid early in the build lifecycle.

Generated HTML Files

Occasionally you might have a need to generate HTML out of markup files that you have as part of your build. For example, you might maintain API Documentation in Markdown or AsciiDoc format, and want to publish HTML versions of this as part of the deployed webapp. (It would even be possible to generate these from your code and then use this plugin to convert this into HTML. Doing this is left as an exercise to the reader.)

Markdown Files

Markdown files can be converted into HTML files by use of the Markdown Page Generator Plugin. This plugin will automatically generate HTML files for all Markdown files that are processed. It can be configured to fully customize the style of the generated files but out of the box it still generates perfectly usable files.

Configuring the build to automatically build Markdown files into HTML files can be done as follows:

<build>
    <plugins>
        <plugin>
            <groupId>com.ruleoftech</groupId>
            <artifactId>markdown-page-generator-plugin</artifactId>
            <version>1.0.0</version>
            <executions>
                <execution>
                    <phase>process-sources</phase>
                    <goals>
                        <goal>generate</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <inputDirectory>
                    ${project.basedir}/src/main/markdown
                </inputDirectory>
                <outputDirectory>
                    ${project.build.directory}/${project.build.finalName}/docs
                </outputDirectory>
            </configuration>
        </plugin>
    </plugins>
</build>

This configuration will process every *.md file in src/main/markdown and produce HTML files in the docs directory of the webapp, exactly the same as if the HTML files themselves had been put into src/main/webapp/docs.

AsciiDoc files

AsciiDoc files can be converted into HTML files by use of the Asciidoctor Maven Plugin. This plugin will automatically generate HTML files for all AsciiDoc files that are processed. It can be configured to fully customize the style of the generated files but out of the box it still generates perfectly usable files.

Configuring the build to automatically build AsciiDoc files into HTML files can be done as follows:

<build>
    <plugins>
        <plugin>
            <groupId>org.asciidoctor</groupId>
            <artifactId>asciidoctor-maven-plugin</artifactId>
            <version>1.5.5</version>
            <executions>
                <execution>
                    <phase>process-resources</phase>
                    <goals>
                        <goal>process-asciidoc</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <sourceDirectory>
                    ${project.basedir}/src/main/asciidoc
                </sourceDirectory>
                <outputDirectory>
                    ${project.build.directory}/${project.build.finalName}/docs
                </outputDirectory>
                <preserveDirectories>true</preserveDirectories>
                <backend>html5</backend>
            </configuration>
        </plugin>
    </plugins>
</build>

This configuration will process every *.ad, *.adoc and *.asciidoc file in src/main/asciidoc and produce HTML files in the docs directory of the webapp, exactly the same as if the HTML files themselves had been put into src/main/webapp/docs.

Summary

Whether it is filtering some templated resource files to add build information, copying CSS files, processing LESS or SCSS files, or transforming Markdown an Asciidoc to HTML, there is a Maven plugin for everything. Each of them have a lot more depth than can be covered here, so if you want to do more with them, it’s likely possible with some configuration work. However, the above configuration examples are usable out of the box to add support for these technologies as a standard part of the build.

Hopefully this has given some ideas on ways to streamline the inclusion of front-end assets in your web application, without the need for complicated multi-stage builds.

Frequently Asked Questions (FAQs) about Building Front-End with Maven

What is the purpose of using Maven in front-end development?

Maven is a powerful project management tool that is primarily used for Java projects. In front-end development, Maven can be used to automate the build process, manage dependencies, and ensure consistency across the project. It simplifies the build process by defining a uniform build system, providing quality project information, and allowing transparent migration to new features. This allows developers to focus more on the coding aspect and less on the build and dependency management.

How do I create a pure JavaScript project using Maven?

Creating a pure JavaScript project using Maven involves setting up a Maven project and configuring the pom.xml file to include the necessary plugins for JavaScript. The frontend-maven-plugin can be used to install Node and NPM, and run NPM scripts. This plugin allows Maven to interact with a range of front-end tools like Node, NPM, Yarn, and Webpack.

What is the frontend-maven-plugin and how does it work?

The frontend-maven-plugin is a plugin that allows Maven to interact with a range of front-end tools like Node, NPM, Yarn, and Webpack. It can install Node and NPM locally for your project, run NPM scripts, and even run Grunt or Gulp tasks. It works by providing a bridge between the front-end tools and the Maven build system.

How does Maven ensure consistency across the project?

Maven ensures consistency across the project by providing a uniform build system. This means that every part of the project follows the same build process and produces the same output. It also manages dependencies to ensure that all parts of the project are using the same versions of libraries and frameworks. This helps to avoid conflicts and inconsistencies that can arise from different parts of the project using different versions of dependencies.

Can I use Maven for non-Java projects?

Yes, while Maven is primarily used for Java projects, it can also be used for projects in other languages. The key is to configure the pom.xml file correctly to include the necessary plugins for the language you are using. For example, for a JavaScript project, you would include the frontend-maven-plugin.

How does Maven simplify the build process?

Maven simplifies the build process by automating it. Once you have configured your pom.xml file, you can run a single command to build your project, run tests, generate documentation, and more. This saves developers time and effort, and ensures that the build process is consistent and reliable.

What is the Maven lifecycle and how does it work?

The Maven lifecycle is a sequence of phases that define the order in which the goals are executed. These phases include validate, compile, test, package, verify, install, and deploy. Each phase represents a stage in the build lifecycle, and the goals associated with each phase are executed in order.

How do I manage dependencies with Maven?

Dependencies in Maven are managed through the pom.xml file. You can specify the libraries and frameworks your project depends on, and Maven will automatically download and include them in your project. This ensures that your project has all the necessary dependencies, and that they are all the correct version.

Can I use Maven with other build tools like Grunt or Gulp?

Yes, you can use Maven with other build tools like Grunt or Gulp. The frontend-maven-plugin allows Maven to run Grunt or Gulp tasks as part of the build process. This means you can take advantage of the features of these tools while still benefiting from the consistency and reliability of Maven.

How do I migrate to new features with Maven?

Maven allows for transparent migration to new features. This means that when new features are added to Maven, you can easily update your project to use them. This is done through the pom.xml file, where you can specify the version of Maven and the plugins you are using.

Graham CoxGraham Cox
View Author

Graham Cox is a Software Developer from the UK who has been writing software for almost 15 years, predominantly using Java and Javascript but also covering a wide variety of other languages.

CSSLESSmarkdownMavennicolaipScss
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week