These tutorials target Micronaut Framework 3. Read, Guides for Micronaut Framework 4.

Micronaut Data from a Spring Boot Application

This guide shows how to use Micronaut Data from a Spring Boot application.

Authors: Sergio del Amo

Micronaut Version: 3.9.2

1. What you will need

To complete this guide, you will need the following:

  • Some time on your hands

  • A decent text editor or IDE

  • JDK 17 or greater installed with JAVA_HOME configured appropriately

2. Introduction

In this guide, you will use Micronaut Data JDBC within a Spring Boot application.

3. 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.

4. Generate a Spring Boot Application

Generate a Spring Boot application using Spring Initializr with Spring Web.

5. Dependencies

Add the following dependencies as described in Using the Micronaut Spring Boot Starter to use Micronaut Features within a Spring Boot application.

pom.xml
<!-- Add the following to your annotationProcessorPaths element -->
<path>
    <groupId>io.micronaut</groupId>
    <artifactId>micronaut-bom</artifactId>
    <version>3.9.2</version>
</path>
<!-- Add the following to your dependencyManagement element -->
<dependency>
    <groupId>io.micronaut</groupId>
    <artifactId>micronaut-bom</artifactId>
    <version>3.9.2</version>
    <type>pom</type>
    <scope>import</scope>
</dependency>

<!-- Add the following to your annotationProcessorPaths element -->
<path>
    <groupId>io.micronaut</groupId>
    <artifactId>micronaut-inject-java</artifactId>
</path>
<!-- Add the following to your annotationProcessorPaths element -->
<path>
    <groupId>jakarta.annotation</groupId>
    <artifactId>jakarta.annotation-api</artifactId>
    <version>@jakarta.annotation-apiVersion@</version>
</path>
<dependency>
    <groupId>jakarta.annotation</groupId>
    <artifactId>jakarta.annotation-api</artifactId>
    <version>@jakarta.annotation-apiVersion@</version>
    <scope>compile</scope>
</dependency>
<!-- Add the following to your annotationProcessorPaths element -->
<path>
    <groupId>jakarta.persistence</groupId>
    <artifactId>jakarta.persistence-api</artifactId>
    <version>@jakarta.persistence-apiVersion@</version>
</path>
<dependency>
    <groupId>jakarta.persistence</groupId>
    <artifactId>jakarta.persistence-api</artifactId>
    <version>@jakarta.persistence-apiVersion@</version>
    <scope>compile</scope>
</dependency>
<dependency>
    <groupId>io.micronaut.spring</groupId>
    <artifactId>micronaut-spring-boot-starter</artifactId>
    <scope>compile</scope>
</dependency>

Moreover, add the following dependencies to use Micronaut Data:

pom.xml
<!-- Add the following to your annotationProcessorPaths element -->
<path>
    <groupId>io.micronaut.data</groupId>
    <artifactId>micronaut-data-processor</artifactId>
</path>
<dependency>
    <groupId>io.micronaut.data</groupId>
    <artifactId>micronaut-data-jdbc</artifactId>
    <scope>compile</scope>
</dependency>
<dependency>
    <groupId>io.micronaut.sql</groupId>
    <artifactId>micronaut-jdbc-hikari</artifactId>
    <scope>compile</scope>
</dependency>
<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <scope>runtime</scope>
</dependency>

6. Configuration

Add configuration for an in-memory H2 Database.

src/main/resources/application.yml
micronaut:
  application:
    name: default
datasources:
  default:
    url: jdbc:h2:mem:devDb;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE
    dialect: H2
    username: sa
    schema-generate: CREATE_DROP
    password: ''
    driverClassName: org.h2.Driver

7. Mapped Entities with Java Records

Create a Micronaut Data Mapped Entity

src/main/java/example/micronaut/Book.java
package example.micronaut;

import io.micronaut.core.annotation.Nullable;
import io.micronaut.data.annotation.GeneratedValue;
import io.micronaut.data.annotation.Id;
import io.micronaut.data.annotation.MappedEntity;

