Sencillo Microservicio en Spring realizado con el alumnado de DAM en 2021/2022.

Overview

Spring-Productos-DAM

Sencillo Microservicio para API Rest en Spring (SpringBoot) realizada conjuntamente con 2 DAM. Curso 2021/2022

Spring LISENCE GitHub

imagen

API REST

Sencilla Api REST con Spring Boot realizada con el alumnado para el curso de 2020/2021. Con ella pondremos a prueba todo lo que hemos aprendido hasta el momento en Acceso a Datos y Programación de Servicios y Procesos.

En este proyecto realizaremos una API REST con Spring Boot. Es decir, un servicio web que accede a datos de una base de datos para gestionar un recurso, donde a su vez, podemos realizar operaciones CRUD (Create, Read, Update, Delete) implementando mecanismos autenticación y autorización.

Arquitectura

arquitectura

arquitectura3

arquitectura2

Componentes Spring

Nuestros componentes principales se etiquetarán con @ para que el framework Spring lo reconozca. Cada uno tiene una misión en nuestra arquitectura:

componentes

Controladores

Se etiquetan como @Controller o en nuestro caso al ser una API REST como @RestController. Estos son los controladores que se encargan de recibir las peticiones de los usuarios y devolver respuestas.

Servicios

Se etiquetan como @Service. Se encargan de implementar la parte de negocio o infraestructura. En nuestro caso puede ser el sistema de almacenamiento o parte de la seguridad y perfiles de usuario.

Repositorios

Se etiquetan como @Repository e implementan la interfaz y operaciones de persistencia de la información. En nuestro caso, puede ser una base de datos o una API externa. Podemos extender de repositorios pre establecidos o diseñar el nuestro propio.

Configuración

Se etiquetan como @Configuration. Se encargan de configurar los componentes de la aplicación. Se se suelen iniciar al comienzo de nuestra aplicación.

Bean

La anotación @Bean, nos sirve para indicar que este bean será administrado por Spring Boot (Spring Container). La administración de estos beans se realiza mediante a anotaciones como @Configuration.

IoC y DI en SpringBoot

Inversión de Control

Inversión de control (Inversion of Control en inglés, IoC) es un principio de diseño de software en el que el flujo de ejecución de un programa se invierte respecto a los métodos de programación tradicionales. En su lugar, en la inversión de control se especifican respuestas deseadas a sucesos o solicitudes de datos concretas, dejando que algún tipo de entidad o arquitectura externa lleve a cabo las acciones de control que se requieran en el orden necesario y para el conjunto de sucesos que tengan que ocurrir.

Inyección de Dependencias

La inyección de dependencias (en inglés Dependency Injection, DI) es un patrón de diseño orientado a objetos, en el que se suministran objetos a una clase en lugar de ser la propia clase la que cree dichos objetos. Esos objetos cumplen contratos que necesitan nuestras clases para poder funcionar (de ahí el concepto de dependencia). Nuestras clases no crean los objetos que necesitan, sino que se los suministra otra clase 'contenedora' que inyectará la implementación deseada a nuestro contrato.

IoC y DI en Spring

El contenedor Spring IoC lee el elemento de configuración durante el tiempo de ejecución y luego ensambla el Bean a través de la configuración. La inyección de dependencia de Spring se puede lograr a través del constructor, el método Setter y el dominio de entidad. Podemos hacer uso de la anotación @Autowired para inyectar la dependencia en el contexto requerido. O si usamos Lombok, podemos hacer uso de la anotación @Setter, @AllArgsConstructor, siempre y cuando declaremos como final las dependencias necesitadas.

A nivel de constructor

El contenedor llamará al constructor con parámetros al instanciar el bean, y cada parámetro representa la dependencia que queremos establecer. Spring analizará cada parámetro, primero lo analizará por tipo, pero cuando sea incierto, luego lo analizará de acuerdo con el nombre del parámetro (obtenga el nombre del parámetro a través de ParameterNameDiscoverer, implementado por ASM).

@Service
public class UserService {
 
  private final UserDAO userDAO;
 
  @Autowired
  public UserService(UserDAO userDAO) {
    this.userDAO = userDAO;
  }
}

A nivel de setter

Spring primero instancia el Bean y luego llama al método Setter que debe inyectarse para lograr la inyección de dependencia.

@Service
public class UserService {
 
  private UserDAO userDAO;
    
  @Autowired
  public void setUserDAO(UserDAO userDAO) {
    this.userDAO = userDAO;
  }
}

DTO y Mappers

