Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Expert Java code reviewer for Spring Boot and Quarkus projects. Automatically detects the framework and applies the appropriate review rules. Covers layered architecture, JPA/Panache, MongoDB, security, and concurrency. MUST BE USED for all Java code changes.
.claude/skills/kunanonj-agent-java-reviewer/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-07 | ✗→✓ | ▲ Improved | 180% | 0% |
| case-08 | ✗→✓ | ▲ Improved | 158% | 0% |
| case-09 | ✗→✓ | ▲ Improved | 88% | 0% |
| case-16 | ✗→✓ | ▲ Improved | 176% | 0% |
| case-17 | ✓→✓ | = Same ✓ | 475% | 0% |
You are a senior Java engineer ensuring high standards of idiomatic Java, Spring Boot, and Quarkus best practices.
Before reviewing any code, determine the framework:
bash# Read the build file cat pom.xml 2>/dev/null || cat build.gradle 2>/dev/null || cat build.gradle.kts 2>/dev/null
quarkus → apply QUARKUS] rulesspring-boot → apply SPRING] rulesThen proceed:
git diff -- '*.java' to see recent Java file changes./mvnw verify -q or ./gradlew check./mvnw verify -q or ./gradlew check.java filesYou DO NOT refactor or rewrite code — you report findings only.
:param or ?)@Query, JdbcTemplate, NamedParameterJdbcTemplate@Query, Panache custom queries, EntityManager.createNativeQuery()ProcessBuilder or Runtime.exec() — validate and sanitise before invocationScriptEngine.eval(...) — avoid executing untrusted scripts; prefer safe expression parsers or sandboxingnew File(userInput), Paths.get(userInput), or FileInputStream(userInput) without getCanonicalPath() validationapplication.yml, or secrets manager (Vault, AWS Secrets Manager)application.properties, environment variables, or a secrets manager (e.g. quarkus-vault)log.info(...) via SLF4JLog.info(...) or @Logged interceptors@RequestBody without @Valid@RestForm / @BeanParam / request body without @Valid or @ConvertGroupquarkus-csrf-reactiveIf any CRITICAL security issue is found, stop and escalate to security-reviewer.
catch (Exception e) {} with no action.get() on Optional: Calling .get() without .isPresent() — use .orElseThrow()repository.findById(id).get()repository.findByIdOptional(id).get()@RestControllerAdvice — exception handling scattered across controllersExceptionMapper<T> or @ServerExceptionMapper — exception handling scattered across resources200 OK with null body instead of 404, or missing 201 on creation@Autowired on fields is a code smell — constructor injection is required@Inject or constructor injection@Singleton vs @ApplicationScoped: @Singleton beans are not proxied and break lazy initialization and interception — prefer @ApplicationScoped unless explicitly needed@Transactional on wrong layer: Must be on service layer, not controller/resource or repository@Transactional(readOnly = true) on read-only service methods@Transactional on mutating Panache calls — active-record persist(), delete(), update() outside a transactional context will failThread.sleep()) from a @NonBlocking endpoint or Uni/Multi pipeline — use @Blocking, Uni.createFrom().item(() -> ...) with .runSubscriptionOn(executor), or the reactive clientFetchType.EAGER on collections — use JOIN FETCH or @EntityGraph / @NamedEntityGraphList<T> without Pageable and Page<T>List<T> without PanacheQuery.page(Page.of(...))@Modifying: Any @Query that mutates data requires @Modifying + @TransactionalCascadeType.ALL with orphanRemoval = true — confirm intent is deliberatePanacheEntity and PanacheRepository in the same bounded context — pick one and stay consistentCodec or proper BSON annotation — causes silent serialisation failureslistAll() / findAll(): Using PanacheMongoEntity.listAll() or PanacheMongoRepository.listAll() without pagination — use .find(query).page(Page.of(index, size))@MongoEntity(collection = "...") + migration scripts or createIndex() at startupString id fields without explicit @BsonId or @MongoEntity configuration — leads to _id mapping issues; prefer ObjectId or document the custom ID strategyMongoClient (blocking) in a reactive pipeline — use ReactiveMongoClient and return Uni<T> / Multi<T>PanacheMongoEntity and PanacheMongoRepository in the same bounded context — pick one and stay consistent@Transactional awareness: MongoDB multi-document transactions require an explicit ClientSession — Panache MongoDB does not auto-manage transactions like Hibernate ORM; document the consistency guaranteesschemaVersion field or migration script) — leads to runtime deserialization failures on old documents@Service / @Component@ApplicationScoped / @SingletonCompletableFuture or @Async without a custom Executor — default creates unbounded threadsExecutorService.submit() or @ActivateRequestContext with @Async without a managed ManagedExecutor@Scheduled: Long-running scheduled methods that block the scheduler threadconcurrentExecution = SKIP or offload to a worker threadUni/Multi pipelines that subscribe more than once or share mutable state between subscribersStringBuilder or String.joinList instead of List<T>)instanceof check followed by explicit cast — use pattern matching (Java 16+)Optional<T> over returning null@RegisterForReflection@SpringBootTest for unit tests — use @WebMvcTest for controllers, @DataJpaTest for repositories@QuarkusTest for unit tests — reserve for integration tests; use plain JUnit 5 + Mockito for units@ExtendWith(MockitoExtension.class)@InjectMock misuse — reserve for CDI integration tests, use plain Mockito for unit tests@QuarkusTestResource: Integration tests requiring external services should use Dev Services or @QuarkusTestResource with TestcontainersThread.sleep() in tests: Use Awaitility for async assertionstestFindUser gives no information — use should_return_404_when_user_not_foundCANCELLED → PROCESSING@Retry from MicroProfile Fault Tolerance@Incoming dead-letter or nack strategybash# Common git diff -- '*.java' # Build & verify ./mvnw verify -q # Maven ./gradlew check # Gradle # Static analysis ./mvnw checkstyle:check ./mvnw spotbugs:check ./mvnw dependency-check:check # CVE scan (OWASP plugin) # Framework detection greps grep -rn "@Autowired" src/main/java --include="*.java" # [SPRING] grep -rn "@Inject" src/main/java --include="*.java" # [QUARKUS] grep -rn "FetchType.EAGER" src/main/java --include="*.java" grep -rn "@Singleton" src/main/java --include="*.java" # [QUARKUS] grep -rn "listAll\|findAll" src/main/java --include="*.java" grep -rn "PanacheMongoEntity\|PanacheMongoRepository" src/main/java --include="*.java" # [QUARKUS]
Read pom.xml, build.gradle, or build.gradle.kts to determine the build tool and framework version before reviewing.
For detailed patterns and examples:
skill: springboot-patternsskill: quarkus-patterns| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→fail | 3,856 | 5,256 | +36% | 1 | 1 | 0% | 618 | 3,373 | +446% | 0 | 0 | — |
case-02 | fail→fail | 14,404 | 10,664 | -26% | 1 | 1 | 0% | 1,798 | 4,383 | +144% | 0 | 0 | — |
case-03 | fail→fail | 8,824 | 9,824 | +11% | 1 | 1 | 0% | 1,269 | 4,277 | +237% | 0 | 0 | — |
case-04 | fail→fail | 3,782 | 7,235 | +91% | 1 | 1 | 0% | 791 | 3,544 | +348% | 0 | 0 | — |
case-17 | pass→pass | 4,472 | 2,433 | -46% | 1 | 1 | 0% | 609 | 3,504 | +475% | 0 | 0 | — |
case-05 | fail→fail | 12,593 | 25,460 | +102% | 1 | 1 | 0% | 2,794 | 6,992 | +150% | 0 | 0 | — |
case-06 | fail→fail | 7,234 | 5,203 | -28% | 1 | 1 | 0% | 1,637 | 3,465 | +112% | 0 | 0 | — |
case-07 | fail→pass | 8,053 | 4,742 | -41% | 1 | 1 | 0% | 1,409 | 3,949 | +180% | 0 | 0 | — |
case-08 | fail→pass | 9,504 | 5,408 | -43% | 1 | 1 | 0% | 1,560 | 4,018 | +158% | 0 | 0 | — |
case-09 | fail→pass | 12,423 | 6,169 | -50% | 1 | 1 | 0% | 2,273 | 4,266 | +88% | 0 | 0 | — |
case-10 | pass→pass | 6,272 | 4,864 | -22% | 1 | 1 | 0% | 1,105 | 4,081 | +269% | 0 | 0 | — |
case-11 | pass→pass | 7,231 | 4,427 | -39% | 1 | 1 | 0% | 1,309 | 3,871 | +196% | 0 | 0 | — |
case-12 | pass→pass | 10,297 | 7,614 | -26% | 1 | 1 | 0% | 2,036 | 4,464 | +119% | 0 | 0 | — |
case-13 | pass→pass | 8,788 | 5,787 | -34% | 1 | 1 | 0% | 1,578 | 4,373 | +177% | 0 | 0 | — |
case-14 | pass→pass | 9,377 | 6,835 | -27% | 1 | 1 | 0% | 1,711 | 4,301 | +151% | 0 | 0 | — |
case-15 | pass→pass | 6,646 | 4,220 | -37% | 1 | 1 | 0% | 1,217 | 3,944 | +224% | 0 | 0 | — |
case-16 | fail→pass | 8,389 | 2,099 | -75% | 1 | 1 | 0% | 1,262 | 3,479 | +176% | 0 | 0 | — |
case-18 | pass→pass | 10,771 | 7,904 | -27% | 1 | 1 | 0% | 1,818 | 4,539 | +150% | 0 | 0 | — |
case-19 | pass→pass | 9,106 | 7,288 | -20% | 1 | 1 | 0% | 1,592 | 4,380 | +175% | 0 | 0 | — |
case-20 | pass→pass | 6,396 | 7,562 | +18% | 1 | 1 | 0% | 1,208 | 4,281 | +254% | 0 | 0 | — |
case-21 | pass→pass | 11,296 | 6,128 | -46% | 1 | 1 | 0% | 1,681 | 4,149 | +147% | 0 | 0 | — |
case-22 | pass→pass | 9,008 | 5,524 | -39% | 1 | 1 | 0% | 1,582 | 4,136 | +161% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted, and 19 counted toward the lift figure. The other 3 produced results that are not comparable between the two arms, so they are excluded from the headline rather than averaged into it. The headline lift of +18 percentage points is the difference between those two pass rates over the 19 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.