@MappedEntity (1)
public record Book(
        @Id (2)
        @GeneratedValue (3)
        @Nullable (4)
        Long id,
        String title,
        int pages
) {
}
1 Annotate the class with @MappedEntity to map the class to the table defined in the schema.
2 Specifies the ID of an entity
3 Specifies that the property value is generated by the database and not included in inserts
4 Annotate it with @Nullabe because it is a generated value.
Learn how to leverage Java records for immutable configuration, Micronaut Data Mapped Entities and Projection DTOs in the Micronaut Data and Java Records guide.

8. JDBC Repository

Next, create a repository interface to define the operations to access the database. Micronaut Data will implement the interface at compilation time.

src/main/java/example/micronaut/BookRepository.java
package example.micronaut;

import io.micronaut.data.jdbc.annotation.JdbcRepository;
import io.micronaut.data.model.query.builder.sql.Dialect;
import io.micronaut.data.repository.CrudRepository;

@JdbcRepository(dialect = Dialect.H2) (1)
public interface BookRepository extends CrudRepository<Book, Long> { (2)

    Book save(String title, int pages);
}
1 @JdbcRepository with a specific dialect.
2 By extending CrudRepository you enable automatic generation of CRUD (Create, Read, Update, Delete) operations.

9. Controller

Create a controller which exposes a GET route at /books.

src/main/java/example/micronaut/BookController.java
package example.micronaut;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.beans.factory.annotation.Autowired;

@RestController (1)
public class BookController {
    @Autowired (2)
    private BookRepository bookRepository;

    @GetMapping("/books") (3)
    Iterable<Book> list() {
        return bookRepository.findAll();
    }
}
1 In Spring’s approach to building RESTful web services, HTTP requests are handled by a controller. These components are identified by the @RestController annotation.
2 Inject a bean of type BookRepository by using @Autowired on the field definition.
3 The @GetMapping ensures that HTTP GET requests to /books are mapped to the list method.

10. Test

The following test shows that you can use Micronaut Data JDBC as your persistence solution in a Spring Boot Application.

src/test/java/example/micronaut/BookControllerTest.java
package example.micronaut;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.test.web.server.LocalServerPort;
import org.springframework.web.util.UriComponentsBuilder;
import static org.junit.jupiter.api.Assertions.*;

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) (1)
class BookControllerTest {
    @LocalServerPort (2)
    private int port;

    @Autowired (3)
    private TestRestTemplate restTemplate;

    @Autowired (4)
    BookRepository bookRepository;

    @Test
    void booksGet() {
        assertEquals(0, booksJsonArray().length);
        Book moreJava17 = bookRepository.save("More Java 17", 951);
        Book[] books = booksJsonArray();
        assertEquals(1, books.length);
        assertNotNull(books[0].id());
        assertEquals(books[0].pages(), 951);
        assertEquals(books[0].title(), "More Java 17");
        bookRepository.delete(moreJava17);
        assertEquals(0, booksJsonArray().length);
    }

    private Book[] booksJsonArray() {
        return restTemplate.getForObject(booksRequestUriString(), Book[].class);
    }

    private String booksRequestUriString() {
        return UriComponentsBuilder.fromUriString("http://localhost:" + port)
                .path("books")
                .build()
                .toUriString();
    }

}
1 The @SpringBootTest annotation tells Spring Boot to look for a main configuration class (one with @SpringBootApplication, for instance) and use that to start a Spring application context.
2 Note the use of webEnvironment=RANDOM_PORT to start the server with a random port (useful to avoid conflicts in test environments) and the injection of the port with @LocalServerPort.
3 Inject a bean of type TestRestTemplate by using @Autowired on the field definition.
4 Inject a bean of type BookRepository by using @Autowired on the field definition.

11. Testing the Application

To run the tests:

./mvnw test

12. Next steps

Read more about Micronaut Spring and Micronaut Data.

13. Help with the Micronaut Framework

The Micronaut Foundation sponsored the creation of this Guide. A variety of consulting and support services are available.