9 date: "2013-12-06T10:58:17+00:00"
10 guid: http://juplo.de/?p=140
13 title: Combining jetty-maven-plugin and wro4j-maven-plugin for Dynamic Reloading of LESS-Resources
14 url: /combining-jetty-maven-plugin-and-wro4j-maven-plugin-for-dynamic-reloading-of-less-resources/
17 Ever searched for a simple configuration, that lets you use your [jetty-maven-plugin](http://wiki.eclipse.org/Jetty/Feature/Jetty_Maven_Plugin "See the documentation for mor information") as you are used to, while working with [LESS](http://www.lesscss.org/ "See LESS CSS documentation for mor informations") to simplify your stylesheets?
19 You cannot do both, use the [Client-side mode](http://www.lesscss.org/#usage "More about the client-side usage of LESS") of LESS to ease development and use the [lesscss-maven-plugin](https://github.com/marceloverdijk/lesscss-maven-plugin "Homepage of the official LESS CSS maven plugin") to automatically compile the LESS-sources into CSS for production. That does not work, because your stylesheets must be linked in different ways if you are switching between the client-side mode - which is best for development - and the pre-compiled mode - which is best for production. For the client-side mode you need something like:
23 <link rel="stylesheet/less" type="text/css" href="styles.less" />
24 <script src="less.js" type="text/javascript"></script>
28 While, for the pre-compiled mode, you want to link to your stylesheets as usual, with:
32 <link rel="stylesheet" type="text/css" href="styles.css" />
36 While looking for a solution to this dilemma, I stumbled accross [wro4j](https://code.google.com/p/wro4j/ "See the documentation of ths wounderfull tool"). Originally intended, to speed up page-delivery by combining and minimizing multiple resources into one through the use of a servlet-filter, this tool also comes with a maven-plugin, that let you do the same offline, while compiling your webapp.
38 The idea is, to use the [wro4j-maven-plugin](http://code.google.com/p/wro4j/wiki/MavenPlugin "See the documentation of hte wro4j-maven-plugin") to compile and combine your LESS-sources into CSS for production and to use the [wro4j filter](http://code.google.com/p/wro4j/wiki/Installation "See how to configure the filter"), to dynamically deliver the compiled CSS while developing. This way, you do not have to alter your HTML-code, when switching between development and production, because you always link to the CSS-files.
42 ## Step 1: Configure wro4j
44 First, we configure **wro4j**, like as we want to use it to speed up our page. The details are explained and linked on wro4j's [Getting-Started-Page](http://code.google.com/p/wro4j/wiki/GettingStarted "Visit the Getting-Started-Page"). In short, we just need two files: **wro.xml** and **wro.properties**.
48 wro.xml tells wro4j, which resources should be combined and how the result should be named. I am using the following configuration to generate all LESS-Sources beneath `base/` into one CSS-file called `base.css`:
52 <groups xmlns="http://www.isdc.ro/wro">
54 <css>/less/base/*.less</css>
59 wro4j looks for `/less/base/*.less` inside the root of the web-context, which is equal to `src/main/webapp` in a normal maven-project. There are [other ways to specifie the resources](http://code.google.com/p/wro4j/wiki/ResourceTypes "See the resource locator documentation of wro4j for more details"), which enable you to store them elswhere. But this approach works best for our goal, because the path is understandable for both: the wro4j servlet-filter, we are configuring now for our development-environment, and the wro4j-maven-plugin, that we will configure later for build-time compilation.
63 wro.properties in short tells wro4j, how or if it should convert the combined sources and how it should behave. I am using the following configuration to tell wro4j, that it should convert `*.less`-sources into CSS and do that on _every request_:
67 managerFactoryClassName=ro.isdc.wro.manager.factory.ConfigurableWroManagerFactory
68 preProcessors=cssUrlRewriting,lessCssImport
74 First of all we specify the `ConfigurableWroManagerFactory`, because otherwise, wro4j would not pick up our pre- and post-processor-configuration. This is a little bit confusing, because wro4j is already reading the `wro.properties`-file - otherwise wro4j would never detect the `managerFactoryClassName`-directive - and you might think: "Why? He is already interpreting our configuration!" But belive me, he is not! You can [read more about that in wro4j's documentation](http://code.google.com/p/wro4j/wiki/ConfigurableWroManagerFactory "Read the full story in wro4j's documentation"). The `disableCache=true` is also crucial, because otherwise, we would not see the changes take effect when developing with **jetty-maven-plugin** later on. The pre-processors `lessCssImport` and `cssUrlRewriting` merge together all our LESS-resources under `/less/base/*.less` and do some URL-rewriting, in case you have specified paths to images, fonts or other resources inside your LESS-code, to reflect that the resulting CSS is found under `/css/base.css` and not `/css/base/YOURFILE.css` like the LESS-resources.
76 You can do much more with your resources here, for example [minimizing](https://code.google.com/p/wro4j/wiki/AvailableProcessors "See all available processors"). Also, there are countless [configuration options](http://code.google.com/p/wro4j/wiki/ConfigurationOptions "See all configuration options") to fine-tune the behaviour of wro4j. But for our goal, we are now only intrested in the compilation of our LESS-sources.
78 ## Step 2: Configure the wro4j servlet-filter
80 Configuring the filter in the **web.xml** is easy. It is explained in wro4j's [installation-insctuctions](https://code.google.com/p/wro4j/wiki/Installation "See the installation instructions for the wro4j servlet-filter"). But the trick is, that we do not want to configure that filter for the production-version of our webapp, because we want to compile the resources offline, when the webapp is build. To acchieve this, we can use the `<overrideDescriptor>`-Parameter of the [jetty-maven-plugin](http://wiki.eclipse.org/Jetty/Feature/Jetty_Maven_Plugin#Configuring_Your_WebApp "Read more about the configuration of the jetty-maven-plugin").
82 ## <overrideDescriptor>
84 This parameter lets you specify additional configuration options for the web.xml of your webapp. I am using the following configuration for my jetty-maven-plugin:
89 <groupId>org.eclipse.jetty</groupId>
90 <artifactId>jetty-maven-plugin</artifactId>
93 <overrideDescriptor>${project.basedir}/src/test/resources/jetty-web.xml</overrideDescriptor>
98 <groupId>ro.isdc.wro4j</groupId>
99 <artifactId>wro4j-core</artifactId>
100 <version>${wro4j.version}</version>
103 <groupId>ro.isdc.wro4j</groupId>
104 <artifactId>wro4j-extensions</artifactId>
105 <version>${wro4j.version}</version>
108 <groupId>javax.servlet</groupId>
109 <artifactId>servlet-api</artifactId>
112 <groupId>org.apache.commons</groupId>
113 <artifactId>commons-lang3</artifactId>
116 <groupId>commons-io</groupId>
117 <artifactId>commons-io</artifactId>
120 <groupId>org.springframework</groupId>
121 <artifactId>spring-web</artifactId>
124 <groupId>com.google.code.gson</groupId>
125 <artifactId>gson</artifactId>
128 <groupId>com.google.javascript</groupId>
129 <artifactId>closure-compiler</artifactId>
132 <groupId>com.github.lltyk</groupId>
133 <artifactId>dojo-shrinksafe</artifactId>
136 <groupId>org.jruby</groupId>
137 <artifactId>jruby-core</artifactId>
140 <groupId>org.jruby</groupId>
141 <artifactId>jruby-stdlib</artifactId>
144 <groupId>me.n4u.sass</groupId>
145 <artifactId>sass-gems</artifactId>
148 <groupId>nz.co.edmi</groupId>
149 <artifactId>bourbon-gem-jar</artifactId>
152 <groupId>org.codehaus.gmaven.runtime</groupId>
153 <artifactId>gmaven-runtime-1.7</artifactId>
156 <groupId>org.webjars</groupId>
157 <artifactId>jshint</artifactId>
160 <groupId>org.webjars</groupId>
161 <artifactId>emberjs</artifactId>
164 <groupId>org.webjars</groupId>
165 <artifactId>handlebars</artifactId>
168 <groupId>org.webjars</groupId>
169 <artifactId>coffee-script</artifactId>
172 <groupId>org.webjars</groupId>
173 <artifactId>jslint</artifactId>
176 <groupId>org.webjars</groupId>
177 <artifactId>json2</artifactId>
180 <groupId>org.webjars</groupId>
181 <artifactId>jquery</artifactId>
190 The dependencies to **wro4j-core** and **wro4j-extensions** are needed by jetty, to be able to enable the filter defined below. Unfortunatly, one of the transitive dependencies of `wro4j-extensions` triggers an uggly error when running the jetty-maven-plugin. Therefore, all unneeded dependencies of `wro4j-extensions` are excluded, as a workaround for this error/bug.
194 And my jetty-web.xml looks like this:
198 <?xml version="1.0" encoding="UTF-8"?>
199 <web-app xmlns="http://java.sun.com/xml/ns/javaee"
200 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
201 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
204 <filter-name>wro</filter-name>
205 <filter-class>ro.isdc.wro.http.WroFilter</filter-class>
208 <filter-name>wro</filter-name>
209 <url-pattern>*.css</url-pattern>
215 The filter processes any URI's that end with `.css`. This way, the wro4j servlet-filter makes `base.css` available under any path, because for exampl `/base.css`, `/css/base.css` and `/foo/bar/base.css` all end with `.css`.
217 This is all, that is needed to develop with dynamically reloadable compiled LESS-resources. Just fire up your browser and browse to `/what/you/like/base.css`. (But do not forget to put some LESS-files in `src/main/webapp/less/base/` first!)
219 ## Step 3: Install wro4j-maven-plugin
221 All that is left over to configure now, is the build-process. If you would build and deploy your webapp now, the CSS-file `base.css` would not be generated and the link to your stylesheet, that already works in our jetty-maven-plugin environment would point to a 404. Hence, we need to set up the **wro4j-maven-plugin**. I am using this configuration:
226 <groupId>ro.isdc.wro4j</groupId>
227 <artifactId>wro4j-maven-plugin</artifactId>
228 <version>${wro4j.version}</version>
230 <wroManagerFactory>ro.isdc.wro.maven.plugin.manager.factory.ConfigurableWroManagerFactory</wroManagerFactory>
231 <cssDestinationFolder>${project.build.directory}/${project.build.finalName}/css/</cssDestinationFolder>
235 <phase>prepare-package</phase>
245 I connected the `run`-goal with the `package`-phase, because the statically compiled CSS-file is needed only in the final war. The `ConfigurableWroManagerFactory` tells wro4j, that it should look up further configuration options in our `wro.properties`-file, where we tell wro4j, that it should compile our LESS-resources. The `<cssDestinationFolder>`-tag tells wro4j, where it should put the generated CSS-file. You can adjust that to suite your needs.
247 That's it: now the same CSS-file, which is created on the fly by the wro4j servlet-filter when using `mvn jetty:run` and, thus, enables dynamic reloading of our LESS-resources, is generated during the build-process by the wro4j-maven-plugin.
249 ## Cleanup and further considerations
251 ### lesscss-maven-plugin
253 If you already compile your LESS-resources with the lesscss-maven-plugin, you can stick with it and skip step 3. But I strongly recommend giving wro4j-maven-plugin a try, because it is a much more powerfull tool, that can speed up your final webapp even more.
255 ### Clean up your mess
257 With a configuration like the above one, your LESS-resources and wro4j-configuration-files will be packed into your production-war. That might be confusing later, because neither wro4j nor LESS is used in the final war. You can add the following to your `pom.xml` to exclude these files from your war for the sake of clarity:
262 <artifactId>maven-war-plugin</artifactId>
275 We only scrached the surface, of what can be done with wro4j. Based on this configuration, you can easily enable additional features to fine-tune your final build for maximum speed. You really should take a look at the [list of available Processors](https://code.google.com/p/wro4j/wiki/AvailableProcessors "Available Processors")!