Aplicaciones Reactivas usando Spring Webflux sobre Oracle Cloud - Parte II

Por Alberto Salazar
Publicado en Octubre 2018

Revisado por Juan Pablo Guizado



En la primera parte de nuestro artículo revisamos los fundamentos para crear aplicaciones reactivas usando spring flux y reactor, ahora vamos a continuar explorando su api cliente y finalmente desplegaremos nuestra aplicación en Oracle Cloud.



Aplicación Reactiva - API Cliente Webflux:


Como revisamos en el anterior artículo el principal beneficio de tener una aplicación reactiva es el manejar de manera eficiente y efectiva los recursos sobre el que corre la aplicación (Menor uso de hilos en el servidor); en esta ocasión vamos a revisar la parte cliente del api de webflux.

WebFlux nos incluye un API funcional para consumir servicios el cual nos brinda acceso a nuestros servicios reactivos expuestos. Crearemos un test basado en este API pero primero recordemos que nuestro proyecto incluye un API Rest reactivo que nos permite bajo la URL: (/reactive/v1/cliente) que nos permite:

  • GET: Obtener una lista de clientes
  • POST: Guardar un cliente
  • PUT: Actualizar un cliente
  • DELETE: Borrar un cliente 




Api reactivo para manejar clientes



Podemos clonar el proyecto usando el link: https://github.com/lasalazarr/reactive-spring-part-I para referencia de como correrlo podemos revisar el REAME.md file parte del mismo.

Ahora vamos a incluir un método de prueba sobre el API Rest en la clase de nuestra aplicación para obtener clientes; para ello en el directorio: src/test/java/ está la clase: ReactiveSpringPartIApplicationTests.java; hemos incluido dos nuevos test de la siguiente manera:

package com.otn.reactive.reactivespringpartI;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.reactive.server.WebTestClient;

import java.time.Duration;

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class ReactiveSpringPartIApplicationTests {

  @Autowired
  private WebTestClient webClient;

  @Test
  public void contextLoads() {
  }

  @Before
  public void setUp() {
     webClient = webClient
           .mutate()
           .responseTimeout(Duration.ofSeconds(300))
           .build();
  }

  @Test
  public void testObtenerListaClietes() {
     byte[] resultado = webClient
           .get().uri("/reactive/v1/cliente")
           .accept(MediaType.APPLICATION_JSON)
           .exchange()
           .expectStatus().isOk()
           .expectBody().returnResult().getResponseBody();
     System.out.format("%s: %s%n", "La lista de clientes:",  new String(resultado));
  }
  @Test
  public void testValidarListaClientes() {

     webClient
           .get().uri("/reactive/v1/cliente")
           .accept(MediaType.APPLICATION_JSON)
           .exchange()
           .expectStatus().isOk()
           .expectBody(String.class).isEqualTo("[{\"id\":\"1005\",\"nombres\":\"Tamara\", \"apellidos\":\"Cisneros\",\"telefono\":4356772,\"direccion\":\"Quito, EC876590\"}, {\"id\":\"1004\",\"nombres\":\"Paola\",\"apellidos\":\"Llanos\",\"telefono\":87878799, \"direccion\":\"Quito, EC179087\"},{\"id\":\"1003\",\"nombres\":\"Maria\",\"apellidos\": \"Valdez\",\"telefono\":82923233,\"direccion\":\"Quito, EC178976\"},{\"id\":\"1002\", \"nombres\":\"Pablo\",\"apellidos\":\"Arizaga\",\"telefono\":22332233,\"direccion\":\"Quito,  EC170104\"},{\"id\":\"1001\",\"nombres\":\"Alberto\",\"apellidos\":\"Salazar\",\"telefono\": 3299999,\"direccion\":\"Quito, EC170102\"}]");
  }
}




Para entender la prueba creada, primero hagamos referencia a la línea:

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) 




Estamos definiendo que se iniciara un servidor en un puerto aleatorio donde invocamos para las pruebas en nuestros métodos que detallamos a continuación:

@Test
  public void testObtenerListaClietes() {
     byte[] resultado = webClient
           .get().uri("/reactive/v1/cliente") 
           .accept(MediaType.APPLICATION_JSON)
           .exchange()
           .expectStatus().isOk()
           .expectBody().returnResult().getResponseBody();
     System.out.format("%s: %s%n", "La lista de clientes:", new String(resultado));
  }




Nuestra nueva prueba incluido con el método testObtenerListaClietes()primero comprueba el estado de la respuesta y luego si respuesta es correcta estamos imprimiendo en consola el listado.

Para el segundo método adicional a obtener la respuesta encontraremos que en el método se verifica el contenido de la respuesta usando el metodo isEqualTo:

