31

I'm a bit befuddled because I'm trying use use @Scheduled annotations, but Spring doesn't seem to be finding my methods. The end result is that, none of my methods annotated with @Scheduled are being executed.

I have invoked Spring's task magic with the following declarations:

<beans> <!-- XMLNS, XSD declarations omitted for brevity -->

  <context:component-scan base-package="com.mypackage"/>

  <task:executor id="executor" pool-size="5"/>
  <task:scheduler id="scheduler" pool-size="5"/>
  <task:annotation-driven scheduler="scheduler" executor="executor"/>

</beans>

And I have an interface that looks something like this:

package com.mypackage;

public interface MyInterface {

    public void executePeriodically();
}

With a corresponding impl like this:

package com.mypackage.impl;
// imports omitted for brevity

@Service
public class MyInterfaceImpl implements MyInterface {

    @Scheduled(cron = "0/5 * * * * ?")
    public void executePeriodically() {
        System.out.println("The time is now : " + new Date());
    }
}

Now the expected result is that I have a very noisy little guy telling me what time it is every 5 seconds...but in reality I get absolutely nothing. I've tried with the annotation on the interface method and on the impl method, but that doesn't seem to change anything.

I know for sure that the executor and scheduler are being initialized because I have the following in my log:

INFO  - ThreadPoolTaskExecutor     - Initializing ExecutorService 
INFO  - XmlWebApplicationContext   - Bean 'executor' is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
INFO  - XmlWebApplicationContext   - Bean 'executor' is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
INFO  - ThreadPoolTaskScheduler    - Initializing ExecutorService  'scheduler'
INFO  - XmlWebApplicationContext   - Bean 'scheduler' is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)

I'm not sure if that line about not being eligible is relevant or a red herring.

At the moment, I'm working around it by declaring my scheduled tasks like so:

<task:scheduled-tasks>
  <task:scheduled ref="sourceDocumentManagerImpl" method="deleteOldDocuments" cron="0 0 * * * ?"/>
</task:scheduled-tasks>

While this works perfectly fine, I'd much rather use the annotations because it's so much more convenient to see directly in the code what the expectations are for that method. Anyone know what I could be doing wrong? For the record, I'm using Spring 3.0.4

Thanks a bunch!

stevevls
  • 10,675
  • 1
  • 45
  • 50

8 Answers8

22

add "task:annotation-driven" ?

<beans> <!-- XMLNS, XSD declarations omitted for brevity -->

  <context:component-scan base-package="com.mypackage"/>
  <task:annotation-driven/>
  <task:executor id="executor" pool-size="5"/>
  <task:scheduler id="scheduler" pool-size="5"/>
  <task:annotation-driven scheduler="scheduler" executor="executor"/>

</beans>

reference http://howtodoinjava.com/2013/04/23/4-ways-to-schedule-tasks-in-spring-3-scheduled-example/

or

Spring @Configuration (non-xml configuration) for annotation-driven tasks

Just add @EnableScheduling on you WebMvcConfig class

@Configuration
@EnableWebMvc
@EnableAsync
@EnableScheduling
public class WebMvcConfig extends WebMvcConfigurerAdapter {
   /** Annotations config Stuff ... **/
}

reference Spring Scheduler does not work

Community
  • 1
  • 1
ahll
  • 2,329
  • 1
  • 19
  • 22
15

So...it looks like there's a problem in Spring 3.0.x (at the very least 3.0.4 and 3.0.5) having to do with discovering @Scheduled annotations on AOP proxies. I've got a pointcut declaration wrapping the @Scheduled method with transactional advice, and that seems to be the root of the problem. If I remove the advice, the job runs. If I add it back in, Spring fails to find and create a task for my annotated method.

So, I'm going to go file a bug with the Spring folks, and in the meantime I'm stuck declaring my tasks manually.

