Spring Boot 3: doc, test y prep. para impl.: Aula 5

This commit is contained in:
devfzn 2023-09-21 17:47:25 -03:00
parent f33e0b19ec
commit 320884a2a3
Signed by: devfzn
GPG Key ID: E070ECF4A754FDB1
7 changed files with 228 additions and 20 deletions

View File

@ -0,0 +1,17 @@
spring:
profile.active: prod
datasource:
url: ${DATASOURCE_URL}
username: ${DATASOURCE_USERNAME}
password: ${DATASOURCE_PASSWORD}
jpa:
show-sql: false
properties:
hibernate:
format_sql: false
server:
error:
include-stacktrace: never
api:
security:
secret: ${JWT_SECRET}

View File

@ -1,5 +1,5 @@
spring:
datasource:
url: jdbc:mysql://${TEST_DB_URL}?createDatabaseIfNotExist=true&serverTimezone=UTC
username: ${DB_USER}
password: ${DB_PASS}
url: ${DATASOURCE_TEST_URL}
username: ${DATASOURCE_USERNAME}
password: ${DATASOURCE_PASSWORD}

View File

@ -1,13 +0,0 @@
spring.datasource.url=jdbc:mysql://${DB_URL}
spring.datasource.username=${DB_USER}
spring.datasource.password=${DB_PASS}
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
server.error.include-stacktrace=never
api.security.secret=${JWT_SECRET}
spring.main.banner-mode=CONSOLE
spring.output.ansi.enabled=ALWAYS

View File

@ -0,0 +1,22 @@
spring:
profile.active: dev, test, prod
datasource:
url: ${DATASOURCE_URL}
username: ${DATASOURCE_USERNAME}
password: ${DATASOURCE_PASSWORD}
jpa:
show-sql: true
properties:
hibernate:
format_sql: true
main:
banner-mode: CONSOLE
output:
ansi:
enabled: ALWAYS
server:
error:
include-stacktrace: never
api:
security:
secret: ${JWT_SECRET}

View File

