Micronaut JAX-RS
Expose endpoints using JAX-RS annotations in a Micronaut application
On this guide
In this section
Getting Started
In this guide, we will create a Micronaut application written in Java.
By default, Micronaut users define their HTTP Routing using the Micronaut @Controller annotation and other built-in Routing Annotations. However, Micronaut JAX-RS allows you to define your Micronaut endpoints with JAX-RS annotations.
What exactly is JAX-RS? JAX-RS is a POJO-based, annotation-driven framework for building web services that comply with RESTful principles. Imagine writing all the low level code to parse an HTTP request and the logic just to wire these requests to appropriate Java classes/methods. The beauty of the JAX-RS API is that it insulates developers from that complexity and allows them to concentrate on business logic. That’s precisely where the use of POJOs and annotations come into play! JAX-RS has annotations to bind specific URI patterns and HTTP operations to individual methods of your Java class.
Gupta, Abhishek. REST assured with JAX-RS: speak HTTP using Java
This application exposes some REST endpoints using JAX-RS annotations and stores data in a MySQL database using Micronaut Data JDBC.
What you will need
To complete this guide, you will need the following:
-
Some time on your hands
-
A decent text editor or IDE (e.g. IntelliJ IDEA)
-
JDK 21 or greater installed with
JAVA_HOMEconfigured appropriately -
Docker installed to run MySQL and to run tests using Testcontainers.
Solution
We recommend that you follow the instructions in the next sections and create the application step by step. However, you can go right to the completed example.
-
Download and unzip the source
Writing the Application
Create an application using the Micronaut Command Line Interface or with Micronaut Launch.
mn create-app example.micronaut.micronautguide \
--features=jax-rs,data-jdbc,mysql,flyway,serialization-jackson,validation,graalvm \
--build=maven \
--lang=java \
--test=junit|
Note
|
If you don’t specify the --build argument, Gradle with the Kotlin DSL is used as the build tool. If you don’t specify the --lang argument, Java is used as the language.If you don’t specify the --test argument, JUnit is used for Java and Kotlin, and Spock is used for Groovy.
|
The previous command creates a Micronaut application with the default package example.micronaut in a directory named micronautguide.
If you use Micronaut Launch, select Micronaut Application as application type and add jax-rs, data-jdbc, mysql, flyway, serialization-jackson, validation, and graalvm features.
|
Note
|
If you have an existing Micronaut application and want to add the functionality described here, you can view the dependency and configuration changes from the specified features, and apply those changes to your application. |
Data Source configuration
Define the datasource in src/main/resources/application.properties.
datasources.default.db-type=mysql
datasources.default.dialect=MYSQL
datasources.default.driver-class-name=com.mysql.cj.jdbc.Driver|
Note
|
This way of defining the datasource properties enables us to externalize the configuration, for example for production environment, and also provide a default value for development. If the environment variables are not defined, the Micronaut framework will use the default values. |
Database Migration with Flyway
We need a way to create the database schema. For that, we use Micronaut integration with Flyway.
Flyway automates schema changes, significantly simplifying schema management tasks, such as migrating, rolling back, and reproducing in multiple environments.
Add the following snippet to include the necessary dependencies:
<dependency>
<groupId>io.micronaut.flyway</groupId>
<artifactId>micronaut-flyway</artifactId>
<scope>compile</scope>
</dependency>We will enable Flyway in the Micronaut configuration file and configure it to perform migrations on one of the defined data sources.
|
Note
|
Configuring multiple data sources is as simple as enabling Flyway for each one. You can also specify directories that will be used for migrating each data source. Review the Micronaut Flyway documentation for additional details. |
Flyway migration will be automatically triggered before your Micronaut application starts. Flyway will read migration commands in the resources/db/migration/ directory, execute them if necessary, and verify that the configured data source is consistent with them.
Create the following migration files with the database schema creation:
DROP TABLE IF EXISTS pet;
CREATE TABLE pet (
id BIGINT NOT NULL AUTO_INCREMENT UNIQUE PRIMARY KEY,
name VARCHAR(255) NOT NULL UNIQUE,
type varchar(255) check (type in ('DOG', 'CAT'))
);During application startup, Flyway will execute the SQL file and create the schema needed for the application.
Domain
Add an enum:
package example.micronaut;
public enum PetType {
DOG,
CAT
}Create an entity:
Service
Create a POJO NameDto:
Create a Repository:
JAX-RS
Dependencies
When you add a jax-rs feature, the generated application includes the following dependencies:
<!-- Add the following to your annotationProcessorPaths element -->
<path>
<groupId>io.micronaut.jaxrs</groupId>
<artifactId>micronaut-jaxrs-processor</artifactId>
</path>
<dependency>
<groupId>io.micronaut.jaxrs</groupId>
<artifactId>micronaut-jaxrs-server</artifactId>
<scope>compile</scope>
</dependency>Resource
Create a POJO to encapsulate the HTTP Request body for a save request:
package example.micronaut;
import io.micronaut.core.annotation.NonNull;
import io.micronaut.serde.annotation.Serdeable;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
@Serdeable
public class PetSave {
@NonNull
@NotBlank
private final String name;
@NonNull
@NotNull
private final PetType type;
public PetSave(@NonNull String name, @NonNull PetType type) {
this.name = name;
this.type = type;
}
@NonNull
public String getName() {
return name;
}
@NonNull
public PetType getType() {
return type;
}
}Define an endpoint using JAX-RS.
Tests
Add a test for the resource:
Test Resources
When the application is started locally, either under test or while running locally, resolution of the datasource URL is detected and the Test Resources service will start a local MySQL docker container, and inject the properties required to use this as the datasource.
For more information, see the JDBC section or R2DBC section of the Test Resources documentation.
Testing the Application
To run the tests:
./mvnw testRunning the Application
To run the application, use the ./mvnw mn:run command, which starts the application on port 8080.
You can execute the endpoints exposed by the application:
curl -id '{"name":"Chase", "type":"DOG"}' \
-H "Content-Type: application/json" \
-X POST http://localhost:8080/petsHTTP/1.1 201 Created
...curl -i localhost:8080/petsHTTP/1.1 200 OK
...
[{"name":"Chase"}]Generate a Micronaut Application Native Executable with GraalVM
We will use GraalVM, an advanced JDK with ahead-of-time Native Image compilation, to generate a native executable of this Micronaut application.
Compiling Micronaut applications ahead of time with GraalVM significantly improves startup time and reduces the memory footprint of JVM-based applications.
|
Note
|
Only Java and Kotlin projects support using GraalVM’s native-image tool. Groovy relies heavily on reflection, which is only partially supported by GraalVM.
|
GraalVM Installation
sdk install java 25.0.2-graalFor installation on Windows, or for a manual installation on Linux or Mac, see the GraalVM Getting Started documentation.
The previous command installs Oracle GraalVM, which is free to use in production and free to redistribute, at no cost, under the GraalVM Free Terms and Conditions.
Alternatively, you can use the GraalVM Community Edition:
sdk install java 25.0.2-graalceNative Executable Generation
To generate a native executable using Maven, run:
./mvnw package -Dpackaging=native-imageThe native executable is created in the target directory and can be run with target/micronautguide.
It is possible to customize the name of the native executable or pass additional build arguments using the Maven plugin for GraalVM Native Image building. Declare the plugin as follows:
You can execute the endpoints exposed by the native executable:
curl -id '{"name":"Chase", "type":"DOG"}' \
-H "Content-Type: application/json" \
-X POST http://localhost:8080/petsHTTP/1.1 201 Created
...curl -i localhost:8080/petsHTTP/1.1 200 OK
...
[{"name":"Chase"}]Configuration for production
When the application is run in a non-local environment, you will need to specify the datasource URL and credentials in a configuration that matches the specific environment. This can be achieved by adding a configuration specific to that environment like so:
datasources.default.url=jdbc:mysql://production-database/exampleDB?generateSimpleParameterMetadata=true&zeroDateTimeBehavior=convertToNull&verifyServerCertificate=false&useSSL=falseAnd then run the application with the following environment variables:
-
MICRONAUT_ENVIRONMENTS=prod -
DATASOURCES_DEFAULT_USERNAME=<username> -
DATASOURCES_DEFAULT_PASSWORD=<password>
|
Note
|
Instead of environment variables, you can also use Micronaut Distributed Configuration to pull these values from a secrets manager such as HashiCorp Vault. |
Next Steps
Read more about:
License
|
Note
|
All guides are released with an Apache License 2.0 for the code and a Creative Commons Attribution 4.0 license for the writing and media (images). |