Introduzione a Micronaut Framework

1. Che cos'è Micronaut

Micronaut è un framework basato su JVM per la creazione di applicazioni modulari leggere. Sviluppato da OCI, la stessa azienda che ha creato Grails, Micronaut è l'ultimo framework progettato per rendere la creazione di microservizi semplice e veloce .

Sebbene Micronaut contenga alcune funzionalità simili a framework esistenti come Spring, ha anche alcune nuove funzionalità che lo distinguono. E con il supporto per Java, Groovy e Kotlin, offre una varietà di modi per creare applicazioni.

2. Caratteristiche principali

Una delle caratteristiche più interessanti di Micronaut è il suo meccanismo di inserimento della dipendenza dal tempo di compilazione. La maggior parte dei framework usa la riflessione e i proxy per eseguire l'inserimento delle dipendenze in fase di esecuzione. Micronaut, tuttavia, crea i suoi dati di inserimento delle dipendenze in fase di compilazione. Il risultato è un avvio più veloce delle applicazioni e un minore ingombro di memoria.

Un'altra caratteristica è il suo supporto di prima classe per la programmazione reattiva, sia per i client che per i server. La scelta di una specifica implementazione reattiva è lasciata allo sviluppatore in quanto sono supportati sia RxJava che Project Reactor.

Micronaut ha anche diverse funzionalità che lo rendono un framework eccellente per lo sviluppo di applicazioni cloud native. Supporta più strumenti di rilevamento dei servizi come Eureka e Consul, e funziona anche con diversi sistemi di tracciamento distribuito come Zipkin e Jaeger.

Fornisce inoltre supporto per la creazione di funzioni lambda AWS, semplificando la creazione di applicazioni serverless.

3. Introduzione

Il modo più semplice per iniziare è utilizzare SDKMAN:

> sdk install micronaut 1.0.0.RC2

Questo installa tutti i file binari di cui abbiamo bisogno per creare, testare e distribuire le applicazioni Micronaut. Fornisce inoltre lo strumento Micronaut CLI, che ci consente di avviare facilmente nuovi progetti.

Gli artefatti binari sono disponibili anche su Sonatype e GitHub.

Nelle sezioni seguenti vedremo alcune caratteristiche del framework.

4. Iniezione di dipendenza

Come accennato in precedenza, Micronaut gestisce l'inserimento delle dipendenze in fase di compilazione, che è diverso dalla maggior parte dei contenitori IoC.

Tuttavia, supporta ancora completamente le annotazioni JSR-330, quindi lavorare con i bean è simile ad altri framework IoC.

Per autowire un bean nel nostro codice, usiamo @Inject:

@Inject private EmployeeService service;

L' annotazione @Inject funziona proprio come @Autowired e può essere utilizzata su campi, metodi, costruttori e parametri.

Per impostazione predefinita, tutti i bean hanno l'ambito come prototipo. Possiamo creare rapidamente bean singleton usando @Singleton. Se più classi implementano la stessa interfaccia bean, @Primary può essere utilizzato per deconflicarle:

@Primary @Singleton public class BlueCar implements Car {}

L' annotazione @Requires può essere utilizzata quando i bean sono facoltativi o per eseguire il collegamento automatico solo quando vengono soddisfatte determinate condizioni.

A questo proposito, si comporta in modo molto simile alle annotazioni Spring Boot @Conditional :

@Singleton @Requires(beans = DataSource.class) @Requires(property = "enabled") @Requires(missingBeans = EmployeeService) @Requires(sdk = Sdk.JAVA, value = "1.8") public class JdbcEmployeeService implements EmployeeService {}

5. Creazione di un server HTTP

Ora diamo un'occhiata alla creazione di una semplice applicazione server HTTP. Per iniziare, utilizzeremo SDKMAN per creare un progetto:

> mn create-app hello-world-server -build maven

Questo creerà un nuovo progetto Java usando Maven in una directory chiamata hello-world-server. All'interno di questa directory, troveremo il codice sorgente dell'applicazione principale, il file POM di Maven e altri file di supporto per il progetto.

L'applicazione predefinita che è molto semplice:

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

5.1. Blocco di HTTP

Di per sé, questa applicazione non farà molto. Aggiungiamo un controller che ha due endpoint. Entrambi restituiranno un saluto, ma uno utilizzerà il verbo GET HTTP e l'altro utilizzerà POST:

@Controller("/greet") public class GreetController { @Inject private GreetingService greetingService; @Get("/{name}") public String greet(String name) { return greetingService.getGreeting() + name; } @Post(value = "/{name}", consumes = MediaType.TEXT_PLAIN) public String setGreeting(@Body String name) { return greetingService.getGreeting() + name; } }

5.2. IO reattivo

