获取 reader 中的 JobParameters 值
Get values of JobParameters in reader
我在获取 JobConfiguration Class 中的 JobParameter 值时遇到问题。
就像文档中的解释一样,我使用 :
@Value("#{jobParameters['xxxxxxxx']}") String xxxxxxx
等
@StepScope
但是,我有以下错误:
Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException:
Failed to instantiate [org.springframework.batch.core.Job]: Factory method 'PeopleJobConfiguration' threw exception;
nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.step1':
Scope 'step' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton;
nested exception is java.lang.IllegalStateException: No context holder available for step scope
我的错误是在我的步骤之前使用了@StepScope。
这是我更正后的代码:
@SpringBootApplication
public class SpringBatchSimpleTestApplication {
private static final Logger log = LoggerFactory.getLogger(SpringBatchSimpleTestApplication.class);
public static void main(String[] args) throws Exception {
Resource[] resource = ctx.getResources("file:c:/tmp/person*.csv");
String filename;
for (int i = 0; i < resource.length; i++) {
filename = resource[i].getFile().getName();
Job job = ctx.getBean("PersonJobConfiguration", Job.class);
JobLauncher jobLauncher = ctx.getBean(JobLauncher.class);
JobParameters params = new JobParametersBuilder()
.addString("file123", filename)
.toJobParameters();
jobLauncher.run(job, params);
}
}
}
=========================================== ==================
@Configuration
@EnableBatchProcessing
public class PeopleJobConfiguration {
private static final Logger log = LoggerFactory.getLogger(PeopleJobConfiguration.class);
@Autowired
public JobBuilderFactory jobBuilderFactory;
@Autowired
public StepBuilderFactory stepBuilderFactory;
@StepScope
@Bean
public FlatFileItemReader<Person> reader1(@Value("#{jobParameters['file123']}") String file123) {
log.debug("A-file123: "+file123);
return new FlatFileItemReaderBuilder<Person>()
.name("personItemReader")
.resource(new ClassPathResource(file123))
.lineTokenizer(new FixedLengthTokenizer() {{ setNames("firstName", "lastName", "age'"); setColumns(new Range(1,4), new Range(5,6),new Range(7)); }})
.fieldSetMapper(new BeanWrapperFieldSetMapper<Person>() {{ setTargetType(Person.class); }})
.build()
;
}
@Bean
public PersonItemProcessor processor() {
return new PersonItemProcessor();
}
@Bean
public JdbcBatchItemWriter<Person> writer1(DataSource dataSource) {
JdbcBatchItemWriter<Person> jdbcBatchItemWriter = new JdbcBatchItemWriter<>();
jdbcBatchItemWriter.setAssertUpdates(true);
jdbcBatchItemWriter.setDataSource(dataSource);
jdbcBatchItemWriter.setSql("INSERT INTO people (first_name, last_name) VALUES (:firstName, :lastName)");
jdbcBatchItemWriter.setItemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<Person>());
return jdbcBatchItemWriter;
}
@Bean
public JdbcBatchItemWriter<Person> writer2(DataSource dataSource) {
return new JdbcBatchItemWriterBuilder<Person>()
.itemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<>())
.sql("INSERT INTO people2 (first_name, last_name, age) VALUES (:firstName, :lastName, :age)")
.dataSource(dataSource)
.build();
}
@Bean
public CompositeItemWriter compositeItemWriter(JdbcBatchItemWriter<Person> writer1,JdbcBatchItemWriter<Person> writer2) {
CompositeItemWriter itemWriter = new CompositeItemWriter();
itemWriter.setDelegates(Arrays.asList(writer1, writer2));
return itemWriter;
}
@Bean
public Job PeopleJobConfiguration(JobEndListener listener, Step step1) {
return jobBuilderFactory.get("PeopleJobConfiguration")
.listener(listener)
.flow(step1)
.end()
.build();
}
@Bean
public Step step1(JdbcBatchItemWriter<Person> writer1,JdbcBatchItemWriter<Person> writer2, FlatFileItemReader<Person> reader1) {
log.debug("B-file123: "+file123);
return stepBuilderFactory.get("step1")
.<Person,Person> chunk(3)
.reader(reader1)
.writer(compositeItemWriter(writer1, writer2))
.build();
}
}
在这里定义一个step-scoped Step
bean是没有意义的:
@StepScope
@Bean
public Step step1(JdbcBatchItemWriter<Person> writer1,JdbcBatchItemWriter<Person> writer2, @Value("#{jobParameters['file123']}") String file123) {
log.debug("B-file123: "+file123);
return stepBuilderFactory.get("step1")
.<Person,Person> chunk(3)
.reader(reader1(file123))
.writer(compositeItemWriter(writer1, writer2))
.build();
}
您需要删除 @StepScope
并在步骤中注入 reader ,就像您为作家所做的那样:
@Bean
public Step step1(JdbcBatchItemWriter<Person> writer1,JdbcBatchItemWriter<Person> writer2, FlatFileItemReader<Person> reader) {
log.debug("B-file123: "+file123);
return stepBuilderFactory.get("step1")
.<Person,Person> chunk(3)
.reader(reader)
.writer(compositeItemWriter(writer1, writer2))
.build();
}
我在获取 JobConfiguration Class 中的 JobParameter 值时遇到问题。 就像文档中的解释一样,我使用 :
@Value("#{jobParameters['xxxxxxxx']}") String xxxxxxx
等
@StepScope
但是,我有以下错误:
Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException:
Failed to instantiate [org.springframework.batch.core.Job]: Factory method 'PeopleJobConfiguration' threw exception;
nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.step1':
Scope 'step' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton;
nested exception is java.lang.IllegalStateException: No context holder available for step scope
我的错误是在我的步骤之前使用了@StepScope。 这是我更正后的代码:
@SpringBootApplication
public class SpringBatchSimpleTestApplication {
private static final Logger log = LoggerFactory.getLogger(SpringBatchSimpleTestApplication.class);
public static void main(String[] args) throws Exception {
Resource[] resource = ctx.getResources("file:c:/tmp/person*.csv");
String filename;
for (int i = 0; i < resource.length; i++) {
filename = resource[i].getFile().getName();
Job job = ctx.getBean("PersonJobConfiguration", Job.class);
JobLauncher jobLauncher = ctx.getBean(JobLauncher.class);
JobParameters params = new JobParametersBuilder()
.addString("file123", filename)
.toJobParameters();
jobLauncher.run(job, params);
}
}
}
=========================================== ==================
@Configuration
@EnableBatchProcessing
public class PeopleJobConfiguration {
private static final Logger log = LoggerFactory.getLogger(PeopleJobConfiguration.class);
@Autowired
public JobBuilderFactory jobBuilderFactory;
@Autowired
public StepBuilderFactory stepBuilderFactory;
@StepScope
@Bean
public FlatFileItemReader<Person> reader1(@Value("#{jobParameters['file123']}") String file123) {
log.debug("A-file123: "+file123);
return new FlatFileItemReaderBuilder<Person>()
.name("personItemReader")
.resource(new ClassPathResource(file123))
.lineTokenizer(new FixedLengthTokenizer() {{ setNames("firstName", "lastName", "age'"); setColumns(new Range(1,4), new Range(5,6),new Range(7)); }})
.fieldSetMapper(new BeanWrapperFieldSetMapper<Person>() {{ setTargetType(Person.class); }})
.build()
;
}
@Bean
public PersonItemProcessor processor() {
return new PersonItemProcessor();
}
@Bean
public JdbcBatchItemWriter<Person> writer1(DataSource dataSource) {
JdbcBatchItemWriter<Person> jdbcBatchItemWriter = new JdbcBatchItemWriter<>();
jdbcBatchItemWriter.setAssertUpdates(true);
jdbcBatchItemWriter.setDataSource(dataSource);
jdbcBatchItemWriter.setSql("INSERT INTO people (first_name, last_name) VALUES (:firstName, :lastName)");
jdbcBatchItemWriter.setItemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<Person>());
return jdbcBatchItemWriter;
}
@Bean
public JdbcBatchItemWriter<Person> writer2(DataSource dataSource) {
return new JdbcBatchItemWriterBuilder<Person>()
.itemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<>())
.sql("INSERT INTO people2 (first_name, last_name, age) VALUES (:firstName, :lastName, :age)")
.dataSource(dataSource)
.build();
}
@Bean
public CompositeItemWriter compositeItemWriter(JdbcBatchItemWriter<Person> writer1,JdbcBatchItemWriter<Person> writer2) {
CompositeItemWriter itemWriter = new CompositeItemWriter();
itemWriter.setDelegates(Arrays.asList(writer1, writer2));
return itemWriter;
}
@Bean
public Job PeopleJobConfiguration(JobEndListener listener, Step step1) {
return jobBuilderFactory.get("PeopleJobConfiguration")
.listener(listener)
.flow(step1)
.end()
.build();
}
@Bean
public Step step1(JdbcBatchItemWriter<Person> writer1,JdbcBatchItemWriter<Person> writer2, FlatFileItemReader<Person> reader1) {
log.debug("B-file123: "+file123);
return stepBuilderFactory.get("step1")
.<Person,Person> chunk(3)
.reader(reader1)
.writer(compositeItemWriter(writer1, writer2))
.build();
}
}
在这里定义一个step-scoped Step
bean是没有意义的:
@StepScope
@Bean
public Step step1(JdbcBatchItemWriter<Person> writer1,JdbcBatchItemWriter<Person> writer2, @Value("#{jobParameters['file123']}") String file123) {
log.debug("B-file123: "+file123);
return stepBuilderFactory.get("step1")
.<Person,Person> chunk(3)
.reader(reader1(file123))
.writer(compositeItemWriter(writer1, writer2))
.build();
}
您需要删除 @StepScope
并在步骤中注入 reader ,就像您为作家所做的那样:
@Bean
public Step step1(JdbcBatchItemWriter<Person> writer1,JdbcBatchItemWriter<Person> writer2, FlatFileItemReader<Person> reader) {
log.debug("B-file123: "+file123);
return stepBuilderFactory.get("step1")
.<Person,Person> chunk(3)
.reader(reader)
.writer(compositeItemWriter(writer1, writer2))
.build();
}