RESTful APIs and Dependency Injection - Learn Quarkus Part 3

RESTful APIs and Dependency Injection - Learn Quarkus Part 3

Introduction

After creating your first Quarkus app in Part 2, it’s time to jump into some of the most important Quarkus core concepts. This article will focus on Dependency Injection (DI) in Quarkus and how to build RESTful APIs more effectively.

Dependency Injection in Quarkus

Dependency Injection is a core concept in modern software design, and Quarkus provides a powerful yet simple DI solution. Dependency Injection is a design pattern that allows a class to receive its dependencies from external sources rather than creating them itself. This pattern facilitates loose coupling, easier testing, and better code organization. Quarkus utilizes CDI (Contexts and Dependency Injection) for its DI mechanism, which is a set of services that allows Java EE components (such as servlets, enterprise beans, and managed beans) to be bound together dynamically.

Implementing DI

  1. Create a Service Class:
    • Create a new service class, for example GreetingService.java, and create a greet method that you will use later from GreetingResource
    • Make sure to mark the class with annotation @ApplicationScoped. This annotation makes the class a CDI managed bean and ensures there is only one instance of it in the application, reducing the amount of memory needed to run the app
     package com.codevup.quarkus.demo.service;
    
     import jakarta.enterprise.context.ApplicationScoped;
    
     @ApplicationScoped
     public class GreetingService {
    
         public String greet(String name) {
             return "Hello " + name + "!";
         }
     }
    
  2. Inject the Service:
    • Modify your GreetingResource to use GreetingService
    • Annotate GreetingService field with @Inject. This ensure that the instance of the service will be automatically injected when GreetingResource is created
     package com.codevup.quarkus.demo;
    
     import com.codevup.quarkus.demo.service.GreetingService;
     import jakarta.inject.Inject;
     import jakarta.ws.rs.GET;
     import jakarta.ws.rs.Path;
     import jakarta.ws.rs.Produces;
     import jakarta.ws.rs.core.MediaType;
    
     @Path("/hello")
     public class GreetingResource {
    
         @Inject
         GreetingService greetingService;
    
         @GET
         @Produces(MediaType.TEXT_PLAIN)
         public String hello() {
             return greetingService.greet("Quarkus");
         }
     }
    

Building RESTful APIs with Quarkus

RESTful APIs are an essential part of modern web development. We’ve already seen how to create GET endpoint. Let’s see now how to deal with other REST methods and how to handle request bodies

In order to be able to serialize and deserialize JSON requests and responses, add the following dependency to pom.xml:

<dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-resteasy-jackson</artifactId>
</dependency>

Let’s also add two new classes to handle json requests/responses, GreetingRequest and GreetingResponse:

public class GreetingRequest {

    private String name;

    @JsonCreator
    public GreetingRequest(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
public class GreetingResponse {
    private String greeting;

    public GreetingResponse(String greeting) {
        this.greeting = greeting;
    }

    public String getGreeting() {
        return greeting;
    }

    public void setGreeting(String greeting) {
        this.greeting = greeting;
    }
}

Let’s modify our endpoints now:

  1. GET:
    • We can add the name as a query parameter with the @QueryParam annotation, and return it as a json:
         @GET
         @Produces(MediaType.APPLICATION_JSON)
         public GreetingResponse hello(@QueryParam("name") String name) {
             return new GreetingResponse(greetingService.greet(name));
         }
    
  2. POST:
    • This method is usually used for storing data. Since we haven’t set up a data storage yet, we will just use it to test it out request body serialization. For this purpose, we will add GreetingRequest in the method signature
        @POST
        @Consumes(MediaType.APPLICATION_JSON)
        public Response createGreeting(GreetingRequest greetingRequest) {
            // Implementation to create a greeting
            return Response.ok().build();
        }
      
    • You cannot test this with a browser, you need to use Postman or Curl. When you make a POST request with the following body the response will have a 200 status
       {
        "name": "Codevup"
       }
      
  3. PUT:
     @DELETE
     @Consumes(MediaType.TEXT_PLAIN)
     public Response deleteGreeting(String name) {
         // Implementation to delete a greeting
         return Response.ok().build();
     }
    
  4. DELETE:
     @PUT
     @Consumes(MediaType.TEXT_PLAIN)
     public Response updateGreeting(String name) {
         // Implementation to update a greeting
         return Response.ok().build();
     }
    

Conclusion

In this article, you’ve learned about Dependency Injection in Quarkus and how to build RESTful APIs efficiently. These concepts are foundational in creating scalable, maintainable, and efficient applications in Quarkus. In the upcoming tutorials, we’ll explore database integration, microservices architecture, and more advanced features of Quarkus.

Roberto
Roberto Founder and Author of Codevup