Per ora, sto utilizzando jobParameters per ottenere i nomi file per FlatFileItemReader e FlatFileItemWriter. Va bene per testare il mio batch, ma il mio obiettivo è leggere un file in qualche directory (c'è solo questo file in questa directory) e il nome del file potrebbe cambiare. Il nome file di output dovrebbe dipendere dal nome file di input.Aggiungere parametri al contesto del processo dal passaggio del tasklet e utilizzare i passaggi successivi in Spring Batch
Pertanto, ho pensato di aggiungere un nuovo passaggio al mio lavoro e questo passaggio imposterà sia i nomi dei file di input che di output cercando nella directory corretta e cercando il file in esso. Ho letto Passing Data to Future Steps da Spring Doc e this thread da SO, ma non riesco a farlo funzionare, i file sono sempre "null".
In primo luogo, ho definito il seguente 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;
}
}
Poi, ho aggiunto il fagiolo promotionListener
@Bean
public ExecutionContextPromotionListener promotionListener() {
ExecutionContextPromotionListener listener = new ExecutionContextPromotionListener();
listener.setKeys(new String[]{
"inputFile", "outputFile"
});
return listener;
}
ho cambiato le jobParameters da un jobExecutionContext nella mia definizione FlatFileItemWriter (non l'ho fatto cambiare una singola riga al codice stesso)
@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;
}
Ho aggiunto il mio T asklet fagioli
@Bean
public SettingFilenamesTasklet settingFilenames() {
return new SettingFilenamesTasklet();
}
e ho creato un nuovo passo per aggiungere nella mia dichiarazione di lavoro
@Bean
public Step stepSettings(StepBuilderFactory stepBuilderFactory, SettingFilenamesTasklet tasklet, ExecutionContextPromotionListener listener) {
return stepBuilderFactory.get("stepSettings").tasklet(tasklet).listener(listener).build();
}
Per ora, il FlatFileItemReader utilizza ancora il valore jobParameters, voglio fare il mio lavoro FlatFileItemWriter prima. Ottengo il seguente errore:
[...]
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
Ho provato a sostituire l'annotazione @StepScope da @JobScope; per mettere i miei parametri direttamente in jobExecutionContext (+ JobExecutionListener) invece di usare StepContext + promotionListener ... Niente funziona. Il file di risorse è sempre nullo quando provo a creare FlatFileItemWriter.
Cosa mi manca?
Grazie per il vostro aiuto.
Puoi provare ad aggiungere '@ BeforeStep' al tuo writer e posizionare un punto di interruzione per controllare cosa c'è in' stepExecution.getExecutionContext() 'e' stepExecution.getJobExecution(). GetExecutionContext() '? Rimuovi '@ Value' in modo da poter iniziare il tuo lavoro per ora. –
Sembra che il mio codice non esegua nemmeno il metodo '@ BeforeStep' che ho scritto ...Ho creato una classe estendendo FlatFileItemWriter per testare quello che hai detto (non vedo come aggiungere un '@ BeforeStep' nella configurazione batch in caso contrario), che istanzia invece del FlatFileItemWriter generico nel mio codice. Il mio debugger non si ferma sui breakpoints che ho impostato ... – Carrm