DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Because the DevOps movement has redefined engineering responsibilities, SREs now have to become stewards of observability strategy.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Related

  • Build a REST API With Just 2 Classes in Java and Quarkus
  • Spring Boot, Quarkus, or Micronaut?
  • Custom Validators in Quarkus
  • Update User Details in API Test Client Using REST Assured [Video]

Trending

  • Endpoint Security Controls: Designing a Secure Endpoint Architecture, Part 2
  • Memory-Optimized Tables: Implementation Strategies for SQL Server
  • Designing AI Multi-Agent Systems in Java
  • Web Crawling for RAG With Crawl4AI
  1. DZone
  2. Software Design and Architecture
  3. Integration
  4. Building a REST API With Quarkus

Building a REST API With Quarkus

Focusing on fast start-up times and low memory usage making it more suitable to run within container orchestration platforms like Kubernetes.

By 
Dan Newton user avatar
Dan Newton
·
Updated Oct. 08, 20 · Tutorial
Likes (9)
Comment
Save
Tweet
Share
13.0K Views

Join the DZone community and get the full member experience.

Join For Free

Quarkus is a Java framework designed to run within containers. Focusing on fast start-up times and low memory usage making it more suitable to run within container orchestration platforms like Kubernetes.

I wanted to write about Quarkus for a while now, and have finally found the time to do so.

The content of this post will focus on writing a simple REST API using Quarkus. I will not explain how Quarkus works, because, well, I haven’t put the time in yet to do so correctly. Hopefully, I can rectify this in future posts. Therefore, if you want more information about Quarkus, I suggest you browse their docs. So far, I have found them detailed, well written, and I will personally continue using them while I explore Quarkus further.

Creating a Project

Quarkus provides a maven command to bootstrap your projects, for example (the below works for Linux and MacOS, see the Quarkus - Getting started guide for more information):

Shell
xxxxxxxxxx
1
 
1
mvn io.quarkus:quarkus-maven-plugin:1.7.2.Final:create \
2
-DprojectGroupId=dev.lankydan \
3
-DprojectArtifactId=quarkus \
4
-DclassName="dev.lankydan.web.people.PersonResource" \
5
    -Dpath="/hello"

This generates a basic project with a HTTP endpoint in PersonResource with the path hello, along with several resources to build and run your application. In fact, you should have enough at this point to run the generated code, both locally and inside a container.

A pom.xml is included that contains the required dependencies. You will need to add to this if you want to write anything past a hello world example.

By running (from inside your project):

./mvnw quarkus:list-extensions

You can see the Quarkus dependencies/extensions available to your project.

Then you can add an extension using a command like the one below:

./mvnw quarkus:add-extension -Dextensions="hibernate-validator"

The other option is to add it manually as I would typically do when sorting out my dependencies. Just thought I’d mention the add-extension command as I hadn’t actually come across this method of dependency management when using Maven.

I keep mentioning Maven, but there is no reason you can’t using something else, such as Gradle.

Quarkus Uses JAX-RS for its REST Capabilities

Quarkus follows the JAX-RS specification with Resteasy providing its implementation. If you have worked with Java for a reasonable time, you have probably seen or written code that follows the JAX-RS spec. And if you haven’t, you probably will at some point. I haven’t needed to use it before myself (I tend to use Spring when in Java land) so it is reasonably new to me. Anyway, in general, you can implement most of a simple REST API by relying on a few annotations.

Quarkus Uses CDI Beans for Dependency Injection

Quarkus’ dependency solution is based on the CDI (Context and Dependency injection) specification. It should be noted that Quarkus does not provide a full CDI implementation, meaning that there will be limitations compared to other frameworks that you might have used. More information can be found in Quarkus’ CDI reference and their Introduction to CDI.

Implementing a REST API

I have put together an example REST API that manages people. I mean, the purpose of the API doesn’t really matter, it’s just an example after all. Here comes a long chunk of code:

Java
 