Usaremos los DTO, como objetos de transporte y con ellos facilitar la transición entre Request y objetos del modelo, y objetos de modelo y Responses. De esta manera podemos ensamblar y desensamblar los objetos de modelo y de transporte según nuestra necesidades.

Los mapeadores nos ayudarán en la misión de mapear los objetos de modelo a objetos de transporte y viceversa. Podemos usar una librería específica para ello como ModelMapper, o podemos usar un mapeador propio.

Fichero de propiedades

A la hora de utilizar el contenedor de Spring es una buena práctica separar la configuración de los beans, parcial o totalmente realizada en ficheros XML o clases de configuración (internamente), y los parámetros de configuración que utilizan esos beans como por ejemplo contraseñas o la ubicación de la base de datos.

Lo habitual es definir los parámetros de configuración en ficheros de propiedades estándar de Java (.properties). Spring permite utilizar cómodamente este tipo de ficheros tal y como vamos a ver y con ello realizar la configuración de los beans sin pasar por el tedioso proceso de configuración de XML.

Podemos tener distintos ficheros por ejemplo para desarrollo y producción.

  • Propiedades globales: src/main/resources/application.properties
  • Propiedades de producción: src/main/resources/application-prod.properties
  • Propiedades de desarrollo: src/main/resources/application-dev.properties

Y luego desde la línea de comandos podemos cargar un perfil concreto de la siguiente manera:

java -jar -Dspring.profiles.active=prod demo-0.0.1-SNAPSHOT.jar

Spring Data

Spring Data es una librería de persistencia que nos permite acceder a bases de datos relacionales de forma sencilla. Para ello podemos extender de la clase JpaRepository, que es una clase de repositorio de Spring Data con más funcionalidades, como pueden ser las operaciones de consulta, inserción, actualización y eliminación, así como las de paginación, ordenación o búsquedas.

Repositorios

Los principales son:

  • CrudRepository: tiene las mayoría de las funcionalidades CRUD.
  • PagingAndSortingRepository: ofrece mecanismos de paginación, ordenación y búsqueda.
  • JpaRepository: proporciona algunos métodos relacionados con JPA, como vaciar el contexto de persistencia y eliminar registros en un lote.

Un ejemplo de controlador que implementa filtrado, paginación y búsqueda puede ser:

 @GetMapping("/all")
    public ResponseEntity<?> listado(
            // Podemos buscar por los campos que quieramos... nombre, precio... así construir consultas
            @RequestParam(required = false, name = "nombre") Optional<String> nombre,
            @RequestParam(required = false, name = "precio") Optional<Double> precio,
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "10") int size,
            @RequestParam(defaultValue = "id") String sort
    ) {
      ...
      Pageable paging = PageRequest.of(page, size, Sort.Direction.ASC, sort);
      Page<Producto> pagedResult = productosRepository.findAll(paging);
      ...
    }

Podemos trabajar con BBDD relacionales de forma sencilla con Spring Data o usar la versión específica para MongoDB.

Definición de entidades

Usaremos las anotaciones de JPA para definir entidades o colecciones, sus atributos y características de los mismos, así como las relacionales existentes.

Definiciones de consultas

Podemos definir consultas personalizadas para las entidades de la aplicación. Para ello podemos usar la anotación @Query con JPQL o @NativeQuery y usar el lenguaje del motor de Base de Datos.

Por otro lado, también podemos definir las consultas en base del nombre del método. Si lo definimos con una signatura determinada con ellos se generará la consulta automáticamente.

Es importante que usando

Spring Security

Spring Security es una librería de seguridad que nos permite controlar el acceso a nuestra aplicación permitiendo mecanismos de autenticación y autorización en base a roles.

Para ello haremos uso de UserDetailsService, un servicio que nos permitirá cargar datos específicos del usuario.

Además, actuará como middleware, analizando las rutas y con ellas a base de roles saber si se puede permitir el acceso a operar con ellas.

security

JWT

Spring Security ofrece una librería para generar y verificar JWT. Gracias a ella podemos realizar el proceso de autenticación y autorización. Json Web Token es un estándar que define una forma auto contenida de transmitir información como JSON. Consta de tres partes separadas por puntos.

  • Header: algoritmo (SHA256, HS512 …) y el tipo de token.
  • Payload: contiene las propiedades(claims) del token.
  • Signature: header (codificado en base64), payload (codificado en base64), una clave, y todo firmado con el algoritmo del header.
  • Claim: porción de información en el cuerpo del token.

La arquitectura de Spring Security para JWT es la siguiente

jwt

Autenticación

jwt02

Autorización

jwt03

Implementación en SpringBoot

Podemos implementar la autenticación y autorización de Spring Security en SpringBoot con JWT de la siguiente manera.

  • Usuarios que extiendan de UserDetails, con ellos usaremos los mecanismos de Spring Security nos indica. Deberemos tener el campo username y password. Además usaremos una lista de roles para la parte de autenticación.
  • CustomUserDetailsService que implementa UserDetailsService con los métodos: loadUserByUsername() y loadUserById().
  • Configuración del PasswordEncoder, por ejemplo con BCryptPasswordEncoder.
  • JwtTokenProvider, donde implementamos los datos del JWT y con ello generar los JWT según nuestras necesidades, así como verificar los mismos.
  • JwtAuthorizationFilter que extiende de OncePerRequestFilter. Nos permite definir el filtro de la cadena de autenticación/autorización en base al contenido del JWT y de nuestra información en BB.DD.
  • JwtAuthenticationEntryPoint que implementa AuthenticationEntryPoint. Nos permite definir el comportamiento de la aplicación cuando no se ha autenticado o el JWT no es el correcto.
  • SecurityConfig que extiende de WebSecurityConfigurerAdapter. Es la clase principal del sistema de Spring Security y se define en base a todas las anteriores.
    • Usará userDetailsService y passwordEncoder.
    • Su authenticationEntryPoint será en base a jwtAuthenticationEntryPoint
    • Definiremos las políticas de acceso en base a roles si ha pasado la autenticación. Es decir, las políticas de autorización por rutas, o verbos HTTP.
    • Aplicará todo estos procesos en base a a los filtros definidos en jwtAuthorizationFilter.

Documentación

Para documentar nuestra API REST podemos hacer uso de Swagger. Swagger es un conjunto de herramientas de software de código abierto para diseñar, construir, documentar, y utilizar servicios web RESTful. Además podemos usar su UI para testear nuestra API.

Pruebas

Junit y Mockito

Podemos probar nuestra API Rest como cualquier aplicación Java usando las librerías JUnit y Mockito, que vienen incluidas en las dependencias de pruebas de Spring.

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

De esta manera podemos realizar test unitarios y de integración sobre repositorios, servicios y controladores. Podemos hacer uso de las anotaciones @Mock, @MockBean e @InjectMocks según nuestros intereses para facilitar el proceso de configurar nuestros mocks.

MockMvc

Con MockMvc podemos mockear desde la propia aplicación las llamadas a la propia API y con ello analizar el funcionamiento de los controladores a nivel de integración con el resto del sistema. Esto nos hace que tengamos un cliente rest que interactúa con nuestro servicio, realizando las peticiones (resquest) oportunas para obtener los resultados de dicha petición al servicio (response).

Posteriormente, podemos analizar usado asserciones si los resultados obtenidos (una vez procesado el JSON de respuesta), son los resultados esperados, como siempre lo haríamos.

Alternativamente, podemos usar lso expect de esta librerías para realizar los test analizando en JSON directamente.

Postman

Para probar nuestra API podemos usar Postman. Con ella podemos probar nuestra API REST y analizar su comportamiento. Además podemos documentarla y subirla a la nube para que pueda ser probada por otros usuarios.

Despliegue

Docker

Para facilitar el despliegue de nuestra API podemos usar Docker. Podemos crear un contenedor de nuestra API y ejecutarla en el puerto por defecto de nuestra API. Además, podemos subir nuestra API a la nube para que pueda ser usada por otros usuarios usando Docker Hub.

Usando Dockefile

Podemos usar el Dockerfile para crear nuestra API. Puedes consultar el Dockerfile. Para generar y ejecutar el contenedor, usamos:

docker build --tag=joseluisgs/springboot-productos-dam:latest . 
docker run -p6969:6969 joseluisgs/spring-boot-productos-dam:latest

Para subirla a Docker Hub, usamos:

docker push joseluisgs/springboot-productos-dam:latest

Usando Docker Compose

Podemos usar Docker Compose para desplegar nuestra API. Puedes consultar el fichero docker-compose.yml. Para levantar lso contenedores y construir las imágenes

docker-compose up --build

Para parar nuestros contenedores

docker-compose down

Heroku

Para subir y distribuir nuestra API en la nube, podemos usar el servicio de Heroku Heroku. Con ello podemos desplegar a partir de los cambios en nuestro repositorio de manera continua. Para ello, necesitamos una cuenta de Heroku y una cuenta de Github. Lo primero es instalar y configurar el CLI de Heroku. Puedes leer toda la información aquí. También puedes automatizar el proceso con Maven.

