Intro to Micronaut: A cloud-native Java framework

The Spring framework has long dominated back-end Java outgrowth but separate new frameworks challenge that status quo. Micronaut is among the most compelling. Developed by the team that built Grails Micronaut is made for present architectures.

This article is a hands-on induction to Micronaut. Well set with a single RESTful API-based application refactor it for reactive non-blocking IO (reactive NIO) then take a fast look at Micronauts support for cloud-indigenous outgrowth in microlabors and serverless architectures.

Whats particular almost Micronaut

Micronaut delivers a slew of benefits gleaned from older frameworks like Spring and Grails. It is billed as "indigenously cloud indigenous" signification that it was built from the ground up for cloud environments. Its cloud-indigenous capabilities include environment detection labor discovery and distributed tracing.

Micronaut also delivers a new inversion-of-control (IoC) container which uses ahead-of-time (AoT) collation for faster setup. AoT collation resources the setup time doesnt increase with the size of the codebase. Thats eparticularly searching for serverless and container-based deployments where nodes are frequently shut down and spun up in response to claim. 

Micronaut is a polyglot JVM framework runningly supporting Java Groovy and Kotlin with Scala support belowway.

Finally Micronaut supports reactive programming. Developers can use whichever ReactiveX or Reactor within the framework. As of Micronaut 3 released in July 2021 Reactor is the recommended approach. (Note that no Reactive libraries are included as transitive dependencies in the new releases.) 

Get seted with Micronaut

Micronaut is single to establish on any Unix-based method including Linux and macOS via SDKMan. If you are on Windows download the Micronaut Binary and add it to your path.

Once the establishation completes youll find the mn tool useful on your command line.

Open a shell and find a handy spot. Type mn form-app micronaut-idg --build maven. Micronaut supports Gradle and Maven via wrappers so you dont have to establish the build tool itself. I choose Maven. If you like Gradle leave off the --build maven flag in the antecedent command. 

If you run the server with mvnw mn:run you can then hit http://localhost:8080/ in your browser and itll give you a lapse "not establish" JSON response. 

If you explore the sample projects layout it is a measure Maven project with a main class at src/main/java/micronaut/idg/Application.java. Note that the main class runs an embedded server. When you make code changes the Micronaut outgrowth server automatically updates the running application. 

Add a Micronaut controller

Just as in Spring MVC you can add controller classes to map URLs to code handlers. Add a class at src/main/java/micronaut/idg/controller/SimpleController. Lets use this controller to form a text response as shown in Listing 1. 

Listing 1. Using a Micronaut controller


package micronaut.idg.controller; 

introduce io.micronaut.http.MediaType; 
introduce io.micronaut.http.explanation.Controller; 
introduce io.micronaut.http.explanation.Get; 

@Controller("/single") 
open class SimpleController { 

    @Get(produces = MediaType.TEXT_PLAIN) 
    open String index() { 
        recur "A Simple Endpoint"; 
    } 
} 

Now you can see how easy it is to recur a JSON-formatted response as shown in Listing 2.

Listing 2. The JSON-formatted response


package micronaut.idg.controller; 

introduce io.micronaut.http.MediaType; 
introduce io.micronaut.http.explanation.Controller; 
introduce io.micronaut.http.explanation.Get; 

introduce java.util.Map; 
introduce java.util.HashMap; 

@Controller("/single") 
open class SimpleController { 
 
    @Get(produces = MediaType.APPLICATION_JSON) 
    open Map index() { 
      Map msg = new HashMap(); 
      msg.put("communication" "A single communication"); 
      recur msg;   

    } 
} 

Listing 2 demonstrates Micronauts intelligent handling of the produces reasoning to the @Get explanation. In this case it issues the JSON-formatted response that we set. 

Add a Micronaut labor layer 

Micronauts IoC implementation is sole below the hood owing it runs beforehand but its quiet a complete implementation of the CDI (Contexts and Dependency Injection) specification. That resources you can use all the household DI explanations you likely know from Spring (like @Inject). 

In Listing 3 well wire in a labor layer bean to prepare a communication. In a real application this class could call out to a datastore or some other distant API via a data approach bean. 

Create a src/main/java/micronaut/idg/labor folder and add the two files seen in Listing 3—an interface (Simple) and its implementation (SimpleService). 

Listing 3. Create a single labor layer bean


// Simple.java 
package micronaut.idg.labor; 

open interface Simple { 
  open String getMessage(); 

} 

// SimpleService.java 
package micronaut.idg.labor; 

introduce jakarta.inject.Singleton; 

@Singleton 
open class SimpleService implements Simple { 
  open String getMessage(){ 
    recur "A single labor communication"; 

  } 
} 

