2015-03-18 19 views
11

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.

+0

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

+0

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

risposta

11

Nel tasklet si dispone di ChunkContext a disposizione quindi non è necessario @BeforeStep, è possibile rimuoverlo (nella mia configurazione non viene invocato affatto e quando lo si pensa come un passo di azione non ha molto senso ma Non vedo NPE quindi indovinare quella parte di lavoro). Abbiamo risolto con uno dei due approcci:

  1. È possibile inserire qualsiasi parametro da tasklet al lavoro ExecutionContext utilizzando direttamente chunkContext.getStepContext().getStepExecution().getJobExecution().getExecutionContext().put("inputFile", inputFilename);

  2. È possibile aggiungere ExecutionContextPromotionListener al vostro passo tasklet e poi fare chunkContext.getStepContext().getStepExecution().getExecutionContext().put("inputFile", inputFilename);

+0

Ho provato entrambe le soluzioni, ho ancora lo stesso messaggio di errore. Dovrei fare qualcosa di più, o dovrebbe funzionare con la mia configurazione attuale? – Carrm

+0

Errore mio: non stavo usando il buon ascoltatore per la seconda soluzione. Funziona bene, grazie! – Carrm

Problemi correlati