24 de febrero de 2019

Spring Boot Parte 1 - Introducción y Hola Mundo



Comenzamos hoy con esta serie tutoriales sobre Spring Boot para renovarnos un poco, especialmente después de haber podido aprender algo de Spring Core y de Spring MVC

Seguramente muchos habrán escuchado de Spring Boot, sobre todo en el ámbito de los microservicios, pero ¿qué es Spring Boot? Spring Boot es un framework ligero que permite eliminar la mayor parte del trabajo de las configuraciones básicas de Spring. Es una de esas maravillas dentro de la maravilla que ya es Spring; literalmente en unos pocos segundos se puede tener una aplicación web recibiendo peticiones y lista para desplegarse, ya que contiene un conjunto inteligente de valores por default, por lo que requiere muy poca o ninguna configuración, y esa poca configuración se da en forma de anotaciones. No por nada ha sido una de las herramientas más utilizados por la comunidad de Spring desde su aparición en 2013.

Además de esto, Spring Boot proporciona un conjunto rico de herramientas integradas para sólo tener que preocuparnos de la lógica de la aplicación. A lo largo de esta serie de tutoriales iremos viendo y configurando cada una de estas herramientas.

Si recuerdan los tutoriales anteriores, uno de los problemas que tenemos con el uso de Spring Core es que es difícil de configurar, se necesitan muchas dependencias y cablear muchas clases para poder tener algo funcional; además era muy simple equivocarse en algún valor (sobre todo si lo usábamos con configuración en XML) nada funcionaba, y muchas veces era complicado lograr encontrar el error.

Con esta breve explicación, comencemos pues con el código del tutorial.

Lo primero es crear el proyecto, pero en vez de hacer esto directamente desde el IDE para posteriormente descargar las dependencias o buscarlas a través de Maven o Gradle, vamos a apoyarnos de Spring Initializr, el cual es una especie de asistente que realizará la configuración inicial básica para comenzar con nuestro proyecto. Este asistente no podría ser más sencillo de utilizar; simplemente colocamos algunos detalles mínimos sobre nuestro proyecto, elegimos un sistema de construcción (Gradle o Maven), un lenguaje (Java, Kotlin o Groovy) y una versión de Spring Boot (que en mi caso será la 2.1.3 que es la más nueva al momento de escribir este tutorial):



Como este es un tutorial introductorio, sólo elegiremos "Web" como dependencia, pero conforme vayamos avanzando y nuestras aplicaciones se hagan más complejas, usaremos más tipos de dependencias; por ejemplo, en el siguiente tutorial usamos Lombok para simplificar la escritura de nuestros POJOs.

Una vez que hemos configurado nuestro proyecto, hacemos clic en el botón "Generate Project" con lo que se descargará un archivo zip con la configuración inicial de nuestra aplicación.

Nota: Esta no es la única forma de generar un proyecto en Spring Boot, pero creo que es la más fácil ya que coloca todas las dependencias necesarias en el archivo de configuración de gradle. Si no les gusta esta forma o por alguna razón no pueden acceder a este sitio, aún es posible crear el proyecto directamente en el IDE.

Este zip contendrá los archivos iniciales del proyecto.



  • build.gradle, el script de construcción (build script) que indica cómo realizar la construcción del proyecto, es el equivalente al pom.xml de Maven.
  • gradlew.bat, un wrapper de Gradle para la línea de comandos. Este wrapper se asegura de que el proyecto siempre se construye usando la misma versión de Gradle, sin importar quién lo ejecute o qué versión de gradle esté instalada en el equipo; con este wrapper se evita incluso tener que instalar Gradle, es suficiente con tener Java.
  • settings.gradle, es otro script de construcción pero global con algunas otras configuraciones. Este archivo se lee antes que build.gradle y es muy útil cuando trabajamos con multiproyectos.
  • Algunos directorios con una clase "main" con algo de código para ejecutar nuestra aplicación.

Una vez que tenemos esta estructura, hay que importarla en Eclipse; vamos al menú "File -> Import...", y en la ventana que se abre seleccionamos "Gradle -> Existing Gradle Project".



Navegamos al directorio en el que descomprimimos el zip de Spring Initializer y presionamos el botón "Finish" (las opciones que por default nos da Eclipse funcionarán muy bien para el proyecto). La importación de este tardará algunos segundos (o minutos) ya que realiza la descarga de algunos plugins. Al final veremos el proyecto en el explorador de proyectos:



Una aplicación Spring Boot se ejecuta igual que una aplicación Java "normal", no es necesario colocarla en algún contenedor o servidor para que se ejecute, y esto es porque las aplicaciones Spring Boot ya tienen un servidor embebido. El servidor que se use por default dependerá, entre otras cosas, de la versión de Spring Boot que estemos usando; en este caso es un Tomcat embebido, pero en versiones anteriores se usaba Netty.