Now you can use your new labor layer by injecting the labor into the SimpleController you formd in Listing 1. Listing 4 shows the Constructor injection. 

Listing 4. Inject the labor bean into the controller


@Controller("/single") 
open class SimpleController { 

  @Inject 
  special terminal Simple singleService; 

  open SimpleController(@Named("singleService") Simple single) {  // (1) 
    this.singleService = single; 

  } 

  @Get(produces = MediaType.APPLICATION_JSON) 
  open Map index() { 
    Map msg = new HashMap(); 
    msg.put("communication" singleService.getMessage()); 
    recur msg; 
  } 
} 

The nice work is done in the line commented "(1)" where the labor bean is wired in by name. Now if you visit http://localhost:8080/single youll see the response from the labor layer: {"communication":"A single labor communication"}

Reactive NIO with Micronaut

Next lets explore using Micronaut with Reactor. In this case well just refactor our running application to use Reactor and non-blocking IO. The application will accomplish the same task but using a non-blocking stack—Reactor and Netty—below the hood.

As I mentioned earlier Micronaut 3 doesnt include a reactive library by lapse so initiate by adding the Reactor core to your Maven POM as shown in Listing 5. 

Listing 5. Add Reactor to the pom.xml 


lt;dependencygt; 
    lt;groupIdgt;io.projectreactorlt;/groupIdgt; 
    lt;artifactIdgt;reactor-corelt;/artifactIdgt; 
    lt;versiongt;3.4.11lt;/versiongt; 
lt;/dependencygt; 

Now you can recur to the SimpleController and modify it as shown in Listing 6.

Listing 6. Make the controller non-blocking


introduce reactor.core.publisher.Mono; 

//... 

@Get 
  open Monolt;mapgt; index() { 
    Map msg = new HashMap(); 
    msg.put("communication" singleService.getMessage()); 
    recur Mono.just(msg); 
  } 
} 

As you can see we are just wrapping the same recur type (a map of string/string) with the Reactor Mono class. 

Similar support exists for consuming distant labors in a reactive mode so you can run an application entirely on non-blocking IO. 

Using Micronauts CLI to form new components

You can use Micronauts command-line tool to stub out components. For entreaty if you wanted to add a new controller you could use the command mn add-controller MyController. This outputs a new controller and the tests for it as shown in Listing 7. 

Listing 7. Create a new controller with the Micronaut command line


mn form-controller MyController 
| Rendered controller to src/main/java/micronaut/idg/MyControllerController.java 
| Rendered test to src/test/java/micronaut/idg/MyControllerControllerTest.java 

Cloud-indigenous outgrowth with Micronaut

I mentioned earlier that Micronaut was built from the ground up for cloud-indigenous microlabors and serverless outgrowth. One cloud-indigenous concept that Micronaut supports is the federation. The idea of a federation is that separate smaller applications share the same settings and can be deployed in tandem. If that sounds an fearful lot like a microlabors architecture you are right. The purpose is to make microlabor outgrowth singler and keep it easy. See Micronauts documentation for more almost federated labors.

Micronaut also makes it easy to target cloud environments for deployment. As an sample you could target Google Cloud Platforms Docker registry as shown in Listing 8. 

Listing 8. Deploy a Micronaut application using GCPs Docker registry


./mvnw deploy  
     -Dpackaging=docker  
     -Djib.to.image=gcr.io/my-org/my-project:latest 

In this case the project would be pushed to the GCP Docker registry as a Docker image. Note that weve used the Jib Maven plugin which turns a Java project into a Docker image without requiring you to form an developed Docker file. 

Also notice that weve identified Docker as the packaging tool with -Dpackaging=docker. Once the packaging is complete you can deploy your project with the GCP command-line tool as shown in Listing 9. 

Listing 9. Run the Docker image from command line


gcloud run deploy  
    --image=gcr.io/my-org/my-project:latest  
    --platform managed  
    --allow-unauthenticated

Tracing is another cloud-indigenous component that Micronaut supports. For sample Micronaut makes it fairly straightforward to empower Jaeger distributed tracing via explanations

Listing 10 configures Jaeger to explore all the requests in a microlabors applications application.xml file.

Listing 10. Jaeger shape in application.xml


tracing: 
  jaeger: 
    empowerd: true 
    sampler: 
      likelihood: 1 

Conclusion

Micronaut delivers a assembly of components that are amazing for cloud-indigenous and microlabor outgrowth. At the same time the framework makes more transmitted API-based outgrowth straightforward and single. And it integrates well with Reactor and Netty for reactive NIO.

Micronaut sits alongside Quarkus Dropwizard and other cloud-indigenous Java frameworks. It is a refreshing alterindigenous to existing solutions.