stevevls
  • 10,675
  • 1
  • 45
  • 50
  • interesting. My job doesn't have a proxy indeed, so this might be the problem. Did you try the latest milestone? – Bozho May 28 '11 at 18:59
  • I haven't...I probably should, but at the moment, I'm in the middle of a big project, and I'm reluctant to try non-release builds. I'll try to circle back and give it a shot when things quiet down. Thanks! – stevevls May 28 '11 at 19:03
  • 1
    @Bozho You may be interested to know that I've been digging, and the problem doesn't seem to be with the task scheduler code at all. Rather, there's a bug with the AOP proxy where TargetClassAware's getTargetClass method is returning, instead of my bean's type, one of it's generic parameters. That explains why the bean post processor isn't finding @Scheduled annotations...it doesn't even have the right class! – stevevls May 29 '11 at 00:15
  • You can also have an AOP-free @Scheduled method that delegates to another proxied class or method. – Konrad Garus Jul 26 '11 at 14:41
  • did you report this as a bug -- if so, did it get resolved? it looks like it's still an issue based on https://jira.springsource.org/browse/SPR-8651 – Ted Pennings May 31 '12 at 18:30
  • I never ended up reporting it...things got busy, and then I forgot about it. But that definitely looks like the culprit! – stevevls Jun 07 '12 at 16:53
  • This may be a bit late and obvious but are you sure had mvc:annotation driven in your webapp configuration. In my case I had mvC:annotation driven but forgot to add the package to component-scan as you have added. – Rohit Banga Feb 22 '13 at 23:15
  • Still the same version problem in 2019. I downgraded from 2.1.4.RELEASE to 2.1.2.RELEASE. Now it's working. – learner May 14 '19 at 11:27
5

I fixed it by adding default-lazy-init="false" to my applicationContext.xml.

<beans .....
    **default-lazy-init="false"**>
Aman Ghrera
  • 51
  • 1
  • 1
4

In spite of that I am using Spring 3.1.2, I am running into the same problem in case i place my executor and scheduler tag in ApplicationContext.xml. i have two xml configuration file for spring in my project which are :

  1. applicationContext.xml
  2. dispatcher-servlet.xml

So try to move your configuration to the last configuration file which spring reads. in my case it is start working by moving my configuration to dispatcher-servlet.xml

here is my example:

applicationContext.xml

<?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:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:context="http://www.springframework.org/schema/context" 
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       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.0.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-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.xsd
       http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd">

    <bean id="config" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
        <property name="location" value="/WEB-INF/configuration.properties" />
    </bean>

    <!-- To fix the problem with Unicode characters in ajax responses -->
    <bean class = "org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
        <property name="messageConverters">
            <array>
                <bean class = "org.springframework.http.converter.StringHttpMessageConverter">
                    <property name="supportedMediaTypes" value = "text/plain;charset=UTF-8" />
                </bean>
                <bean id="byteArrayMessageConverter" class="org.springframework.http.converter.ByteArrayHttpMessageConverter" />
            </array>
        </property>
    </bean>

    <!-- Hibernate Configuration
        p:driverClassName="com.mysql.jdbc.Driver"
        p:url="jdbc:mysql://localhost:3306/iss"
        p:username="root"
        p:password="root"
    -->
    <bean name="DataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"
          p:driverClassName="org.postgresql.Driver"
          p:url="jdbc:postgresql://localhost:5432/iss"
          p:username="postgres"
          p:password=""

    />

    <!--<bean name="SessionFactory" class="org.springframework.orm.hibernate4.annotation.AnnotationSessionFactoryBean">-->
    <bean name="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource">
            <ref bean="DataSource" />
        </property>
        <property name="hibernateProperties">
            <props>
                <!--<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>-->
                <prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>
                <prop key="hibernate.hbm2ddl.auto">update</prop>
                <prop key="hibernate.show_sql">true</prop>
                <!--<prop key="hibernate.current_session_context_class">thread</prop>-->
                <!--<prop key="hibernate.current_session_context_class">managed</prop>-->
                <!--<prop key="hibernate.search.default.indexBase">/tmp/hibernate/indexes/</prop>-->
                <!--<prop key="hibernate.flushMode">AUTO</prop>-->
                <prop key="hibernate.connection.useUnicode">true</prop>
                <prop key="hibernate.connection.characterEncoding">UTF-8</prop>
                <prop key="hibernate.cache.use_second_level_cache">false</prop>
                <prop key="hibernate.cache.use_query_cache">false</prop>
                <prop key="hibernate.connection.autocommit">false</prop>
            </props>
        </property>
        <property name="packagesToScan" value="iss.DB" />
    </bean>

    <bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>

    <mvc:interceptors>
        <bean class="org.springframework.orm.hibernate4.support.OpenSessionInViewInterceptor">
            <property name="sessionFactory" ref="sessionFactory" />
        </bean>
    </mvc:interceptors>

    <tx:annotation-driven transaction-manager="txManager" proxy-target-class="true"/>


