This repository contains Retry mechanism implemented in Spring-Batch project
Use regular RetryTemplate from spring-retry
reporting.app.retry.maxAttempts=33
reporting.app.retry.initialDelay=333
@EnableRetry
@Configuration
@Import(PropsConfig::class)
class RetryConfig {
@Bean
fun retryTemplate(retryProps: RetryProps): RetryTemplate =
RetryTemplate().apply {
setBackOffPolicy(
ExponentialBackOffPolicy().apply {
initialInterval = retryProps.initialDelay
}
)
setRetryPolicy(
SimpleRetryPolicy(
retryProps.maxAttempts
)
)
}
}
@ConstructorBinding
@ConfigurationProperties("reporting.app.retry")
data class RetryProps(
val maxAttempts: Int,
val initialDelay: Long,
)
@JobScope
@Component
class MyTasklet(
private val retryTemplate: RetryTemplate, // (*)
private val myService: MyServiceUsesSpringDataJpa,
) : Tasklet {
override fun execute(contribution: StepContribution, chunkContext: ChunkContext): RepeatStatus? = run {
val jobId = chunkContext.stepContext.jobInstanceId
println("Try executing MyTasklet(jobId=$jobId)")
val result = retryTemplate.execute<MyData, Throwable> { // (*)
println("A try:")
myService.writableMethod(jobId, myData)
}
println("A try result: $result")
RepeatStatus.FINISHED
}
}
@StepScope
@Component
class EnrichUsersDataProcessor(private val myClient: MyClient) : ItemProcessor<MyData, MyData> {
@Retryable // (*)
override fun process(item: MyData): MyData =
myClient.getData(item.id).run {
item.copy(
fullName = "$firstName $lastName",
)
}
}
But: If any method in retry is market with @Transactional annotation, then make sure you have done it like so:
@Service
@Transactional(readOnly = true, propagation = REQUIRES_NEW)
class MyServiceUsesSpringDataJpa(val myRepository: MySpringDataJpaRepository) {
@Transactional(readOnly = false, propagation = REQUIRES_NEW)
fun writableMethod(/*...*/): MyData =
myRepository.save(/*...*/) // saveAll(/*...*/) // deleteAll() // etc...
fun readableMethod(/*...*/): List<MyData> =
myRepository.findAll() // findById(/*...*/) // count() // etc...
}
Transaction propagation must be REQUIRED_NEW
rm -rf ~/.m2/repository/com/github/daggerok
mvn clean package install
mvn spring-boot:start -f apps/user-service
mvn spring-boot:start -f apps/payment-service
mvn spring-boot:start -f apps/app
http post :8080/api/launch-payments-report ; sleep 20s ; http get :8080/api
mvn spring-boot:stop -f apps/app
mvn spring-boot:stop -f apps/user-service
mvn spring-boot:stop -f apps/payment-service
cat ./apps/app/target/payments-report.csv