1. ¿Qué es Micronaut?
Micronaut es un marco JVM para construir aplicaciones modulares ligeras. Fue desarrollado por OCI, la misma compañía que nos dio Grails. Micronaut es un marco moderno diseñado para facilitar y agilizar la creación de aplicaciones de microservicios.
Micronaut contiene características similares a los marcos existentes como Spring, pero al mismo tiempo implementa algunas ideas nuevas que son su sello distintivo. Junto con el soporte para Java, Groovy y Kotlin, ofrece muchas formas de crear aplicaciones.
2. Características clave
Una de las características más interesantes de Micronaut es la inyección de dependencia (DI) en tiempo de compilación. La mayoría de los frameworks usan objetos de reflexión y proxy para inyectar dependencias en tiempo de ejecución. Micronaut también recopila datos para la inyección de dependencia en la etapa de compilación. El resultado es tiempos de inicio de aplicaciones más rápidos y menos consumo de memoria.
Su próxima oportunidad es un soporte de primera clase para la programación reactiva, tanto para clientes como para servidores. La elección de una implementación específica del enfoque reactivo se deja a los desarrolladores de la solución, y RxJava y Project Reactor son compatibles de inmediato.
Además, Micronaut tiene varias características que lo convierten en un excelente marco de desarrollo nativo de la nube. Admite muchos mecanismos de descubrimiento de servicios, como Eureka y Consul, y también funciona con varios sistemas de rastreo distribuidos como Zipkin y Jaeger.
Además, proporciona soporte para crear funciones lambda AWS, lo que facilita la creación de aplicaciones sin servidor.
3. Comenzando
La forma más fácil de comenzar es usar SDKMAN:
> sdk install micronaut 1.0.0.M2
SDKMAN instalará todos los binarios que necesita para compilar, probar e implementar aplicaciones Micronaut. Además, recibirá una aplicación de consola Micronaut CLI, que le permitirá iniciar fácilmente un nuevo proyecto.
Los artefactos binarios también están disponibles en Sonatype y en Github.
En las siguientes secciones, veremos algunas de las características de Micronaut.
4. Inyección de dependencia (DI)
Como se mencionó anteriormente, Micronaut maneja la inyección de dependencia en tiempo de compilación, lo que lo distingue de la mayoría de los contenedores de IoC.
Sin embargo, es totalmente compatible con las anotaciones JSR-330, por lo que el manejo de beans es similar a otros marcos de IoC.
Para inyectar un contenedor en nuestro código, usamos
@Inject
:
@Inject private EmployeeService service;
La
@Inject
funciona igual que
@Autowired
y se puede usar con campos, métodos, constructores y parámetros.
Por defecto, todos los beans tienen un alcance: prototipo. Podemos crear rápidamente singletones usando la anotación
@Singleton
. Si varios beans implementan la misma interfaz, podemos usar la anotación
@Primary
para resolver el conflicto:
@Primary @Singleton public class BlueCar implements Car {}
La
@Requires
se puede usar cuando los beans son opcionales o para realizar una inyección cuando se cumplen ciertas condiciones.
En este sentido, se comporta de la misma manera que la anotación 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. Crear un servidor HTTP
Ahora, intentemos crear una aplicación de servidor HTTP simple. Para comenzar, usaremos SDKMAN:
> mn create-app hello-world-server -build maven
Entonces crearemos un nuevo proyecto Java con Maven en un directorio llamado hello-world-server. Dentro de este directorio encontraremos el código de la aplicación principal, el archivo POM de Maven y otros archivos de proyecto.
La aplicación más simple se ve así:
public class ServerApplication { public static void main(String[] args) { Micronaut.run(ServerApplication.class); } }
5.1 Bloqueo de HttpRequest
La aplicación en sí misma no hace casi nada. Agreguemos un controlador con dos controladores. Ambos devolverán un saludo, pero uno responderá a las solicitudes GET y el otro responderá a 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; } }
Del traductor: su humilde servidor fue e hizo todo lo que se cuenta en este artículo. Si en este momento está a punto de iniciar la aplicación y ver si funciona, no olvide habilitar el procesamiento de anotaciones en Eclipse / IntelliJ IDEA.5.2 IO reactivo
Por defecto, Micronaut implementa estos manejadores como una E / S de bloqueo tradicional. Sin embargo, podemos implementar rápidamente controladores sin bloqueo simplemente cambiando el tipo de retorno a cualquiera de los tipos reactivos sin bloqueo.
Por ejemplo, con RxJava podemos usar
Observable
. Del mismo modo, con Reactor podemos devolver los tipos
Mono
o
Flux
:
@Get("/{name}") public Mono<String> greet(String name) { return Mono.just(greetingService.getGreeting() + name); }
Del traductor: para este ejemplo necesitará Project Reactor en las dependencias de Maven: <dependency> <groupId>io.projectreactor</groupId> <artifactId>reactor-core</artifactId> <version>3.1.8.RELEASE</version> </dependency>
Tanto los controladores bloqueantes como los no bloqueantes utilizan el servidor Netty HTTP.
Por lo general, las solicitudes se procesan en el grupo de subprocesos de E / S principal, que se crea en el inicio, lo que las bloquea.
Sin embargo, si el controlador devuelve tipos de datos sin bloqueo, Micronaut usa el bucle de eventos Netty, haciendo que toda la solicitud no sea bloqueada.
6. Crear un cliente HTTP
Ahora, creemos una aplicación cliente para los controladores que acabamos de crear. Micronaut proporciona dos formas de crear clientes HTTP:
- declarativo
- software
6.1 Creación declarativa de un cliente HTTP
La primera y más simple forma de crear es usando un enfoque declarativo:
@Client("/greet") public interface GreetingClient { @Get("/{name}") String greet(String name); }
Tenga en cuenta que no implementamos una sola línea de código para llamar al servicio. En cambio, Micronaut entiende cómo invocar un servicio a partir de una firma de método y anotaciones.
Para probar este cliente, podemos crear una prueba JUnit que use la API del servidor para ejecutar el servidor incrustado:
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"); } }
De un traductor: para lectores curiosos perezosos hay un proyecto listo para usar en Github: github.com/jreznot/micronaut-introduction6.2 Creación programática de un cliente HTTP
Hay una opción para crear un cliente HTTP tradicional si necesita más control sobre su comportamiento e implementación:
@Singleton public class ConcreteGreetingClient { private RxHttpClient httpClient; public ConcreteGreetingClient(@Client("/") RxHttpClient httpClient) { this.httpClient = httpClient; } public String greet(String name) { HttpRequest<String> req = HttpRequest.GET("/greet/" + name); return httpClient.retrieve(req).blockingFirst(); } public Single<String> greetAsync(String name) { HttpRequest<String> req = HttpRequest.GET("/async/greet/" + name); return httpClient.retrieve(req).first("An error as occurred"); } }
El cliente usa RxJava de manera predeterminada, por lo que puede usar fácilmente llamadas bloqueantes y no bloqueantes.
7. Micronaut CLI
Ya vimos cómo funcionaba la utilidad CLI de Micronaut cuando creamos la aplicación.
En nuestro caso, era una aplicación separada, pero esta utilidad admite varias otras características.
7.1 Proyectos de múltiples aplicaciones (Federación)
En Micronaut, la federación es simplemente un grupo de aplicaciones individuales que se desarrollan en un solo proyecto. Mediante la federación, podemos administrarlos todos juntos de manera sencilla y asegurarnos de que usen la misma configuración.
Cuando usamos la CLI para generar federación, la utilidad toma los mismos argumentos que el comando create-app. Creará el directorio principal del proyecto y colocará cada aplicación en un subdirectorio.
7.2 Características
Al crear una aplicación o federación, podemos elegir qué características necesita nuestra aplicación. Esto le permite utilizar el conjunto mínimo de dependencias en el proyecto.
Indicamos las posibilidades en el argumento saw
-features
, separándolos con comas.
Puede enumerar las funciones disponibles con el siguiente comando:
> 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
Del traductor: bueno, aquí no se sorprenda, el equipo debe ejecutarse fuera del directorio del proyecto. El directorio del proyecto no funciona, tal vez en la versión .M3 lo arreglaron. Ella ya se ha ido.7.3 Proyectos existentes
Podemos usar la CLI para modificar proyectos existentes. Esto nos permite crear contenedores, clientes, controladores, etc. Cuando ejecutamos el comando "mn" en el directorio del proyecto, estarán disponibles los siguientes comandos:
> mn help | Command Name Command Description
8. Conclusión
En esta breve introducción a Micronaut, vimos lo fácil que es crear servidores y clientes HTTP bloqueantes y no bloqueantes. También observamos un par de características de CLI.
Este es solo un pequeño pedazo del pastel que ofrece Micronaut. Bajo el capó, tiene soporte para funciones sin servidor, descubrimiento de servicios, rastreo distribuido, monitoreo y métricas, configuraciones distribuidas y mucho más.
Sin embargo, dado que muchas de las características de Micronaut se tomaron prestadas de marcos existentes como Grails y Spring, ofrece características únicas que lo diferencian de otros.