<!-- in this file it wont work
        <task:executor id="myExecutor" pool-size="1" />
    <task:scheduler id="myScheduler" pool-size="1" />
    <task:annotation-driven 
        executor="myExecutor"
        scheduler="myScheduler"/>    
-->
</beans>

dispatcher-servlet.xml

<?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:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       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/aop 
       http://www.springframework.org/schema/aop/spring-aop.xsd
       http://www.springframework.org/schema/tx 
       http://www.springframework.org/schema/tx/spring-tx-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/task http://www.springframework.org/schema/task/spring-task-3.0.xsd" 
       xmlns:context="http://www.springframework.org/schema/context">

    <bean class="org.springframework.web.servlet.mvc.support.AnnotationControllerTypePredicate"/>

    <context:component-scan base-package="iss"/>
    <context:component-scan base-package="com.hazhir"/>

    <!--Internationalization -->
    <bean id="messageSource"
          class="org.springframework.context.support.ResourceBundleMessageSource">
        <property name="basename" value="iss.languages.text" />
    </bean>

    <bean id="localChangeInterseptor"
          class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
        <property name="paramName" value="language" />
    </bean>

    <bean id="localeResolver"
          class="org.springframework.web.servlet.i18n.CookieLocaleResolver">
        <property name="defaultLocale" value="en_US" />
        <property name="cookieName" value="clientLanguage" />
        <property name="cookieMaxAge" value="99999999"/>
    </bean>

    <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
        <property name="alwaysUseFullPath" value="true" />
        <property name="interceptors">
            <list>
                <ref bean="localChangeInterseptor" />
            </list>
        </property>
    </bean>

    <bean id="viewResolver"
          class="org.springframework.web.servlet.view.InternalResourceViewResolver"
          p:prefix="/WEB-INF/jsp/"
          p:suffix=".jsp">
        <property name="exposeContextBeansAsAttributes" value="true" />
    </bean>

    <!-- Multipart form data -->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="maxUploadSize" value="1000000000" />
    </bean>

    <context:annotation-config />

    <!-- here is a right place for such configuration
        -->
    <task:executor id="myExecutor" pool-size="1" />
    <task:scheduler id="myScheduler" pool-size="1" />
    <task:annotation-driven 
        executor="myExecutor"
        scheduler="myScheduler"/> 
</beans>

hope it helps.

Hazhir
  • 780
  • 1
  • 6
  • 18
  • Thank you, also using 3.1.2 and had exact same problem. Had to move task configuration to the bottom of another spring configuration file. Could be a defect just in 3.1.2. – Sheamus O'Halloran Dec 17 '12 at 08:04
  • Idk, I declared: inside appContext and it works, in my controller I autowire class which implements those schedule methods. (dunno if Schedule methods should run automatically, but until I autowired they didnt work). – Aubergine Sep 09 '13 at 03:59
4

The only difference that I see from my setup (which works), is that my class is annotated with @Component rather than @Service. Other things to check:

  • whether you have the proper jars on the classpath (spring-context, I think)
  • put a breakpoint and check whether it really isn't executing
  • double-check the cron expression (I admit I always consult the docs for that). Or use a fixed delay, just to check if it works
  • try upgrading to 3.0.5 or the latest 3.1 snapshot.
Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
  • Check, check, check, and check. Thanks for the advice... Ultimately, it looks to be a bug (or feature?) in Spring. See my answer... – stevevls May 28 '11 at 18:55
2

This is pretty old question but since this keeps up coming in google search results let me add the solution that worked for me in Spring 5. For me it didn't work until I added @Component to the class having @Scheduled annotated methods.

nabeel
  • 305
  • 2
  • 7
1

I Solve it by remove use-default-filters="false" in context:component-scan my old config is

 <context:component-scan base-package="com.XXXx" use-default-filters="false">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

my spring version 3.2.3

0

I solved by adding both:

xmlns:task="http://www.springframework.org/schema/task"
xmlns:tx="http://www.springframework.org/schema/tx"

then:

<!-- TASK -->
    <task:scheduler id="searchScheduler" pool-size="1"/>
    <task:executor id="searchExecutor" pool-size="1"/>
    <task:annotation-driven executor="searchExecutor"  scheduler="searchScheduler"/>

and in the bootom of my applicationContext.xml:

<tx:annotation-driven/>
Mike
  • 1
  • 2