2011-11-14 7 views
18

Ho un requisito in cui un tasklet memorizza tutti i file nelle directory in un array. La dimensione della lista è memorizzata nel contesto di esecuzione del lavoro. Successivamente questo conteggio è accessibile da un'altra tasklet in un altro passo. Come lo fanno? Ho cercato di conservare in un contesto jobexecution, a runtime genera un'eccezione raccolta immodificabile,Memorizzazione in JobExecutionContext dal tasklet e accesso in un'altra tasklet

public RepeatStatus execute(StepContribution arg0, ChunkContext arg1) 
throws Exception { 
    StepContext stepContext = arg1.getStepContext(); 
    StepExecution stepExecution = stepContext.getStepExecution(); 
    JobExecution jobExecution = stepExecution.getJobExecution(); 
    ExecutionContext jobContext = jobExecution.getExecutionContext(); 
    jobContext.put("FILE_COUNT",150000); 

memorizzato anche il riferimento stepexection in beforestep annotazione non .still possioble.kindly fatemi sapere, come condividere i dati tra due tasklets.

risposta

43

di avere almeno 4 possibilità:

  1. utilizzano l'ExecutionPromotionListener a pass data to future steps
  2. usare un fagiolo (primavera) per contenere i dati inter-passo, per esempio un ConcurrentHashMap
    • senza seguito questi dati non sarà accessibile per un re-start
  3. accesso JobExecutionContext nel tasklet, deve essere utilizzato con cautela, causerà problemi filetto di iniziative parallele
  4. utilizzare il nuovo jobscope (introdotto con molla lotto 3)

Esempio di codice per l'accesso da JobExecution Tasklet:

  1. impostando un valore

    public class ChangingJobExecutionContextTasklet implements Tasklet { 
    
        /** {@inheritDoc} */ 
        @Override 
        public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { 
         // set variable in JobExecutionContext 
         chunkContext 
           .getStepContext() 
           .getStepExecution() 
           .getJobExecution() 
           .getExecutionContext() 
           .put("value", "foo"); 
    
         // exit the step 
         return RepeatStatus.FINISHED; 
        } 
    
    } 
    
  2. estrarre un valore

    public class ReadingJobExecutionContextTasklet implements Tasklet { 
    
        private static final Logger LOG = LoggerFactory.getLogger(ChangingJobExecutionContextTasklet.class); 
    
        /** {@inheritDoc} */ 
        @Override 
        public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { 
         // pull variable from JobExecutionContext 
         String value = (String) chunkContext 
                .getStepContext() 
                .getStepExecution() 
                .getJobExecution() 
                .getExecutionContext() 
                .get("value"); 
    
         LOG.debug("Found value in JobExecutionContext:" + value); 
    
         // exit the step 
         return RepeatStatus.FINISHED; 
        } 
    } 
    

ho creato esempi di codice per i primi 3 soluzioni in my spring-batch-examples github repository, vedere Modulo complesso E FOGLIO interstepcommunication

+0

grazie guarderò questo. Voglio un valore in jobexecutioncontext da estrarre dal bean JobExecutionDecider –

+0

@MichaelLange: Perché il codice originale di Suresh genera un'eccezione? Sembra semanticamente uguale allo snippet di codice che hai fornito. –

+0

beh dovrebbe funzionare, immagino che abbia usato 'chunkContext.getStepContext(). GetJobExecutionContext(). Put (...)' prima, questo genererebbe l'eccezione non modificabile –

4

Un altro modo è utilizzare StepExecutionListener che viene chiamato dopo l'esecuzione del passo. Il tasklet può implementarlo e condividere l'attributo locale.

public class ReadingJobExecutionContextTasklet implements Tasklet, StepExecutionListener { 
    private String value; 

    @Override 
    public ExitStatus afterStep(StepExecution stepExecution) { 
     ExecutionContext jobExecutionContext = stepExecution.getJobExecution().getExecutionContext(); 

     jobExecutionContext.put("key", value); 
     //Return null to leave the old value unchanged. 
     return null; 
    } 
} 

Quindi, nel passaggio, il bean è un tasklet e un listener come il muggito. Si dovrebbe anche configurare l'ambito di passo a "step":

<batch:step id="myStep" next="importFileStep"> 
     <batch:tasklet> 
      <ref bean="myTasklet"/> 
      <batch:listeners> 
       <batch:listener ref="myTasklet"/> 
      </batch:listeners> 
     </batch:tasklet> 
    </batch:step> 

    <bean id="myTasklet" class="ReadingJobExecutionContextTasklet" scope="step"> 
Problemi correlati