Introduction au framework Micronaut

Introduction au framework Micronaut

1. Qu'est-ce que Micronaut

Micronaut est un framework basé sur JVM pour la création d'applications légères et modulaires. Développé par OCI, la même société qui a créé Grails,Micronaut is the latest framework designed to make creating microservices quick and easy.

Bien que Micronaut contienne des fonctionnalités similaires aux frameworks existants tels que Spring, il comporte également de nouvelles fonctionnalités qui le distinguent. Et avec le support de Java, Groovy et Kotlin, il offre une variété de façons de créer des applications.

2. Caractéristiques principales

L’une des fonctionnalités les plus intéressantes de Micronaut est son mécanisme d’injection de dépendance de temps de compilation. La plupart des frameworks utilisent la réflexion et les mandataires pour effectuer une injection de dépendance au moment de l'exécution. Micronaut, however, builds its dependency injection data at compile time. Le résultat est un démarrage plus rapide de l'application et une plus petite empreinte mémoire.

Another feature is its first class support for reactive programming, for both clients and servers. Le choix d'une implémentation réactive spécifique est laissé au développeur car RxJava et Project Reactor sont pris en charge.

Micronaut possède également plusieurs fonctionnalités qui en font un excellent cadre de développement d’applications natives en nuage. It supports multiple service discovery tools such as Eureka and Consul, and also works with different distributed tracing systems such as Zipkin and Jaeger.

Il fournit également une assistance pour la création de fonctions AWS lambda, facilitant la création d'applications sans serveur.

3. Commencer

Le moyen le plus simple de commencer est d'utiliserSDKMAN:

> sdk install micronaut 1.0.0.RC2

Cela installe tous les fichiers binaires dont nous aurons besoin pour créer, tester et déployer les applications Micronaut. Il fournit également l'outil d'interface de ligne de commande Micronaut, qui nous permet de démarrer facilement de nouveaux projets.

Les artefacts binaires sont également disponibles surSonatype etGitHub.

Dans les sections suivantes, nous examinerons certaines fonctionnalités du framework.

4. Injection de dépendance

Comme mentionné précédemment, Micronaut gère l’injection de dépendance au moment de la compilation, ce qui est différent de la plupart des conteneurs IoC.

Cependant, il est toujoursfully supports JSR-330 annotations donc travailler avec des beans est similaire à d'autres frameworks IoC.

Pour faire passer automatiquement un bean dans notre code, nous utilisons@Inject:

@Inject
private EmployeeService service;

L'annotation@Inject fonctionne exactement comme@Autowired et peut être utilisée sur les champs, les méthodes, les constructeurs et les paramètres.

Par défaut, tous les haricots sont définis comme un prototype. Nous pouvons créer rapidement des beans singleton en utilisant@Singleton.  Si plusieurs classes implémentent la même interface de bean,@Primary peut être utilisé pour les déconfliger:

@Primary
@Singleton
public class BlueCar implements Car {}

L'annotation@Requires peut être utilisée lorsque les beans sont facultatifs, ou pour effectuer le câblage automatique uniquement lorsque certaines conditions sont remplies.

À cet égard, il se comporte un peu comme les annotations de 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. Construire un serveur HTTP

Voyons maintenant la création d'une application serveur HTTP simple. Pour commencer, nous utiliserons SDKMAN pour créer un projet:

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

Cela créera un nouveau projet Java utilisant Maven dans un répertoire nomméhello-world-server. Dans ce répertoire, nous trouverons le code source de notre application principale, le fichier Maven POM et d’autres fichiers de support pour le projet.

L'application par défaut qui est très simple:

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

5.1. Bloquer HTTP

À elle seule, cette application ne fera pas grand-chose. Ajoutons un contrôleur qui a deux points de terminaison. Les deux renverront un message d'accueil, mais l'un utilisera le verbe HTTPGET, et l'autre utiliseraPOST:

@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. E / S réactives

Par défaut, Micronaut implémentera ces points de terminaison en utilisant les E / S de blocage classiques. Cependant,we can quickly implement non-blocking endpoints by merely changing the return type to any reactive non-blocking type.

