问题描述
目前,我正在使用jobParameters来获取FlatFileItemReader和FlatFileItemWriter的文件名。可以测试我的批处理,但我的目标是读取某个目录中的文件(此目录中只有此文件),文件名可能会更改。输出文件名应该取决于输入文件名。
For now, I'm using jobParameters to get the filenames for both my FlatFileItemReader and FlatFileItemWriter. It's okay for testing my batch, but my goal is to read a file in some directory (there is only this file in this directory) and the filename might change. The output filename should depend on the input filename.
因此,我考虑在我的工作中添加一个新步骤,此步骤将通过搜索设置输出和输入文件名好的目录,并在其中寻找文件。我从Spring Doc上阅读 ,以及来自SO的 ,但我不能使它工作,文件总是空。
Therefore, I thought about adding a new step to my job, and this step will set both output and input filenames by searching the good directory and looking for the file into it. I read Passing Data to Future Steps from Spring Doc, and this thread from SO, but I can't make it work, the files are always "null".
首先,我已经定义了以下Tasklet
First, I've defined the following Tasklet
public class SettingFilenamesTasklet implements Tasklet {
private StepExecution stepExecution;
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
// TODO Search folder and set real filenames
String inputFilename = "D:/TestInputFolder/dataFile.csv";
String outputFilename = "D:/TestOutputFolder/dataFile-processed.csv";
ExecutionContext stepContext = stepExecution.getExecutionContext();
stepContext.put("inputFile", inputFilename);
stepContext.put("outputFile", outputFilename);
return RepeatStatus.FINISHED;
}
@BeforeStep
public void saveStepExecution(StepExecution stepExec) {
stepExecution = stepExec;
}
}
然后,我添加了promotionListener bean
Then, I added the promotionListener bean
@Bean
public ExecutionContextPromotionListener promotionListener() {
ExecutionContextPromotionListener listener = new ExecutionContextPromotionListener();
listener.setKeys(new String[]{
"inputFile", "outputFile"
});
return listener;
}
我在FlatFileItemWriter定义中通过jobExecutionContext更改了jobParameters(我没有将单行更改为代码本身)
I changed the jobParameters by a jobExecutionContext in my FlatFileItemWriter definition (I didn't change a single line to the code itself)
@Bean
@StepScope
public FlatFileItemWriter<RedevableCRE> flatFileWriter(@Value("#{jobExecutionContext[outputFile]}") String outputFile) {
FlatFileItemWriter<Employee> flatWriter = new FlatFileItemWriter<Employee>();
FileSystemResource isr;
isr = new FileSystemResource(new File(outputFile));
flatWriter.setResource(isr);
DelimitedLineAggregator<RedevableCRE> aggregator = new DelimitedLineAggregator<RedevableCRE>();
aggregator.setDelimiter(";");
BeanWrapperFieldExtractor<RedevableCRE> beanWrapper = new BeanWrapperFieldExtractor<RedevableCRE>();
beanWrapper.setNames(new String[]{
"id", "firstName", "lastName", "phone", "address"
});
aggregator.setFieldExtractor(beanWrapper);
flatWriter.setLineAggregator(aggregator);
flatWriter.setEncoding("ISO-8859-1");
return flatWriter;
}
我添加了我的Tasklet bean
I added my Tasklet bean
@Bean
public SettingFilenamesTasklet settingFilenames() {
return new SettingFilenamesTasklet();
}
我创建了一个新的步骤来添加我的工作声明
And I created a new Step to add in my job declaration
@Bean
public Step stepSettings(StepBuilderFactory stepBuilderFactory, SettingFilenamesTasklet tasklet, ExecutionContextPromotionListener listener) {
return stepBuilderFactory.get("stepSettings").tasklet(tasklet).listener(listener).build();
}
现在,FlatFileItemReader仍然使用jobParameters值,我想让我的FlatFileItemWriter首先工作。我收到以下错误:
For now, the FlatFileItemReader still uses the jobParameters value, I want to make my FlatFileItemWriter work first. I get the following error :
[...]
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.batch.item.file.FlatFileItemWriter]: Factory method 'flatFileWriter' threw exception; nested exception is java.lang.NullPointerException
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:189)
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:591)
... 87 common frames omitted
Caused by: java.lang.NullPointerException: null
at java.io.File.<init>(Unknown Source)
at batchTest.BatchConfiguration.flatFileWriter(BatchConfiguration.java:165)
at batchTest.BatchConfiguration$$EnhancerBySpringCGLIB$$5d415889.CGLIB$flatFileWriter$1(<generated>)
at batchTest.BatchConfiguration$$EnhancerBySpringCGLIB$$5d415889$$FastClassBySpringCGLIB$$969a8527.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:312)
at batchTest.BatchConfiguration$$EnhancerBySpringCGLIB$$5d415889.flatFileWriter(<generated>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162)
... 88 common frames omitted
我试图用@JobScope替换@StepScope注释;将我的参数直接放入jobExecutionContext(+ JobExecutionListener)而不是使用StepContext + promotionListener ......没有任何作用。当我尝试创建FlatFileItemWriter时,资源文件总是为空。
I tried to replace the @StepScope annotation by @JobScope ; to put my parameters directly into jobExecutionContext (+ JobExecutionListener) instead of using StepContext + promotionListener... Nothing works. The resource file is always null when I try to create the FlatFileItemWriter.
我缺少什么?
谢谢为了你的帮助。
推荐答案
在tasklet中你有 ChunkContext
供您使用所以你不需要 @BeforeStep
,你可以将它删除(在我的配置中它根本没有被调用,当你想到它时,一个动作步骤不会做太多感觉,但我没有看到NPE所以猜测那部分工作)。我们用以下两种方法之一解决了它:
In tasklet you have ChunkContext
at your disposal so you do not need @BeforeStep
, you can remove it (in my configuration it is not invoked at all, and when you think of it as one action step does not make much sense but I do not see NPE so guess that part work). We solved it with one of two approaches:
-
您可以将任何参数从tasklet放到job
ExecutionContext
直接使用chunkContext.getStepContext()。getStepExecution()。getJobExecution()。getExecutionContext()。put(inputFile,inputFilename);
您可以将 ExecutionContextPromotionListener
添加到您的tasklet步骤,然后执行 chunkContext.getStepContext ()。getStepExecution()。getExecutionContext()。put(inputFile,inputFilename);
You can add ExecutionContextPromotionListener
to your tasklet step and then do chunkContext.getStepContext().getStepExecution().getExecutionContext().put("inputFile", inputFilename);
这篇关于从tasklet步骤向作业上下文添加参数,并在Spring Batch的后续步骤中使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!