2011-11-14 9 views
18

Mam wymaganie, w którym tasklet, przechowuje wszystkie pliki w katalogach na liście tablic. Rozmiar listy jest przechowywany w kontekście wykonywania zadania. Później ten licznik jest dostępny z innego zadania w innym kroku. Jak to robi? Starałem się zachować w kontekście jobexecution, w czasie wykonywania rzutów niemodyfikowalne wyjątek zbiórki,Przechowywanie w JobExecutionContext z taskletu i uzyskiwanie dostępu w innym zadaniu

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); 

przechowywane również odniesienie stepexection w beforestep adnotacji nie .still possioble.kindly daj mi znać, jak udostępnić dane między dwoma tasklets.

Odpowiedz

43

mieć co najmniej 4 możliwości:

  1. wykorzystują ExecutionPromotionListener do pass data to future steps
  2. użycie sprężyny (fasola) do przechowywania danych pomiędzy etapami, na przykład ConcurrentHashMap
    • bez dalszego działania te dane nie będą dostępne do ponownego uruchomienia
  3. Otwórz JobExecutionContext w tasklet, należy stosować ostrożnie, spowoduje problemy dla równoległych wątków krokach
  4. używać nowy jobscope (wprowadzono sprężyny seria 3)

przykład kodu dostępu JobExecution z Tasklet:

  1. ustawienie wartości

    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. ekstrakcji wartość

    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; 
        } 
    } 
    

i utworzony przykłady kodu dla pierwszych 3 rozwiązań my spring-batch-examples github repository patrz modułu złożony i pakować interstepcommunication

+0

dziękuję, popatrzę na to. Chcę, aby wartość w contextexecutioncontext zostały wyodrębnione z JobExecutionDecider bean –

+0

@MichaelLange: Dlaczego oryginalny kod Suresh zgłasza wyjątek? Wygląda semantycznie tak samo, jak podany fragment kodu. –

+0

Cóż, to powinno działać, tylko domyślam się, że użył 'chunkContext.getStepContext(). GetJobExecutionContext(). Put (...)' wcześniej, to rzuciłoby niemodyfikowalny wyjątek –

4

Innym sposobem jest użycie StepExecutionListener, która jest wywoływana po wykonaniu kroku. Twój tasklet może go zaimplementować i udostępnić atrybut lokalny.

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; 
    } 
} 

Tak więc, w kroku, twój komponent to zadanie i słuchacz jak poniżej. Powinieneś także skonfigurować zakres swojego kroku, aby "krok":

<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"> 
Powiązane problemy