Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring's @Scheduled error : Only one AsyncAnnotationBeanPostProcessor may exist within the context

I am trying Spring 3's @Scheduled annotation . Here is my configuration (app.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:context="http://www.springframework.org/schema/context"
  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.0.xsd
      http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
      http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-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/task http://www.springframework.org/schema/task/spring-task-3.0.xsd
      "
>

  <context:component-scan base-package="destiny.web"/>  
  <context:annotation-config/>
  // other beans

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

And this is my service class :

@Service
public class ServiceImpl implements Service , Serializable
{
  //other injections

  @Override
  @Transactional
  public void timeConsumingJob()
  {
    try
    {
      Thread.sleep(10*1000);
    }
    catch (InterruptedException e)
    {
      e.printStackTrace();
    }
  }

  @Override
  @Scheduled(cron="* * * * * ?") 
  public void secondly()
  {
    System.err.println("secondly : it is " + new Date());
  }
}

It works fine when testing in my eclispe + junit , when testing a timeConsumingJob method , I can see secondly() continues outputting message secondly.

But when deployed to a container (Resin/4.0.13) , it throws :

[11-03-26 12:10:14.834] {main} org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Configuration problem: Only one AsyncAnnotationBeanPostProcessor may exist within the context.
Offending resource: class path resource [app.xml]
 at org.springframework.beans.factory.parsing.FailFastProblemReporter.error(FailFastProblemReporter.java:68)
 at org.springframework.beans.factory.parsing.ReaderContext.error(ReaderContext.java:85)
 at org.springframework.beans.factory.parsing.ReaderContext.error(ReaderContext.java:72)
 at org.springframework.scheduling.config.AnnotationDrivenBeanDefinitionParser.parse(AnnotationDrivenBeanDefinitionParser.java:82)

I searched but seldom find similar situations , I think it is the most basic setting , but don't know why it doesn't work .

Can somebody take a look at it ? Thanks a lot !

(Spring 3.0.5 , Resin 4.0.13)

------------ updated ---------

After I dig deeper , I found the app.xml is imported by another xml. Maybe this is the reason makes task:annotation-driven not working.

Well , after re-arranging some beans' location , it is solved, but I still feel puzzled. (Because it worked fine , and other.xml needs beans in app.xml )

like image 724
smallufo Avatar asked Mar 26 '11 05:03

smallufo


4 Answers

I have faced this once after implementing our own AsyncTaskExecutor and forgetting to remove default <task:annotation-driven/>

Check if you have something like this, if yes remove one of the task.

<task:annotation-driven executor="customAsyncTaskExecutor" scheduler="taskScheduler"/>

<task:annotation-driven/>
like image 40
Rajesh Avatar answered Nov 12 '22 23:11

Rajesh


The application context is being initialized twice but org.springframework.scheduling.config.AnnotationDrivenBeanDefinitionParser fails registering bean ASYNC_ANNOTATION_PROCESSOR_BEAN_NAME second time.

I encountered this problem in unit tests where @ContextConfiguration("/path/to/applicationContext.xml") was accidentally on both the parent test class and child test class (with default value of inheritLocations true).

like image 51
Tomáš Záluský Avatar answered Nov 12 '22 23:11

Tomáš Záluský


This happens when spring parses the <task:annotation-driven/> text twice in a config XML.

For me this was happening because both applicationContext-root.xml and applicationContext-where-annotation-driven-is-specififed.xml were imported in my WEB.xml in <context-param> section.

Leaving only applicationContext-root.xml in WEB.xml solved the issue.

like image 7
Babken Vardanyan Avatar answered Nov 12 '22 23:11

Babken Vardanyan


I had this problem when I copied applicationContext.xml and created new one called applicationContextAdditional.xml. I didn't try to find the reason, but both contained namespace

<bean ...
    xmlns:task="http://www.springframework.org/schema/task"
    ...
    xsi:schemaLocation="
   http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd" >

    ...

</bean>

when I removed the namespace from the second one my problem was solved. Maybe it helps someone.

like image 6
Betlista Avatar answered Nov 12 '22 23:11

Betlista