diff --git a/010_spring_boot/api_rest/api3/src/main/resources/application-prod.yml b/010_spring_boot/api_rest/api3/src/main/resources/application-prod.yml new file mode 100644 index 0000000..9e51b2a --- /dev/null +++ b/010_spring_boot/api_rest/api3/src/main/resources/application-prod.yml @@ -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} \ No newline at end of file diff --git a/010_spring_boot/api_rest/api3/src/main/resources/application-test.yml b/010_spring_boot/api_rest/api3/src/main/resources/application-test.yml index 474c5c3..35f8a0f 100644 --- a/010_spring_boot/api_rest/api3/src/main/resources/application-test.yml +++ b/010_spring_boot/api_rest/api3/src/main/resources/application-test.yml @@ -1,5 +1,5 @@ spring: datasource: - url: jdbc:mysql://${TEST_DB_URL}?createDatabaseIfNotExist=true&serverTimezone=UTC - username: ${DB_USER} - password: ${DB_PASS} \ No newline at end of file + url: ${DATASOURCE_TEST_URL} + username: ${DATASOURCE_USERNAME} + password: ${DATASOURCE_PASSWORD} \ No newline at end of file diff --git a/010_spring_boot/api_rest/api3/src/main/resources/application.properties b/010_spring_boot/api_rest/api3/src/main/resources/application.properties deleted file mode 100644 index 88e1c83..0000000 --- a/010_spring_boot/api_rest/api3/src/main/resources/application.properties +++ /dev/null @@ -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 \ No newline at end of file diff --git a/010_spring_boot/api_rest/api3/src/main/resources/application.yml b/010_spring_boot/api_rest/api3/src/main/resources/application.yml new file mode 100644 index 0000000..573c03c --- /dev/null +++ b/010_spring_boot/api_rest/api3/src/main/resources/application.yml @@ -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} \ No newline at end of file diff --git a/010_spring_boot/api_rest/api3/target/api-0.0.1-SNAPSHOT.jar b/010_spring_boot/api_rest/api3/target/api-0.0.1-SNAPSHOT.jar new file mode 100644 index 0000000..aa03272 Binary files /dev/null and b/010_spring_boot/api_rest/api3/target/api-0.0.1-SNAPSHOT.jar differ diff --git a/010_spring_boot/jpa_avanzado.md b/010_spring_boot/jpa_avanzado.md index 59514b4..3f611e9 100644 --- a/010_spring_boot/jpa_avanzado.md +++ b/010_spring_boot/jpa_avanzado.md @@ -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 ... diff --git a/010_spring_boot/spring_boot_3.md b/010_spring_boot/spring_boot_3.md index 8d9cc41..6e407d2 100644 --- a/010_spring_boot/spring_boot_3.md +++ b/010_spring_boot/spring_boot_3.md @@ -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///vollmed_api \ + -DDATASOURCE_USERNAME= \ + -DDATASOURCE_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 `war` al archivo `pom.xml` del +proyecto, y esta etiqueta debe ser hija de la etiqueta raíz `` + + ```xml + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 3.0.0 + + + med.voll + api + 0.0.1-SNAPSHOT + api + war + ``` + +2. Agregar la siguiente dependencia: + + ```xml + + org.springframework.boot + spring-boot-starter-tomcat + provided + + ``` + +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 + + org.graalvm.buildtools + native-maven-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.