Java Spring @tâches Planifiées de l'exécution de deux fois

j'ai une méthode d'essai simple ici qui est réglée pour fonctionner toutes les 5 secondes et il le fait, mais en regardant le système.dehors, vous pouvez voir qu'il semble faire quelque chose de bizarre.

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

sortie:

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...

pourquoi tourne-t-il deux fois (apparaissent) à chaque fois?

25
demandé sur ROMANIA_engineer 2013-01-09 20:55:03

17 réponses

Si vous regardez la documentation, il y a une note qui appelle explicitement ce phénomène.

la note se trouve sous section 25.5.1 à ce lien , et se lit comme suit:

assurez-vous que vous n'initialisez pas plusieurs instances de la même classe d'annotation @Scheduled à l'exécution, à moins que vous ne vouliez programmer des callbacks pour chacune de ces instances. À cet égard, assurez-vous que vous n'utilisez pas @Configurable sur les classes de haricots qui sont annotés avec @programmable et enregistrés comme des haricots de printemps réguliers avec le conteneur: vous obtiendriez une double initialisation sinon, une fois à travers le conteneur et une fois à travers l'aspect @Configurable, avec la conséquence de chaque méthode @Programmable être invoquée deux fois.

je comprends qu'il s'agit simplement d'une suggestion à ce stade, mais je ne pense pas que nous ayons assez d'information pour diagnostiquer la question plus avant.

21
répondu nicholas.hauschild 2013-01-09 17:55:59

je connais la réponse!!

Ne pas init votre Prévues deux fois

Butin à votre web journal :

WebApplicationContext une fois et servlet une fois

donc dans votre servlet.xml ne faites pas comme ça

import resource="classpath:applicationContext.xml"
4
répondu user2408678 2013-05-22 09:10:55

il se passe en raison de l'auditeur de contexte

Juste enlever

< listener >

< listener-class >org.springframework.Web.cadre.ContextLoaderListener< / listener-class >

< / listener >

de web.xml, il doit travailler.

4
répondu Girish Kumar 2014-01-12 08:10:09

j'ai rencontré un problème similaire. Il pourrait être à cause de raisons ci-dessous.

  1. un bug dans les versions de printemps https://jira.spring.io/browse/SPR-10830

  2. contexte étant chargé deux fois.

  3. le log4j.xml j'écris les journaux deux fois. C'est arrivé dans mon cas, pas sûr que la vôtre. Si vous avez essayé les autres options, essayez celui-ci également.

2
répondu jchandrra 2015-01-15 09:11:56

j'ai eu un problème similaire, j'ai résolu le mien en faisant ceci:

package com.sample.config;

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

@Configuration
@EnableScheduling
public class JobExecutorConfig {
}

comme configuration pour le démarrage à ressort. Et j'ajoute ceci comme jobclass:

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
}
2
répondu ciberkids 2017-05-07 21:36:09

j'ai eu ce même problème, et j'ai finalement découvert que le problème est survenu suite à des grains en cours de création dans le root context ainsi que le servlet context .

donc, pour corriger cela, vous devez séparer la création des haricots dans les contextes appropriés.

Cette réponse , explique vraiment bien comment, à qui et ce qui a été corrigé mon problème.

1
répondu jlars62 2017-05-23 12:17:58

j'ai eu le même problème. Passé des heures à essayer de résoudre.

La Solution

était que L'application était déployée deux fois sur Tomcat.

en essayant de nettoyer Tomcat il a donné une erreur.

vérification du serveur.j'ai remarqué que le même fichier Tomcat était déployé deux fois. Il y avait aussi une étiquette "hôte" non fermée. Vous ne savez pas lequel de ces fixe, mais soulagé d'avoir fonctionner de nouveau correctement.

1
répondu Daryn 2017-07-05 01:27:32

j'utilise spring 4.0.3 et j'ai ce problème. je l'ai résolu en renommant mes haricots.

à:

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

j'ai remarqué un enregistrement D'INFO disant qu'aucun haricot nommé taskScheduler n'a trouvé, créant une nouvelle instance. Donc, je disais qu'il y avait deux instance de la taskScheduler.

Laissez-moi savoir si cela fonctionne pour vous aussi :)

0
répondu Titi Wangsa bin Damhore 2014-04-16 08:49:40

Eh bien, dans mon cas, le travail avait une annotation @Component et j'avais ceci dans mon contexte d'application.xml:

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

donc la solution est de supprimer la définition de la fève (la deuxième ligne) parce que:

<task:annotation-driven/> : permet la détection d'annotations @Async et @Scheduled sur n'importe quel objet géré par ressort de sorte qu'il n'est pas nécessaire de définir le travail ou il sera appelé deux fois.

0
répondu Khalil Kitar 2014-08-03 19:10:03

Selon ce poste et "151930920 de" Printemps " Jira c'est un bug dans le Cadre du Printemps composant Planificateur.

0
répondu Prashant 2014-10-30 06:58:34

vous pourriez vouloir vérifier si vous scannez des composants pour le même paquet dans deux contextes différents si votre application est WEB, par exemple applicationContext.xml, puis de nouveau quelques-servlet.XML.

0
répondu bcavlin 2015-02-14 03:44:26
<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>

C'est ma toile.XML. Donc , vous pouvez voir que "/WEB-INF/spring/appServlet/printemps-contexte.xml" est chargé deux fois (une fois dans context-param , une fois dans servlet -> init-param ).

0
répondu Ax Constantin 2015-03-31 19:04:12

j'ai fait face à la même situation et résolu par ceci:

1) Service D'Ordonnanceur

@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) Classe Ouvrière

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

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

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

}
0
répondu Bahadir Tasdemir 2016-06-01 12:43:06

j'ai eu le même problème aujourd'hui.

dans mon projet j'utilisais le scheduler avec mon application de démarrage à ressort et dans ma classe Schedlinedtaks j'utilisais l'annotation @Component. Mais j'ai fait une erreur parce que le @ Component représente un haricot pour ma classe et dans ma classe D'Application j'ai créé un autre haricot pour cette classe avec le code:

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();
  }
}

je viens de supprimer cette annotation et le planificateur fonctionne percectly.

Suivre l'exemple de mon code ScheduledTasks classe:

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()) );
  }
}

et le résultat:

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
0
répondu Lucas Araújo 2016-10-20 14:25:05

j'ai eu le même problème, en regardant dans mon code et après avoir essayé tout ce qui est ici, j'ai trouvé que j'ai eu un SpringApplicationBuilder deux fois dans la classe de 2 diferents

0
répondu Chocolim 2018-04-25 19:16:35

dans la demande.propriétés, ajouter la propriété suivante qui indique à L'Application D'amorçage de printemps de ne pas commencer la tâche de lot au démarrage de L'Application.

spring.batch.job.enabled=false
0
répondu jalpa 2018-09-04 11:47:40

j'ai eu le même problème. J'utilisais la configuration basée sur l'annotation comme suit:

@Configuration
@EnableScheduling
public class SchedulerConfig {

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

j'étendais aussi AbstractAnnotationConfigDispatcherservletinitializer pour initialiser le même.

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 };
}

}

la suppression de la méthode SchedulerConfig.class de la méthode getRootConfigClasses() a fait l'affaire pour moi.

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

j'espère que cela aidera.

0
répondu Nasir 2018-09-30 09:42:17