agentleFS
piominpiomin/claude-ai-quarkus/skills/quarkus/SKILL.md

quarkus

Skill7 starsChanged 24 days agoApache-2.0View on GitHub

Quarkus development - REST APIs, Panache, Security, Testing, and Cloud-native patterns. Use for building enterprise Java applications with Quarkus.

1 other project uses a version of this.

Adopted by

Most recently taken up by

  • Other versions1 project uses a version of this.

    Word for word · 0

    None found.

    Edited · 0

    None found.

    Wrote their own version · 1

    1. Mindrally/skills★ 275same name

    How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.

  • In this repository6 other files it gives its agents.

The file

We split this skill into the rules it gives an agent

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

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈2

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 2

    Very specific

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

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Secure: - Add Quarkus Security (OIDC/JWT), method security.

    line 22
  2. Very specific:

    Test: - Write unit tests and @QuarkusTest integration tests.

    line 23
  3. Distinctive:

    Use case driven design

    line 225
  4. Very specific:

    Don't copy a request-scoped value (e.g.

    line 251

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill 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
SKILL.md

Quarkus Skill

Enterprise Quarkus development with focus on clean architecture and production-ready, cloud-native (and optionally native-image-compilable) code.

Core Workflow

  1. Analyze - Understand requirements, identify service boundaries, APIs, data models
  2. Design - Plan architecture, confirm design before coding
  3. Implement - Build with constructor injection and layered architecture
  4. Secure - Add Quarkus Security (OIDC/JWT), method security; verify tests pass
  5. Test - Write unit tests and @QuarkusTest integration tests; run ./mvnw test and confirm all pass
  6. Deploy - Health checks come from SmallRye Health automatically; validate /q/health returns UP

Quick Start Templates

Entity (Panache)

@Entity
@Table(name = "products")
public class Product extends PanacheEntity {

    @NotBlank
    public String name;

    @DecimalMin("0.0")
    public BigDecimal price;

    // Panache active-record entities use public fields instead of getters/setters -
    // that's Panache's own boilerplate removal, not a "skip validation" shortcut.
}

Repository

@ApplicationScoped
public class ProductRepository implements PanacheRepository<Product> {

    public List<Product> findByNameContainingIgnoreCase(String name) {
        return find("lower(name) like ?1", "%" + name.toLowerCase() + "%").list();
    }
}

Service

@ApplicationScoped
public class ProductService {
    private final ProductRepository repo;

    public ProductService(ProductRepository repo) {
        this.repo = repo;
    }

    public List<ProductResponse> search(String name) {
        return repo.findByNameContainingIgnoreCase(name).stream()
            .map(ProductResponse::from)
            .toList();
    }

    @Transactional
    public ProductResponse create(ProductRequest request) {
        var product = new Product();
        product.name = request.name();
        product.price = request.price();
        repo.persist(product);
        return ProductResponse.from(product);
    }
}

REST Resource

@Path("/api/v1/products")
public class ProductResource {
    private final ProductService service;

    public ProductResource(ProductService service) {
        this.service = service;
    }

    @GET
    public List<ProductResponse> search(@QueryParam("name") @DefaultValue("") String name) {
        return service.search(name);
    }

    @POST
    @Status(201)
    public ProductResponse create(@Valid ProductRequest request) {
        return service.create(request);
    }
}

DTOs (Records)

public record ProductRequest(
    @NotBlank String name,
    @DecimalMin("0.0") BigDecimal price
) {}

public record ProductResponse(Long id, String name, BigDecimal price) {
    public static ProductResponse from(Product product) {
        return new ProductResponse(product.id, product.name, product.price);
    }
}

Global Exception Handler

@Provider
public class GlobalExceptionMapper implements ExceptionMapper<Exception> {

    @Override
    public Response toResponse(Exception ex) {
        return switch (ex) {
            case ConstraintViolationException e -> Response.status(400)
                .entity(Map.of("errors", e.getConstraintViolations().stream()
                    .collect(Collectors.toMap(
                        v -> v.getPropertyPath().toString(),
                        v -> v.getMessage() != null ? v.getMessage() : "Invalid"))))
                .build();
            case EntityNotFoundException e -> Response.status(404)
                .entity(Map.of("error", e.getMessage()))
                .build();
            default -> Response.status(500)
                .entity(Map.of("error", "Unexpected error"))
                .build();
        };
    }
}

Test Slice

@QuarkusTest
class ProductResourceTest {

    @InjectMock
    ProductService service;

    @Test
    void createProduct_validRequest_returns201() {
        var response = new ProductResponse(1L, "Widget", new BigDecimal("10.00"));
        when(service.create(any())).thenReturn(response);

        given()
            .contentType(ContentType.JSON)
            .body("""
                {"name":"Widget","price":10.0}
                """)
            .when().post("/api/v1/products")
            .then()
                .statusCode(201)
                .body("name", is("Widget"));
    }
}

Reference Guide

Load detailed patterns based on context:

TopicReferenceWhen to Load
Web/RESTreferences/web.mdJAX-RS resources, validation, exception handling, REST clients
Data Accessreferences/data.mdPanache, repositories, transactions, queries
Securityreferences/security.mdQuarkus Security, OIDC, JWT, method security, Keycloak Dev Services
Cloud/Configreferences/cloud.mdService discovery (Stork), resilience, virtual threads, HTTP clients, native image, OTel tracing
Testingreferences/testing.mdUnit, integration tests, RestAssured, Dev Services

