1

I have Quartz 2.2.1 and Spring 3.2.2. app on Eclipse Juno

This is my bean configuration:

<beans xmlns="http://www.springframework.org/schema/beans"
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-3.0.xsd">

<!-- Spring Quartz -->

<bean id="checkAndRouteDocumentsTask" class="net.tce.task.support.CheckAndRouteDocumentsTask" />

<bean name="checkAndRouteDocumentsJob" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">

    <property name="jobClass" value="net.tce.task.support.CheckAndRouteDocumentsJob" />
    <property name="jobDataAsMap">
        <map>
            <entry key="checkAndRouteDocumentsTask" value-ref="checkAndRouteDocumentsTask" />
        </map>
    </property>
    <property name="durability" value="true" />

</bean>

<!-- Simple Trigger, run every 30 seconds -->
<bean id="checkAndRouteDocumentsTaskTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">

    <property name="jobDetail" ref="checkAndRouteDocumentsJob" />
    <property name="repeatInterval" value="30000" />
    <property name="startDelay" value="15000" />

</bean>

<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
    <property name="jobDetails">
        <list>
            <ref bean="checkAndRouteDocumentsJob" />
        </list>
    </property>

    <property name="triggers">
        <list>
            <ref bean="checkAndRouteDocumentsTaskTrigger" />
        </list>
    </property>
</bean>

My mvc spring servlet config:

    <?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    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-3.0.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context-3.0.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">  
    <bean id="propertyConfigurer" 
     class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    </bean>
    <mvc:annotation-driven />
    <context:annotation-config />
    <context:component-scan base-package="net.tce" />
    <import resource="spring-quartz.xml"/>  
</beans>

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_2_5.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>OperationalTCE</display-name>
  <servlet>
    <servlet-name>mvc-dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>0</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>mvc-dispatcher</servlet-name>
    <url-pattern>/rest/*</url-pattern>
  </servlet-mapping>
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/mvc-dispatcher-servlet.xml</param-value>
  </context-param>
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
</web-app>

My problem is that always when startup my application, Quartz creates two jobs at the same time. My job must be execute every 30 seconds:

INFO: Starting TASK on Mon Nov 04 15:36:46 CST 2013...
INFO: Starting TASK on Mon Nov 04 15:36:46 CST 2013...
INFO: Starting TASK on Mon Nov 04 15:37:16 CST 2013...
INFO: Starting TASK on Mon Nov 04 15:37:16 CST 2013...
INFO: Starting TASK on Mon Nov 04 15:37:46 CST 2013...
INFO: Starting TASK on Mon Nov 04 15:37:46 CST 2013...

Thanks for your help.

Osy
  • 1,613
  • 5
  • 21
  • 35
  • Is this starting in a clustered environment, or is there only one instance of the application? I've seen this behavior in a two-node cluster where we ended up just deploying the quartz jobs as it's own project on a single node. – David Fleeman Nov 04 '13 at 21:54
  • It just donned on me as well if you are loading spring-quartz.xml into your application via your web.xml file, and then importing it from other servlet config xml file, then it will be loaded twice resulting in two executions. If that is the case, then you would simply need to get rid of the import statement in your second file. – David Fleeman Nov 04 '13 at 21:57

2 Answers2

2

Your ContextLoaderListener and DispatcherServlet are both loading the mvc-dispatcher-servlet.xml. Basically duplicating all your beans resulting in 2 executions as that is also duplicated.

Split your configuration into one that is being loaded by the ContextLoaderListener (containing your services, dao, timers etc.) and one loaded by the DispatcherServlet (containing only web related beans controllers, view resovlers etc.).

Or ditch the ContextLoaderListener altogether and only use the DispatcherServlet to load everything.

M. Deinum
  • 115,695
  • 22
  • 220
  • 224
  • You right, I removed tag containing "ContextLoaderListener" within web.xml and the problem was fixed, thanks. – Osy Nov 05 '13 at 17:58
1

Make sure you are not loading both the files in your web.xml file for your project. If you load the spring-quartz.xml file separately, and then load the servlet-config.xml file separately that "imports" the spring-quartz.xml file, then you are loading the file twice which would result in 2 instances of your scheduler. The easy fix would be to either (1) ensure you are not loading spring-quartz.xml in your web.xml file OR (2) remove the import statement in your other xml file.

Updated: Thanks for showing us the web.xml to rule that out. After closer inspection of your xml files, you are setting up the SchedulerFactoryBean with both the job details and the trigger. This is your problem. The job details are included as part of your trigger, so putting them in again causes it to be scheduled twice. Please read the documentation on these two links about the setJobDetails() method:

http://docs.spring.io/spring/docs/2.5.6/api/org/springframework/scheduling/quartz/SchedulerFactoryBean.html

http://docs.spring.io/spring/docs/2.5.6/api/org/springframework/scheduling/quartz/SchedulerAccessor.html#setJobDetails%28org.quartz.JobDetail[]%29

http://docs.spring.io/spring/docs/2.5.6/api/org/springframework/scheduling/quartz/SchedulerAccessor.html#setTriggers%28org.quartz.Trigger[]%29

Excerpt of important info:

setJobDetails public void setJobDetails(JobDetail[] jobDetails) Register a list of JobDetail objects with the Scheduler that this FactoryBean creates, to be referenced by Triggers. This is not necessary when a Trigger determines the JobDetail itself: In this case, the JobDetail will be implicitly registered in combination with the Trigger.

The solution would be to remove the jobDetails from the SchedulerFactoryBean like this:

<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
    <list>
        <ref bean="checkAndRouteDocumentsTaskTrigger" />
    </list>
</property>
</bean>
David Fleeman
  • 2,588
  • 14
  • 17
  • Please check web.xml added, I don't import spring-quartz.xml. – Osy Nov 04 '13 at 22:23
  • Also there is a single instance, non-clustered env. – Osy Nov 04 '13 at 22:32
  • I removed jobDetails section but still happening same behavior :Double execution. Let me tell you that I think spring servlet configuration is the problem. – Osy Nov 05 '13 at 17:50
  • In the other answer, the person says DispatcherServlet is also loading mvc-dispatcher-servlet.xml. I do not see where that is happening, but it may very well be. Have you explored that yet? – David Fleeman Nov 05 '13 at 17:55
  • 1
    @DavidFleeman That is the default, the `DispatcherServlet` by default loads a `[servlet-name]-servlet.xml` file for configuration. The `contextConfigLocation` as a context-param is used by the `ContextLoaderListener`. Result duplicate loading of the same xml file. – M. Deinum Nov 05 '13 at 18:02
  • @M. Deinum - thanks for the additional explanation - have not set up a project from scratch in some time that used DispatcherServlet. – David Fleeman Nov 05 '13 at 18:04