Debemos tener en cuenta que el entorno de ejecución de Heroku es Java 8. Si nuestro proyecto es Java 11 (<java.version>11</java.version>) debes cambiarlo a 8, o, crear en la raíz de tu proyecto un fichero llamado system.properties, con la cadena java.runtime.version=11.

Por otro lado, Heroku expone el puerto 8080 por defecto. Si quieres usar otro puerto, debes indicarlo en la plataforma como variable de entorno, o usar este. Puedes consultar la documentación de Heroku al respecto.

Antes de publicar en Heroku, debemos tener en cuenta que nuestro repositorio debe estar actualizado en el último commit. Para ello, debemos ejecutar el siguiente comando:

git add .
git commit -m "heroku init"

Ahora creamos nuestra aplicación Heroku o con su web, o usando el CLI instalado con el siguiente comando:

heroku create springboot-productos-dam

Desplegamos la apliacación con el siguiente comando:

git push heroku master

El tiempo de despliegue tarda un poco, una vez terminada puedes ver la consola remota con:

heroku open

Puedes consultar los logs con:

heroku logs --tail

Podremos consultarla una vez desplegada en: https://springboot-productos-dam.herokuapp.com/rest/productos/

Como es de suponer, el servicio de Heroku al ser gratis, tiene algunas limitaciones, como el almacenamiento efímero de ficheros persistente, o el uso de base de datos, la cual podemos usar una versión limitada y gratis de PostgreSQL que ofrecen. Si no, debemos usar una alternativa de pago, o usar para el almacenamiento de ficheros otras opciones existentes y usar otras bases de datos en la nube, como MongoDB Atlas, o alternativas globales como Amazon Web Services S3 o Google Firebase.

Autor

Codificado con 💖 por José Luis González Sánchez

Twitter GitHub

Contacto

Cualquier cosa que necesites házmelo saber por si puedo ayudarte 💬 .

        

Licencia

Este proyecto está licenciado bajo licencia MIT, si desea saber más, visite el fichero LICENSE para su uso docente y educativo.

You might also like...

Projeto realizado durante o bootcamp da Generation.

Projeto realizado durante o bootcamp da Generation.

Projeto de conclusão do BlOCO - I QUAL A MISSÃO DO PROJETO? Disseminar a cultura de doação voluntária de sangue entre a população. O POSSO DOAR nasceu

Oct 19, 2021

Conteúdo prático realizado em sala durante o projeto Entra21 Em aditivo oportunidades de aprendizado em

Conteúdo prático realizado em sala durante o projeto Entra21 Em aditivo oportunidades de aprendizado em

entra21 Java avançado Repositório com as práticas realizadas em aula Conteúdo prático realizado em sala durante o projeto Entra21 Em aditivo oportunid

Oct 4, 2022

Sistema de control de computadoras con base de datos

 Sistema de control de computadoras con base de datos

Sistema sobre control de computadoras con base de datos en PostgreSQL donde se puede registrar una computadora, en procesos podemos buscar una computadora según su numero de serie y registrar el estado actual de una computadora.

Jan 23, 2022

Aplicación Java tipo Ant con conexión a BD SQLite y CRUD.

CRUD-Java-Netbeans-TDEA Aplicación Java tipo Ant con conexión a BD SQLite y CRUD. Este proyecto es para el curso Desarrollo de Software 2 en el Tecnol

Dec 16, 2022

Hacktoberfest 2022 : Repository for open-source contributions towards Hacktoberfest 2022

Hacktoberfest 2022  : Repository for open-source contributions towards Hacktoberfest 2022

