Micronaut Framework — The basics

A modern, JVM-Based, Full-Stack framework for building modular, easily testable microservices.

Friskovec Miha
Javarevisited
5 min readDec 9, 2022

--

Source: https://micronaut.io/

What is Micronaut

Micronaut is a modern, JVM-based framework for building efficient, lightweight microservice applications. It offers a unique approach to building microservices by using ahead-of-time (AOT) compilation, which allows for faster startup time and lower memory consumption compared to traditional JVM-based frameworks.

Micronaut’s AOT compilation is achieved through the use of GraalVM, which is a high-performance, polyglot virtual machine that supports multiple languages, including Java, JavaScript, and Ruby. GraalVM allows Micronaut to compile applications ahead of time, resulting in faster startup times and lower memory consumption.

One of the key features of Micronaut is its support for reactive programming. Reactive programming is a programming paradigm that focuses on asynchronous data streams and the propagation of data changes. This can greatly improve the performance and scalability of microservice applications, as it allows them to handle a large number of concurrent requests without running into memory or CPU constraints.

Micronaut also offers first-class support for cloud-native environments, making it a great choice for building microservices that are designed to run on platforms like Kubernetes. It provides integrations with popular cloud-native tools and services, such as Netflix Eureka and Consul for service discovery, and Kubernetes and Docker for deployment and orchestration.

One of the standout features of Micronaut is its ability to run in both cloud-native environments and traditional JVM-based environments. This allows developers to build microservices that can run on-premises, in the cloud, or even in a hybrid environment with ease.

Overall, Micronaut is a powerful and efficient framework for building microservice applications. Its support for reactive programming, cloud-native environments, and AOT compilation makes it a great choice for building scalable, high-performance microservices.

Hello World

This example creates a simple “hello world” microservice that listens on a specified port and responds to HTTP requests with a “hello world” message.

First, we need to add the Micronaut dependency to our build.gradle file:

dependencies {
compile "io.micronaut:micronaut-http-server-netty"
}

Next, we can create a Micronaut application by using the @MicronautApplication annotation on our main class:

import io.micronaut.runtime.Micronaut;

@MicronautApplication
public class HelloWorldApplication {

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

Next, we can create a simple controller that listens for HTTP requests and returns a “hello world” message:

import io.micronaut.http.MediaType;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;

@Controller("/hello")
public class HelloWorldController {

@Get(produces = MediaType.TEXT_PLAIN)
public String index() {
return "Hello World!";
}
}

Finally, we can specify the port that our microservice should listen on by adding the micronaut.server.port property to our application.yml file:

micronaut:
server:
port: 8080

With this configuration in place, our microservice will start up and listen on port 8080 for HTTP requests. When a request is received, the HelloWorldController will handle it and return a "hello world" message.

Testing

One of the key benefits of Micronaut is its ability to run tests in a “thin” JVM, which means that tests can be executed quickly and efficiently. This is achieved through the use of reflection and other performance-enhancing techniques. In addition, Micronaut provides a range of testing utilities that make it easy to write tests for your application.

For example, Micronaut provides support for unit testing, which allows you to test individual components of your application in isolation. This is achieved through the use of the @MicronautTest annotation, which can be applied to a test class to enable the Micronaut testing infrastructure.

Micronaut also provides support for integration testing, which allows you to test the integration of multiple components within your application. This is achieved through the use of the @MicronautTest annotation, along with the @MicronautDataTest annotation, which can be used to load test data from a variety of sources, including in-memory databases and external files.

In addition to these testing capabilities, Micronaut also provides support for writing tests that interact with external systems, such as databases and HTTP servers. This is achieved through the use of the @MockBean annotation, which allows you to easily create mock implementations of external dependencies, allowing you to test your application in a controlled environment.

Unit Tests

A unit test is a test that tests a single component or module of an application in isolation. In Micronaut, you can write a unit test by annotating your test class with the @MicronautTest annotation, which enables the Micronaut testing infrastructure.

You can then use the @Inject annotation to inject the component you want to test, and use standard JUnit or TestNG assertions to verify the behavior of the component. Here is a simple example:

@MicronautTest
public class MyServiceTest {

@Inject
MyService myService;

@Test
public void testSomeMethod() {
// Use the @Inject MyService instance to test the myService.someMethod() method
assertEquals("expected result", myService.someMethod());
}
}

This test will use the Micronaut testing infrastructure to create an instance of the MyService class, and then invoke the myService.someMethod() method to test its behavior. The assertEquals() method is used to verify that the method returns the expected result.

Integration Tests

An integration test is a test that tests the integration of multiple components or modules within an application. In Micronaut, you can write an integration test by annotating your test class with the @MicronautTest and @MicronautDataTest annotations, which enables the Micronaut testing infrastructure and allows you to load test data from external sources. You can then use the @Inject annotation to inject the components you want to test, and use standard JUnit or TestNG assertions to verify the behavior of the integrated components. Here is a simple example:

@MicronautTest
@MicronautDataTest
public class MyServiceTest {

@Inject
MyService myService;

@Inject
DataSource dataSource;

@Test
public void testSomeMethod() {
// Use the @MicronautDataTest annotation to load test data from a file
loadTestData("test-data.sql");

// Use the @Inject MyService instance and @Inject DataSource instance to test the integration of these components
assertEquals("expected result", myService.someMethod(dataSource));
}
}

This test will use the Micronaut testing infrastructure to create instances of the MyService and DataSource classes, load test data from the specified file using the loadTestData() method, and then invoke the myService.someMethod() method to test the integration of these components. The assertEquals() method is used to verify that the method returns the expected result.

Summary

I hope this example helps to give you an idea of how to use Micronaut to create a simple microservice. Of course, there is much more to Micronaut than what is shown here, so be sure to check out the official documentation for more information.

One of the key features of Micronaut is its emphasis on testability, which makes it easy to write tests for your application. Micronaut provides support for unit testing, integration testing, and testing of external systems, and offers a range of testing utilities that make it easy to write effective tests. By using Micronaut’s testing capabilities, you can ensure that your application is well-tested and maintainable.

Have you used Micronaut and its testing capabilities in your own projects?

What has your experience been like?

--

--