Stocker dans JobExecutionContext à partir de tasklet et accéder dans un autre tasklet

j'ai une condition dans laquelle une tasklet, stocke tous les fichiers dans les répertoires dans une arraylist. La taille de la liste est stockée dans le contexte d'exécution des tâches. Plus tard, ce compte est accédé à partir d'un autre tasklet dans une autre étape. Comment faire cela. J'ai essayé de stocker dans le contexte jobexécution, à runtime jette collection unmodifiable exception,

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

a également stocké la référence stepexection dans l'annotation beforestep .toujours pas possioble.veuillez me faire savoir ,comment les partager des données entre deux tasklets.

19
demandé sur skaffman 2011-11-14 07:42:18

2 réponses

vous avez au moins 4 possibilités:

  1. utilisez L'Exécutionpromotionlistener pour passer des données aux étapes à venir
  2. utiliser une fève (ressort) pour conserver les données inter-étapes, p.ex. une carte à balise concurrente
    • sans autre action de ces données ne sera pas accessible pour un re-démarrage
  3. accédez au JobExecutionContext dans votre tasklet, doit être utilisé avec prudence, va causer des problèmes de thread pour les étapes parallèles
  4. utilisation la nouvelle jobscope (introduite avec spring batch 3)
  1. définir une valeur

    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. extraction d'une valeur

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

j'ai créé des exemples de code pour les 3 premières solutions mon ressort-lot-exemples github, voir module complexe et d'emballage interstepcommunication

51
répondu Michael Pralow 2015-01-05 07:23:58

une Autre façon est d'utiliser StepExecutionListener qui est appelé après l'exécution step. Votre tasklet peut l'implémenter et partager un attribut local.

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

ainsi, dans l'étape, votre haricot est un tasklet et un auditeur comme bellow. Vous devez également configurer la portée de votre pas en "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">
4
répondu user1067920 2012-02-06 10:41:29