.expectBody(String.class).isEqualTo 




Finalmente podemos ejecutar los test en nuestro IDE de preferencia u podemos ejecutarlos mediante maven en consola en la raíz del proyecto de la siguiente manera:

mvn clean test 




El resultado sería el listado impreso en nuestra consola y adicional las 3 pruebas escritas correctamente de la siguiente manera:



Resultado de ejecución de nuestras pruebas



Hemos realizado una revisión rápida del API cliente reactivo que viene con spring, ahora en la siguiente sección vamos a desplegar nuestra aplicación en Oracle Cloud.





Preparar nuestra aplicación para el despliegue en Oracle Cloud:



Para poder realizar el despliegue en Oracle's Application Container Cloud Service ACCS vamos a necesitar un archivo adicional que le permite al contenedor en la nube entender cómo desplegar nuestra aplicación; para ello vamos a seguir los siguientes pasos:

  1. Crear el archivo en el directorio donde tenemos nuestra ejecutable como jar; es decir en en: /target/Manifest.json con la siguiente información:

    {
        "runtime": {
            "majorVersion": "8"
        },
        "command": "java -jar reactive-spring-0.0.1-SNAPSHOT.jar",
        "notes": "Aplicacion Reactiva"
    }

     
  2. Agrupar como Zip nuestra ejecutable reactive-spring-0.0.1-SNAPSHOT.jar junto con el archivo Manifest.json que acabamos de crear; esto puede ser realizado mediante click derecho luego de escoger los dos archivos bajo el directorio target o podemo usar la consola de comandos de la siguiente manera:

    zip reactive.zip Manifest.json reactive-spring-0.0.1-SNAPSHOT.jar 

     

El proyecto completo que incluye los archivos creados en este articulo lo pueden encontrar en github en el siguiente link: https://github.com/lasalazarr/reactive-spring-part-II 





Despliegue en Oracle Cloud:



Antes de comenzar el despliegue sobre de nuestra aplicación en Oracle Cloud, asegurate de tener una cuenta sobre Oracle Cloud u adquierala una cuenta de prueba gratuitamente en el siguiente link (https://cloud.oracle.com/en_US/sign-in ).

Vamos a usar el Servicio en nube de contenedores de aplicaciones de Oracle (Oracle's Application Container Cloud Service ACCS). Oracle ACCS es un entorno de contenedores de aplicaciones políglota para varias plataformas, por ejemplo Java SE, Node u otros. Vamos a crear una instancia en el panel de control de nuestro ambiente de cloud y dar click en el botón Contenedor Clásico “Oracle Application Container Cloud” y vamos a dar click en el botón crear aplicación y escogemos Java SE:



Creación de una Aplicación en Oracle Application Container Cloud Services



Luego de llenar la información de  nuestra instancia, podremos usarla para nuestro despliegue y cargamos nuestro archivo .zip previamente creado en la anterior sección:



Carga de Zip de una Aplicación en Oracle Application Container Cloud Services



Finalmente luego de procesar nuestro archivo reactive.zip veremos el siguiente resultado:



Resultado de crear  una Aplicación en Oracle Application Container Cloud Services



Y podremos acceder a nuestro servicio de consulta en el link público provisto por oracle cloud incluyendo nuestro contexto de servicios de la siguiente manera:

https://reactive2-asalazar.brcom-central-1.oraclecloud.com/reactive/v1/cliente
Teniendo como resultado la lista de usuarios:



Resultado de ejecución de nuestra Aplicación en Oracle Application Container Cloud Services





Resumen


A través de este serie de artículos hemos aprendido cómo utilizar desde la definición de una aplicación reactiva, como construir un API de servicios reactivo y luego usamos el API cliente de WebFlux para realizar pruebas de unidad de nuestros servicios. Finalmente mostramos lo fácil que es realizar el despliegue de nuestra aplicación en Oracle Cloud.




Alberto Salazar es un profesional con más de 17 años de experiencia en la creación de arquitecturas Java para sistemas escalables y de gran carga de transacciones, desde J2EE 1.3, honrado como Auth0 Ambassador y coautor del libro 'Software Architecture with Spring 5.0'.
JUG Leader, Auth0Ambassador & JCP Member. Fundador de Java Users Group Ecuador y Javaday Ecuador Conference. Ponente en conferencias de clase mundial tales como: OracleCodeOne, JavaOne, Oracle Code, Redhat Summit, Voxxed Days, Oracle Code Latam Tour, Oracle OTN LAD y el Grupo de Usuarios de Java Ecuador.

Este artículo ha sido revisado por el equipo de productos Oracle y se encuentra en cumplimiento de las normas y prácticas para el uso de los productos Oracle.