# 5. Retry and transactions [← 4. @ConcurrencyLimit](04-concurrency-limit.md) · [Index](../README.md) · Next: [6. What is left for Resilience4j →](06-what-is-left-for-resilience4j.md) [`StockWriter.record`](../src/main/java/com/ankurm/resilience/tx/StockWriter.java) is `@Retryable @Transactional`, inserts a row, and fails twice. ## Which interceptor is outside `RetryAnnotationBeanPostProcessor`'s constructor calls `setBeforeExistingAdvisors(true)` (`javap -c` on spring-context 7.0.9). The transaction advisor is applied first by the auto-proxy creator; the retry advisor is then inserted at index 0 ([`proxy-stock-writer.txt`](output/proxy-stock-writer.txt)). The `order` attribute of `@EnableResilientMethods` is the post-processor's order, not the advice's position, and does not change this. ## Alone: each attempt is its own transaction [`tx-standalone.txt`](output/tx-standalone.txt) - three connection holders, one row: ``` "attempts": [ "attempt 1: transaction active=true, connection holder @6aa73704", "attempt 2: transaction active=true, connection holder @1978b580", "attempt 3: transaction active=true, connection holder @7d5534c2" ], "rows in stock_movement": 1 ``` This is what you want: the failed attempts rolled back their inserts. ## Called from inside a transaction: the retry cannot help [`OrderFacade.placeOrder`](../src/main/java/com/ankurm/resilience/tx/OrderFacade.java) is `@Transactional` and calls the same method ([`tx-joined.txt`](output/tx-joined.txt)): ``` "caller got": "org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only", "attempts": [ "attempt 1: transaction active=true, connection holder @6135f416", "attempt 2: transaction active=true, connection holder @6135f416", "attempt 3: transaction active=true, connection holder @6135f416" ], "rows in stock_movement": 0 ``` Every attempt joins the outer transaction (`REQUIRED`). The first failure passes through the inner `TransactionInterceptor`, which marks the *shared* transaction rollback-only. The third attempt succeeds, the retry returns normally, and the outer commit throws. Three attempts, zero rows, an exception the caller did not expect. The retry belongs at the outermost transactional boundary - or the inner method needs `REQUIRES_NEW`. The [@Transactional article](https://ankurm.com/transactional-propagation-isolation-silent-failures/) covers the rollback-only mechanics.