Saltar a contenido

Semana 13 - Gestores de Dependencias en Java

¿Para qué sirve un gestor de dependencias?

Un gestor de dependencias es una herramienta que automatiza la gestión de bibliotecas y dependencias externas en un proyecto de software. Sus principales funciones son:

  • Descarga automática de dependencias: Obtiene bibliotecas y sus versiones específicas desde repositorios remotos (como Maven Central o JCenter).
  • Gestión de versiones: Resuelve conflictos entre versiones de dependencias y asegura compatibilidad.
  • Configuración centralizada: Define todas las dependencias en un solo archivo, facilitando su mantenimiento.
  • Automatización de tareas: Compila, prueba, empaqueta y despliega el proyecto.
  • Reproducibilidad: Garantiza que todos los entornos (desarrollo, producción) usen las mismas versiones de bibliotecas.
  • Transitividad: Maneja dependencias de dependencias automáticamente.

En Java, los gestores de dependencias más populares son Maven y Gradle.


Maven

¿Qué es Maven?

Maven es un gestor de dependencias y herramienta de construcción ampliamente utilizado en proyectos Java. Se basa en un archivo de configuración XML llamado pom.xml (Project Object Model).

Características principales

  • Estructura estandarizada: Define una estructura de directorios predeterminada (src/main/java, src/test/java, etc.).
  • Repositorios centralizados: Usa Maven Central como repositorio principal, pero permite configurar otros.
  • Ciclo de vida de construcción: Incluye fases predefinidas como compile, test, package, install, y deploy.
  • Gestión de dependencias: Declara dependencias en pom.xml, y Maven las descarga y gestiona automáticamente.
  • Plugins: Extiende funcionalidades mediante plugins (por ejemplo, para empaquetar un JAR o ejecutar pruebas).

Ejemplo de pom.xml

<?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.example</groupId>
    <artifactId>my-app</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>3.3.4</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>3.3.4</version>
            </plugin>
        </plugins>
    </build>
</project>

Ventajas

  • Configuración sencilla y estandarizada.
  • Gran comunidad y soporte.
  • Amplia disponibilidad de dependencias en Maven Central.
  • Fácil integración con herramientas CI/CD (Jenkins, GitHub Actions).

Desventajas

  • Archivos XML extensos en proyectos grandes.
  • Menos flexible que Gradle para tareas personalizadas.
  • Curva de aprendizaje inicial para configurar plugins avanzados.

Comandos comunes

  • mvn clean: Limpia el directorio de compilación.
  • mvn compile: Compila el código.
  • mvn test: Ejecuta pruebas.
  • mvn package: Empaqueta el proyecto (JAR/WAR).
  • mvn install: Instala el artefacto en el repositorio local.
  • mvn dependency:tree: Muestra el árbol de dependencias.

Gradle

¿Qué es Gradle?

Gradle es un gestor de dependencias y herramienta de construcción moderna que usa un lenguaje basado en Groovy o Kotlin (DSL) para configurar proyectos. Su archivo principal es build.gradle.

Características principales

  • Flexibilidad: Permite scripts personalizados y configuraciones complejas.
  • Rendimiento: Usa un modelo incremental y caching para construcciones más rápidas.
  • Sintaxis concisa: Los archivos build.gradle son más compactos que pom.xml.
  • Soporte multiplataforma: Compatible con Java, Android, Kotlin, y más.
  • Ecosistema de plugins: Similar a Maven, pero con mayor facilidad para tareas personalizadas.

Ejemplo de build.gradle (Kotlin DSL)

plugins {
    id("org.springframework.boot") version "3.3.4"
    id("io.spring.dependency-management") version "1.1.6"
    java
}

group = "com.example"
version = "1.0-SNAPSHOT"

repositories {
    mavenCentral()
}

dependencies {
    implementation("org.springframework.boot:spring-boot-starter-web:3.3.4")
    testImplementation("org.springframework.boot:spring-boot-starter-test:3.3.4")
}

tasks.test {
    useJUnitPlatform()
}

Ventajas

  • Sintaxis más legible y concisa.
  • Construcciones más rápidas gracias a la compilación incremental.
  • Mayor flexibilidad para proyectos no estándares.
  • Soporte nativo para Kotlin DSL, ideal para proyectos modernos.

Desventajas

  • Menor estandarización que Maven, lo que puede llevar a configuraciones inconsistentes.
  • Curva de aprendizaje para Groovy/Kotlin si no estás familiarizado.
  • Menos adoptado en proyectos empresariales tradicionales.

Comandos comunes

  • gradle build: Compila, prueba y empaqueta el proyecto.
  • gradle clean: Limpia el directorio de compilación.
  • gradle test: Ejecuta pruebas.
  • gradle dependencies: Muestra las dependencias.
  • gradle wrapper: Genera el Gradle Wrapper para reproducibilidad.

Comparación entre Maven y Gradle

Característica Maven Gradle
Lenguaje de configuración XML (pom.xml) Groovy/Kotlin (build.gradle)
Rendimiento Más lento en proyectos grandes Más rápido (compilación incremental)
Flexibilidad Menos flexible, estandarizado Muy flexible, personalizable
Curva de aprendizaje Media (XML) Media-alta (Groovy/Kotlin)
Estandarización Alta (convenciones estrictas) Media (más libertad)
Uso principal Proyectos empresariales Proyectos modernos, Android

¿Cuándo usar cada uno? - Maven: Ideal para proyectos que requieren estandarización, simplicidad y una gran comunidad (empresas, proyectos legacy). - Gradle: Mejor para proyectos que necesitan flexibilidad, rendimiento optimizado o están en ecosistemas modernos como Android o Kotlin.


Tutorial: Proyecto Básico con Vaadin, MySQL y JPA (Instalación de dependencias)

En este tutorial, construiremos una aplicación web simple para gestionar tareas usando Vaadin para la interfaz de usuario, Spring Data JPA para la persistencia y MySQL como base de datos. La aplicación permitirá agregar, editar, eliminar y listar tareas con una interfaz amigable.

Tecnologías utilizadas

  • Java 21: Lenguaje de programación.
  • Spring Boot 3.3.4: Framework para el backend.
  • Vaadin 24.5.0: Framework para la interfaz de usuario.
  • Spring Data JPA: Para interactuar con la base de datos.
  • MySQL: Base de datos relacional.
  • Maven: Sistema de construcción.

Prerrequisitos

  • Java 21 instalado (verifica con java -version).
  • Maven instalado (verifica con mvn -version).
  • MySQL instalado y corriendo.
  • Un IDE como IntelliJ IDEA, Eclipse o VS Code (opcional, pero recomendado).

Estructura del Proyecto

La estructura del proyecto sigue el estándar de un proyecto Maven con Spring Boot. A continuación, se detalla la organización de carpetas y archivos:

vaadin-todo-app/
├── src/
│   ├── main/
│   │   ├── java/
│   │   │   └── com/example/vaadintodoapp/
│   │   │       ├── MainView.java                # Vista principal de Vaadin
│   │   │       ├── Task.java                   # Entidad JPA
│   │   │       ├── TaskRepository.java         # Repositorio JPA
│   │   │       └── VaadinTodoAppApplication.java # Clase principal de Spring Boot
│   │   └── resources/
│   │       └── application.properties          # Configuración de la base de datos
├── pom.xml                                     # Archivo de configuración de Maven
└── README.md                                   # (Opcional) Documentación del proyecto

Paso 1: Configurar el Proyecto

1.1 Crear el proyecto Maven

  1. Crea un directorio llamado vaadin-todo-app y navega a él:
    mkdir vaadin-todo-app
    cd vaadin-todo-app
    
  2. Crea un archivo pom.xml con las dependencias necesarias para Spring Boot, Vaadin, JPA y MySQL.