For deeper, standalone dives also available as separate skills in this plugin: jpa-patterns, testing-patterns, java-modern, design-patterns, code-quality, logging-patterns.

Constraints

MUST DO

  • Constructor injection, with a single constructor (CDI/ArC picks it up automatically — @Inject on it is never needed)
  • @Valid on request parameters/bodies
  • @Transactional for multi-step writes
  • Skip @Transactional on simple single reads — Quarkus's @Transactional has no readOnly attribute
  • Type-safe config with @ConfigMapping
  • Global exception handling with a @Provider-annotated ExceptionMapper
  • Externalize secrets (environment variables or mounted files, not properties files)

MUST NOT DO

  • Field injection (@Inject on fields)
  • Skip input validation on endpoints
  • Mix blocking (@RunOnVirtualThread/plain) and Mutiny-reactive return types in the same resource without a clear reason
  • Store secrets in application.properties
  • Hardcode URLs, credentials, environment values, or a group ID/package convention the project doesn't already use

Architecture Patterns

Project Structure:

src/main/java/<base-package>/
├── resource/    # JAX-RS endpoints
├── service/     # Business logic
├── repository/  # Data access (Panache)
├── entity/      # Panache/JPA entities
├── dto/         # Request/Response DTOs
├── config/      # @ConfigMapping interfaces
└── exception/   # Custom exceptions + ExceptionMapper

Layering:

  • Resource → Service → Repository
  • Resource handles HTTP, validation
  • Service handles business logic, transactions
  • Repository handles data persistence

Clean Architecture Principles:

  • Domain models independent of frameworks
  • Use case driven design
  • Dependency inversion (interfaces)
  • Clear boundaries between layers

Common Annotations

AnnotationPurpose
@Path / @GET/@POST/...JAX-RS resource and HTTP method mapping
@ApplicationScopedCDI singleton-scoped bean (services, repositories)
@TransactionalTransaction management (jakarta.transaction.Transactional)
@ValidTrigger Bean Validation
@ConfigMappingBind a group of properties to a type-safe interface
@RolesAllowedMethod/class-level role-based access control

CDI Scopes and Pitfalls

ScopeClient proxy?Notes
@ApplicationScopedYes (lazy)Default for services and repositories; mockable with @InjectMock
@SingletonNoSlightly cheaper; without a proxy the instance is created as soon as it is injected; not mockable with @InjectMock by default
@RequestScopedYesSafe to inject into an @ApplicationScoped bean — the proxy resolves the current request's instance
@DependentNoNew instance per injection point, bound to the owner's lifecycle
  • Creating a bean with new bypasses CDI: no injection and no interceptors (@Transactional, @Timed, ...). Fine in a plain unit test, wrong in production code.
  • @ApplicationScoped/@Singleton beans are shared across threads — keep them stateless, or make shared state thread-safe.
  • Don't copy a request-scoped value (e.g. identity.getPrincipal()) into a field of an application-scoped bean; inject the proxy and read it per call.
  • Several implementations of one type, or lazy lookup: inject @Any Instance<T>.
  • Quarkus removes unused beans at build time; a bean looked up only dynamically (e.g. CDI.current().select(...)) needs @Unremovable.
  • Startup work: observe StartupEvent (void onStart(@Observes StartupEvent e)) or annotate the bean with @Startup.

Reactive Resource (Mutiny)

@Path("/api/v1/orders")
public class OrderResource {
    private final OrderService orderService;

    public OrderResource(OrderService orderService) {
        this.orderService = orderService;
    }

    @GET
    @Path("/{id}")
    public Uni<Response> getOrder(@PathParam("id") UUID id) {
        return orderService.findById(id)
            .map(order -> Response.ok(order).build())
            .onItem().ifNull().continueWith(Response.status(404).build());
    }

    @POST
    public Uni<OrderDto> createOrder(@Valid CreateOrderRequest request) {
        return orderService.create(request);
    }
}

RestAssured tests this resource exactly like a blocking one — no separate reactive test client is needed, since it just drives real HTTP calls regardless of what runs behind the endpoint (see references/testing.md).

Quarkus Security — JWT

# application.properties - validate bearer tokens, no custom filter needed
mp.jwt.verify.publickey.location=publicKey.pem
mp.jwt.verify.issuer=https://issuer.example.com
quarkus.http.auth.permission.public.paths=/q/health/*,/api/v1/auth/*
quarkus.http.auth.permission.public.policy=permit
@Path("/api/v1/orders")
public class OrderResource {

    @GET
    @RolesAllowed("USER")
    public List<OrderDto> listMine(@Context SecurityContext ctx) {
        String username = ctx.getUserPrincipal().getName();
        // ...
    }

    @DELETE
    @Path("/{id}")
    @RolesAllowed("ADMIN")
    public void delete(@PathParam("id") Long id) { /* ... */ }
}

quarkus-smallrye-jwt validates the Authorization: Bearer header declaratively from the extension/config above — there is no Java security configuration class to write (see references/security.md).

Knowledge Base

Quarkus, Java 21+, Jakarta REST (Quarkus REST), Hibernate ORM with Panache, Quarkus Security, OIDC/JWT (SmallRye JWT), Hibernate, Mutiny, SmallRye Reactive Messaging, SmallRye Fault Tolerance, SmallRye Stork, Micrometer, OpenTelemetry, JUnit 5, RestAssured, Mockito, Maven, GraalVM Native Image, Podman/Docker/Jib, Kubernetes/OpenShift/Knative extensions

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.