domingo, 27 de noviembre de 2016

Spring Boot Rules!!!

imageHace unos meses cuando publicamos el hola mundo de Asp.Net Core Pedro me comentó que era muy parecido a Spring Boot.
Recientemente hemos publicado un hola mundo en Java con Maven, asi que como continuación vamos a hacer un hola mundo con una aplicación web utilizando Sping Boot.

Antes de empezar y para los que no lo conozcan ¿qué es Spring y qué es Spring Boot?
Cuando comencé a oír de Spring se utilizaba como inyección de dependencias, alrededor de este fueron creciendo utilidades y diversificando las técnicas utilizadas (programación orientada a aspectos, cachés, transaccionalidad, etc) con el tiempo la comunidad fue madurando y ofreciendo frameworks para desarrollar aplicaciones web, servicios, etc. Sping Boot es una forma concreta de hacer aplicaciones web, con todo el soporte de Spring basado en convenciones y reduciendo en la medida de lo posible las configuraciones (Convention over configuration)

Hagamos una aplicación web. Aunque Spring Boot ofrece un inicializador de proyectos en su web, lo vamos a hacer a mano, así que empezaremos por el POM, donde incluireos el proyecto padre spring-boot-starter-web, la dependencia con spring-boot-starter-web y el plugin spring-boot-maven-plugin

<?xml version="1.0" encoding="UTF-8"?>
<project 
    xmlns="http://maven.apache.org/POM/4.0.0" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    
    <groupId>com.nocompila</groupId>
    <artifactId>spring-boot-rules</artifactId>
    <version>0.1.0</version>
    
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.4.2.RELEASE</version>
    </parent>
    
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
    
    <properties>
        <java.version>1.8</java.version>
    </properties>
    
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

A diferencia del proyecto anterior, no hemos configurado el tipo de empaquetado, ni un plugin con la clase de contiene el public static void main. El plugin Spring Boot Maven ya se encarga de todo eso sin configurarlo, creando un jar que contiene todos los jars encontrados en el classpath y marcando el jar como ejecutable detectando.

Los siguiente que haremos es crear el directorio del código md src\main\java\rules directorio donde crearemos la siguiente clase:

package rules;

import org.springframework.boot.*;
import org.springframework.boot.autoconfigure.*;

@EnableAutoConfiguration
public class SpringBootRules{
    public static void main (String [] args) throws Exception{
        SpringApplication.run(SpringBootRules.class, args);
    }
}

Con la anotación @EnableAutoConfiguration le decimos a Spring que configure la aplicación, como detecta la dependencia spring-boot-starter-web asume que estamos haciendo una aplicación web y configura un Tomcat y Spring MVC. Lo cierto es que al añadir spring-boot-starter-web se añaden muchas dependencias de las que no somos conscientes. Si ejecutamos mvn dependency:tree veremos que tenemos todas estas dependencias:

[INFO] com.nocompila:spring-boot-rules:jar:0.1.0
[INFO] \- org.springframework.boot:spring-boot-starter-web:jar:1.4.2.RELEASE:compile
[INFO]    +- org.springframework.boot:spring-boot-starter:jar:1.4.2.RELEASE:compile
[INFO]    |  +- org.springframework.boot:spring-boot:jar:1.4.2.RELEASE:compile
[INFO]    |  +- org.springframework.boot:spring-boot-autoconfigure:jar:1.4.2.RELEASE:compile
[INFO]    |  +- org.springframework.boot:spring-boot-starter-logging:jar:1.4.2.RELEASE:compile
[INFO]    |  |  +- ch.qos.logback:logback-classic:jar:1.1.7:compile
[INFO]    |  |  |  +- ch.qos.logback:logback-core:jar:1.1.7:compile
[INFO]    |  |  |  \- org.slf4j:slf4j-api:jar:1.7.21:compile
[INFO]    |  |  +- org.slf4j:jcl-over-slf4j:jar:1.7.21:compile
[INFO]    |  |  +- org.slf4j:jul-to-slf4j:jar:1.7.21:compile
[INFO]    |  |  \- org.slf4j:log4j-over-slf4j:jar:1.7.21:compile
[INFO]    |  +- org.springframework:spring-core:jar:4.3.4.RELEASE:compile
[INFO]    |  \- org.yaml:snakeyaml:jar:1.17:runtime
[INFO]    +- org.springframework.boot:spring-boot-starter-tomcat:jar:1.4.2.RELEASE:compile
[INFO]    |  +- org.apache.tomcat.embed:tomcat-embed-core:jar:8.5.6:compile
[INFO]    |  +- org.apache.tomcat.embed:tomcat-embed-el:jar:8.5.6:compile
[INFO]    |  \- org.apache.tomcat.embed:tomcat-embed-websocket:jar:8.5.6:compile
[INFO]    +- org.hibernate:hibernate-validator:jar:5.2.4.Final:compile
[INFO]    |  +- javax.validation:validation-api:jar:1.1.0.Final:compile
[INFO]    |  +- org.jboss.logging:jboss-logging:jar:3.3.0.Final:compile
[INFO]    |  \- com.fasterxml:classmate:jar:1.3.3:compile
[INFO]    +- com.fasterxml.jackson.core:jackson-databind:jar:2.8.4:compile
[INFO]    |  +- com.fasterxml.jackson.core:jackson-annotations:jar:2.8.4:compile
[INFO]    |  \- com.fasterxml.jackson.core:jackson-core:jar:2.8.4:compile
[INFO]    +- org.springframework:spring-web:jar:4.3.4.RELEASE:compile
[INFO]    |  +- org.springframework:spring-aop:jar:4.3.4.RELEASE:compile
[INFO]    |  +- org.springframework:spring-beans:jar:4.3.4.RELEASE:compile
[INFO]    |  \- org.springframework:spring-context:jar:4.3.4.RELEASE:compile
[INFO]    \- org.springframework:spring-webmvc:jar:4.3.4.RELEASE:compile
[INFO]       \- org.springframework:spring-expression:jar:4.3.4.RELEASE:compile

Esta vez para compilar y ejecutar vamos a utilizar mvn spring-boot:run. Podemos hacer eso porque hemos añadido como padre de la aplicación spring-boot-starter-parent en el POM. Al arrancar la aplicación veremos que al iniciar el programa se inicia un Tomcat en el puerto 8080 de nuestra máquina. Pero si pedimos una página nos dará un error el siguiente error porque no tenemos nada para responder:
image

Lo único que nos falta por hacer es poner una respuesta en algún sitio, como este es un primer ejemplo, vamos a intentar hacer todo lo más pequeño posible, así que lo vamos a hacer todo en la misma clase para que se vea bien (pero no lo hagáis en vuestro código de producción)

package rules;

import org.springframework.boot.*;
import org.springframework.boot.autoconfigure.*;
import org.springframework.web.bind.annotation.*;

@RestController
@EnableAutoConfiguration
public class SpringBootRules{
    public static void main (String [] args) throws Exception{
        SpringApplication.run(SpringBootRules.class, args);
    }

    @RequestMapping("/**")
    String allSite (){
        return "Spring Boot Rules!!!";
    }
}

Como hemos dicho anteriormente, Sping Boot nos ha añadido SpringMVC, así que vamos a utilizar este framework. Marcamos la clase no la anotación @RestController (una meta anotación compuesta por @Controller y @ResponseBod) y añadimos un método que devuelve un String anotado con @RequestMapping(“/**”) con lo que le estamos diciendo a Spring que todas las peticiones web serán respondidas por este método.
Si volvemos a ejecutar la aplicación ahora y pedimos una página tendremos una respuesta mejor:
image

Como mencionamos anteriormente, al usar spring-boot-maven-plugin, no tenemos que configurar nada, y en el directorio target tendremos dos ficheros un jar súpervitaminado (“uber-jar”) que contiene todas las dependencias del classpath y otro finalizado jar.original que no contiene las dependencias.
El .jar lo podemos ejecutar con java –jar, por ejemplo desde el directorio raíz con java -jar target\spring-boot-rules-0.1.0.jar

En resumen, hemos hecho una aplicación de consola con un public static void main que arranca una aplicación web iniciando un Tomcat… ¿No suena esto parecido al hola mundo que hicimos con Asp.Net Core? ¿Vosotros qué creéis?
Ahh se me olvidaba, el código completo lo tenéis en GitHub

No hay comentarios:

Publicar un comentario