Spring Boot configuration of wro4j

Spring Boot configuration of wro4j

Posted by Stanislav Miklik | August 6, 2015 | spring

What is wro4j

Since you are here, you most likely know, but for others. wro4j (Web Resource Optimizer for Java) allows you (as name suggests) to optimize your web resources. Typically when you build (rich) web application you use several CSS/JS frameworks and develop additional CSS/JS of your own. And all of this needs to be downloaded to browser. That is not typically big problem for desktops with broad-band internet, but in era of mobile internet it is very helpful if you can bundle all of this to few HTTP requests that download everything needed together and in addition minimize and gzip the content (e.g. by removing your comments from JS).

wro4j can work in two modes – runtime and compile time. You can do all this magic compile time and just use results in your JAR/WAR. This has clear benefits (like no runtime dependency on wro4j, no runtime “compilation” etc) but also the setup was more complicated, you need to properly configure your IDE to “hot” recompile your resources as you are developing and you need to configure some features by yourself (e.g. caching/gzip). So for now I decided to use runtime setup with wro http filter.

Spring Boot setup

wro4j itself does not have spring boot support, nor spring boot can autoconfigure it. I have found 3rd party library for that but I didn’t want to add additional maven repository just for that. Additionally I don’t like that is support only “pre-selected” configuration options (although the most used are there). Therefore I decided to configure it myself.

So first you need to add wro4j as dependency to your project (in my case maven):

		<!-- wro4j -->
		<dependency>
			<groupId>ro.isdc.wro4j</groupId>
			<artifactId>wro4j-core</artifactId>
			<version>1.7.8</version>
		</dependency>
		<dependency>
			<groupId>ro.isdc.wro4j</groupId>
			<artifactId>wro4j-extensions</artifactId>
			<version>1.7.8</version>
		</dependency>

Then we need to configure wro4j filter in one of your @Configuration classes.

	@Bean
	FilterRegistrationBean webResourceOptimizer(Environment env) {
		FilterRegistrationBean fr = new FilterRegistrationBean();
		ConfigurableWroFilter filter = new ConfigurableWroFilter();
		filter.setProperties(buildWroProperties(env));
		fr.setFilter(filter);
		fr.addUrlPatterns("/wro/*");
		return fr;
	}

	private static final String[] OTHER_WRO_PROP = new String[] { ConfigurableProcessorsFactory.PARAM_PRE_PROCESSORS,
			ConfigurableProcessorsFactory.PARAM_POST_PROCESSORS };

	private Properties buildWroProperties(Environment env) {
		Properties prop = new Properties();
		for (ConfigConstants c : ConfigConstants.values()) {
			addProperty(env, prop, c.name());
		}
		for (String name : OTHER_WRO_PROP) {
			addProperty(env, prop, name);
		}
		log.debug("Wro4J properties {}", prop);
		return prop;
	}

	private void addProperty(Environment env, Properties to, String name) {
		String value = env.getProperty("wro." + name);
		if (value != null) {
			to.put(name, value);
		}
	}

As you can see from code, it register filter to /wro/* path and reads all properties from your application.properties (or alternative) with “wro.” prefix. Unfortunately not all wro properties are part of ro.isdc.wro.config.jmx.ConfigConstants, so if you need anything else, just extend OTHER_WRO_PROP.

All what’s left is to “use” wro4j – create your wro.xml in WEB-INF directory

<?xml version="1.0" encoding="UTF-8"?>
<groups xmlns="http://www.isdc.ro/wro">

    <group name="other">
        <js>classpath:static/jquery/jquery-1.10.1.min.js</js>
        <js>classpath:static/timeago/jquery.timeago.1.4.1.js</js>
        <css>classpath:static/slider/slider.css</css>
    </group>
    
</groups>

and setup your application.properties as you want.

# wro4j config
wro.preProcessors=cssUrlRewriting,cssImport,semicolonAppender,lessCss
wro.postProcessors=cssVariables,cssMinJawr,jsMin
# set to 1 second to check for resource changes
wro.resourceWatcherUpdatePeriod = 0
wro.ignoreMissingResources = false

Enjoy.

Update: If you are not deploying .war file, you need to override where wro.xml comes from. Check this sample project

Blog Comments

Thanks for this, a great help – except when I bootRun the project, I can’t work out how to get the wro.xml file into the WEB-INF directory, and I can’t find any help on the web for this?

I’ve tried in src/main/resources, src/main/resources/public/WEB-INF and so on and none seem to work 🙁

How did you manage it, or do you not bootRun?

I must (with shame :)) admit that I am packing application as WAR (see doc) although it is not very boot-way.

If I or someone solve this problem, I can add it to blog later on.

Thanks for making the update for non-war applications. I’ve implemented it but it’s not finding the src/main/resources/wro.xml file. In fact, it’s not even writing out the log message at the beginning of Wro4jCustomXmlModelManagerFactory.newModelFactory() so it seems like it’s not loading. I’m banging my head to figure this out but not having any luck. Any ideas?

Does sample project work for you? Wro4jCustomXmlModelManagerFactory is registered during filter registration at startup but Wro4J uses lazy initialization and creates the model factory only with first request.

Add a comment

*Please complete all fields correctly

Related Blogs

Posted by miklik | 16 April 2015
Nowadays you can hear lot about microservices. Spring Boot is an excellent choice for building single microservice but you need to interconnect them somehow. That's what Spring Cloud tries to…
Posted by miklik | 26 September 2014
I have came across an interesting blog about exception handling in Spring MVC. It nicely describe different options how to handle exceptions in MVC controllers. As usual Spring gives you…