2016-08-04 2 views
1

Ich habe einen Spring-Stapeljob mit einem ersten Schritt, der eine Datei liest und in eine Datenbank schreibt. Wenn die Datei nicht existiert, möchte ich, dass das System x Minuten wartet und dann den Schritt bis zur Anzahl der Versuche wiederholt. Wie kann ich das machen?Spring Batch - zu lesende Datei ist nicht verfügbar

Einzelheiten

Die ItemReader ist wie folgt:

@Bean 
    public ItemReader<Car> reader(LineMapper<Car> lineMapper, File file) { 
     FlatFileItemReader<Car> flatFileItemReader = new FlatFileItemReader<Car>(); 
     flatFileItemReader.setResource(new FileSystemResource(file)); 
     final int NUMBER_OF_HEADER_LINES = 1; 
     flatFileItemReader.setLinesToSkip(NUMBER_OF_HEADER_LINES); 
     flatFileItemReader.setLineMapper(lineMapper); 
     return flatFileItemReader; 
    } 

Derzeit wenn die file nicht vorhanden ist, wird die folgende Ausnahme ausgelöst wird und der Auftrag nicht.

2016-08-05 09:30:10.277 ERROR 7668 --- [   main] o.s.batch.core.step.AbstractStep   : Encountered an error executing step stepLoadFile in job testJob 

org.springframework.batch.item.ItemStreamException: Failed to initialize the reader 
    at org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader.open(AbstractItemCountingItemStreamItemReader.java:147) ~[spring-batch-infrastructure-3.0.6.RELEASE.jar:3.0.6.RELEASE] 
    at org.springframework.batch.item.support.CompositeItemStream.open(CompositeItemStream.java:96) ~[spring-batch-infrastructure-3.0.6.RELEASE.jar:3.0.6.RELEASE] 
    at org.springframework.batch.core.step.tasklet.TaskletStep.open(TaskletStep.java:310) ~[spring-batch-core-3.0.6.RELEASE.jar:3.0.6.RELEASE] 
    at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:197) ~[spring-batch-core-3.0.6.RELEASE.jar:3.0.6.RELEASE] 
    at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:148) [spring-batch-core-3.0.6.RELEASE.jar:3.0.6.RELEASE] 
    at org.springframework.batch.core.job.AbstractJob.handleStep(AbstractJob.java:392) [spring-batch-core-3.0.6.RELEASE.jar:3.0.6.RELEASE] 
    at org.springframework.batch.core.job.SimpleJob.doExecute(SimpleJob.java:135) [spring-batch-core-3.0.6.RELEASE.jar:3.0.6.RELEASE] 
    at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:306) [spring-batch-core-3.0.6.RELEASE.jar:3.0.6.RELEASE] 
    at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:135) [spring-batch-core-3.0.6.RELEASE.jar:3.0.6.RELEASE] 
    at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:50) [spring-core-4.2.4.RELEASE.jar:4.2.4.RELEASE] 
    at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:128) [spring-batch-core-3.0.6.RELEASE.jar:3.0.6.RELEASE] 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_91] 
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_91] 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_91] 
    at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.8.0_91] 
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:302) [spring-aop-4.2.4.RELEASE.jar:4.2.4.RELEASE] 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190) [spring-aop-4.2.4.RELEASE.jar:4.2.4.RELEASE] 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) [spring-aop-4.2.4.RELEASE.jar:4.2.4.RELEASE] 
    at org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$PassthruAdvice.invoke(SimpleBatchConfiguration.java:127) [spring-batch-core-3.0.6.RELEASE.jar:3.0.6.RELEASE] 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) [spring-aop-4.2.4.RELEASE.jar:4.2.4.RELEASE] 
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:208) [spring-aop-4.2.4.RELEASE.jar:4.2.4.RELEASE] 
    at com.sun.proxy.$Proxy78.run(Unknown Source) [na:na] 
    at org.springframework.boot.autoconfigure.batch.JobLauncherCommandLineRunner.execute(JobLauncherCommandLineRunner.java:215) [spring-boot-autoconfigure-1.3.1.RELEASE.jar:1.3.1.RELEASE] 
    at org.springframework.boot.autoconfigure.batch.JobLauncherCommandLineRunner.executeLocalJobs(JobLauncherCommandLineRunner.java:232) [spring-boot-autoconfigure-1.3.1.RELEASE.jar:1.3.1.RELEASE] 
    at org.springframework.boot.autoconfigure.batch.JobLauncherCommandLineRunner.launchJobFromProperties(JobLauncherCommandLineRunner.java:124) [spring-boot-autoconfigure-1.3.1.RELEASE.jar:1.3.1.RELEASE] 
    at org.springframework.boot.autoconfigure.batch.JobLauncherCommandLineRunner.run(JobLauncherCommandLineRunner.java:118) [spring-boot-autoconfigure-1.3.1.RELEASE.jar:1.3.1.RELEASE] 
    at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:804) [spring-boot-1.3.1.RELEASE.jar:1.3.1.RELEASE] 
    at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:788) [spring-boot-1.3.1.RELEASE.jar:1.3.1.RELEASE] 
    at org.springframework.boot.SpringApplication.afterRefresh(SpringApplication.java:775) [spring-boot-1.3.1.RELEASE.jar:1.3.1.RELEASE] 
    at org.springframework.boot.SpringApplication.doRun(SpringApplication.java:366) [spring-boot-1.3.1.RELEASE.jar:1.3.1.RELEASE] 
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:305) [spring-boot-1.3.1.RELEASE.jar:1.3.1.RELEASE] 
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1124) [spring-boot-1.3.1.RELEASE.jar:1.3.1.RELEASE] 
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1113) [spring-boot-1.3.1.RELEASE.jar:1.3.1.RELEASE] 
    at com.myorg.LoadApplication.main(LoadApplication.java:15) [bin/:na] 