@ -7,8 +7,9 @@
- Hibernate
[user guide](https://docs.jboss.org/hibernate/orm/current/userguide/html_single/Hibernate_User_Guide.html)
Trabajando sobre el [proyecto](./jpa/tienda/src/main/java/com/latam/alura/tienda/)
anterior
Trabajando sobre el proyecto anterior
[tienda](./jpa/tienda/src/main/java/com/latam/alura/tienda/),
como [tienda2](./jpa/tienda2/src/main/java/com/latam/alura/tienda/)
```mermaid
erDiagram
@ -69,8 +70,8 @@ Web Console server running at http://127.0.1.1:8082 (only local connections)
```
En [pom.xml](./jpa/tienda2/pom.xml) cambiar la `url` para usar base de datos
creada anteriormente
En [persistence.xml](./jpa/tienda2/src/main/resources/META-INF/persistence.xml)
cambiar la `url` para usar base de datos creada anteriormente
```xml
...

View File

@ -1218,4 +1218,185 @@ class ConsultaControllerTest {
## Build del proyecto
Migración de configuración de desarrollo `application.properties` (xml) a
`application.yml`. Con esto se tienen 3 perfiles de configuración:
- **DEV** [application.yml](./api_rest/api3/src/main/resources/application.yml)
- **TEST**
[application-test.yml](./api_rest/api3/src/main/resources/application-test.yml)
- **PROD**
[application-prod.yml](./api_rest/api3/src/main/resources/application-prod.yml)
Una forma de hacer la ***build*** del proyecto es en la pestañaa de maven en:
`api -> Lifecycle -> package` *click-secundario* y `Run Maven Build`.
Para correr la aplicación pasando manualmente la configuración y variables de
entorno:
```sh
java -DDATASOURCE=jdbc:mysql//<DB_URL>/vollmed_api \
-DDATASOURCE_USERNAME=<USER> \
-DDATASOURCE_PASSWORD=<PASSWORD> \
-jar target/api-0.0.1-SNAPSHOT.jar --spring.profiles.active=prod
```
#### WAR
Los proyectos que utilizan Spring Boot generalmente usan el formato `jar` para
empaquetar la aplicación. Sin embargo, Spring Boot brinda soporte para empaquetar
en formato `war`, que era ampliamente utilizado en aplicaciones Java antiguas.
Para hacer el build del proyecto empaquete la aplicación en un archivo en formato
`war`, se deben realizar los siguientes cambios:
1. Agregar la etiqueta `<packaging>war</packaging>` al archivo `pom.xml` del
proyecto, y esta etiqueta debe ser hija de la etiqueta raíz `<project>`
```xml
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.0.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>med.voll</groupId>
<artifactId>api</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>api</name>
<packaging>war</packaging>
```
2. Agregar la siguiente dependencia:
```xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
```
3. Modificar en la clase principal del proyecto `ApiApplication` para heredar de
la clase `SpringBootServletInitializer`, y sobrescribir el método `configure`:
```java
@SpringBootApplication
public class ApiApplication extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(
SpringApplicationBuilder application) {
return application.sources(ApiApplication.class);
}
public static void main(String[] args) {
SpringApplication.run(ApiApplication.class, args);
}
}
```
Ahora, al realizar el build del proyecto, se generará un archivo con la
extensión `war` en el directorio target, en lugar del `jar`.
#### GraalVM Native Image
Una de las características más destacadas de la versión 3 de Spring Boot es el
soporte para imágenes nativas, algo que reduce significativamente el consumo de
memoria y el tiempo de inicio de una aplicación. Algunos otros frameworks
competidores de Spring Boot, como ***Micronaut*** y ***Quarkus***, ya ofrecían
soporte para esta función.
De hecho, era posible generar imágenes nativas en aplicaciones con Spring Boot
antes de la versión 3, pero esto requería el uso de un proyecto llamado
***Spring Native*** que agregaba soporte para ello. Con la llegada de la versión
3 de Spring Boot, ya no es necesario utilizar este proyecto.
#### Native Image
Una imagen nativa es una tecnología utilizada para compilar una aplicación Java,
incluyendo todas sus dependencias, generando un archivo binario ejecutable que
puede ser ejecutado directamente en el sistema operativo sin necesidad de utilizar
la JVM. Aunque no se ejecute en una JVM, la aplicación también contará con sus
recursos, como la gestión de memoria, el recolector de basura y el control de la
ejecución de hilos.
> Documentación tecnología de [imágenes nativas](https://www.graalvm.org/native-image).
#### Native Imagen com Spring Boot 3
Una forma muy sencilla de generar una imagen nativa de la aplicación es mediante
un plugin de Maven, que debe incluirse en el archivo `pom.xml`:
```xml
<plugin>
<groupId>org.graalvm.buildtools</groupId>
<artifactId>native-maven-plugin</artifactId>
</plugin>
```
Esta es la única modificación necesaria en el proyecto. Después de esto, la
generación de la imagen debe hacerse a través de la terminal, con el siguiente
comando de Maven que se ejecuta en el directorio raíz del proyecto:
`./mvnw -Pnative native:compile`
Este comando puede tardar varios minutos en completarse, lo cual es completamente
normal.
> **NOTE** Para ejecutar el comando anterior y generar la imagen nativa del
proyecto, es necesario que tener instalado en ***GraalVM*** *(una máquina virtual
Java con soporte para la función Native Image)* en una versión igual o superior
a **22.3**.
Después de que el comando anterior termine, se generará en la terminal un registro
como el siguiente:
```log
Top 10 packages in code area: Top 10 object types in image heap:
3,32MB jdk.proxy4 19,44MB byte[] for embedded resources
1,70MB sun.security.ssl 16,01MB byte[] for code metadata
1,18MB java.util 8,91MB java.lang.Class
936,28KB java.lang.invoke 6,74MB java.lang.String
794,65KB com.mysql.cj.jdbc 6,51MB byte[] for java.lang.String
724,02KB com.sun.crypto.provider 4,89MB byte[] for general heap data
650,46KB org.hibernate.dialect 3,07MB c.o.s.c.h.DynamicHubCompanion
566,00KB org.hibernate.dialect.function 2,40MB byte[] for reflection metadata
563,59KB com.oracle.svm.core.code 1,30MB java.lang.String[]
544,48KB org.apache.catalina.core 1,25MB c.o.s.c.h.DynamicHu~onMetadata
61,46MB for 1482 more packages 9,74MB for 6281 more object types
--------------------------------------------------------------------------------
9,7s (5,7% of total time) in 77 GCs | Peak RSS: 8,03GB | CPU load: 7,27
--------------------------------------------------------------------------------
Produced artifacts:
/home/rodrigo/Desktop/api/target/api (executable)
/home/rodrigo/Desktop/api/target/api.build_artifacts.txt (txt)
================================================================================
Finished generating 'api' in 2m 50s.
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 03:03 min
[INFO] Finished at: 2023-01-17T12:13:04-03:00
[INFO] ------------------------------------------------------------------------
```
La imagen nativa se genera en el directorio `target/`, junto con el archivo `jar`
de la aplicación, como un archivo ejecutable de nombre api.
A diferencia del archivo `jar`, que se ejecuta en la JVM mediante el comando
`java -jar`, la imagen nativa es un archivo binario y debe ejecutarse directamente
desde la terminal: `./target/api`
Al ejecutar el comando anterior se generará el registro de inicio de la
aplicación, que al final muestra el tiempo que tardó la aplicación en iniciarse:
```log
INFO 127815 --- [restartedMain] med.voll.api.ApiApplication : Started ApiApplication in 0.3 seconds (process running for 0.304)
```
La aplicación tardó menos de medio segundo en iniciarse, algo realmente
impresionante, ya que cuando se ejecuta en la JVM, a través del archivo `jar`,
este tiempo aumenta a alrededor de 5 segundos.