A JBoss Project
Red Hat

Web resource optimization and Maven Profiles

posted by Fred Bricon on Apr 17, 2014.

jbosstools jbds maven optimization wro4j Comments

Some time ago, I described how to perform CSS and JS minification using Eclipse, Maven and WRO4J, thanks to m2e-wro4j.

In this article, we’ll deploy a Java EE 6 Restful application with an HTML5 front-end on a Wildfly application server. We’ll see how, using m2e-wro4j, m2e-wtp and the JBoss Tools Maven Profile Management UI, you can easily switch between minified and regular build profiles.

Setup your Eclipse-based IDE

First you’ll need to install a couple things into an Eclipse Java EE installation. I recommend you use Red Hat JBoss Developer Studio, as it comes with m2e, m2e-wtp, the Maven Profile Manager, the Wildfly server adapter and JBoss Central out-of-the-box, but any Eclipse based installation (Kepler) will do, provided you install the proper plugins.

Red Hat JBoss Developer Studio Eclipse Java EE
  • You can download and install Red Hat JBoss Developer Studio 7.1.1 from here

  • or install it over an existing Eclipse (Kepler) installation from the Eclipse Marketplace

Make sure you install the following JBoss Tools features :

  • Maven Profiles Management

  • JBossAS Server

  • JBoss Central

m2e-wro4j can then be installed from JBoss Central’s Software/Update tab :

m2e wro4j installation

Alternatively, you can find and install m2e-wro4j from the Eclipse Marketplace too.

Also make sure you have a Wildfly server installed on your machine.

About m2e-wro4j

The m2e-wro4j connector allows wro4j-maven-plugin to be invoked when .js, .css, .coffee, .less, .sass, .scss, .json, .template or pom.xml files are modified.

Given the following configuration :

<plugin>
            <groupId>ro.isdc.wro4j</groupId>
            <artifactId>wro4j-maven-plugin</artifactId>
            <version>${version.ro.isdc.wro4j}</version>
            <executions>
                <execution>
                    <phase>compile</phase>
                    <goals>
                        <goal>run</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <targetGroups>app.min,m.screen.min,d.screen.min</targetGroups>
                <cssDestinationFolder>${project.build.directory}/${project.build.finalName}/css/</cssDestinationFolder>
                <jsDestinationFolder>${project.build.directory}/${project.build.finalName}/js/</jsDestinationFolder>
                <wroManagerFactory>ro.isdc.wro.maven.plugin.manager.factory.ConfigurableWroManagerFactory</wroManagerFactory>
            </configuration>
        </plugin>

