agentleFS
AlessandroMartiniAlessandroMartini/Awesome_IA_Rules/.cursor/rules/backend/java-quarkus-backend.mdc

Awesome_IA_Rules / backend

Cursor rule1 starsChanged 3 days agoMITView on GitHub

Java 21+ and Quarkus backend standards, Hexagonal Architecture, CDI, Panache, Virtual Threads, and testing

The file

Show its rules and text

We split this java-quarkus-backend.mdc into the rules it gives an agent

15 rules. About 0 are common, 0 are distinctive, and 15 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈0

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 15

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Java Records for Immutability: Use record for all Value Objects, Commands, Queries, Request/Response DTOs, and Domain Events.

    line 41
  2. Very specific:

    Sealed Interfaces & Pattern Matching: Use sealed interface and exhaustive switch expressions for domain states, payment methods, or typed …

    line 56
  3. Very specific:

    Null Safety: Never return null from collections (return List.of()) or optional lookups (return Optional<T>).

    line 58
  4. Very specific:

    Constructor Injection Only: Always use constructor injection with final fields.

    line 65
  5. Very specific:

    Keep the domain package free of CDI annotations where possible, or wire domain services via @Produces in an infrastructure configuration …

    line 69
  6. Very specific:

    Prefer @ConfigMapping(prefix = "app.payment") interfaces over scattered @ConfigProperty annotations to group and validate configuration at …

    line 72
  7. Very specific:

    Avoid dynamic reflection (Class.forName, MethodHandles), runtime bytecode generation, or unannotated serialization classes.

    line 84
  8. Very specific:

    If a third-party DTO requires reflection in GraalVM native mode, annotate with @RegisterForReflection.

    line 85
  9. Very specific:

    Strict Separation: Never annotate Domain Entities with @Entity or @Table.

    line 92
  10. Very specific:

    Transaction Boundaries: Place @Transactional at the Application Command Handler boundary (execute method).

    line 94
  11. Very specific:

    Prevent N+1 Queries: Use FetchType.LAZY on all associations (@ManyToOne, @OneToMany) by default, and use explicit JOIN FETCH queries or …

    line 95
  12. Very specific:

    Test Domain Entities, Value Objects, Domain Services, and Application Handlers using plain JUnit 5 + Mockito + AssertJ …

    line 111
  13. Very specific:

    Do not boot @QuarkusTest for domain or application unit tests—keep unit test execution under milliseconds.

    line 112
  14. Very specific:

    Use @QuarkusTest with RestAssured and Quarkus Dev Services / Testcontainers for REST entrypoints, database repositories, and messaging …

    line 114
  15. Very specific:

    Use @InjectMock sparingly, only for external outbound boundaries.

    line 115

≈ “Common” is an estimate: at least 1 in 5 of the 6,668 Cursor rule files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
java-quarkus-backend.mdc
---
description: "Java 21+ and Quarkus backend standards, Hexagonal Architecture, CDI, Panache, Virtual Threads, and testing"
globs: "**/*.java"
alwaysApply: false
---

# Java & Quarkus Backend Engineering Standards

> **Scope**: All Java (`*.java`) source, test, and configuration (`application.properties` / `application.yaml`) files.
> **Mandate**: Build cloud-native, GraalVM native-image compatible, high-throughput applications using Modern Java (21+) and Quarkus build-time optimization principles within a Clean/Hexagonal Architecture.

---

## 1. Project Structure & Hexagonal Architecture

Maintain strict inward dependency flow: `infrastructure/entrypoint → application → domain`.

```text
src/main/java/com/acme/service/
├── domain/                         # Pure Java (Zero Quarkus/JPA/Jackson annotations)
│   ├── model/                      # Entities, Aggregate Roots, Value Objects (Records)
│   ├── exception/                  # Semantic Domain Exceptions (Conflict, Validation, NotFound)
│   ├── service/                    # Stateless cross-entity Domain Services
│   └── port/                       # Repository & Core Domain Capability interfaces
├── application/                    # Use Case Orchestration (CDI @ApplicationScoped)
│   ├── command/                    # Write Command Handlers & Command DTOs
│   ├── query/                      # Read Query Handlers & Read Models
│   └── port/                       # Outbound Gateway & Integration interfaces
└── infrastructure/                 # Quarkus & External Adapters
    ├── entrypoint/rest/            # Jakarta REST (@Path), Request/Response Records, ExceptionMappers
    ├── entrypoint/messaging/       # SmallRye Reactive Messaging consumers/producers
    ├── persistence/                # Panache/JPA Entities, Repositories, Entity Mappers
    ├── client/                     # Quarkus REST Client (@RegisterRestClient) & Adapters
    └── config/                     # @ConfigMapping typed configuration interfaces
```

---

## 2. Modern Java (Java 21+) Idioms

- **Java Records for Immutability**: Use `record` for all Value Objects, Commands, Queries, Request/Response DTOs, and Domain Events. Enforce compact constructor validation on Value Objects:
  ```java
  public record Money(BigDecimal amount, String currency) {
      public Money {
          Objects.requireNonNull(amount, "amount is required");
          Objects.requireNonNull(currency, "currency is required");
          if (amount.compareTo(BigDecimal.ZERO) <= 0) {
              throw new DomainValidationException("amount must be greater than zero");
          }
          if (currency.length() != 3) {
              throw new DomainValidationException("currency must be a 3-letter ISO code");
          }
      }
  }
  ```
