Spring Batch Retry永远不会重试简单的XML配置

时间:2018-04-23 18:09:21

标签: java spring spring-batch

我们有两年前使用gradle构建的旧式XML配置开发的Spring批处理应用程序。简单设置为自定义运行时异常的重试添加了作业。我们没有打算将此应用程序迁移到最新的基于注释的配置,因为它现在正在生产中运行。

最近发现,由于一些神秘的原因,重试根本不起作用。我尝试将Spring批量版本本地升级到最新版本,但它没有帮助。最初在调用@Service类以获取@PostContruct中的一些数据的步骤中发现了这一点,认为这是因为@PostContruct,使用Tasklet创建了一个额外的步骤并尝试了。我尝试了所有选项,最新的更改只是尝试直接抛出java.lang.Exception但不起作用。在类和方法级别试过@Retryable,从来没有工作过,现在我开始怀疑,这次重试会不会有效?我放弃了这一点,但迫切需要一些帮助。任何可以提供解决这个问题的线索或解决方案的人都是我的英雄!谢谢!

这里有一些代码部分(Groovy代码,一些不必要的Java语法)(我已经简化了一些方法来显示实际关注的区域,但随时可以要求更多的配置更改) -

dependencies {

    testCompile "org.hamcrest:hamcrest-all:1.3"
    testCompile "info.cukes:cucumber-groovy:${cukes.version}"
    testCompile "info.cukes:cucumber-junit:${cukes.version}"
    testCompile "junit:junit:4.11"
    testCompile "org.spockframework:spock-core:${spock.version}"
    testCompile "org.spockframework:spock-spring:${spock.version}"

    compile "org.codehaus.groovy:groovy-all:${groovy.version}"
    compile "org.springframework:spring-test:${spring.version}"
    compile "org.springframework:spring-core:${spring.version}"
    compile "org.springframework.batch:spring-batch-core:4.0.1.RELEASE"
    compile "org.springframework.batch:spring-batch-infrastructure:4.0.1.RELEASE"
    compile "org.springframework.retry:spring-retry:1.2.2.RELEASE"
    compile "org.springframework.batch:spring-batch-test:4.0.1.RELEASE"
    compile "org.springframework.data:spring-data-jpa:1.9.0.RELEASE"
    compile "org.springframework.data:spring-data-commons:1.9.0.RELEASE"
    compile "org.springframework:spring-web:${spring.version}"
    ...
    }

<batch:job id="facebookPermissionsReminderEmailJob" restartable="true">

    <batch:step id="businessPageProcess" parent="faultTolerance" next="facebookPermissionsReminderEmailStep">
        <tasklet ref="businessPageProcessor" retry-limit="5">
            <retryable-exception-classes>
                <include class="java.lang.Exception"/>
                <include class="com.reachlocal.data.synchronizer.model.ApiException"/>
            </retryable-exception-classes>

            <batch:retry-listeners>
                <batch:listener ref="retryLoggerListener" />
            </batch:retry-listeners>

        </tasklet>
    </batch:step>

<bean id="faultTolerance" class="org.springframework.batch.core.step.item.FaultTolerantStepFactoryBean" abstract="true">
  <property name="backOffPolicy">
    <bean class="org.springframework.retry.backoff.ExponentialBackOffPolicy">
        <property name="initialInterval" value="180000" />
        <property name="multiplier" value="2" />
    </bean>
  </property>
</bean>

