Подтвердить что ты не робот

Java Spring Задачи, выполняемые в два раза:

У меня есть простой метод тестирования здесь, который запускается каждые 5 секунд, и он это делает, но, глядя на System.out, вы можете видеть, что он делает что-то странное.

@Scheduled(cron="*/5 * * * * ?")
public void testScheduledMethod() {
     System.out.println(new Date()+" > Running testScheduledMethod...");
}

Вывод:

Wed Jan 09 16:49:15 GMT 2013 > Running testScheduledMethod...
Wed Jan 09 16:49:15 GMT 2013 > Running testScheduledMethod...
Wed Jan 09 16:49:20 GMT 2013 > Running testScheduledMethod...
Wed Jan 09 16:49:20 GMT 2013 > Running testScheduledMethod...
Wed Jan 09 16:49:25 GMT 2013 > Running testScheduledMethod...
Wed Jan 09 16:49:25 GMT 2013 > Running testScheduledMethod...
Wed Jan 09 16:49:30 GMT 2013 > Running testScheduledMethod...
Wed Jan 09 16:49:30 GMT 2013 > Running testScheduledMethod...

Почему он запускает TWICE (появляется) каждый раз?

4b9b3361

Ответ 1

Если вы посмотрите на документацию, есть заметка, которая явно вызывает это явление.

Примечание находится в разделе в разделе 25.5.1 по этой ссылке и читается:

Убедитесь, что вы не инициализируете несколько экземпляров одного и того же класса аннотаций @Scheduled во время выполнения, если вы не хотите планировать обратные вызовы для каждого такого экземпляра. В связи с этим убедитесь, что вы не используете @Configurable в классах bean, которые аннотируются с помощью @Scheduled и зарегистрированы как обычные Spring beans с контейнером: вы получили бы двойную инициализацию в противном случае, один раз через контейнер и один раз через @Configurable аспект, вследствие того, что каждый метод @Scheduled вызывается дважды.

Я понимаю, что это просто предложение на данный момент, но я не думаю, что у нас достаточно информации, чтобы еще больше диагностировать проблему.

Ответ 2

Я знаю ответ!

Не запускайте дважды запланированный

Loot в вашем веб-журнале:

WebApplicationContext один раз и один сервлет

поэтому в servlet.xml не делайте этого

import resource="classpath:applicationContext.xml"

Ответ 3

это происходит из-за прослушивания контекста

Просто удалите

< слушатель >

< listener-class > org.springframework.web.context.ContextLoaderListener </listener-class >

</прослушиватель >

из web.xml он должен работать.

Ответ 4

Я столкнулся с подобной проблемой. Это может быть из-за причин.

  • Ошибка в версиях spring https://jira.spring.io/browse/SPR-10830

  • Контекст загружается дважды.

  • Журнал log4j.xml записывает журналы дважды. Это случилось в моем случае, не уверенном в твоем. Если вы попробовали другие параметры, попробуйте также это.

Ответ 5

Я объявил свой класс как "Сервис", а также использовал аннотацию @Scheduled, чтобы объявить его планировщиком. Планировщик вызывает его нормально, но так как мы объявили класс как сервис. Это было начато дважды.

Я удалил Сервисную аннотацию. И объявил этот класс как bean-компонент в контексте XML, который я поддерживал. (пользовательский контекст XML, который объявлен в web.xml). Это исправило проблему для меня. Надеюсь, это кому-нибудь поможет.

Ответ 6

У меня была такая же проблема, и в итоге я выяснил, что проблема возникла в результате создания beans в root context, а также servlet context.

Итак, чтобы исправить это, вам нужно отделить создание beans в соответствующих контекстах.

Этот ответ очень хорошо объясняет, как это и было исправлено мою проблему.

Ответ 7

У меня была аналогичная проблема, я решил, что сделал это:

package com.sample.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;

@Configuration
@EnableScheduling
public class JobExecutorConfig {
}

в качестве конфигурации для загрузки spring. И я добавляю это как класс работы:

package com.sample.jobs;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class Job {

  private final Logger log = LoggerFactory.getLogger(this.getClass());

  @Autowired
  MyOtherClass moc;

  @Scheduled(fixedRate = 60000) // every 60 seconds
  public void doJob() {
    log.debug("Job running !!!");
    try {
     moc.doSomething()
    } catch (Exception e) {
      log.error(e.getMessage());
    }
    finally {

      log.debug("job Done !!!");
    }

  }

  // examples of other CRON expressions
  // * "0 0 * * * *" = the top of every hour of every day.
  // * "*/10 * * * * *" = every ten seconds.
  // * "0 0 8-10 * * *" = 8, 9 and 10 o'clock of every day.
  // * "0 0/30 8-10 * * *" = 8:00, 8:30, 9:00, 9:30 and 10 o'clock every day.
  // * "0 0 9-17 * * MON-FRI" = on the hour nine-to-five weekdays
  // * "0 0 0 25 12 ?" = every Christmas Day at midnight
}

Ответ 8

Я использую spring 4.0.3, и у меня есть эта проблема. я решил это, переименовав мой beans.

в

<task:annotation-driven executor="taskExecutor"
    scheduler="taskScheduler" />
<task:executor id="taskExecutor" pool-size="25" />
<task:scheduler id="taskScheduler" pool-size="25" />

Я заметил некоторые записи INFO, в которых говорилось, что no bean с именем taskScheduler найдено, создавая новый экземпляр. Поэтому я решил, что есть два экземпляра taskScheduler.

Сообщите мне, если это сработает для вас:)

Ответ 9

В моем случае у задания bean была аннотация @Component, и у меня это было в моем приложении ApplicationContext.xml:

<task:annotation-driven/> <bean id="getxxx" class="com.kitar.xxxx.jobs.RomeExample"></bean>