Per impostazione predefinita, Micronaut implementerà questi endpoint utilizzando l'I / O di blocco tradizionale. Tuttavia, possiamo implementare rapidamente endpoint non bloccanti semplicemente modificando il tipo restituito in qualsiasi tipo reattivo non bloccante .

Ad esempio, con RxJava possiamo usare Observable . Allo stesso modo, quando si utilizza Reactor, possiamo restituire i tipi di dati Mono o Flux :

@Get("/{name}") public Mono greet(String name) { return Mono.just(greetingService.getGreeting() + name); }

Sia per gli endpoint di blocco che per quelli non di blocco, Netty è il server sottostante utilizzato per gestire le richieste HTTP.

Normalmente, le richieste vengono gestite sul pool di thread I / O principale che viene creato all'avvio, facendole bloccare.

Tuttavia, quando un tipo di dati non bloccante viene restituito da un endpoint del controller, Micronaut utilizza il thread del ciclo di eventi Netty, rendendo l'intera richiesta non bloccante.

6. Creazione di un client HTTP

Ora costruiamo un client per utilizzare gli endpoint che abbiamo appena creato. Micronaut offre due modi per creare client HTTP:

  • Un client HTTP dichiarativo
  • Un client HTTP programmatico

6.1 Client HTTP dichiarativo

Il primo e più rapido modo per creare è utilizzare un approccio dichiarativo:

@Client("/greet") public interface GreetingClient { @Get("/{name}") String greet(String name); }

Nota come non implementiamo alcun codice per chiamare il nostro servizio . Invece, Micronaut capisce come chiamare il servizio dalla firma del metodo e dalle annotazioni che abbiamo fornito.

To test this client, we can create a JUnit test that uses the embedded server API to run an embedded instance of our server:

public class GreetingClientTest { private EmbeddedServer server; private GreetingClient client; @Before public void setup() { server = ApplicationContext.run(EmbeddedServer.class); client = server.getApplicationContext().getBean(GreetingClient.class); } @After public void cleanup() { server.stop(); } @Test public void testGreeting() { assertEquals(client.greet("Mike"), "Hello Mike"); } }

6.2. Programmatic HTTP Client

We also have the option of writing a more traditional client if we need more control over its behavior and implementation:

@Singleton public class ConcreteGreetingClient { private RxHttpClient httpClient; public ConcreteGreetingClient(@Client("/") RxHttpClient httpClient) { this.httpClient = httpClient; } public String greet(String name) { HttpRequest req = HttpRequest.GET("/greet/" + name); return httpClient.retrieve(req).blockingFirst(); } public Single greetAsync(String name) { HttpRequest req = HttpRequest.GET("/async/greet/" + name); return httpClient.retrieve(req).first("An error as occurred"); } }

The default HTTP client uses RxJava, so can easily work with blocking or non-blocking calls.

7. Micronaut CLI

We've already seen the Micronaut CLI tool in action above when we used it to create our sample project.

In our case, we created a standalone application, but it has several other capabilities as well.

7.1. Federation Projects

In Micronaut, a federation is just a group of standalone applications that live under the same directory. By using federations, we can easily manage them together and ensure they get the same defaults and settings.

When we use the CLI tool to generate a federation, it takes all the same arguments as the create-app command. It will create a top-level project structure, and each standalone app will be created in its sub-directory from there.

7.2. Features

When creating a standalone application or federation, we can decide which features our app needs. This helps ensure the minimal set of dependencies is included in the project.

We specify features using the -features argument and supplying a comma-separated list of feature names.

We can find a list of available features by running the following command:

> mn profile-info service Provided Features: -------------------- * annotation-api - Adds Java annotation API * config-consul - Adds support for Distributed Configuration with Consul * discovery-consul - Adds support for Service Discovery with Consul * discovery-eureka - Adds support for Service Discovery with Eureka * groovy - Creates a Groovy application [...] More features available

7.3. Existing Projects

We can also use the CLI tool to modify existing projects. Enabling us to create beans, clients, controllers, and more. When we run the mn command from inside an existing project, we'll have a new set of commands available:

> mn help | Command Name Command Description ----------------------------------------------- create-bean Creates a singleton bean create-client Creates a client interface create-controller Creates a controller and associated test create-job Creates a job with scheduled method

8. Conclusion

In this brief introduction to Micronaut, we've seen how easy it is to build both blocking and non-blocking HTTP servers and clients. Also, we explored some features of its CLI.

But this is just a small taste of the features it offers. There is also full support for serverless functions, service discovery, distributed tracing, monitoring and metrics, a distributed configuration, and much more.

And while many of its features are derived from existing frameworks such as Grails and Spring, it also has plenty of unique features that help it stand out on its own.

Come sempre, possiamo trovare il codice di esempio sopra nel nostro repository GitHub.