Micronaut

Language: Java

Web

Micronaut was created to address limitations in traditional Java frameworks for microservices and serverless environments. It uses ahead-of-time (AOT) compilation to generate dependency injection and configuration metadata at compile time, reducing reflection usage and improving startup performance.

Micronaut is a modern, JVM-based framework for building modular, easily testable microservices and serverless applications. It emphasizes low memory footprint, fast startup time, and dependency injection with compile-time optimizations.

Installation

maven: Add io.micronaut:micronaut-bom and dependencies like micronaut-runtime, micronaut-inject in pom.xml
gradle: Add implementation platform('io.micronaut:micronaut-bom:3.10.0') and dependencies like implementation 'io.micronaut:micronaut-runtime'

Usage

Micronaut allows developers to build HTTP servers, clients, and microservices with minimal boilerplate. It supports reactive programming, dependency injection, declarative HTTP clients, and seamless integration with databases, messaging systems, and cloud services.

Creating a simple HTTP controller

import io.micronaut.http.annotation.*;

@Controller("/hello")
public class HelloController {
    @Get
    public String index() {
        return "Hello Micronaut!";
    }
}

Defines a basic HTTP controller that responds to GET requests at `/hello`.

Starting a Micronaut application

import io.micronaut.runtime.Micronaut;

public class Application {
    public static void main(String[] args) {
        Micronaut.run(Application.class);
    }
}

Bootstraps a Micronaut application using the main method.

Dependency Injection

import jakarta.inject.Singleton;

@Singleton
public class MyService {
    public String getMessage() { return "Service Message"; }
}

@Controller("/service")
public class ServiceController {
    private final MyService myService;

    public ServiceController(MyService myService) {
        this.myService = myService;
    }

    @Get
    public String message() {
        return myService.getMessage();
    }
}

Demonstrates constructor-based dependency injection using `@Singleton` service.

Reactive HTTP client

import io.micronaut.http.client.annotation.*;
import io.micronaut.http.annotation.*;
import reactor.core.publisher.Mono;

@Client("https://api.example.com")
interface ExampleClient {
    @Get("/data")
    Mono<String> getData();
}

Defines a declarative HTTP client using Micronaut's reactive HTTP client support.

Configuration properties

import io.micronaut.context.annotation.*;

@Singleton
@ConfigurationProperties("app")
public class AppConfig {
    private String name;

    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
}

Binds configuration properties to a Java class for type-safe access.

Handling exceptions globally

import io.micronaut.http.annotation.*;
import io.micronaut.http.*;

@Error(global = true)
public HttpResponse<String> handleException(Exception e) {
    return HttpResponse.<String>serverError("Error: " + e.getMessage());
}

Defines a global error handler for exceptions in the application.

Error Handling

BeanInstantiationException: Occurs when a bean cannot be created. Check constructor parameters and dependency injection setup.
ConfigurationPropertyNotFoundException: Ensure all required configuration properties are defined in application.yml or application.properties.
Port already in use: Change the server port in configuration or ensure no other service is running on the same port.

Best Practices

Use compile-time dependency injection and AOT compilation to improve performance.

Leverage declarative HTTP clients for clean microservice communication.

Keep controllers thin and delegate business logic to services.

Use configuration properties classes for type-safe access to application settings.

Write reactive and non-blocking code when dealing with I/O for scalability.