Además del servidor, Spring Boot integra todas las dependencias que necesita para funcionar dentro de un Uber Jar (del cual hablaremos más a detalle más adelante).

¿Cómo sabe Gradle qué dependencias usa Spring Boot? Si recuerdan al inicio del tutorial usamos Spring Initializer y seleccionamos "Web" como dependencia; esta dependencia requiere a su vez de un conjunto de librerías para funcionar de manera correcta, esto aplica para todas las dependencias que vayamos a usar en nuestros proyectos conforme se vayan volviendo más complejos. Para poder manejar todo este conjunto de dependencias de una manera sencilla, Spring Boot integra algo que se llaman "starters", que es una especie de paquetes virtuales que no contienen código, sino una lista de las dependencias que necesita para funcionar. Si abrimos el archivo "build.gradle" podremos ver que en la sección de dependencias tenemos actualmente dos:

  • org.springframework.boot:spring-boot-starter-web
  • org.springframework.boot:spring-boot-starter-test




Estas son los starters para web y para pruebas, pero existen literalmente decenas de starters dependiendo de las dependencias que hayamos seleccionado. Algunos de los starters que podríamos usar en tutoriales más avanzados de la serie son, por ejemplo:

  • spring-boot-starter-thymeleaf
  • spring-boot-starter-data-mongodb-reactive
  • spring-boot-starter-webflux


Además de esto, Spring Initializer creó una clase para iniciar nuestra aplicación. En mi caso la clase se llama "Tutorial1Application" y está en el paquete "com.javatutoriales.stringboot.tutorial1". La clase tiene el siguiente contenido:

package com.javatutoriales.stringboot.tutorial1;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Tutorial1Application {

    public static void main(String[] args) {
        SpringApplication.run(Tutorial1Application.class, args);
    }
 
}
Como vemos, esta clase está decorada con la anotacicón "@SpringBootApplication" y sólo tiene un método main que manda llamar un método estático "SpringApplication.run". A continuación, una explicación de estos elementos:

  • La anotación "@SpringBootApplication" le dice a Spring Boot que cuando se lance la clase, debe escanear recursivamente por componentes de Spring dentro del paquete en el que se encuentra la clase (en mi caso "com.javatutoriales.stringboot.tutorial1" y subpaquetes) y que los registre en el contexto de Spring. También indica que se debe habilitar la autoconfiguración, que es un proceso donde se crean ciertos beans de forma automática basado en ciertas clases encontradas en el classpath, valores en archivos de propiedades, y otros factores. Finalmente, indica que esta clase ("Tutorial1Application") también es una fuente de definiciones de beans de Spring.
  • SpringApplication.run le indica a Spring Boot cuál clase es el punto inicial de la aplicación. En este caso es la misma clase Tutorial1Application, pero podría ser alguna otra.


A partir de aquí ya podemos ejecutar nuestra aplicación. Tenemos dos formas de hacerlo, la tradicional "Run As -> Java Application" (Alt + Shift + X, J) o desde el panel de "Gradle Task", en la categoría de "application", con el task "bootRun", debemos hacer clic derecho en esta tarea y seleccionar "Run Gradle Task" en el menú que aparece.



Con cualquiera de las dos opciones comenzará la ejecución de nuestra aplicación y deberemos ver una salida muy similar a la siguiente en la consola:



En la salida anterior quiero resaltas los siguientes elementos:



  1. El banner superior nos indica que la aplicación se inició y qué versión de Spring Boot se está utilizando. Este banner se puede cambiar poniendo un archivo llamado "banner.txt" o "banner.png" con el contenido que queramos que aparezca; este archivo debe ponerse en el directorio "src/main/resources".
  2. El Tomcat embebido se inició en el puerto 8080.
  3. Se indica el tiempo que tomó la aplicación en iniciar, en la imagen anterior son 26.458 segundos.
Ahora podemos ir a nuestro navegador y colocar la siguiente dirección:

http://localhost:8080

Con lo que debemos ver una pantalla como la siguiente:



Aunque la pantalla anterior es de un error, no deben preocuparse ya que este error quiere decir que no hay ningún recurso o página que apunte a la URL base del proyecto ("/"); si nos fijamos bien la página nos dice que se trata de un error 404 (Not found), esto es porque, aunque ya tenemos nuestra aplicación esta continúa estando vacía.

Lo que es importante resaltar aquí es que sin mayor esfuerzo tenemos una aplicación que se ejecuta en un tomcat embebido y no hemos tenido que escribir ni una sola línea de configuración o código.

Escribamos una clase para regresar un mensaje y que nuestra aplicación deje de estar vacía.

Vamos a crear un nuevo paquete llamado "controllers" y dentro de este una clase llamada "HelloWorldController". Dentro de esta clase pondremos un nuevo método llamado "saludos" que reciba un String como parámetro y regrese también un String, de la siguiente forma:

package com.javatutoriales.stringboot.tutorial1.controllers;

public class HelloWorldController {