- **Sealed Interfaces & Pattern Matching**: Use `sealed interface` and exhaustive `switch` expressions for domain states, payment methods, or typed outcomes instead of deep class hierarchies or `instanceof` chains.
- **Virtual Threads (`@RunOnVirtualThread`)**: For I/O-bound blocking workloads on Java 21+, prefer Quarkus Resteasy Reactive with `@RunOnVirtualThread` over complex reactive chains (`Uni`/`Multi`), unless true backpressure streaming is required. Avoid `synchronized` blocks around I/O to prevent carrier thread pinning (use `ReentrantLock` if needed).
- **Null Safety**: Never return `null` from collections (return `List.of()`) or optional lookups (return `Optional<T>`). Never pass `Optional` as a method parameter or field.

---

## 3. Quarkus & CDI Best Practices (Build-Time First)

### Dependency Injection (ArC)
- **Constructor Injection Only**: Always use constructor injection with `final` fields. Never use `@Inject` on fields or setters (breaks testability and immutability). Omit `@Inject` when a single constructor exists.
- **Explicit Bean Scopes**:
  - `@ApplicationScoped` for stateless use cases, adapters, and repositories.
  - `@RequestScoped` only when request-bound state is strictly necessary.
  - Keep the `domain` package free of CDI annotations where possible, or wire domain services via `@Produces` in an infrastructure configuration class.

### Typed Configuration
- Prefer `@ConfigMapping(prefix = "app.payment")` interfaces over scattered `@ConfigProperty` annotations to group and validate configuration at startup:
  ```java
  @ConfigMapping(prefix = "app.payment-gateway")
  public interface PaymentGatewayConfig {
      URI baseUrl();
      Duration timeout();
      @WithDefault("3")
      int maxRetries();
  }
  ```

### Native Image Compatibility
- Avoid dynamic reflection (`Class.forName`, MethodHandles), runtime bytecode generation, or unannotated serialization classes.
- If a third-party DTO requires reflection in GraalVM native mode, annotate with `@RegisterForReflection`.

---

## 4. Persistence, REST & Resilience

### Persistence (Hibernate ORM with Panache)
- **Strict Separation**: Never annotate Domain Entities with `@Entity` or `@Table`. Keep JPA/Panache entities (`*JpaEntity`) inside `infrastructure.persistence`, and map explicitly to/from Domain models (using MapStruct or dedicated static mappers).
- **Repository Pattern**: Implement `PanacheRepositoryBase<PaymentJpaEntity, UUID>` rather than the Active Record pattern to keep persistence logic testable and decoupled.
- **Transaction Boundaries**: Place `@Transactional` at the Application Command Handler boundary (`execute` method). Use `@Transactional(Transactional.TxType.SUPPORTS)` or read-only queries for read paths.
- **Prevent N+1 Queries**: Use `FetchType.LAZY` on all associations (`@ManyToOne`, `@OneToMany`) by default, and use explicit `JOIN FETCH` queries or projections (`project(ReadModel.class)`) when loading relations.

### REST Entrypoints & Error Handling (RFC 9457)
- Validate inbound DTOs at the REST boundary using Jakarta Bean Validation (`@Valid`, `@NotBlank`, `@Positive`, `@Size`).
- Implement a centralized `@ServerExceptionMapper` that maps Domain/Application exceptions and `ConstraintViolationException` to **RFC 9457 `ProblemDetails`** JSON responses (`type`, `title`, `status`, `detail`, `code`, `errors`).
- **Proximity Logging**: Log infrastructure/database/client failures once at the adapter/repository source using `org.jboss.logging.Logger` with MDC context (`traceId`, `entityId`). Never re-log in use cases or controllers, and never expose internal exception messages on `500 Internal Server Error`.

### Outbound Clients & Fault Tolerance
- Declare outbound HTTP integrations using `@RegisterRestClient` interfaces.
- Apply SmallRye Fault Tolerance annotations (`@Timeout`, `@Retry` with jitter, `@CircuitBreaker`) on idempotent outbound operations.

---

## 5. Testing Standards (JUnit 5, Mockito & QuarkusTest)

- **Fast Unit Tests (`*Test.java`)**:
  - Test Domain Entities, Value Objects, Domain Services, and Application Handlers using **plain JUnit 5 + Mockito + AssertJ** (`@ExtendWith(MockitoExtension.class)`).
  - Do **not** boot `@QuarkusTest` for domain or application unit tests—keep unit test execution under milliseconds.
- **Integration & Contract Tests (`*IT.java` / `*ResourceTest.java`)**:
  - Use `@QuarkusTest` with **RestAssured** and Quarkus Dev Services / Testcontainers for REST entrypoints, database repositories, and messaging adapters.
  - Use `@InjectMock` sparingly, only for external outbound boundaries.
- **Conventions**:
  - Naming: `should<ExpectedOutcome>_when<Condition>()`.
  - Structure: Strict **Arrange-Act-Assert (AAA)** with fluent test Builders (`PaymentTestBuilder`) and AssertJ assertions (`assertThat(...)`, `assertThatThrownBy(...)`).
  - Determinism: Inject `java.time.Clock` into domain/application classes instead of calling `Instant.now()` or `LocalDateTime.now()` directly.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.