Caused by: java.lang.IllegalStateException: Input resource must exist (reader is in 'strict' mode): file [C:\test\TestData.csv] 
    at org.springframework.batch.item.file.FlatFileItemReader.doOpen(FlatFileItemReader.java:251) ~[spring-batch-infrastructure-3.0.6.RELEASE.jar:3.0.6.RELEASE] 
    at org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader.open(AbstractItemCountingItemStreamItemReader.java:144) ~[spring-batch-infrastructure-3.0.6.RELEASE.jar:3.0.6.RELEASE] 
    ... 33 common frames omitted 

com.myorg.LoadApplication Code startet die Batch-Anwendung und ist:

@SpringBootApplication 
public class LoadApplication { 

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

} 

aktualisieren

Nach dimitrisli Antwort zu lesen, habe ich versucht, dies in meiner @Configuration Klasse (Anmerkung: I hinzugefügt @EnableRetry in die Konfigurationsklasse):

@Bean 
public ItemReader<Test> reader(LineMapper<Test> lineMapper, ApplicationProperties properties) { 
    FlatFileItemReader<Test> flatFileItemReader = new FlatFileItemReader<Test>() { 
     @Override 
     @Retryable(value = {ItemStreamException.class}, maxAttempts=5) 
     public void open(ExecutionContext executionContext) throws ItemStreamException { 
      super.open(executionContext); 
     } 

     @Override 
     @Retryable(maxAttempts=5) 
     public Holding read() throws UnexpectedInputException, ParseException, Exception { 
      return super.read(); 
     } 

    }; 
    flatFileItemReader.setResource(new FileSystemResource(properties.getLoadFile())); 
    flatFileItemReader.setLineMapper(lineMapper); 
    return flatFileItemReader; 
} 

ItemStreamException wird ausgelöst und die Anwendung wird beendet, ohne erneut zu versuchen. Wie kann ich es erneut versuchen?

+0

von dimitrisli Antwort auf die ItemReader (Code gezeigt in Update oben) Anwendung, konnte ich diese endlich an die Arbeit. Die Anwendung wurde beendet, ohne erneut zu versuchen, anscheinend aufgrund eines Bugs (?) In Spring-Boot-Starter-Batch Version 1.3.1.RELEASE. Nach dem Wechsel zu 1.4.0.RELEASE funktionierte der Versuch wie erwartet. Die Antwort von dimitrisli so richtig zu formulieren, wie sie meine ursprüngliche Frage beantwortet hat. – James

Antwort

1

von Spring Retry, das Standalone-Spin-off-Projekt von Spring Batch mit: die Ausnahme möglicherweise geworfen Unter der Annahme, dass Sie von erholen möchten und versuchen, sagt 5 mal, ist ItemStreamException dann werden Sie Ihre Methode, die möglicherweise diese wirft dekorieren müssen Ausnahme als:

@Retryable(value = {ItemStreamException.class}, maxAttempts = 5) 
public void myMethod() { 
    //.. 
} 
+0

Das Problem ist, dass diese Ausnahme nicht aus meinem Code geworfen wird. Spring Batch wirft die Ausnahme. Ich habe dem OP eine vollständige Stapelverfolgung hinzugefügt. Wenn ich den Stack-Trace betrachte, könnte ich die Hauptmethode '@ Retryable' hinzufügen (wo die Spring-Boot-Batch-Anwendung ausgeführt wird). Ist das Ihre Empfehlung oder gibt es einen besseren (gezielteren) Ort, um diese Annotation zu platzieren? – James

0

Sie sollten die spring-retry verwenden.

Ein RetryTemplate in Kombination mit einem TimeoutRetryPolicy ermöglicht Ihnen, die gewünschte Funktion zu schreiben.

Sie müssen die @EnableRetry der Konfigurationsklasse und @Retryable der Methode hinzufügen.

Muss der ItemReader zuerst instanziiert werden, bevor die Anwendung gestartet werden kann? Wenn nicht, sollten Sie nur die Bean erstellen und eine andere Methode initialisieren, nachdem der Kontext aktualisiert wurde.

+0

Ich habe diesen Link gelesen, aber ich weiß nicht, wie er für das von mir beschriebene Szenario verwendet/konfiguriert werden kann. Können Sie bitte ein Codebeispiel angeben, wie Sie dies erreichen würden? – James

Verwandte Themen