x
50


 
1
@Path("/people")
2
public class PersonResource {
3
 
           
4
  private final PersonRepository personRepository;
5
 
           
6
  public PersonResource(PersonRepository personRepository) {
7
    this.personRepository = personRepository;
8
  }
9
 
           
10
  @GET
11
  @Produces(MediaType.APPLICATION_JSON)
12
  public List<Person> all() {
13
    return personRepository.findAll();
14
  }
15
 
           
16
  @GET
17
  @Path("/{id}")
18
  @Produces(MediaType.APPLICATION_JSON)
19
  public Person get(@PathParam("id") UUID id) {
20
    return personRepository.findById(id);
21
  }
22
 
           
23
  @POST
24
  @Produces(MediaType.APPLICATION_JSON)
25
  public Person post(Person person) {
26
    return personRepository.insert(
27
        new Person(UUID.randomUUID(), person.getName(), person.getAge())
28
    );
29
  }
30
 
           
31
  @PUT
32
  @Path("/{id}")
33
  @Produces(MediaType.APPLICATION_JSON)
34
  public Person put(@PathParam("id") UUID id, Person person) {
35
    if (personRepository.findById(id) == null) {
36
      throw new PersonNotFoundException(id);
37
    }
38
    return personRepository.update(new Person(id, person.getName(), person.getAge()));
39
  }
40
 
           
41
  @DELETE
42
  @Path("/{id}")
43
  @Produces(MediaType.APPLICATION_JSON)
44
  public void delete(@PathParam("id") UUID id) {
45
    if (personRepository.findById(id) == null) {
46
      throw new PersonNotFoundException(id);
47
    }
48
    personRepository.deleteById(id);
49
  }
50
}



As I mentioned earlier, Quarkus uses Resteasy as its JAX-RS implementation. All of the annotations in this class are related to JAX-RS. Let’s have a quick look at one of the functions:

Java
 




xxxxxxxxxx
1


 
1
@GET
2
@Path("/{id}")
3
@Produces(MediaType.APPLICATION_JSON)
4
public Person get(@PathParam("id") UUID id) {
5
  return personRepository.findById(id);
6
}



  • @GET specifies that the method handles GET HTTP requests.
  • @Path("/{id}") and @PathParam work together to take the HTTP path variable id and use it as the endpoint’s input
  • @Produces(MediaType.APPLICATION_JSON) denotes the type of data that the endpoint returns as JSON

That’s enough about annotations. The rest of the method consists of finding the Person matching the input id and returning it to whatever called the endpoint. Instead of returning a Person directly, you could use a Response object, but I wanted to keep it simple and easier to read.

JSON Serialization

You have a choice between using JSON-B or Jackson for your serialization. Personally, I tend to use Jackson so I went ahead and plugged it in. You will need to add the extension for whichever you choose:

XML
 




xxxxxxxxxx
1


 
1
<dependency>
2
  <groupId>io.quarkus</groupId>
3
  <artifactId>quarkus-resteasy-jackson</artifactId>
4
</dependency>



Or via the command:

./mvnw quarkus:add-extension -Dextensions="resteasy-jackson"

Replace “jackson” with “jsonb” to switch over to JSON-B

Connecting to a Database Using JDBC

This API is not going to do anything useful if it isn’t persisting data somewhere.

Quarkus provides JDBC implementations for connecting to databases. I chose to use Postgres for this project’s database, but you can obviously use whatever suits your needs. More information can be found in Quarkus’ data source documentation.

The first thing you need to add to connect to a database, is a JDBC driver dependency:

XML
 




xxxxxxxxxx
1


 
1
<dependency>
2
  <groupId>io.quarkus</groupId>
3
  <artifactId>quarkus-jdbc-postgresql</artifactId>
4
</dependency>



You could also run:

./mvnw quarkus:add-extension -Dextensions="jdbc-postgresql"

Then add properties specifying the connection type and the details (to your application.properties):

Properties files
 




x


 
1
quarkus.datasource.db-kind=postgresql
2
# Change this part to match your connection details!
3
quarkus.datasource.jdbc.url=jdbc:postgresql://localhost:5432/mytestdb
4
quarkus.datasource.username=admin
5
quarkus.datasource.password=admin