Итак, решение состоит в том, чтобы удалить определение bean (вторая строка), потому что:

<task:annotation-driven/>: разрешить обнаружение @Async и @Scheduled аннотаций на любом объекте Spring, поэтому нет необходимости определять задание bean или он будет вызываться дважды.

Ответ 10

Согласно этот пост и Spring Jira это ошибка в компоненте Spring Framework Scheduler.

Ответ 11

Возможно, вы захотите проверить, сканируете ли вы компоненты для одного и того же пакета в двух разных контекстах, если ваше приложение является WEB, например. applicationContext.xml, а затем снова some-servlet.xml.

Ответ 12

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
         /WEB-INF/spring/root-context.xml
         /WEB-INF/spring/security/spring-security.xml
         /WEB-INF/spring/mongo/mongo-config.xml
         /WEB-INF/spring/appServlet/spring-context.xml
    </param-value>
</context-param>
<servlet>
    <servlet-name>appServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/spring/appServlet/spring-context.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

Это мой web.xml. Итак, вы можете видеть, что "/WEB-INF/ spring/appServlet/spring-context.xml" загружается дважды (один раз в контексте-param, один раз в сервлет → init-param).

Ответ 13

Я столкнулся с такой же ситуацией и решил:

1) Служба планировщика

@Service
public class SchedulerService {

    @Autowired
    @Qualifier("WorkerClass")
    private Worker worker;

    @Scheduled(cron="0/5 * * * * ?", zone="Asia/Colombo")//zone is a sample
    public void doSchedule() {
        worker.work();
    }

}

2) Рабочий класс

@Component("WorkerClass")
public class WorkerClass implements Worker {

    @Override
    public void work() {
        doSomething();
    }

    protected void doSomething() {
        system.out.pringln("What must I do?");
    }

}

Ответ 14

У меня была та же проблема. Проработанные часы пытаются решить.

Решение

Решение было распространено дважды на Tomcat.

При попытке очистить Tomcat он дал ошибку.

Проверка файла server.xml Tomcat Я заметил, что то же самое развертывалось дважды. Был также закрытый тег "хозяин". Не уверен, какой из них исправил его, но с облегчением он снова работал правильно.

Ответ 15

У меня была такая же проблема, глядя в моем коде, и после попытки всего, что здесь, я обнаружил, что у меня был SpringApplicationBuilder дважды в 2 различных классах

Ответ 16

У меня такая же проблема. Я использовал конфигурацию на основе аннотаций следующим образом:

@Configuration
@EnableScheduling
public class SchedulerConfig {

    @Scheduled(fixedDelay = 60 * 1000)
    public void scheduledJob() { 
        // this method gets called twice... 
    }   
}

Я также расширяю AbstractAnnotationConfigDispatcherServletInitializer для инициализации того же самого.

public class SpringWebApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

@Override
protected Class<?>[] getRootConfigClasses() {
    return new Class<?>[] { MainConfig.class, SchedulerConfig.class };
}

@Override
protected Class<?>[] getServletConfigClasses() {
    return new Class<?>[] {SpringWebConfig.class};
}

@Override
protected String[] getServletMappings() {
    return new String[] { "/" };
}

@Override
protected Filter[] getServletFilters() {
    final CharacterEncodingFilter encodingFilter = new CharacterEncodingFilter();
    encodingFilter.setEncoding(CHARACTER_ENCODING);
    encodingFilter.setForceEncoding(true);
    return new Filter[] { encodingFilter };
}

}

Удаление SchedulerConfig.class из getRootConfigClasses() мне.

@Override
protected Class<?>[] getRootConfigClasses() {
    return new Class<?>[] { MainConfig.class };
}

Надеюсь, это поможет.

Ответ 18

У меня была такая же проблема, я попробовал все предложенные методы, но у меня ничего не получалось. Наконец, я смог найти решение, удалив расширение SpringBootServletInitializer и метод configure моего класса WebApplication, и с этим я перестал дублировать свою запланированную задачу.

Ответ 19

Сегодня у меня была такая же проблема.

В моем проекте я использовал планировщик с моим приложением загрузки spring, а в моем классе ScheduledTaks я использовал аннотацию @Component. Но я ошибся, потому что @Component представляет bean для моего класса и в моем классе Application я создаю еще один bean для этого класса с кодом:

public class Application extends SpringBootServletInitializer {

  @Override
  protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
      return application.sources(Application.class);
  }

  public static void main(String[] args) throws Exception {
      SpringApplication.run(Application.class, args);
  }

  @Bean
  public ScheduledTasks getScheduledTasks() {
    return new ScheduledTasks();
  }
}

Я просто удаляю эту аннотацию, и планировщик работает заметно.

Следуйте примеру моего кода ScheduledTasks class:

public class ScheduledTasks {
  private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");

  @Scheduled(cron = "00 14 11  * * *")
  public void reportCurrentTime() {
    log.info("The date is: {} " + dateFormat.format(new Date()) );
  }
}

И результат:

2016-10-20 11:13:41.298  INFO 6832 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http)
2016-10-20 11:13:41.302  INFO 6832 --- [           main] br.com.Application                       : Started Application in 9.257 seconds (JVM running for 9.676)
2016-10-20 11:14:00.002  INFO 6832 --- [pool-2-thread-1] br.com.scheduler.ScheduledTasks          : The date is: {} 11:14:00

Ответ 20

В application.properties добавьте следующее свойство, которое сообщает приложению Spring Boot не запускать пакетное задание при запуске приложения.

spring.batch.job.enabled=false

Ответ 21

Была такая же проблема.

В моем случае я переместил свои функции @Scheduled из @Service в новый отдельный класс с аннотацией @Component, и это решило мою проблему