import dev.caskeleton.adapter.outbound.persistence.api.PersistenceOperationName; import dev.caskeleton.adapter.outbound.persistence.api.error.JpaFailureContext; import dev.caskeleton.adapter.outbound.persistence.api.error.SerializationFailureException; import dev.caskeleton.adapter.outbound.persistence.api.transaction.*; import dev.caskeleton.adapter.outbound.persistence.transaction.*; import java.time.*; import java.util.concurrent.atomic.AtomicInteger; import org.springframework.transaction.*; import org.springframework.transaction.support.SimpleTransactionStatus; public class JpaCustomRetryPolicyProbe { public static void main(String[] args) { AtomicInteger customPolicyCalls = new AtomicInteger(); AtomicInteger workCalls = new AtomicInteger(); PlatformTransactionManager tm = new PlatformTransactionManager() { public TransactionStatus getTransaction(TransactionDefinition d) { return new SimpleTransactionStatus(true); } public void commit(TransactionStatus s) {} public void rollback(TransactionStatus s) {} }; Clock clock = Clock.fixed(Instant.parse("2026-08-29T00:00:00Z"), ZoneOffset.UTC); SpringJpaTransactionExecutor executor = new SpringJpaTransactionExecutor(tm, clock); JpaRetryPolicy custom = (failure, attempt) -> { customPolicyCalls.incrementAndGet(); return RetryDecision.fail("custom-policy-called"); }; FullTransactionRetryCoordinator coordinator = new FullTransactionRetryCoordinator( executor, custom, ignored -> {}, clock, Duration.ofSeconds(30), RetryEventListener.noop()); RetryProfile retry = RetryProfile.boundedContention("probe.write", 2); TransactionProfile profile = TransactionProfile.write("probe.write", Duration.ofSeconds(5)).withRetryProfile(retry); PersistenceOperationName operation = new PersistenceOperationName("probe.write"); try { coordinator.execute(operation, profile, () -> { int call = workCalls.incrementAndGet(); throw new SerializationFailureException( JpaFailureContext.retryable(operation, "40001", call, Duration.ZERO, null)); }); } catch (SerializationFailureException expected) { System.out.println("thrown=" + expected.category()); } System.out.println("customPolicyCalls=" + customPolicyCalls.get()); System.out.println("workCalls=" + workCalls.get()); } }