2015-12-01 39 views
7

Poiché "Solo i metodi di annullamento del reso possono essere annotati con @Scheduled", come posso utilizzare Spring Batch e Spring Scheduler Task quando sto usando la configurazione @Bean invece della configurazione xml? Di seguito puoi trovare il mio file di configurazione completo. Funziona perfettamente quando faccio scattare da main() ma solo una volta. Voglio aggiungere @Scheduled(fixedrate=9999) per evocare lo stesso lavoro a determinate frequenze. Per quanto posso vedere, per fare ciò, dovevo aggiungere @Scheduled al metodo step1, ma non posso perché restituisce un valore diverso da void.Come utilizzare @Configuration e @EnableScheduling insieme a Spring Batch

@Configuration 
@EnableBatchProcessing 
@EnableScheduling 
public class BatchConfiguration { 
     private static final Logger log = LoggerFactory 
        .getLogger(BatchConfiguration.class); 

     @Bean 
     @StepScope 
     public FlatFileItemReader<Person> reader() { 
       log.info(new Date().toString()); 
       FlatFileItemReader<Person> reader = new FlatFileItemReader<Person>(); 
       reader.setResource(new ClassPathResource("test_person_json.js")); 
       reader.setLineMapper(new DefaultLineMapper<Person>() { 
        { 
          setLineTokenizer(new DelimitedLineTokenizer() { 
            { 
             setNames(new String[] {"firstName", "lastName" }); 
            } 
          }); 
          setFieldSetMapper(new BeanWrapperFieldSetMapper<Person>() { 
            { 
             setTargetType(Person.class); 
            } 
          }); 
        } 
       }); 
       return reader; 
     } 

     @Bean 
     public ItemProcessor<Person, Person> processor() { 
       return new PersonItemProcessor(); 
     } 

     @Bean 
     public ItemWriter<Person> writer(DataSource dataSource) { 
       JdbcBatchItemWriter<Person> writer = new JdbcBatchItemWriter<Person>(); 
       writer.setItemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<Person>()); 
       writer.setSql("INSERT INTO people (first_name, last_name) VALUES (:firstName, :lastName)"); 
       writer.setDataSource(dataSource); 
       return writer; 
     } 

     @Bean 
     public Job importUserJob(JobBuilderFactory jobs, Step s1, 
        JobExecutionListener listener) { 
       return jobs.get("importUserJob").incrementer(new RunIdIncrementer()) 
          .listener(listener).flow(s1).end().build(); 
     } 

     @Bean 
     public Step step1(StepBuilderFactory stepBuilderFactory, 
        ItemReader<Person> reader, ItemWriter<Person> writer, 
        ItemProcessor<Person, Person> processor) { 
       return stepBuilderFactory.get("step1").<Person, Person> chunk(10) 
.reader(reader).processor(processor).writer(writer).build(); 
     } 

     @Bean 
     public JdbcTemplate jdbcTemplate(DataSource dataSource) { 
       return new JdbcTemplate(dataSource); 
     } 
} 


//Question updated on Dec 3th 2015 with first suggestion 
import org.springframework.batch.core.Job; 
import org.springframework.batch.core.JobParameters; 
import org.springframework.batch.core.launch.JobLauncher; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.beans.factory.annotation.Qualifier; 
import org.springframework.scheduling.annotation.Scheduled; 
import org.springframework.stereotype.Component; 

@Component 
public class PersonScheduler { 
    private Job myImportJob; 
    private JobLauncher jobLauncher; 

    @Autowired 
    public PersonScheduler(JobLauncher jobLauncher, @Qualifier("myImportJob") Job myImportJob){ 
     this.myImportJob = myImportJob; 
     this.jobLauncher = jobLauncher; 
    } 

    @Scheduled(fixedRate=9999) 
    public void runJob{ 
     jobLauncher.run(myImportJob, new JobParameters()); 
    } 
} 

risposta

4

Basta creare componente separato, dove si autowire il vostro lavoro e pianificato:

@Component 
public class MyScheduler{ 
    private Job myImportJob; 
    private JobLauncher jobLauncher; 

    @Autowired 
    public MyScheduler(JobLauncher jobLauncher, @Qualifier("myImportJob") Job myImportJob){ 
     this.myImportJob = myImoportJob; 
     this.jobLauncher = jobLauncher; 
    } 

    @Scheduled(fixedRate=9999) 
    public void runJob(){ 
     jobLauncher.run(myImportJob, new JobParameters()); 
    } 
} 

Reazione al terzo commento:

Proprio utilizzare .allowStartIfComplete(true) quando si crea il passo.

+0

sto ottenendo due avvertimenti: 1 - (a destra sulla @Scheduled) L'annotazione @Scheduled viene annullato a causa di questa posizione 2 - (proprio sul metodo di runJob) Molteplici marcatori in questa linea - Errore di sintassi, inserire ";" per completare FieldDeclaration - void è un tipo non valido per la variabile runJob Ho aggiornato la mia domanda aggiungendo il tuo suggerimento. Ho mostrato le importazioni e di solito tali avvisi appaiono quando non abbiamo le importazioni corrette ma credo di essere corretto su di esso. Dovrei aggiungere @SuppressWarnings? –

+1

Io perdono parentesi per il metodo runJob(). È aggiornato ora. – luboskrnac

+0

Riesco a vedere che lo scheduler funziona ma sto ricevendo SimpleStepHandler: fase già completata o non riavviabile, quindi nessuna azione da eseguire: StepExecution: id = 1, version = 3, name = step1, status = COMPLETED, exitStatus = COMPLETED, readCount = 1, filterCount = 0, writeCount = 1 readSkipCount = 0, writeSkipCount = 0, processSkipCount = 0, commitCount = 1, rollbackCount = 0, exitDescription =. Mi sembra che dopo che il mio lavoro sia stato eseguito due volte, non può più essere eseguito. Immagino che la prima volta sia in esecuzione mentre avvio l'applicazione, poi la seconda mentre il programma di avvio si attiva. Dopo questo, lo stato è "completato" per sempre. –