<?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.example</groupId>
    <artifactId>vaadin-todo-app</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>Vaadin To-Do App</name>
    <description>Proyecto básico con Vaadin, MySQL y JPA</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.3.4</version>
        <relativePath/>
    </parent>

    <properties>
        <java.version>21</java.version>
        <vaadin.version>24.5.0</vaadin.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.vaadin</groupId>
            <artifactId>vaadin-spring-boot-starter</artifactId>
            <version>${vaadin.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>
  1. Si usas un IDE, importa el proyecto como un proyecto Maven.

Paso 2: Configurar la Base de Datos

2.1 Crear la base de datos en MySQL

Crea una base de datos llamada todo_db:

CREATE DATABASE todo_db;

2.2 Configurar la conexión a MySQL

Crea el archivo application.properties en src/main/resources para configurar la conexión a la base de datos.

MySQL configuration.

spring.datasource.url = jdbc:mysql://localhost:3306/data_b1?createDatabaseIfNotExist=true&useSSL=false&serverTimezone=UTC
spring.datasource.username = root
spring.datasource.password = 
spring.jpa.hibernate.ddl-auto = update
  • Reemplaza tu_contraseña con la contraseña de tu usuario de MySQL.
  • spring.jpa.hibernate.ddl-auto=update crea o actualiza las tablas automáticamente según las entidades JPA.

Paso 3: Crear el Modelo de Datos

3.1 Definir la Entidad Task

Crea la clase Task en src/main/java/com/example/vaadintodoapp. Esta entidad representa una tarea con un ID, una descripción y un estado (completada o no).

package com.example.vaadintodoapp;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import lombok.Data;

@Entity
@Data
public class Task {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String description;
    private boolean completed;
}
  • @Entity: Marca la clase como una entidad JPA.
  • @Id y @GeneratedValue: Define el campo id como clave primaria con incremento automático.
  • @Data (Lombok): Genera getters, setters y otros métodos automáticamente.

Paso 4: Crear el Repositorio JPA

Crea la interfaz TaskRepository en src/main/java/com/example/vaadintodoapp para manejar las operaciones CRUD.

package com.example.vaadintodoapp;

import org.springframework.data.jpa.repository.JpaRepository;

public interface TaskRepository extends JpaRepository<Task, Long> {
}
  • JpaRepository<Task, Long> proporciona métodos CRUD predefinidos como save, findAll, delete, etc.

Paso 5: Crear la Interfaz de Usuario con Vaadin

Crea la clase MainView en src/main/java/com/example/vaadintodoapp para definir la interfaz de usuario. Esta vista incluye un formulario para agregar/editar tareas y una tabla para mostrarlas.

package com.example.vaadintodoapp;

import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.checkbox.Checkbox;
import com.vaadin.flow.component.grid.Grid;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.textfield.TextField;
import com.vaadin.flow.data.binder.Binder;
import com.vaadin.flow.router.Route;
import org.springframework.beans.factory.annotation.Autowired;

@Route("")
public class MainView extends VerticalLayout {

    private final TaskRepository taskRepository;
    private final TextField descriptionField = new TextField("Descripción");
    private final Checkbox completedCheckbox = new Checkbox("Completada");
    private final Button saveButton = new Button("Guardar");
    private final Button deleteButton = new Button("Eliminar");
    private final Grid<Task> taskGrid = new Grid<>(Task.class);
    private final Binder<Task> binder = new Binder<>(Task.class);

    public MainView(TaskRepository taskRepository) {
        this.taskRepository = taskRepository;

        // Configurar el formulario
        binder.bind(descriptionField, Task::getDescription, Task::setDescription);
        binder.bind(completedCheckbox, Task::isCompleted, Task::setCompleted);

        saveButton.addClickListener(e -> saveTask());
        deleteButton.addClickListener(e -> deleteTask());

        // Configurar la cuadrícula
        taskGrid.setColumns("description", "completed");
        taskGrid.asSingleSelect().addValueChangeListener(e -> {
            binder.setBean(e.getValue());
        });
        refreshGrid();

        // Layout
        HorizontalLayout formLayout = new HorizontalLayout(descriptionField, completedCheckbox, saveButton, deleteButton);
        add(formLayout, taskGrid);
    }

    private void saveTask() {
        Task task = binder.getBean() != null ? binder.getBean() : new Task();
        try {
            binder.writeBean(task);
            taskRepository.save(task);
            refreshGrid();
            binder.setBean(null);
            clearForm();
        } catch (com.vaadin.flow.data.binder.ValidationException e) {
            // Handle validation exception (e.g., show a notification)
            e.printStackTrace();
        }
    }

    private void deleteTask() {
        Task task = binder.getBean();
        if (task != null) {
            taskRepository.delete(task);
            refreshGrid();
            binder.setBean(null);
            clearForm();
        }
    }

    private void refreshGrid() {
        taskGrid.setItems(taskRepository.findAll());
    }

    private void clearForm() {
        descriptionField.clear();
        completedCheckbox.clear();
    }
}
  • @Route(""): Define esta vista como la página principal (ruta raíz).
  • Binder: Vincula los campos del formulario con los atributos de la entidad Task.
  • Grid: Muestra las tareas en una tabla.

Paso 6: Crear la Clase Principal de Spring Boot

Crea la clase VaadinTodoAppApplication en src/main/java/com/example/vaadintodoapp para iniciar la aplicación.

package com.example.vaadintodoapp;

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

@SpringBootApplication
public class VaadinTodoAppApplication {
    public static void main(String[] args) {
        SpringApplication.run(VaadinTodoAppApplication.class, args);
    }
}

Paso 7: Ejecutar la Aplicación

  1. Asegúrate de que MySQL esté corriendo y la base de datos todo_db esté creada.
  2. Desde la raíz del proyecto, ejecuta:
    mvn spring-boot:run
    
  3. Abre tu navegador en http://localhost:8080.

Interfaz de la aplicación

  • Formulario: Ingresa una descripción y marca si la tarea está completada.
  • Botón "Guardar": Agrega una nueva tarea o actualiza una existente.
  • Tabla: Muestra todas las tareas. Selecciona una tarea para editarla o eliminarla.
  • Botón "Eliminar": Elimina la tarea seleccionada.

Paso 8: Probar la Aplicación

  1. Agrega una tarea:
  2. Escribe "Comprar víveres" en el campo de descripción.
  3. Marca la casilla "Completada" si corresponde.
  4. Haz clic en "Guardar".
  5. Edita una tarea:
  6. Selecciona una tarea en la tabla.
  7. Modifica la descripción o el estado.
  8. Haz clic en "Guardar".
  9. Elimina una tarea:
  10. Selecciona una tarea en la tabla.
  11. Haz clic en "Eliminar".