A SpringBoot Developer’s Guide To Micronaut

This is a guide for spring application developers, who want to get started with using Micronaut. With this guide, you will get enough information to work with Micronaut framework.

Introduction

The Framework provides dependency injection, inversion of control (IOC), and Aspect-Oriented Programming (AOP) which is similar to that provided by Spring. Using Micronaut, you can create a command-line application, HTTP server application, and even event-driven application.

With this introduction, let's look into creating an application with Micronaut.

Creating a project

You can alternatively install a command-line utility using SDKMan. The command-line utility does the same as the launch site. More details about this are here

While creating a project, add Hibernate-JPA feature because we will be creating a project with CRUD capabilities. Once you have generated the project, we will look at the various things you would normally do as a spring developer.

Creating a bean

  • @controller — To define your controller class for your rest endpoints.
  • @repository — To define your repository bean.
  • @singleton — To define a bean with singleton scope.
  • @prototype — To define a bean with prototype scope
  • @requestscope — To define a bean with request scopes.

There is no @service or @component annotation, but rather you can use the above annotations to create a service or a component.

In addition to these, we have @infrastructure to define a bean that is critical for the application running which should not be overridden, and @threadlocal annotation to scope the bean per thread.

To inject a particular bean, Micronaut supports the same injection mechanism like constructor based, setter based, name based, which is similar to what spring provides. In case of an @autowire , you would now use an @inject annotation.

You can also have bean life cycle methods, conditional beans, bean qualifiers, etc, which are similar to those provided by spring. You can always read more about it in Micronaut’s documentation here.

Dependencies

   <dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-inject</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-http-server-netty</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.micronaut.data</groupId>
<artifactId>micronaut-data-hibernate-jpa</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.micronaut.sql</groupId>
<artifactId>micronaut-jdbc-hikari</artifactId>
<scope>compile</scope>
</dependency>

Apart from these, I had to add mysql-connector-java driver to communicate with MySQL.

JPA configuration

@Entity
@Table(name = "Orders")
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

Your data source and hibernate config also remains pretty much the same

datasources:
default:
url: jdbc:mysql://localhost:3306/ORDER
username: root
password: root
jpa:
default:
properties:
hibernate:
hbm2ddl:
auto: update
show_sql: true
dialect: org.hibernate.dialect.MySQL8Dialect

For querying your database, we get implementations from Micronaut for interfaces you create by extending interfaces like CRUDRepository or JPARepository. We also have JPA query support using the @query annotation. Here is the code for a JPA repository with an example query method.

@Repository
public interface OrderRepository extends CrudRepository<Order, Long> {

@Query("select o from Order as o")
List<Order> getAllOrders();
}

REST Controller

@Controller("/order")
public class WebController {

private final OrderService orderService;

public WebController(OrderService orderService) {
this.orderService = orderService;
}

@Get("/{id}")
public HttpResponse<OrderDTO> getOrder(@PathVariable("id") Long id) {

Optional<OrderDTO> mayBeOrder = orderService.getOrder(id);
if (mayBeOrder.isPresent()) {
return HttpResponse.created(mayBeOrder.get());
}
return HttpResponse.notFound();
}

Performance

__  __ _                                  _   
| \/ (_) ___ _ __ ___ _ __ __ _ _ _| |_
| |\/| | |/ __| '__/ _ \| '_ \ / _` | | | | __|
| | | | | (__| | | (_) | | | | (_| | |_| | |_
|_| |_|_|\___|_| \___/|_| |_|\__,_|\__,_|\__|
Micronaut (v2.5.8)
12:55:07.769 [main] INFO com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Starting...
12:55:08.150 [main] INFO com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Start completed.
12:55:08.157 [main] INFO org.hibernate.Version - HHH000412: Hibernate ORM core version [WORKING]
12:55:08.248 [main] INFO o.h.annotations.common.Version - HCANN000001: Hibernate Commons Annotations {5.1.2.Final}
12:55:08.351 [main] INFO org.hibernate.dialect.Dialect - HHH000400: Using dialect: org.hibernate.dialect.MySQL57Dialect
12:55:09.059 [main] INFO io.micronaut.runtime.Micronaut - Startup completed in 1928ms. Server Running: http://localhost:8080

Now, there is a catch here.

When the application starts up, the beans are yet to be wired up and this happens lazily. When the application receives the first request, the bean wiring takes place and hence there is a little delay for the first request that is being served. The subsequent requests are then pretty fast.

Here are the statistics.

Now to achieve the real boost in startup performance, we can create a Native image. With a native image, you can get a startup time of about 90 ms.

Yes, 90 milliseconds with JPA CRUD capabilities.

To learn how to achieve this incredible initial startup time. You can read my next article “Boost Java Application Performance With Micronaut”.

As usual, I have uploaded the code for this article on GitHub.

Software Craftsman, Tech Enthusiast. I run https://refactorfirst.com to post all my articles