    public String saludos(String nombre) {
  
    }
}
Ahora vamos a colocar la lógica del método, este simplemente verá si la cadena "nombre" está vacía, de ser así regresará un saludo genérico y en caso contrario regresará un saludo con el nombre del usuario, de la siguiente forma:

public String saludos(String nombre) {
    return "".equals(nombre) ? "Hola Mundo!" : "Hola " + nombre;
}
Lo que sigue es decorar la clase y método anteriores para que sean reconocidos como controladores de peticiones de Spring Boot. Las anotaciones que usaremos son:

  • "@RestController" que indica que la clase será usada como manejadora de peticiones para servicios web tipo REST. Esto quiere decir que no regresará una página HTML como resultado, sino que este resultado será escrito directamente en el cuerpo de la respuesta. Usaremos esta anotación para decorar nuestra clase.
  • "@GetMapping" esta anotación es una abreviación para "@RequestMapping(method = RequestMethod.GET)" que vimos en el tutorial anterior. Usaremos esta anotación para decorar el método "saludos".
  • "@RequestParam" que indicará que "nombre" es un parámetro que estamos esperando recibir en la petición. Colocaremos algunos atributos adicionales en esta anotación para indicar que el parámetro no es requerido y además le daremos un valor por default. Usaremos esta anotación para decorar el parámetro "nombre".
Nuestra clase completa queda de la siguiente forma:

package com.javatutoriales.stringboot.tutorial1.controllers;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController 
public class HelloWorldController {
 
    @GetMapping
    public String saludos(@RequestParam(required = false, defaultValue = "") String nombre) {
        return "".equals(nombre) ? "Hola Mundo!" : "Hola " + nombre;
    }
}
Ahora lo que sigue es reiniciar nuestra aplicación, cuando volvamos a entrar a la ruta:

http://localhost:8080
Debemos ver la siguiente salida:



Y al entrar a:

http://localhost:8080/?nombre=Alex

Debemos ver la siguiente salida:



Para terminar este tutorial, veremos cómo generar el über jar de esta aplicación. Un über jar es simplemente un jar que contiene todas las clases y dependencias que necesita nuestra aplicación para funcionar; esto es, las clases que nosotros mismos hemos escrito, las clases de Spring Boot y las que necesita para trabajar, y cualquier otra librería que nuestra aplicación necesite y esté declarada de forma directa o transitiva en el archivo de configuración de Gradle. Además de este empaquetado, el über jar tiene la configuración necesaria para poder ejecutarse como una aplicación.

Crear este über jar es muy sencillo gracias a Gradle; lo único que debemos hacer es ir al panel de Gradle Tasks, encontrar el grupo de tareas "build", expandirlo, encontrar la tarea "bootJar", hacer clic derecho sobre la tarea, y seleccionar la opción "Run Gradle Task":



Con esto Eclipse (o mejor dicho Gradle) comenzará a compilar, probar y ensamblar nuestra aplicación en ese único Jar. Una vez que termine podemos ir al directorio "build\libs" de nuestro directorio de trabajo, y ahí deberemos ver un jar con el nombre y versión de nuestro proyecto, en mi caso "tutorial1-0.0.1-SNAPSHOT.jar". Noten el tamaño del jar, que en mi caso es de poco más de 16Mb.



Esto es debido a todas las clases que contiene. Si abren el jar con cualquier herramienta para abrir archivos .zip verán su contenido y que este es diferente a los jars normales, esto es porque Spring Boot usa una estructura particular para guardar las clases que se usan para ejecutar la aplicación.



Para ejecutar nuestra aplicación y comprobar que efectivamente este jar contiene todo lo que necesitamos vamos a abrir una línea de comandos y movernos al directorio en el que se encuentra nuestro jar; una vez ahí ejecutamos el siguiente comando:

java -jar tutorial1-0.0.1-SNAPSHOT.jar
Con esto debemos ver la misma salida que en la consola del Eclipse:



Si entramos nuevamente a la ruta:

http://localhost:8080/?nombre=Alex

Debemos ver la siguiente pantalla:



Con esto podemos comprobar que nuestra aplicación funciona correctamente.

Como podemos ver, en unos cuantos minutos pudimos tener listo el esqueleto de una aplicación Spring Boot muy simple, esto gracias al uso de Spring Initializr y de los valores por default de Spring Boot, los cuales usan un conjunto de configuraciones inteligentes para configurar de manera automática nuestra aplicación.

A lo largo de esta serie de tutoriales veremos más elementos de Spring Boot y cómo se integran con otros componentes de Spring como Spring Data JPA, Spring Validator, entre otros.

Espero que este tutorial les sea de utilidad. Si tienen alguna duda, sugerencia, comentario o aclaración, pueden dejarla en la sección de comentarios o enviar un correo a programadorjavablog@gmail.com (pueden agregarme al chat de gmail). También pueden seguir JavaTutoriales en las siguientes redes sociales:
Descarga los archivos de este tutorial desde aquí: