Featured resource
2026 Tech Forecast
2026 Tech Forecast

1,500+ tech insiders, business leaders, and Pluralsight Authors share their predictions on what’s shifting fastest and how to stay ahead.

Download the forecast
  • Lab
    • Libraries: If you want this lab, consider one of these libraries.
    • Core Tech
Labs

Guided: Building a Quarkus Microservice

Build a Quarkus Task Tracker microservice that uses CDI for dependency injection and Quarkus REST (JAX-RS) for CRUD endpoints. You will progressively add injection, scopes, producers/qualifiers, and REST annotations. Each task is validated by an incremental test.

Lab platform
Lab Info
Level
Beginner
Last updated
Apr 03, 2026
Duration
45m

Contact sales

By clicking submit, you agree to our Privacy Policy and Terms of Use, and consent to receive marketing emails from Pluralsight.
Table of Contents
  1. Challenge

    CDI Basics with @Inject (Wiring the Layers)

    In this step, you will connect the REST layer (resource) to a service, and the service to a repository using CDI.

    Key CDI Ideas

    • Contexts and Dependency Injection (CDI) is Quarkus' way of assembling application components.
    • @Inject marks an injection point where the container provides an instance.
    • Why it's better than new:
      • Centralizes lifecycle management
      • Supports interceptors/decorators
      • Simplifies testing and swapping implementations

    How to Think About the Layering

    • Resource: HTTP-facing (validation + mapping HTTP to service calls)
    • Service: business rules (what should happen)
    • Repository: data access (how it's stored)

    Your goal is to rely on CDI to connect these layers so that each class stays focused on its responsibility. CDI eliminates manual object construction and makes your components easier to test and evolve. @Inject expresses dependencies declaratively and lets the container manage lifecycles for you. Layering (resource → service → repository) keeps business logic out of your API layer. CDI injection ensures your repository can be swapped, decorated, or mocked more easily. info> This lab experience was developed by the Pluralsight team using Forge, an internally developed AI tool utilizing Gemini technology. All sections were verified by human experts for accuracy prior to publication. For issue reporting, please contact us.

  2. Challenge

    Bean Scopes and Lifecycle (State and Request Context)

    Why Scopes Matter in Microservices

    In a REST microservice, requests come in concurrently. CDI scopes determine:

    • Whether a bean instance is shared
    • How long it lives
    • Whether it can safely hold mutable state

    Common Scopes You'll Use

    • @ApplicationScoped: one instance per application (shared state; must be thread-safe)
    • @RequestScoped: one instance per HTTP request (great for request metadata)

    Lifecycle Callbacks

    • @PostConstruct runs after CDI creates your bean and injection is complete.
    • Use it for initialization that depends on the container lifecycle.

    Request-scoped beans are created per HTTP request and cleaned up automatically. They are useful for request metadata (correlation IDs, auth context, timing, etc.). Scope determines lifecycle and whether your state is shared. For an in-memory repository in a demo microservice, you typically want shared state across requests. Bean lifecycle hooks (like @PostConstruct) let you set up your internal state after CDI constructs the bean. This is safer than doing complex initialization in constructors, especially when injection is involved. Within a single request, you should use the same ID consistently. Two separate HTTP calls should yield different IDs.

  3. Challenge

    Producers and Qualifiers (Selecting and Constructing Beans)

    The Problem: Multiple Beans for One Interface

    When two implementations satisfy the same injection point, CDI needs help choosing.

    Qualifiers

    • A qualifier is a custom annotation you use to label beans.
    • Injection points request a specific label.

    Producers

    • A producer method lets CDI call your factory logic to create an object.
    • They are useful when:
      • The class is from a library you can't annotate
      • Creation depends on configuration
      • You want to centralize construction and keep injection points clean CDI needs a clear way to select which bean to inject when there are multiple candidates. Qualifiers make your intent explicit and keep wiring readable. Producers let you create objects that you can't annotate directly (third-party classes) or that need configuration-driven creation. They centralize your creation logic and keep injection points simple. Qualifiers only help if your injection points ask for them. This makes your service resilient if additional implementations are added later.
  4. Challenge

    JAX-RS CRUD Endpoints (Paths, Verbs, Parameters)

    REST Endpoints in Quarkus

    Quarkus exposes REST APIs using Jakarta REST (commonly referred to as JAX-RS).

    Core Annotations You'll Use

    • @Path: defines the URL path for a resource or method
    • @GET / @POST / @PUT / @DELETE: map HTTP verbs to Java methods
    • @PathParam: binds a path segment like /tasks/{id}

    REST Correctness Goals

    • Use the correct HTTP verb for the operation
    • Return meaningful status codes (200, 201, 204, 404)
    • Keep the resource thin by delegating to the service GET endpoints are the foundation of RESTful read operations. @Path and @GET define your resource routing; @PathParam binds URL segments. POST and PUT support the write side of CRUD. @Consumes and @Produces ensure correct JSON handling. Proper status codes (201, 200, 404) make your API predictable for clients. DELETE completes your CRUD. Returning appropriate status codes (204 vs 404) is a key REST detail.
  5. Challenge

    Query Params and Content Negotiation (Polishing the API)

    Optional Parameters with @QueryParam

    Query parameters provide optional behavior without changing your resource identity.

    • Example: /tasks?status=OPEN
    • If missing, your default behavior should be sensible.

    Content Types with @Produces and @Consumes

    • @Produces tells clients what your API returns (e.g., JSON).
    • @Consumes tells clients what your API accepts in the request body.

    Integration Thinking

    Once your individual methods work, you need confidence that CDI wiring selects the right beans, scopes behave correctly, and your REST endpoints interact correctly across operations. Unit tests validate individual tasks, but an integration test ensures everything works together and reduces deployment surprises for you. @QueryParam is how your REST API supports optional filters and projections. It enables clients to retrieve only relevant data without extra endpoints. @Produces and @Consumes communicate your API expectations. Consistency prevents hard-to-debug client/server mismatches. ### Try It Out

    Now that your microservice is complete, start it in dev mode and interact with it from the Terminal:

    ./mvnw quarkus:dev
    

    In the other TTerminal, try these commands:

    # List all tasks
    curl -s http://localhost:8080/tasks | jq
    
    # Create a new task
    curl -s -X POST http://localhost:8080/tasks 
      -H 'Content-Type: application/json' 
      -d '{"title":"Learn Quarkus","description":"Build a microservice"}' | jq
    
    # Filter tasks by status
    curl -s 'http://localhost:8080/tasks?status=OPEN' | jq
    
    # Update a task (replace <id> with an actual task ID)
    curl -s -X PUT http://localhost:8080/tasks/<id> 
      -H 'Content-Type: application/json' 
      -d '{"status":"DONE"}' | jq
    
    # Delete a task
    curl -s -X DELETE http://localhost:8080/tasks/<id> -w '\nHTTP %{http_code}\n'
    

    Press q in the dev mode Terminal to stop Quarkus.

    What You Built

    You implemented a complete Quarkus microservice using:

    • CDI (@Inject, @ApplicationScoped, @RequestScoped) for dependency injection and lifecycle management
    • Producers and Qualifiers (@Produces, @Qualifier) for configuration-driven bean selection
    • JAX-RS (@Path, @GET, @POST, @PUT, @DELETE, @QueryParam) for a full CRUD REST API
    • Content negotiation (@Produces, @Consumes) for consistent JSON handling
About the author

Pluralsight’s AI authoring technology is designed to accelerate the creation of hands-on, technical learning experiences. Serving as a first-pass content generator, it produces structured lab drafts aligned to learning objectives defined by Pluralsight’s Curriculum team. Each lab is then enhanced by our Content team, who configure the environments, refine instructions, and conduct rigorous technical and quality reviews. The result is a collaboration between artificial intelligence and human expertise, where AI supports scale and efficiency, and Pluralsight experts ensure accuracy, relevance, and instructional quality, helping learners build practical skills with confidence.

Real skill practice before real-world application

Hands-on Labs are real environments created by industry experts to help you learn. These environments help you gain knowledge and experience, practice without compromising your system, test without risk, destroy without fear, and let you learn from your mistakes. Hands-on Labs: practice your skills before delivering in the real world.

Learn by doing

Engage hands-on with the tools and technologies you’re learning. You pick the skill, we provide the credentials and environment.

Follow your guide

All labs have detailed instructions and objectives, guiding you through the learning process and ensuring you understand every step.

Turn time into mastery

On average, you retain 75% more of your learning if you take time to practice. Hands-on labs set you up for success to make those skills stick.

Get started with Pluralsight