Spring 4 MVC + WRO4J Integration Example using Annotation and XML

By Arvind Rai, April 6, 2016
This page will walk through spring 4 MVC and WRO4J integration example using annotation and XML. WRO4J is Web Resource Optimizer for Java. WRO4J makes it easy to load CSS and JS in our view. The view code will contain only few lines to load JS and CSS after using WRO4J. Our all JS and CSS files will be configured in wro.xml. While loading JS and CSS resources, WRO4J will optimize these files using different JS and CSS tools. To integrate spring MVC and WRO4J, we need to create a bean for ConfigurableWroFilter and while configuring DelegatingFilterProxy, we need to use ConfigurableWroFilter bean name as target bean name. Here on this page we will provide complete example for spring 4 MVC and WRO4J integration using annotation and XML.

WRO4J (Web Resource Optimizer for Java)

WRO4J is Web Resource Optimizer for Java. It is used to analyze and optimize web resources. WRO4J provides easy loading of CSS and JS in our view. It minifies the resource files and many other JS and CSS tools to optimize it. At runtime all the CSS files are clubbed in one CSS file and all the JS files are clubbed in one JS file and are minified which facilitates easy loading.
WRO4J provides a wro.xml where we configure our all JS and CSS files within a group. WRO4J provides ConfigurableWroFilter and we need to create a bean of it assigning java Properties for wro.properties. ConfigurableWroFilter bean name is assigned to DelegatingFilterProxy to set up WRO4J environment. The URL pattern in filter mapping will be used to load CSS and JS in our view.
If our view is loading JS and CSS files as below.
<head>
 <link rel="stylesheet" type="text/css" href="mycss1.css">
 <link rel="stylesheet" type="text/css" href="mycss2.css">
 <script type="text/javascript" src="myjs1.js"></script>
 <script type="text/javascript" src="myjs2.js"></script>
</head> 
Then using WRO4J, we need to write only below lines.
<head>
  <link rel="stylesheet" type="text/css" href="<%=request.getContextPath()%>/wro/allcss.css"/>
  <script type="text/javascript" src="<%=request.getContextPath()%>/wro/alljs.js"></script>
</head> 

Spring 4 MVC and WRO4J Integration Example using Annotation

Here we will provide spring 4 MVC and WRO4J integration using annotation. We create ConfigurableWroFilter bean in JavaConfig. Find the complete detail.

Software Used

Find the software used in our demo.
1. Java 8
2. Spring 4.2.5.RELEASE
3. WRO4J 1.7.9
4. Eclipse
5. Maven

Project Structure in Eclipse

Find the project structure in eclipse for JavaConfig.
Spring 4 MVC + WRO4J Integration Example using Annotation and XML

Maven to Build Project

Find the maven file to build the project.
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" 
		 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
		 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
		 		   http://maven.apache.org/maven-v4_0_0.xsd">	
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.concretepage</groupId>
	<artifactId>springwro4j</artifactId>
	<version>1</version>
	<packaging>war</packaging>
	<properties>	
		<context.path>springwro4j</context.path>
	</properties>
	<dependencies>	
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
			<version>1.3.3.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>eu.michael-simons</groupId>
			<artifactId>wro4j-spring-boot-starter</artifactId>
			<version>0.0.8</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-tomcat</artifactId>
			<version>1.3.3.RELEASE</version>
			<scope>provided</scope>			
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-war-plugin</artifactId>
				<configuration>
					<warName>${context.path}</warName>					
				</configuration>
			</plugin>
		</plugins>
	</build>	
</project> 

wro.xml

All the web resources like JS and CSS are configured in wro.xml. We create groups to configure JS and CSS files. We can create a group for JS and another group for CSS with name attribute. It is also possible to create a single group which will contain both JS and CSS files. To configure JS, WRO4J provides <js> and for CSS it provides <css> tag.
wro.xml
<?xml version="1.0" encoding="UTF-8"?>
<groups xmlns="http://www.isdc.ro/wro">
    <group name="allcss">
        <css>/resources/css/mycss1.css</css>
        <css>/resources/css/mycss2.css</css>        
    </group>
    <group name="alljs">
        <js>/resources/js/myjs1.js</js>
        <js>/resources/js/myjs2.js</js>        
    </group>    
