Spring MVC, Spring Scheduling, Maven example

This is an example showcasing Spring’s scheduling capabilities sitting on top on a Spring MVC Maven project.

First the POM looks like this:

<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/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.dimitrisli.springmvc</groupId>
  <artifactId>SpringMVCScheduler</artifactId>
  <packaging>war</packaging>
  <version>1.0</version>
  <build>
  	<finalName>SpringMVCScheduler</finalName>
  	<plugins>
  		<plugin>
  			<groupId>org.apache.maven.plugins</groupId>
  			<artifactId>maven-compiler-plugin</artifactId>
  			<version>2.3.2</version>
  			<configuration>
  				<source>1.6</source>
  				<target>1.6</target>
  				<encoding>${project.build.sourceEncoding}</encoding>
  			</configuration>
  		</plugin>
  	</plugins>
  </build>
  <dependencies>
    <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.16</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>3.1.0.RELEASE</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
  		<groupId>javax.servlet</groupId>
  		<artifactId>servlet-api</artifactId>
  		<version>2.5</version>
  		<scope>provided</scope>
  	</dependency>
  	<dependency>
  		<groupId>javax.servlet.jsp</groupId>
  		<artifactId>jsp-api</artifactId>
  		<version>2.2</version>
  		<scope>provided</scope>
  	</dependency>
  </dependencies>
  <properties>
  	<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>
</project>

Notice that the spring-webmvc dependency is enough to bring along all the other Spring jars that are necessary thanks to the dependency hierarchy that Maven is taking care off behind the scenes so gracefully.

The web.xml of the web app looks like this:

<!--?xml version="1.0" encoding="UTF-8"?-->

		spring
		org.springframework.web.servlet.DispatcherServlet
		1

		spring
		/

		log4jConfigLocation
		/WEB-INF/log4j.properties

		org.springframework.web.util.Log4jConfigListener

		contextConfigLocation
		/WEB-INF/application-context.xml

		org.springframework.web.context.ContextLoaderListener

A few things to notice:

  • The sole Servlet we need to define is Spring’s DispatcherServlet that we map to any incoming url pattern
  • Spring’s ContextLoaderListener is defined in the web.xml and is initialising the container similar to the ApplicationContext or the old deprecated XMLFactoryBean (it was giving too much unnecessary power).
  • If we want Log4j to be initialised, up and running when the Spring app is starting up we can define Spring’s helper Log4jConfigListener¬†
  • With the context-param element we can explicitly specify the main config file of the Spring context.

This application context looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	   		http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
	   		http://www.springframework.org/schema/context
	   		http://www.springframework.org/schema/context/spring-context-3.1.xsd
			http://www.springframework.org/schema/mvc
			http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd">

	<!-- Scans the classpath under the base-package for annotated components -->
	<context:component-scan base-package="com.dimitrisli.springmvc.controller" />

	<!-- Scheduling config -->
	<import resource="scheduling-context.xml" />

</beans>

whereas the autoloaded spring-servlet.xml based on the DispatcherServlet‘s servlet-name we define in web.xml that defines how the view url resolves:


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	   		http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">

	<!-- Declare a view resolver -->
		<bean
		class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix">
			<value>/WEB-INF/jsp/</value>
		</property>
		<property name="suffix">
			<value>.jsp</value>
		</property>
	</bean>

</beans>

The scheduler context looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:p="http://www.springframework.org/schema/p"
	xmlns:task="http://www.springframework.org/schema/task"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	   		http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
	   		http://www.springframework.org/schema/task
			http://www.springframework.org/schema/task/spring-task-3.1.xsd">

	<!-- Spring's scheduling support -->
	<task:scheduled-tasks scheduler="taskScheduler">
		<!-- task:scheduled ref="fixedDelayService" method="performService" fixed-delay="5000"/-->
		<!-- task:scheduled ref="fixedRateService" method="performService" fixed-rate="5000"/-->
    	<task:scheduled ref="cronService" method="performService" cron="*/5 * * * * ?"/>
	</task:scheduled-tasks>

	<!-- The bean that does the actual work -->
	<bean id="fixedDelayService" class="com.dimitrisli.springmvc.scheduling.FixedDelayServiceImpl" />
	<bean id="fixedRateService" class="com.dimitrisli.springmvc.scheduling.FixedRateServiceImpl" />
	<bean id="cronService" class="com.dimitrisli.springmvc.scheduling.CronServiceImpl" />

	<!-- Defines a ThreadPoolTaskScheduler instance with configurable pool size. -->
	<task:scheduler id="taskScheduler" pool-size="1"/>

</beans>

Things to consider here:

  • Spring’s namespaces and namely the task namespace, is allowing us to define the scheduler and its scheduled tasks.
  • Each one of the scheduled tasks is a bean we define specifying the method we would like to execute once the scheduler kick-starts the job
  • We showcase 3 different scheduled tasks Spring provides fixed-delay, fixed-rate and the cron-way.

The code can be found in this Github repository.