Wie erhalte ich in Spring Batch Zugriff auf Jobparameter von ItemReader?

73

Dies ist ein Teil von mir job.xml:

<job id="foo" job-repository="job-repository">
  <step id="bar">
    <tasklet transaction-manager="transaction-manager">
      <chunk commit-interval="1"
        reader="foo-reader" writer="foo-writer"
      />
    </tasklet>
  </step>
</job>

Dies ist der Item Reader:

import org.springframework.batch.item.ItemReader;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component("foo-reader")
public final class MyReader implements ItemReader<MyData> {
  @Override
  public MyData read() throws Exception {
    //...
  }
  @Value("#{jobParameters['fileName']}")
  public void setFileName(final String name) {
    //...
  }
}

Das sagt Spring Batch zur Laufzeit:

Field or property 'jobParameters' cannot be found on object of 
type 'org.springframework.beans.factory.config.BeanExpressionContext'

Was ist hier los? Wo kann ich in Spring 3.0 mehr über diese Mechanismen lesen?

yegor256
quelle

Antworten:

75

Wie bereits erwähnt, muss Ihr Leser über einen Schritt verfügen. Sie können dies über die @Scope("step")Anmerkung erreichen. Es sollte für Sie funktionieren, wenn Sie Ihrem Leser diese Anmerkung wie folgt hinzufügen:

import org.springframework.batch.item.ItemReader;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component("foo-reader")
@Scope("step")
public final class MyReader implements ItemReader<MyData> {
  @Override
  public MyData read() throws Exception {
    //...
  }

  @Value("#{jobParameters['fileName']}")
  public void setFileName(final String name) {
    //...
  }
}

Dieser Bereich ist standardmäßig nicht verfügbar, wird jedoch verwendet, wenn Sie den batchXML-Namespace verwenden. Wenn dies nicht der Fall ist, wird durch Hinzufügen der folgenden Elemente zu Ihrer Spring-Konfiguration der Bereich gemäß der Spring Batch-Dokumentation verfügbar :

<bean class="org.springframework.batch.core.scope.StepScope" />
Sean Kleinjung
quelle
8
StepScopeist jetzt standardmäßig verfügbar
Zarathustra
1
Es gibt auch eine Verknüpfung seit v2.2 mit @StepScope mit @Bean
Guillaume Husta
@Scope("step")nicht für mich arbeiten, während @StepScopetat
Pixelmaster
Der Frühling mag keine Abschlussklassen
gstackoverflow
24

Wenn Sie Ihre ItemReaderInstanz und Ihre StepInstanz in einer einzelnen JavaConfig-Klasse definieren möchten. Sie können die @StepScopeund die @ValueAnmerkungen verwenden, z.

@Configuration
public class ContributionCardBatchConfiguration {

   private static final String WILL_BE_INJECTED = null;

   @Bean
   @StepScope
   public FlatFileItemReader<ContributionCard> contributionCardReader(@Value("#{jobParameters['fileName']}")String contributionCardCsvFileName){

     ....
   }

   @Bean
   Step ingestContributionCardStep(ItemReader<ContributionCard> reader){
         return stepBuilderFactory.get("ingestContributionCardStep")
                 .<ContributionCard, ContributionCard>chunk(1)
                 .reader(contributionCardReader(WILL_BE_INJECTED))
                 .writer(contributionCardWriter())
                 .build();
    }
}

Der Trick besteht darin, dem itemReader einen Nullwert zu übergeben, da dieser durch die @Value("#{jobParameters['fileName']}")Annotation eingefügt wird .

Vielen Dank an Tobias Flohre für seinen Artikel: Spring Batch 2.2 - JavaConfig Teil 2: JobParameters, ExecutionContext und StepScope

Ortomala Lokni
quelle
Wie werden wir das testen?
RBz
20

Ziemlich spät, aber Sie können dies auch tun, indem Sie eine @ BeforeStep-Methode mit Anmerkungen versehen:

@BeforeStep
    public void beforeStep(final StepExecution stepExecution) {
        JobParameters parameters = stepExecution.getJobExecution().getJobParameters();
        //use your parameters
}
Alex Pruss
quelle
8
Dies ist nur dann sinnvoll, wenn die Verwendung der Jobparameter den Status des ItemReader nicht verändert . Wenn sie beispielsweise verwendet werden, um festzulegen, welche Daten gelesen werden sollen, kann die gleichzeitige Ausführung des Lesegeräts zu einem falschen Verhalten führen.
Tveon
@tveon, dies kann mit StepScope gelöst werden, wenn die Reader Bean deklariert wird, oder?
Kajzer
@ Kajzer ja, und wenn Sie den Leser nicht später im selben Job wiederverwenden, können Sie es auch mitJobScope
tveon
14

Um die jobParameters verwenden zu können, müssen Sie Ihren Reader als Scope-Schritt definieren. Ich bin mir jedoch nicht sicher, ob Sie dies mithilfe von Anmerkungen tun können.

Mit xml-config würde es so aussehen:

<bean id="foo-readers" scope="step"
  class="...MyReader">
  <property name="fileName" value="#{jobExecutionContext['fileName']}" />
</bean>

Weitere Informationen finden Sie in der Spring Batch-Dokumentation .

Vielleicht funktioniert es, @Scopeindem Sie den Schrittbereich in Ihrer XML-Konfiguration verwenden und definieren:

<bean class="org.springframework.batch.core.scope.StepScope" />
abalogh
quelle
Ich interessiere mich speziell für Anmerkungen. Dieses Konfigurationsformat ist alt und dokumentiert.
yegor256
Sie haben nicht angegeben, dass Sie nur an einer Lösung nur für Anmerkungen interessiert sind. Trotzdem danke für die Abstimmung.
Abalogh
3

Ergänzend zu einem zusätzlichen Beispiel können Sie auf alle Jobparameter in der JavaConfig-Klasse zugreifen:

@Bean
@StepScope
public ItemStreamReader<GenericMessage> reader(@Value("#{jobParameters}") Map<String,Object> jobParameters){
          ....
}
dmotta
quelle
2

Während der Ausführung des Jobs müssen die Jobparameter wie folgt übergeben werden:

JobParameters jobParameters= new JobParametersBuilder().addString("file.name", "filename.txt").toJobParameters();   
JobExecution execution = jobLauncher.run(job, jobParameters);  

Mit der Ausdruckssprache können wir den Wert wie folgt importieren:

 #{jobParameters['file.name']}
Premraj
quelle
-2

Haben Sie die Jobparameter als Map richtig als Bean deklariert?

Oder haben Sie möglicherweise versehentlich ein JobParameters- Objekt instanziiert , das keinen Getter für den Dateinamen hat?

Weitere Informationen zur Ausdruckssprache finden Sie in der Spring-Dokumentation hier .

Omnaest
quelle