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

Continue reading %Building your Front End with Maven: Simple Resources%


Source: Sitepoint