Hacktoberfest 2022 OPEN Pull Request - FREE T-SHIRT's 😢 DON'T COMMIT ~ PR REPO HAS BEEN EXCULDED ( DON'T KNOW THE EXACT REASON ~ RUMORS ARE THAT THIS

Jan 9, 2023

Programación de Servicios y Procesos - 01 Programación Multiproceso. 2DAM. Curso 2021-2022

Programación de Servicios y Procesos - 01 Programación Multiproceso. 2DAM. Curso 2021-2022

Programación de Servicios y Procesos - 01 Programación Multiproceso Tema 01 Programación Multiproceso. Curso 2021/2022. Contenidos Concurrencia y Para

Dec 27, 2022

Repository for FIRST Tech Challenge team 3916 Apex Robotics for the 2021-2022 game year (Freight Frenzy)

FTC Team 3916 - Apex Robotics This is our repo for the 2020-2021 game year - Ultimate Goal Installation Clone this repo. You can do this through the w

Nov 4, 2021

Concurrent Programming - 2021/2022 - Fall - LI51D - LI51N

s2122i-li51d-li51n Concurrent Programming - 2021/2022 - Fall - LI51D - LI51N See docs for documentation resources. See jvm for JVM-based code examples

Apr 8, 2022

Programación de Servicios y Procesos - 03 Programación de comunicaciones en red. 2DAM. Curso 2021-2022

Programación de Servicios y Procesos - 03 Programación de comunicaciones en red. 2DAM. Curso 2021-2022

Programación de Servicios y Procesos - 03 Programación de comunicaciones en red Tema 03. Programación de comunicaciones en red. Curso 2021/2022. Conte

Dec 27, 2022
Owner
José Luis González Sánchez
Dr. en Informática (PhD). Profe de Secundaria en DAM/DAW/ASIR. Soy GitHub Campus Advisor y Embajador de GitKraken. Tenis, rock, guitarra y buenos momentos.
José Luis González Sánchez
Programación - 03 Aplicación de Estructuras de Almacenamiento. 1DAM. Ejercicios realizados por el alumnado. Curso 2021-2022

Programacion-03-Ejercicios-2021-2022 Programación - 03 Aplicación de Estructuras de Almacenamiento. 1DAM. Ejercicios realizados por el alumnado. Curso

José Luis González Sánchez 15 Dec 27, 2022
Programación - 05 Programación Avanzada Orientada a Objetos. 1DAM. Ejercicios realizados por el alumnado. Curso 2021-2022.

Programacion-05-Ejercicios-2021-2022 Programación - 05 Programación Avanzada Orientada a Objetos. 1DAM. Ejercicios realizados por el alumnado. Curso 2

José Luis González Sánchez 7 Dec 27, 2022
Programación - 06 Tipos de Datos Asbtractos. 1DAM. Ejercicios realizados por el alumnado. Curso 2021-2022.

Programacion-06-Ejercicios-2021-2022 Programación - 06 Tipos de Datos Abstractos. 1DAM. Ejercicios realizados por el alumnado. Curso 2021-2022 ¿Cómo C

José Luis González Sánchez 7 Dec 27, 2022
Programación - 04 Programación Orientada a Objetos. 1DAM. Ejercicios realizados por el alumnado. Curso 2021-2022.

Programacion-04-Ejercicios-2021-2022 Programación - 04 Programación Orientada a Objetos. 1DAM. Ejercicios realizados por el alumnado. Curso 2021-2022

José Luis González Sánchez 8 Dec 27, 2022
Acceso a Datos - 02 XML. 2DAM. Ejercicios realizados por el alumnado. Curso 2021-2022

Acceso a Datos - 02 - Ejercicios - 2021-2022 Acceso a Datos - 02 XML. 2DAM. Ejercicios realizados por el alumnado. Curso 2021-2022 ¿Cómo Colaborar? Es

José Luis González Sánchez 5 Dec 27, 2022
Programación - Ejemplo de Colecciones y Genéricos con TDAs. 1DAM. Curso 2021-2022.

Programación - Tipo de Datos Abstractos, Colecciones y Genéricos Tema 06 Tipo de Datos Abstracto. 1DAM. Curso 2021/2022. Programación - Tipo de Datos

José Luis González Sánchez 8 Sep 15, 2022
Spring Productos DAM

Sencillo Microservicio en Spring realizado con el alumnado de DAM en 2021/2022.

José Luis González Sánchez 13 Oct 6, 2022
Projeto Realizado na Semana Spring React

Para rodar o web site basta executar o arquivo java e depois os camandos: npm install yarn start Tecnologias usadas para criar o web site: Frontend: R

Hitalo chaves 4 Sep 15, 2021
循序渐进,学习Spring Boot、Spring Boot & Shiro、Spring Batch、Spring Cloud、Spring Cloud Alibaba、Spring Security & Spring Security OAuth2,博客Spring系列源码:https://mrbird.cc

Spring 系列教程 该仓库为个人博客https://mrbird.cc中Spring系列源码,包含Spring Boot、Spring Boot & Shiro、Spring Cloud,Spring Boot & Spring Security & Spring Security OAuth2

mrbird 24.8k Jan 6, 2023
Projeto realizado em SQUAD na Generation Brasil

projeto-integrador Projeto integrador realizado em SQUAD na Generation Brasil Autores Caique Batista Inaie Forster João Claúdio Melissa Amorim Sâmila

João Claudio 5 Nov 25, 2021