When m2e-wtp is present, m2e-wro4j automatically translates ${project.build.directory}/${project.build.finalName}/* output directories (the default values used by wro4j-maven-plugin) to ${project.build.directory}/m2e-wtp/web-resources/. This gives you on-the-fly redeployment of optimized resources on WTP controlled servers.

In order to use wro4j-maven-plugin, you need a wro.xxx descriptor (that would be src/main/webapp/WEB-INF/wro.xml by default) and a wro.properties. Read https://code.google.com/p/wro4j/wiki/MavenPlugin for more details.

Create an HTML 5 project

Now let’s get to work. From the JBoss Central Getting Started tab, click on the HTML 5 project icon to create a Maven based web application with a JAX-RS back-end and an HTML 5 front-end.

html5 project jboss central

I used kitchensink as a project name.

This project already has some wro4j-maven-plugin configuration we can use. All we need is to make the switch between regular and minified versions of the build more user friendly.

Enable minification

First, we need to remove one xml snippet from the pom.xml which prevents wro4j-maven-plugin from running during Eclipse builds, thus cancelling m2e-wro4j’s efforts. Go to the minify profile and delete :

<pluginManagement>
            <plugins>
                <!--This plugin's configuration is used to store Eclipse m2e settings only. It has no influence on the Maven build itself.-->
                <plugin>
                    <groupId>org.eclipse.m2e</groupId>
                    <artifactId>lifecycle-mapping</artifactId>
                    <version>${version.org.eclipse.m2e}</version>
                    <configuration>
                        <lifecycleMappingMetadata>
                            <pluginExecutions>
                                <pluginExecution>
                                    <pluginExecutionFilter>
                                        <groupId>ro.isdc.wro4j</groupId>
                                        <artifactId>
                                            wro4j-maven-plugin
                                        </artifactId>
                                        <version>${version.ro.isdc.wro4j}</version>
                                        <goals>
                                            <goal>run</goal>
                                        </goals>
                                    </pluginExecutionFilter>
                                    <action>
                                        <ignore></ignore>
                                    </action>
                                </pluginExecution>
                            </pluginExecutions>
                        </lifecycleMappingMetadata>
                    </configuration>
                </plugin>
            </plugins>
        </pluginManagement>

In order to use the minified versions of javascript and css files in the app, the original index.html file requires you to (un)comment several lines like :

yep: {
            //assign labeled callbacks for later execution after script loads.
            //we are on mobile device so load appropriate CSS
            "jqmcss": "css/jquery.mobile-1.3.1.min.css",
            // For minification, uncomment this line
            //"mcss": "css/m.screen.min.css"
            // For minification, comment out this line
            "mcss": "css/m.screen.css"
        },
        nope: {
            //we are on desktop
            // For minification, uncomment this line
            //"scss": "css/d.screen.min.css"
            // For minification, comment out this line
            "scss": "css/d.screen.css"
        },

This is clearly not practical if you want to be able to quickly switch between minified and original versions of your files.

Fortunately, we can take advantage of some Maven black magic, also known as web resource filtering, to dynamically use the proper (non-minified) version of these files, depending on the profile we’re building with.

We have 3 things to do :

  1. define a maven property for the minified file extension currently in use

  2. enable web resource filtering in the maven-war-plugin configuration

  3. modify index.html so it uses the aforementioned maven property

Setup the maven property

In the main <properties> block, at the top of your pom.xml, add the following property :

<!-- By default, the original filename will be used -->
        <min.ext></min.ext>

Now add a <properties> block to the minify profile :

<properties>
          <min.ext>.min</min.ext>
        </properties>

Enable web resource filtering

Modify the default maven-war-plugin configuration to enable filtering on html files :

<plugin>
          <artifactId>maven-war-plugin</artifactId>
          <version>${version.war.plugin}</version>
          <configuration>
            <!-- Java EE 6 doesn't require web.xml, Maven needs to catch up! -->
            <failOnMissingWebXml>false</failOnMissingWebXml>
            <webResources>
              <webResource>
                <directory>src/main/webapp</directory>
                <filtering>true</filtering>
                <includes><include>*.html</include></includes>
              </webResource>
            </webResources>
          </configuration>
        </plugin>

Use the maven property

In index.html, replace at least the following occurrences :

from to

js/app.js

js/app${min.ext}.js

css/m.screen.css

css/m.screen{min.ext}.css

css/d.screen.css

css/d.screen{min.ext}.css

You can also apply similar changes to lodash and jquery if you want.

At this point, you should see the filtered target/m2e-wtp/web-resources/index.html references the original resources, as the minified extension enabled by default is an empty string.

Switch between minified and regular profiles

Let’s see what happens when enabling the minify profile. Ctrl+Alt+P is a shortcut bringing up the Maven Profile Management UI. Just check/uncheck profiles to enable/disable them :

profile selection

Once the minify profile is active, you’ll see that :

  • css/m.screen.min.css, css/d.screen.min.css,js/app.min.js are generated under target/m2e-wtp/web-resources/

  • target/m2e-wtp/web-resources/index.html now references the minified versions of the resources

minified resources

Deploy the application on WildFly

  • Right click on your project and select Run As > Run on Server …​

  • Create a new Wildfly Server if necessary, pointing at your locally installed server

  • Once the server is created and deployed, a browser window should open :

deployed application1

If you’re on a desktop, modify the color of the h1 class in src/main/webapp/css/d.screen.css and save. This will trigger wro4j-maven-plugin:run which will regenerate the minified version under target/m2e-wtp/web-resources/css/d.screen.min.css, which in turn will be deployed on Wildfly by the server adapter.

Reloading the page (after the build is complete) will show the changes directly :

deployed application2

Now you can switch back to using the regular, non-minified version by hitting Ctrl+Alt+P in the workbench, unselect the minify profile and wait for the build to complete. After you reload your browser page, you’ll notice, if you look at the source page, the minified versions are not referenced anymore.

The minified files still exist under target/m2e-wtp/web-resources/ and are deployed as such. They’re unused, so they’re harmless, but you’d need to perform a clean build to remove them, if necessary.

Conclusion

Dealing with optimized resources in Eclipse is made really easy with a combination of the right tools. Just focus on code, save your work, see the changes instantly. WRO4J and wro4j-maven-plugin can give you much more than what we just saw here (resource aggregation, obfuscation, less processing …​). Hopefully you’ll want to give it a try after reading this article, and if you do, don’t forget to give us your feedback.

Issues with m2e-wro4j can be opened at https://github.com/jbosstools/m2e-wro4j/issues.

Issues with the Maven Profile Manager can be opened at :

As always, for all your WRO4J or wro4j-maven-plugin specific issues, I strongly encourage you to :

Have fun!

Latest posts

What’s New in JavaScript Tools

by Denis Golovin on Nov 25, 2014.

Fabulous Forge Fun

by Koen Aers on Nov 21, 2014.

New Videos on Hybrid Mobile Developement Tools

by Xavier Coulon on Nov 20, 2014.

Looking for older articles ? See the Archived entries.
back to top