Connection Pooling

You don’t want to directly manage the database connections yourself (I assume so anyway).

Quarkus’ preferred JDBC data source and connection pooling library is Agroal. Below is a quote from the Quarkus data source documentation.

Agroal is a modern, light weight connection pool implementation designed for very high performance and scalability, and features first class integration with the other components in Quarkus, such as security, transaction management components, health metrics.

What this means for you:

  • Add the Agroal extension to your dependencies:
XML
 




xxxxxxxxxx
1


 
1
<dependency>
2
  <groupId>io.quarkus</groupId>
3
  <artifactId>quarkus-agroal</artifactId>
4
</dependency>



Or run:

./mvnw quarkus:add-extension -Dextensions="agroal"

  • Inject the DataSource that it initialises into your code (either directly via AgroalDataSource or using the DataSource interface).

Creating a Repository

Once you have sorted out the data source connection and have enabled connection pooling, you can now start writing queries. Below is a slimmed-down version of the PersonRepository since its using raw JDBC meaning that the code is quite lengthy and duplicated between functions:

Java
 




xxxxxxxxxx
1
29


 
1
@ApplicationScoped
2
public class PersonRepository {
3
 
           
4
  private static final String FIND_BY_ID = "SELECT * FROM people WHERE id = ?";
5
 
           
6
  private final DataSource dataSource;
7
 
           
8
  public PersonRepository(DataSource dataSource) {
9
    this.dataSource = dataSource;
10
  }
11
 
           
12
  public Person findById(UUID id) {
13
    try (Connection connection = dataSource.getConnection();
14
        PreparedStatement statement = connection.prepareStatement(FIND_BY_ID)) {
15
      statement.setObject(1, id);
16
      try (ResultSet resultSet = statement.executeQuery()) {
17
        if (resultSet.next()) {
18
          return new Person(
19
              UUID.fromString(resultSet.getString("id")),
20
              resultSet.getString("name"),
21
              resultSet.getInt("age"));
22
        }
23
      }
24
    } catch (SQLException e) {
25
      throw new PersistenceException(e);
26
    }
27
    return null;
28
  }
29
}



The main take away of this snippet is the usage of the DataSource which Agroal provided the implementation for. You can inject it into your components after only needing to include the dependencies for a JDBC driver and Agroal itself. In regards to the JDBC code, more information on general JDBC usage can be found here.

Running the Application

To run a Quarkus application, execute:

./mvnw compile quarkus:dev

This runs the application in dev mode, which enables hot-reloading. Making your development experience a bit smoother. Although, I did find it hard to break the habit of restarting my application after every code change…

To run your application for real, or non dev mode, you need to build the application’s jar and run it. You can do this using:

./mvnw package
java -jar target/quarkus-1.0-SNAPSHOT-runner.jar

./mvnw package places the generated jar in the target directory

If you used the command I showed at the beginning of this post to generate your project, you would have a README.md containing all this information. Including how to construct a native executable and running your Quarkus application within a container. I will cover some of this in future blog posts.

Summary

You should now have a good idea on how to write a REST API using Quarkus. Like most other frameworks, you can leverage dependencies to quickly and effectively build your applications. Quarkus allows you to do the same. That can be seen by the number of times I told you to add a new dependency!

Bringing the focus back onto what Quarkus provides you, remember it’s a framework specialising on fast start-up times and low memory usage. I purposely left further discussion on these factors out to allow the post to focus on building an application using Quarkus, which is pretty much the same as building any REST application that uses JAX-RS. So when developers/engineers, like you, search for how to build a REST API using Quarkus, they can see that it is nothing alien. I will cover the benefits of using Quarkus in future content

I have left parts out to not distract from the main content, but you can find all of the code I used to create the example in my GitHub repository.

REST API Web Protocols Quarkus

Published at DZone with permission of Dan Newton, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Build a REST API With Just 2 Classes in Java and Quarkus
  • Spring Boot, Quarkus, or Micronaut?
  • Custom Validators in Quarkus
  • Update User Details in API Test Client Using REST Assured [Video]

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!