</groups> 
To access JS and CSS in our view, the URL will be used as follows.
<link rel="stylesheet" type="text/css" href="<%=request.getContextPath()%>/wro/allcss.css"/>
<script type="text/javascript" src="<%=request.getContextPath()%>/wro/alljs.js"></script> 
If CSS and JS are clubbed in one group wro.xml as follows
<groups xmlns="http://www.isdc.ro/wro">
    <group name="all">
        <css>/resources/css/*.css</css>
        <js>/resources/js/*.js</js>       
    </group>
</groups> 
Then the URL to access CSS and JS in our view will be given as below.
<link rel="stylesheet" type="text/css" href="<%=request.getContextPath()%>/wro/all.css"/>
<script type="text/javascript" src="<%=request.getContextPath()%>/wro/all.js"></script> 

wro.properties

Find the wro4j property file used in demo.
wro.properties
# Default is true
debug=true
# Default is true
gzipEnabled=true
# Default is 0
cacheUpdatePeriod=0
# Default is 0
modelUpdatePeriod=0
# Default is false.
disableCache=false
# Default is UTF-8
encoding=UTF-8 

JavaConfig for ConfigurableWroFilter

We will create bean for ro.isdc.wro.http.ConfigurableWroFilter in JavaConfig which will use wro.properties file as a java Properties. This bean will be referred to DelegatingFilterProxy assigning to initialization parameter targetBeanName.

AppConfig.java
package com.concretepage;
import java.io.IOException;
import java.util.Properties;
import org.springframework.beans.factory.config.PropertiesFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import ro.isdc.wro.http.ConfigurableWroFilter;
@Configuration
@ComponentScan("com.concretepage")
@EnableWebMvc
public class AppConfig {
    @Bean  
    public InternalResourceViewResolver viewResolver() {  
	InternalResourceViewResolver resolver = new InternalResourceViewResolver();  
        resolver.setPrefix("/WEB-INF/view/");  
        resolver.setSuffix(".jsp");
        return resolver;  
    }	
    @Bean
    public Properties wroProperties() {
    	PropertiesFactoryBean pfb = new PropertiesFactoryBean();
    	pfb.setLocation(new ClassPathResource("wro.properties"));
    	Properties prop= null;
    	try {
    		prop = pfb.getObject();
	} catch (IOException e) {
		e.printStackTrace();
	}
    	return prop;
    }
    @Bean(name="wroFilter")
    public ConfigurableWroFilter configurableWroFilter() {
    	ConfigurableWroFilter cwfilter = new ConfigurableWroFilter();
    	cwfilter.setProperties(wroProperties());
	return cwfilter;
    }
} 


Web Application Initializer for DispatcherServlet and DelegatingFilterProxy

Find the web application initializer for DispatcherServlet and DelegatingFilterProxy. Here we need to assign ConfigurableWroFilter bean name to DelegatingFilterProxy. We will also specify filter URL pattern to access resources from WRO4j. In our case we have defined it as /wro/*
WebAppInitializer.java
package com.concretepage;
import javax.servlet.FilterRegistration;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.filter.DelegatingFilterProxy;
import org.springframework.web.servlet.DispatcherServlet;
public class WebAppInitializer implements WebApplicationInitializer {
   public void onStartup(ServletContext servletContext) throws ServletException {  
        AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();  
        ctx.register(AppConfig.class);  
        ctx.setServletContext(servletContext);    
        ServletRegistration.Dynamic srDynamic = servletContext.addServlet("dispatcher", new DispatcherServlet(ctx));  
        srDynamic.addMapping("/");  
        srDynamic.setLoadOnStartup(1);  
        FilterRegistration.Dynamic frDynamic = servletContext.addFilter("webResourceOptimizer",  
		      new DelegatingFilterProxy());
	frDynamic.setInitParameter("targetBeanName", "wroFilter");
	frDynamic.setInitParameter("targetFilterLifecycle", "true");
	frDynamic.addMappingForUrlPatterns(null, true, "/wro/*");
   }  
}  

Create View

Find the view created in our demo.
home.jsp
<html>
<head> <title> Web Resource Optimizer for Java </title>
<link rel="stylesheet" type="text/css" href="<%=request.getContextPath()%>/wro/allcss.css"/>
<script type="text/javascript" src="<%=request.getContextPath()%>/wro/alljs.js"></script>
</head>
<body onload="methodOne('id1'); methodTwo('id2');"> 
  <div class="cssone"> Demo for CSS file one  </div>
  <div class="csstwo"> Demo for CSS file two </div>
  <div id="id1"> </div>
  <div id="id2"> </div>  
</body>
</html>  

Create Controller

Find the controller.
HomeController.java
package com.concretepage;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class HomeController {
	@RequestMapping("/home")
	public String login() {
 		return "home";
 	}
} 

JS and CSS file used in Demo

Find the JS files.
myjs1.js
function methodOne(id) {
	document.getElementById(id).innerHTML = "<h3>Written by JS file ONE.</h3>";
} 

myjs2.js
function methodTwo(id) {
	document.getElementById(id).innerHTML = "<h5>Written by JS file TWO.</h5>";
} 
Find the CSS files.
mycss1.css
.cssone { 
    background-color: red;
               color: green;
} 

mycss2.css
.csstwo { 
    background-color: green;
               color: red;
} 

log4j.xml

Find the log4j.xml used in our example.
log4j.xml
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
	<!-- Appenders -->
	<appender name="console" class="org.apache.log4j.ConsoleAppender">
		<param name="Target" value="System.out" />
		<layout class="org.apache.log4j.PatternLayout">
			<param name="ConversionPattern" value="%-5p: %c - %m%n" />
		</layout>
	</appender>
       <logger name="ro.isdc.wro">
            <level value="debug" />
       </logger>
       <!-- Root Logger -->
       <root>
	   <priority value="warn" />
	   <appender-ref ref="console" />
       </root>
</log4j:configuration> 

Spring 4 MVC and WRO4J Integration Example using XML

Here we will provide spring 4 MVC and WRO4J integration example using XML. We will create ConfigurableWroFilter bean in our spring context XML. Using PropertiesFactoryBean bean we will load wro.properties and it will be used to create ConfigurableWroFilter bean. The name of this bean will be used with DelegatingFilterProxy in web.xml. In XML configuration demo, we are taking all JS and CCS files, properties, controller, view and wro.xml from annotation demo.

Project Structure in Eclipse

Find the project structure in eclipse for XML configuration.
Spring 4 MVC + WRO4J Integration Example using Annotation and XML

web.xml for DispatcherServlet and DelegatingFilterProxy

Find the web.xml where we configure DispatcherServlet and DelegatingFilterProxy. We need to assign ConfigurableWroFilter bean name to DelegatingFilterProxy . The URL pattern defined here will be used to load CSS and JS in view.
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
    http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
	<display-name>Spring Example</display-name>
	<servlet>
		<servlet-name>dispatcher</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>dispatcher</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>
		   /WEB-INF/dispatcher-servlet.xml
		</param-value>
	</context-param>
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
	<!-- Web Resource Optimizer Configuration -->
	<filter>
		<filter-name>webResourceOptimizer</filter-name>
		<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
		<init-param>
		    <param-name>targetBeanName</param-name>
		    <param-value>wroFilter</param-value>
		</init-param>
		<init-param>
		    <param-name>targetFilterLifecycle</param-name>
		    <param-value>true</param-value>
		</init-param>		
	</filter>
	<filter-mapping>
		<filter-name>webResourceOptimizer</filter-name>
		<url-pattern>/wro/*</url-pattern>
	</filter-mapping>
</web-app>  

Spring XML Configuration for ConfigurableWroFilter

The property file is being accessed using spring PropertiesFactoryBean and then this bean is being used to create ConfigurableWroFilter bean.
dispatcher-servlet.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans     
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context.xsd">
        
	<context:component-scan base-package="com.concretepage" />
	<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
	    <property name="prefix" value="/WEB-INF/view/"/>
	    <property name="suffix" value=".jsp"/> 
        </bean>
	<bean id="wroFilter" class="ro.isdc.wro.http.ConfigurableWroFilter">
	    <property name="properties" ref="wroProperties"/>
	</bean>
	<bean id="wroProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">  
	    <property name="location" value="classpath:wro.properties" />  
	</bean>  
</beans> 

Run Application

To run application use the URL http://localhost:8080/springwro4j/home
Spring 4 MVC + WRO4J Integration Example using Annotation and XML

References

GitHub: wro4j-spring
Getting Started with wro4j

Download Complete Source Code

POSTED BY
ARVIND RAI
ARVIND RAI
LEARN MORE








©2024 concretepage.com | Privacy Policy | Contact Us