@Slf4j
@Scope("step")
@Component("businessPageProcessor")
class BusinessPageProcessor implements Tasklet {

@Autowired
BusinessPagesService businessPagesService

@Autowired
PermissionReminderDetails reminderDetails

Map<String, BusinessPage> nameToPageMap = [:]
Date currentDate

@Override
RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {

    log.info("Inside FacebookFirstReminderProcessor.initProcessorDetails() - retrieving facebook Business info")
    List<BusinessPage> businessPages = businessPagesService.getAll()
    log.info("Business Pages info retrieved from facebook: ${businessPages}")

    businessPages.forEach({ page ->
        String pageUrl = extractPageName(page.link ? page.link : page.pageResponse?.link)
        nameToPageMap.put(pageUrl, page)
    })
    log.info("Generated Page to Status Map is: ${nameToPageMap}")

    currentDate = new Date()
    log.info("--------DATE-------- : run date is ${currentDate} for current batch process")

    reminderDetails.currentDate = this.currentDate
    reminderDetails.nameToPageMap = this.nameToPageMap


    RepeatStatus.FINISHED

}

}

@Service
class BusinessPagesService {

@Autowired
PlatformProperty platformProperty

@Autowired
ApiCaller apiCaller

List<BusinessPage> getAll() {
    String businessId = platformProperty.facebookReachLocalBusinessId
    getAll(businessId)
}
List<BusinessPage> getAll(String businessId) {
    List<BusinessPage> businessPages = []
    Assert.isTrue(StringUtils.isNotBlank(businessId), EMPTY_BUSINESS_ID_ERROR_MESSAGE)

    String approvedPagesEndPoint = enrichApiUrlForGetApprovedPages(businessId)
    String pendingPagesEndPoint  = enrichApiUrlForGetPendingPages(businessId)

    List<BusinessPage> approvedPages = getBusinessPages(businessId, approvedPagesEndPoint)
    //FB does not return access info, so manually setting the value for rest of the workflow logic to work as it is.
    approvedPages.stream().forEach({page -> page.accessStatus = FacebookPageAccessStatus.CONFIRMED})

    List<BusinessPage> pendingPages = getBusinessPages(businessId, pendingPagesEndPoint)
    //FB does not return access info, so manually setting the value for rest of the workflow logic to work as it is.
    pendingPages.stream().forEach({page -> page.accessStatus = FacebookPageAccessStatus.PENDING})

    businessPages.addAll(approvedPages)
    businessPages.addAll(pendingPages)
    businessPages

}

List<BusinessPage> getBusinessPages(String businessId, String endPointUrl) {
    List<BusinessPage> businessPages = []
    while (true) {
        log.info("Retrieving Business Pages details for Business Id of: ${businessId} using enriched URL of: ${endPointUrl}")

        BusinessPagesResponse response = getSubSetOfBusinessPages(endPointUrl)
        log.info("Successfully retrieve Business Pages details ${response}")

        if(response.businessPages) {
            businessPages.addAll(response.businessPages)
            endPointUrl = response.paging?.next
        } else {
            break
        }
        if (!endPointUrl) {
            break
        }
    }
    businessPages

}
BusinessPagesResponse getSubSetOfBusinessPages (String endPointURL) {
    BusinessPagesResponse response
    try {
        response = (BusinessPagesResponse) apiCaller.call(
                endPointURL,
                new ParameterizedTypeReference<BusinessPagesResponse>() {},
                Optional.empty(),
                HttpMethod.GET)
        throw new Exception("Test Exception")
        //log.info("Successfully retrieve Business Pages details ${response}")
    } catch (ApiException apiEx){
        if (apiEx.message.contains(EXCESS_DATA_REQUESTED_FAILURE_TEXT)) {
            log.error("ExcessDataRequestedException occurred - retrying")
            String exceptionClass = apiEx.class.name.concat("-")
            throw new Exception(exceptionClass.concat(apiEx.message)) // will trigger retry upto defined max.
        } else {
            throw apiEx
        }
    }
    //response
}

@Component
class RetryLoggerListener extends RetryListenerSupport  {

private Logger logger = LoggerFactory.getLogger(this.getClass())

@Override
<T, E extends Throwable> void onError(RetryContext context, RetryCallback<T, E> callback,Throwable throwable) {
    logger.error("Error occurred during operation {}",throwable.getMessage())
}
}

0 个答案:

没有答案