2017-11-07 4 views
0

Wir haben Batch-Job mit Einzelschritt konfiguriert. Die allgemeine Struktur ist wie,Verwenden von Ende in Einzelschritt-Batch-Job in Spring Batch

<batch:job id="mainJob"> 
    <batch:step id="step1"> 
     <batch:tasklet> 
      <batch:chunk reader="fileReader" writer="jmsItemWriter" > 
       <batch:retryable-exception-classes> 
        <batch:include class="org.springframework.dao.CannotAcquireLockException"/> 
       </batch:retryable-exception-classes> 
      </batch:chunk> 
     </batch:tasklet> 
     <batch:end on="UNKNOWN"/> 
     <batch:next on="*" to="step1"/> 
     <batch:listeners> 
      <batch:listener ref="listener1"/> 
      <batch:listener ref="listener2"/> 
     </batch:listeners> 

    </batch:step> 
    <batch:listeners> 
     <batch:listener ref="jobListener"/> 
    </batch:listeners> 
    </batch:job> 

Filereader FlatFileItemReader ist, die eine Datei Zeile für Zeile liest und übergibt jede Zeile zu ‚listener2‘. Wenn es in listen2 einen Fehler in der Zeile gibt, sollte der Status auf 'unbekannt' gesetzt werden (nicht fehlgeschlagen, da der Job nicht erneut gestartet werden sollte) und dann den Job stoppen.

Um dies zu erreichen, haben wir.

<batch:end on="UNKNOWN"/> 
<batch:next on="*" to="step1"/> 

Aber der Batch-Job endet nicht auf Unbekannt und geht wegen "nächsten" in die Schleife. Es gibt eine Ausnahme, wenn "next" nicht erwähnt wird.

Wie können wir das auflösen?

Edit:

Einige weitere Erklärung für Deans Antwort.

Listener2 erhält FieldSet d. H. Dateieinträge Zeile für Zeile. Wenn während der Verarbeitung dieser Einträge einige Bedingungen (die auch Datenbankabfragen betreffen) erfüllt sind, sollte der Job keine weitere Datei lesen und anhalten. Da die Verarbeitung in der Override-Methode 'mapFieldSet' erfolgt, die keine Ausnahme auslöst, kann keine neue Ausnahme verwendet werden, und die Rückgabe von null liest nur die nächste Zeile. Im Allgemeinen haben die Dateien Tausende von Zeilen, aber innerhalb der ersten 2 Zeilen wird bestimmt, ob weiteres Lesen notwendig ist oder nicht.

+0

ich mehr auf die Antwort hinzugefügt habe unten auf der Grundlage Ihres Updates –

Antwort

0

Was Sie getan haben, ist ziemlich nicht-Standard. Hier ist, was ich tun würde ...

  • Remove Listener 2 (dies ist nicht wirklich, wie Fehler behandelt werden soll)
  • Sie die Validierungsarbeiten in einem ItemProcessor stattdessen für den JMS-Schreiber des Wartens scheitern
  • Entweder eine Ausnahme oder null zurück von dem Prozessor für ungültige Elemente
  • eine Ausnahme Listener (StepExecutionListener) werfen, dass der Ausfall Ausnahmen überprüft und die ExitStatus
Flips

Beispiel Schritt Ausführung Zuhörer afterStep Methode:

public ExitStatus afterStep(StepExecution stepExecution) { 
    for (Throwable t : stepExecution.getFailureExceptions()) { 
     if ("EXPECTED MESSAGE".equals(t.getMessage())) { 
      return ExitStatus.UNKNOWN; 
     } 
    } 
    return null; 
} 

UPDATE Basierend auf neue Info In Frage:

Von dem, was Sie angegeben haben, scheint es wie ein Decider tatsächlich könnte sein, Ihre sauberste Lösung.

Modification des Auftragsflusses:

<batch:job id="mainJob"> 
    <batch:decision id="decision" decider="someDecider"> 
     <next on="PROCESS" to="step1" /> 
     <end on="STOP" /> 
     <fail on="*" /> 
    </batch:decision> 
    <batch:step id="step1"> 
     <!-- . . . --> 
    </batch:step> 
    <!-- . . . --> 
</batch:job> 

Beispiel Decider Klasse:

public class ProcessFileDecider implements JobExecutionDecider { 

    private Resource resource; 

    @Override 
    public FlowExecutionStatus decide(final JobExecution jobExecution, final StepExecution stepExecution) { 
     try (BufferedReader reader = new BufferedReader(new InputStreamReader(resource.getInputStream()))) { 
      final String lineOne = reader.readLine(); 
      final String lineTwo = (lineOne != null) ? reader.readLine() : null; 

      final boolean processFile = true; //some logic here 
      if (processFile) { 
       return new FlowExecutionStatus("PROCESS"); 
      } 
      return new FlowExecutionStatus("STOP"); 

     } catch (final IOException e) { 
      throw new IllegalStateException("Hit error deciding whether to process the resource!", e); 
     } 
    } 

    public void setResource(Resource resource) { 
     this.resource = resource; 
    } 

} 
+0

aktualisiert Frage für Ihre Anregungen. – Nets

+0

danke für den Vorschlag. Das sieht nach der saubersten Lösung aus. Ich werde es versuchen und hier aktualisieren. – Nets

+0

das funktionierte sehr gut und mit benutzerdefinierten Exit-Status konnte ich auch richtige Nachricht protokollieren. Danke noch einmal. – Nets

Verwandte Themen