$npx -y skills add ducpm2303/claude-java-plugins --skill java-resilienceUse when the user asks to add resilience patterns, handle service failures, implement circuit breaker, retry, rate limiter, bulkhead, or timeout in a Spring Boot project using Resilience4J.
| 1 | # Resilience4J Skill |
| 2 | |
| 3 | Detect the existing setup, then apply the correct pattern. |
| 4 | |
| 5 | ## Step 1 — Detect setup |
| 6 | |
| 7 | Check `pom.xml` or `build.gradle`: |
| 8 | - `resilience4j-spring-boot3` → Spring Boot 3.x (use `io.github.resilience4j:resilience4j-spring-boot3`) |
| 9 | - `resilience4j-spring-boot2` → Spring Boot 2.x |
| 10 | - `spring-cloud-starter-circuitbreaker-resilience4j` → Spring Cloud Circuit Breaker abstraction |
| 11 | - None present → offer to add (recommend `resilience4j-spring-boot3` for Boot 3.x) |
| 12 | |
| 13 | Check Java version: Java 17+ enables records for fallback DTOs; Java 8+ supported throughout. |
| 14 | |
| 15 | --- |
| 16 | |
| 17 | ## Mode: `review` |
| 18 | |
| 19 | User asks to review existing Resilience4J config. Check for: |
| 20 | |
| 21 | - [ ] Circuit breaker thresholds are tuned — `slidingWindowSize`, `failureRateThreshold`, `waitDurationInOpenState` set explicitly (not defaults) |
| 22 | - [ ] `slowCallDurationThreshold` and `slowCallRateThreshold` configured — slow calls should also trip the breaker |
| 23 | - [ ] Fallback methods match the same signature as the guarded method (same return type + `Throwable` param) |
| 24 | - [ ] `@CircuitBreaker` and `@Retry` not stacked without `fallbackMethod` on the outer annotation — will swallow exceptions silently |
| 25 | - [ ] Retry has `ignoreExceptions` for business errors (e.g. `IllegalArgumentException`, `EntityNotFoundException`) — don't retry 4xx errors |
| 26 | - [ ] `RateLimiter` uses `limitForPeriod` appropriate for downstream SLA — not an arbitrary number |
| 27 | - [ ] Bulkhead `maxConcurrentCalls` sized against thread pool or reactive scheduler |
| 28 | - [ ] Actuator endpoints exposed: `management.endpoints.web.exposure.include=health,circuitbreakers,retries,ratelimiters` |
| 29 | - [ ] Circuit breaker state changes logged via `CircuitBreakerEvent` listener — not silent |
| 30 | - [ ] No `@Retry` on `@Transactional` methods — retries after a rolled-back transaction reopen a new transaction |
| 31 | |
| 32 | --- |
| 33 | |
| 34 | ## Mode: `circuit-breaker` |
| 35 | |
| 36 | User asks to add a circuit breaker to protect a downstream call. |
| 37 | |
| 38 | 1. Add dependency (see `references/patterns.md` → Setup) |
| 39 | 2. Configure in `application.yml` — set `sliding-window-size`, `failure-rate-threshold`, `wait-duration-in-open-state` |
| 40 | 3. Annotate the method with `@CircuitBreaker(name = "serviceName", fallbackMethod = "fallback")` |
| 41 | 4. Write the fallback method — same return type, extra `Throwable` parameter |
| 42 | 5. Expose circuit breaker health: `management.health.circuitbreakers.enabled=true` |
| 43 | 6. Add event listener to log state transitions (CLOSED→OPEN→HALF_OPEN) |
| 44 | |
| 45 | Version note: |
| 46 | - Spring Boot 3.x → `resilience4j-spring-boot3` |
| 47 | - Spring Boot 2.x → `resilience4j-spring-boot2` |
| 48 | |
| 49 | --- |
| 50 | |
| 51 | ## Mode: `retry` |
| 52 | |
| 53 | User asks to add automatic retry for flaky remote calls. |
| 54 | |
| 55 | 1. Configure retry in `application.yml` — `max-attempts`, `wait-duration`, `exponential-backoff-multiplier` |
| 56 | 2. Set `ignore-exceptions` for non-retryable errors (validation errors, 4xx responses) |
| 57 | 3. Set `retry-exceptions` explicitly (e.g. `IOException`, `TimeoutException`) |
| 58 | 4. Annotate with `@Retry(name = "serviceName", fallbackMethod = "fallback")` |
| 59 | 5. For HTTP clients: check response status before retrying — use `retryOnResultPredicate` to retry on 5xx, not 4xx |
| 60 | 6. Warn if stacking with `@CircuitBreaker` — retry fires first, circuit breaker wraps it; set `retry.max-attempts` lower than circuit breaker `sliding-window-size` |
| 61 | |
| 62 | --- |
| 63 | |
| 64 | ## Mode: `rate-limiter` |
| 65 | |
| 66 | User asks to limit how often a method can be called (outgoing rate limiting or incoming API protection). |
| 67 | |
| 68 | 1. Configure `limit-for-period` (requests per window), `limit-refresh-period`, `timeout-duration` |
| 69 | 2. Annotate with `@RateLimiter(name = "serviceName", fallbackMethod = "fallback")` |
| 70 | 3. For incoming API protection: place on controller method or use a filter |
| 71 | 4. For outgoing: place on the service/client method calling the downstream |
| 72 | |
| 73 | --- |
| 74 | |
| 75 | ## Mode: `bulkhead` |
| 76 | |
| 77 | User asks to limit concurrent calls to isolate failures (prevent thread starvation). |
| 78 | |
| 79 | Two types — choose based on context: |
| 80 | - **Semaphore bulkhead** (default): limits concurrent calls via a counter — lightweight, same thread pool |
| 81 | - **ThreadPool bulkhead**: executes in a dedicated pool — true isolation, for blocking I/O |
| 82 | |
| 83 | Configure `max-concurrent-calls` and `max-wait-duration` (semaphore) or pool size (thread pool). |
| 84 | Annotate with `@Bulkhead(name = "serviceName", type = Bulkhead.Type.SEMAPHORE)`. |
| 85 | |
| 86 | --- |
| 87 | |
| 88 | ## Mode: `timeout` |
| 89 | |
| 90 | User asks to add a timeout to a method. |
| 91 | |
| 92 | 1. Use `@TimeLimiter` for reactive/async methods (returns `CompletableFuture` or `Flux`/`Mono`) |
| 93 | 2. For blocking methods: use `@CircuitBreaker` with `slowCallDurationThreshold` instead |
| 94 | 3. Configure `timeout-duration` in `application.yml` |
| 95 | 4. `@TimeLimiter` requires the metho |