Par exemple, avec RxJava, nous pouvons utiliserObservable. De même, lors de l'utilisation de Reactor, nous pouvons renvoyer les types de donnéesMono ouFlux:

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

Netty est le serveur sous-jacent utilisé pour gérer les demandes HTTP, que ce soit pour les points d'extrémité bloquants ou non bloquants.

Normalement, les demandes sont gérées sur le pool de threads d'E / S principal créé au démarrage, ce qui les bloque.

Toutefois, lorsqu'un type de données non bloquant est renvoyé par un noeud final de contrôleur, Micronaut utilise le thread de boucle d'événement Netty, ce qui rend toute la demande non bloquante.

6. Construire un client HTTP

Créons maintenant un client pour utiliser les points de terminaison que nous venons de créer. Micronaut propose deux manières de créer des clients HTTP:

  • Un client HTTP déclaratif

  • Un client HTTP programmatique

6.1 Declarative HTTP Client

Le premier et le plus rapide moyen de créer consiste à utiliser une approche déclarative:

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

Remarquez commentwe don’t implement any code to call our service. Au lieu de cela, Micronaut comprend comment appeler le service à partir de la signature de la méthode et des annotations fournies.

Pour tester ce client, nous pouvons créer un test JUnit qui utilise l'API de serveur intégrée pour exécuter une instance intégrée de notre serveur:

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. Client HTTP programmatique

Nous avons également la possibilité d'écrire un client plus traditionnel si nous avons besoin de plus de contrôle sur son comportement et sa mise en œuvre:

@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");
   }
}

Le client HTTP par défaut utilise RxJava et peut donc facilement travailler avec des appels bloquants ou non bloquants.

7. Micronaut CLI

Nous avons déjà vu l'outil CLI Micronaut en action ci-dessus lorsque nous l'avons utilisé pour créer notre exemple de projet.

Dans notre cas, nous avons créé une application autonome, mais elle dispose également de plusieurs autres fonctionnalités.

7.1. Projets de la Fédération

In Micronaut, a federation is just a group of standalone applications that live under the same directory. En utilisant des fédérations, nous pouvons facilement les gérer ensemble et nous assurer qu'elles obtiennent les mêmes valeurs par défaut et paramètres.

Lorsque nous utilisons l'outil CLI pour générer une fédération, il prend tous les mêmes arguments que la commandecreate-app. Il créera une structure de projet de niveau supérieur et chaque application autonome sera créée dans son sous-répertoire à partir de là.

7.2. Caractéristiques

When creating a standalone application or federation, we can decide which features our app needs. Cela aide à garantir que le jeu minimal de dépendances est inclus dans le projet.

Nous spécifions les fonctionnalités en utilisant les-features argument et en fournissant une liste de noms de fonctionnalités séparés par des virgules.

Nous pouvons trouver une liste des fonctionnalités disponibles en exécutant la commande suivante:

> 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. Projets existants

We can also use the CLI tool to modify existing projects. Nous permettant de créer des beans, des clients, des contrôleurs, etc. Lorsque nous exécutons la commandemn depuis un projet existant, nous aurons un nouvel ensemble de commandes disponibles:

> 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

Dans cette brève introduction à Micronaut, nous avons vu à quel point il est facile de créer des serveurs et des clients HTTP bloquants et non bloquants. Nous avons également exploré certaines fonctionnalités de son interface de ligne de commande.

Mais ceci n’est qu’un petit aperçu des fonctionnalités qu’il offre. Il prend également en charge les fonctions sans serveur, la découverte de services, le traçage, la surveillance et les métriques distribués, une configuration distribuée et bien plus encore.

Et si bon nombre de ses fonctionnalités sont dérivées de frameworks existants tels que Grails et Spring, il possède également de nombreuses fonctionnalités uniques qui lui permettent de se distinguer.

Comme toujours, nous pouvons trouver les exemples de code ci-dessus dans nosGitHub repo.