Шаг Spring Batch не совершает транзакцию немедленно - PullRequest
1 голос
/ 27 февраля 2020

Я настроил шаг для чтения и проверки данных. Если какая-либо проверка завершается неудачно, я обновляю статус таблицы ошибок (созданной для отслеживания сведений о файле) как сбой, а причину - как сообщение проверки (BatchFileDetail - таблица ошибок в приведенном ниже коде). как только я сохранил это в БД, я сразу же выдал исключение на основе состояния таблицы ошибок

ниже мой код

    @Bean
    public Job fileParserJob() {
        return jobBuilderFactory.get("fileParserJob")
                .incrementer(new RunIdIncrementer())
                .start(validateFileStep())
                .build();
    }

    public Step validateFileStep() {
        return stepBuilderFactory.get("validateFileStep")
                .tasklet(fileTasklet)
                .build();
    }

    @Override
    @Transactional(dontRollbackOn=BatchServiceException.class)
    public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws 
    Exception {
        Resource resource = new FileSystemResource(filePath);
        BatchFileDetail batchFileDetail = new BatchFileDetail();
        batchFileDetail.setFileId(String.valueOf(System.currentTimeMillis()));
        batchFileDetail.setFileName(resource.getFilename());
        batchFileDetail.setStatus("STARTED");
        batchFileDetail.setProcessedOn(new Date());
        CommonUtillity.validateBatchResource(resource, StringConstants.FILE_NAME, batchFileDetail);
        validateBatchFileDetail(resource.getFile(), batchFileDetail);
        batchFileDetailRepository.saveAndFlush(batchFileDetail);
        if(CBOSConstants.FAILED.equals(batchFileDetail.getStatus())) {
            throw new BatchServiceException(batchFileDetail.getReason());
        }
        return RepeatStatus.FINISHED;
    }

}

Но данные, которые я сохранил в таблице ошибок, возвращаются обратно. Обработка исключений приводит к переходу к другому шагу, но я хочу завершить текущую работу с записью в таблице ошибок. Любая помощь приветствуется.

Ответы [ 2 ]

0 голосов
/ 27 февраля 2020

Решение, которое я нашел, может быть не лучшим, но на данный момент я продолжаю с нижеприведенным.

@Bean
public Job fileParserJob() {
    return jobBuilderFactory.get("fileParserJob")
            .incrementer(new RunIdIncrementer())
            .start(validateFileStep())
            .next(validateFileStatusStep())
            .build();
}

public Step validateFileStep() {
    return stepBuilderFactory.get("validateFileStep")
            .tasklet(fileTasklet)
            .build();
}

public Step validateFileStatusStep() {
    return stepBuilderFactory.get("validateFileStatusStep")
            .tasklet(validateBatchFileDetailTasklet)
            .build();
}

FileTasklet.java
-----------------
@Override
@Transactional(dontRollbackOn=BatchServiceException.class)
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
    Resource resource = new FileSystemResource(filePath);
    BatchFileDetail batchFileDetail = new BatchFileDetail();
    batchFileDetail.setFileId(String.valueOf(System.currentTimeMillis()));
    batchFileDetail.setFileName(resource.getFilename());
    batchFileDetail.setStatus("STARTED");
    batchFileDetail.setProcessedOn(new Date());
    CommonUtillity.validateBatchResource(resource, StringConstants.FILE_NAME, batchFileDetail);
    validateBatchFileDetail(resource.getFile(), batchFileDetail);
    batchFileDetailRepository.saveAndFlush(batchFileDetail);
    return RepeatStatus.FINISHED;
}

}

ValidateBatchFileDetailTasklet
------------------------------
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
    BatchFileDetail batchFileDetail = batchFileDetailRepository.getRecentFailedTransactionStatus(StringConstants.FILE_NAME);
    if(StringConstants.FAILED.equals(batchFileDetail.getStatus())) {
        throw new BatchServiceException(batchFileDetail.getReason());
    }
    return RepeatStatus.FINISHED;
}

С этим решением обновляется первая таблица ошибок с указанием статуса ошибки и причины ошибки, затем транзакция фиксируется в один шаг. На следующем шаге выборка последней записи на основе имени файла и проверка статуса выбранной записи. Если это было FAILED, выдается исключение для завершения текущего задания.

Если статус не только FAILED, необходимо обработать следующие данные. Если статус был FAILED, мы должны прекратить текущее пакетное задание.

0 голосов
/ 27 февраля 2020

Вы аннотируете свой тасклет с помощью @Transactional(dontRollbackOn=BatchServiceException.class). Это не то, как Spring Batch не должен откатывать транзакцию для данного типа исключения.

Ваш тасклет будет выполняться в области транзакции, контролируемой Spring Batch, которую вы можете настроить с помощью атрибутов транзакции, см. AbstractTaskletStepBuilder #actionAttribute .

Таким образом, в вашем случае вы сможете выполнить свое требование, удалив @Transactional на тасклете и определив свой шаг с помощью чего-то вроде:

@Bean
public Step validateFileStep() {
    TransactionAttribute transactionAttributes = new DefaultTransactionAttribute() {
        @Override
        public boolean rollbackOn(Throwable exception) {
            return !(exception instanceof BatchServiceException);
        }
    };

    return stepBuilderFactory.get("validateFileStep")
            .tasklet(fileTasklet)
            .transactionAttribute(transactionAttributes)
            .build();
}

Это для простого тасклета. Для ориентированного на чанки тасклета это можно сделать с помощью FaultTolerantStepBuilder # noRollback (Class) .

...