2016-04-03 123 views
1

我有這個將文件上傳到Amazon S3的tasklet。現在,我想在拋出AmazonClientException時重試任務執行。我想通過使用@Retryable註釋來完成這項工作。Spring批處理:使用@Retryable和@EnableRetry註釋重試一個tasklet

任務蕾:

@Component 
@StepScope 
@Retryable(value=AmazonClientException.class, stateful=true, [email protected](2000)) 
public class S3UploadTasklet extends ArgsSupport implements Tasklet { 

    @Autowired 
    private S3Client s3Client; 

    @Autowired 
    private S3Properties s3Properties; 

    private static final Logger LOGGER = LoggerFactory.getLogger(S3UploadTasklet.class); 

    private static final String FILE_EXTENSION = ".gpg"; 

    @Override 
    public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { 
     try { 
      String localFilename = getTempOutputFilename() + FILE_EXTENSION; 
      String s3Filename = s3Properties.getReportPath() + getS3OutputFilename() + FILE_EXTENSION; 
      File f = new File(localFilename); 
      if(f.exists()) { 
       LOGGER.info("Uploading " + localFilename + " to s3..."); 
       s3Client.upload(localFilename, s3Filename, s3Properties.getBucketName()); 
       LOGGER.info("Uploading done!"); 
      } else { 
       throw new RuntimeException("Encrypted file not found! Encryption process might have failed."); 
      } 
     } catch(AmazonClientException e) { 
      LOGGER.error("Problems uploading to S3. " + e.getMessage(), e); 
      throw e; 
     } catch(RuntimeException e) { 
      LOGGER.error("Runtime error occured. " + e.getMessage(), e); 
      throw e; 
     } 

     return RepeatStatus.FINISHED; 
    } 
} 

作業配置:

@Configuration 
@EnableBatchProcessing 
@EnableRetry 
public class BatchConfiguration { 
    @Autowired 
    private JobBuilderFactory jobBuilderFactory; 

    @Autowired 
    private Step generateReport; 

    @Autowired 
    private Step encrypt; 

    @Autowired 
    private Step upload; 

    @Autowired 
    private Step cleanUp; 

    @Bean 
    @Transactional(value="appTransactionManager", isolation=Isolation.READ_COMMITTED) 
    public Job generateReconJob() { 
     return jobBuilderFactory.get("reconJob") 
       .incrementer(new RunIdIncrementer()) 
       .start(generateReport) 
        .on("COMPLETED").to(encrypt) 
       .from(generateReport) 
        .on("NOOP").end() 
       .from(generateReport) 
        .on("FAILED").to(cleanUp) 
       .from(encrypt) 
        .on("COMPLETED").to(upload) 
       .from(encrypt) 
        .on("FAILED").to(cleanUp) 
       .from(upload) 
        .on("*").to(cleanUp) 
       .from(cleanUp) 
        .on("*").end() 
       .end() 
       .build(); 
    } 
} 

但是,它不會做什麼是應該做的。當拋出異常時,批處理作業仍不會重試該tasklet。

有什麼想法?

這裏的配置也

@Configuration 
public class ReportConfiguration { 
    ... 

    @Autowired 
    private S3UploadTasklet s3UploadTasklet; 

    ... 

    @Bean 
    public Step upload() { 
     return stepBuilderFactory.get("upload") 
       .tasklet(s3UploadTasklet) 
       .build(); 
    } 
} 
+0

當你說它不重試,拋出異常時會發生什麼? –

+0

@MichaelPralow我看到異常被拋出,但它只是繼續下一步。 – makalshrek

+0

我不認爲重試註釋應該位於Tasklet本身上。相反,我會打電話給亞馬遜在它自己的方法,並在那裏使用可重試。 – IcedDante

回答

0

的@Retryable(值= AmazonClientException.class,狀態=真,退避= @退避(2000))註釋應該是要重試的方法,而不是類。

+0

[Retryable](http://docs.spring.io/spring-retry/docs/1.1.2.RELEASE/apidocs/org/springframework/retry/annotation/Retryable.html)註釋有 '@Target(value = {METHOD,TYPE})',所以它可以在方法/類/接口上。使用'@ Retryable'註釋類與註釋類中的所有方法相同。因此,如果您的類中的所有方法都有一個共同的重試配置,請註釋該類/接口。這裏的方法適用於公共方法,因爲'Retryable'是使用Spring AOP實現的。 –