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?

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" />

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


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
}

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" />

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){
          ....
}

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']}

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

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.