UD2 · Sección 9 — Maven: gestión de dependencias externas
| Dato | Valor |
|---|---|
| Unidad Didáctica | UD2 — Programación Orientada a Objetos con la API de Java |
| Resultado de Aprendizaje | RA2 — Escribe y prueba programas sencillos, reconociendo y aplicando los fundamentos de la programación orientada a objetos. |
| Sección | 9 de 10 — Maven: gestión de dependencias externas |
| Evaluación | 1.ª Evaluación |
| Duración estimada | 2,5 horas lectivas |
| Criterios de evaluación cubiertos | CE 2.2 (escribe programas simples), CE 2.7 (incorpora y utiliza librerías de objetos), CE 2.9 (utiliza el entorno integrado de desarrollo en la creación y compilación de programas simples) |
| Prerrequisitos | UD1 completa, UD2 Secciones 1 a 8 |
| Paquete del código de ejemplo | dam.programacion.ud2 |
| Herramientas | JDK 25, IntelliJ IDEA Community, Maven 3.9.x, conexión a internet |
1. Punto de partida
Hasta ahora, todo lo que has usado vive dentro del JDK: String, Math, Random, LocalDate, Integer, Objects... Son clases que Oracle empaqueta y prueba, y que se incluyen con el JDK 25 que instalaste en UD1. No has necesitado instalar nada adicional: con import te bastaba.
Pero el mundo Java es inmenso y el JDK solo es el núcleo. Para hacer cosas más allá de lo básico (probar código con JUnit, trabajar con JSON, conectar con una base de datos, generar PDFs, construir interfaces gráficas con JavaFX), necesitas librerías externas: código escrito por terceros y publicado en internet para que cualquiera lo use.
Aquí entra Maven, la herramienta de construcción (build tool) más usada en el ecosistema Java. En UD1 la usaste de forma automática al crear el proyecto en IntelliJ; en esta sección vas a entender qué hace realmente, cómo gestiona dependencias y cómo puedes añadir librerías externas a tu proyecto. Es la sección que abre la puerta al ecosistema Java profesional.
Al terminar serás capaz de: entender el pom.xml, buscar y añadir dependencias externas, ejecutar los comandos básicos del ciclo de vida de Maven, y tener un primer contacto con JUnit 5 para escribir pruebas automáticas.
2. Qué es Maven y qué problema resuelve
2.1. El problema de las dependencias
Imagina que quieres usar una librería como Jackson para trabajar con JSON. Sin una herramienta de gestión de dependencias, tendrías que:
- Ir a la web del proyecto Jackson.
- Buscar la última versión estable.
- Descargar el
.jar(el formato de paquete de Java). - Descargar también todos los
.jarde los que Jackson depende (porque Jackson a su vez usa otras librerías). - Descargar las dependencias de esas dependencias (dependencias transitivas).
- Colocar todos esos
.jaren tu proyecto. - Configurar IntelliJ para que los encuentre al compilar.
- Repetir el proceso cada vez que sale una nueva versión o cuando cambias de equipo.
Para una librería como Jackson, esto puede significar descargar manualmente 10 o 20 archivos .jar. Es insostenible.
2.2. La solución de Maven
Maven automatiza todo ese proceso. Tú solo declaras en el pom.xml qué librerías necesitas y en qué versión; Maven se encarga de:
- Descargarlas de un repositorio central (Maven Central).
- Descargar también sus dependencias transitivas.
- Hacerlas disponibles para tu código al compilar y ejecutar.
- Cachearlas localmente (en tu carpeta
~/.m2/repository) para no volver a descargarlas en otros proyectos.
Analogía del cocinero y el supermercado. Sin Maven, eres un cocinero que tiene que ir a granjas, molinos y bodegas para conseguir cada ingrediente, transportarlos a casa y almacenarlos. Con Maven, haces una lista de la compra y Maven la entrega en tu cocina. Cada ingrediente ya viene con sus subingredientes preprocesados (harina, levadura, etc.). Y si vuelves a pedir lo mismo mañana, lo tiene en la despensa y no vuelve a salir a buscarlo.
3. Anatomía del pom.xml
El pom.xml es el corazón de un proyecto Maven. POM significa Project Object Model: describe tu proyecto y sus necesidades. Ya lo viste brevemente en UD1; ahora vamos a desmenuzarlo.
3.1. Las coordenadas GAV
Cada proyecto Maven (y cada librería) tiene una identidad única formada por tres elementos, conocidos como coordenadas GAV:
| Coordenada | Significado | Ejemplo |
|---|---|---|
groupId |
Identifica a la organización o grupo que hace el proyecto | dam, org.junit.jupiter, com.fasterxml.jackson |
artifactId |
Identifica el proyecto o librería concreto dentro del grupo | programacion, junit-jupiter, jackson-databind |
version |
Versión exacta | 1.0.0, 5.11.0, 2.17.0 |
La combinación de los tres es única en todo el ecosistema Maven: no puede haber dos librerías con el mismo groupId + artifactId + version. Por eso Maven puede localizarlas sin ambigüedad.
Analogía del DNI. Las coordenadas GAV son como un DNI compuesto: groupId es el apellido (la familia a la que perteneces), artifactId es tu nombre de pila (quién eres dentro de la familia), y version es tu edad o momento vital (la versión concreta de ti en este instante).
3.2. Propiedades
La sección <properties> define variables reutilizables. Las más importantes para nosotros:
maven.compiler.sourceymaven.compiler.target: versión de Java del código fuente y del bytecode generado. Para Java 25, usa25.project.build.sourceEncoding: codificación de los archivos fuente, normalmenteUTF-8.
3.3. Dependencias
Cada <dependency> tiene sus propias coordenadas GAV. El elemento <scope> (ámbito) es opcional pero importante:
| Scope | Cuándo está disponible | Uso típico |
|---|---|---|
compile (por defecto) |
Siempre: compilar, probar, ejecutar | Librerías necesarias en producción |
test |
Solo durante los tests | JUnit, Mockito |
provided |
En compilación y tests, pero no se empaqueta (lo proporciona el entorno) | Servlet API en servidores |
runtime |
En tests y ejecución, pero no en compilación | Drivers JDBC |
system |
Como provided, pero con ruta explícita (evitar) |
Casos raros, no recomendado |
JUnit, por ejemplo, se declara con <scope>test</scope> porque solo lo necesitas al ejecutar los tests, no en el .jar final que entregas a producción.
4. El repositorio Central de Maven
4.1. Qué es
Maven Central (https://search.maven.org/) es un repositorio público enorme con cientos de miles de librerías Java. Es el supermercado de Maven: cualquier librería que quieras usar, probablemente esté ahí.
También hay sitios web más amigables para buscar, como MvnRepository (https://mvnrepository.com/), que ofrece una interfaz más clara y muestra versiones, dependencias transitivas y estadísticas de uso.
4.2. Cómo buscar una dependencia
Procedimiento típico:
- Ve a https://mvnrepository.com/ o https://search.maven.org/.
- Busca por nombre de librería (por ejemplo, "junit jupiter" o "jackson databind").
- Selecciona la versión adecuada (normalmente la última estable).
- Copia el fragmento XML de dependencia que te ofrecen (suele haber un botón "Maven" o similar).
- Pégalo dentro de
<dependencies>en tupom.xml. - Recarga el proyecto Maven en IntelliJ (aparece un icono de recarga en la esquina superior derecha del editor cuando detecta cambios en el
pom.xml).
4.3. Repositorios: local y remoto
Maven usa varios niveles de repositorios:
flowchart LR
C["Tu codigo<br/>necesita Jackson"] --> M["Maven"]
M --> L["Repositorio local<br/>~/.m2/repository"]
L -->|Si esta| OK["Usar copia local"]
L -->|Si no esta| R["Repositorio remoto<br/>Maven Central"]
R --> D["Descargar a local"]
D --> OK
style M fill:#1565c0,color:#fff,stroke:#0d47a1
style L fill:#2e7d32,color:#fff,stroke:#1b5e20
style R fill:#ef6c00,color:#fff,stroke:#e65100
style OK fill:#2e7d32,color:#fff,stroke:#1b5e20
- Repositorio local (
~/.m2/repositoryen Linux/Mac,%USERPROFILE%\.m2\repositoryen Windows): carpeta en tu disco donde Maven cachea todo lo que descarga. Si dos proyectos usan la misma librería, solo se descarga una vez. - Repositorio remoto (Maven Central por defecto): de donde Maven descarga lo que no tiene localmente.
- Repositorios internos (opcionales): en empresas grandes, se usa un servidor tipo Nexus o Artifactory como intermediario, para caching y para publicar librerías privadas. No las verás en este curso.
5. El ciclo de vida de Maven
Maven define un conjunto de fases que se ejecutan en orden. Cada fase ejecuta todas las anteriores automáticamente. Las más usadas:
| Fase | Qué hace | Comando |
|---|---|---|
validate |
Valida que el pom.xml es correcto |
mvn validate |
compile |
Compila el código fuente (src/main/java) |
mvn compile |
test |
Compila y ejecuta los tests (src/test/java) |
mvn test |
package |
Empaqueta el proyecto en un .jar (o .war) |
mvn package |
verify |
Ejecuta verificaciones de calidad (integración, checks) | mvn verify |
install |
Copia el .jar en tu repositorio local |
mvn install |
deploy |
Sube el .jar a un repositorio remoto |
mvn deploy |
Regla fundamental: al ejecutar una fase, Maven ejecuta todas las anteriores en orden. Si haces mvn package, se ejecutarán validate, compile, test y package. Si los tests fallan, Maven se detiene y no genera el .jar.
Analogía de la fábrica. Imagina una fábrica de coches:
validate: comprueba que tienes los planos correctos.compile: fabrica las piezas según los planos.test: prueba cada pieza (¿el motor arranca? ¿los frenos frenan?).package: ensambla el coche y lo deja listo en la puerta.install: lo aparca en tu garaje.deploy: lo envía al concesionario.
No puedes empaquetar sin haber pasado los tests; no puedes instalar sin haber empaquetado. Todo fluye en orden.
5.1. Cómo ejecutar Maven
Desde IntelliJ
En el panel lateral "Maven" de IntelliJ puedes ver las fases del ciclo de vida y ejecutarlas con doble clic. También puedes crear configuraciones de ejecución personalizadas.
Desde la terminal
En la carpeta raíz del proyecto (donde está el pom.xml):
mvn clean borra la carpeta target/ (donde Maven guarda los compilados). Es útil cuando algo va mal y quieres empezar de cero.
6. Estructura de carpetas de un proyecto Maven
Maven impone una estructura de carpetas estándar. Si la respetas, Maven "encuentra" todo sin configuración adicional.
| Carpeta | Contenido |
|---|---|
src/main/java |
Código fuente de tu aplicación |
src/main/resources |
Ficheros no Java: configuración, plantillas, imágenes |
src/test/java |
Tests automáticos |
src/test/resources |
Recursos para los tests |
target |
Generada al compilar; contiene .class, .jar, informes de tests. Se puede borrar sin problema |
pom.xml |
Descriptor del proyecto |
En IntelliJ, esta estructura se refleja visualmente con colores: las carpetas java se marcan como "Sources Root" (azul), las resources como "Resources Root", las de tests en tonos verdes. IntelliJ detecta automáticamente la estructura Maven.
7. Primer contacto con JUnit 5
Vamos a poner en práctica lo aprendido añadiendo JUnit 5, el framework de pruebas estándar de Java, y escribiendo un test básico. No es objetivo de esta sección enseñar JUnit a fondo (eso será más adelante en el curso); solo queremos ver cómo encaja una dependencia externa en el proyecto.
7.1. Añadir la dependencia
Edita tu pom.xml para que tenga la dependencia:
Tras guardar, IntelliJ detectará el cambio y mostrará un icono de recarga (esquina superior derecha del editor). Haz clic para que Maven descargue la librería. La primera vez tarda varios segundos porque descarga JUnit y todas sus dependencias transitivas.
7.2. Escribir un test básico
Crea la clase dam.programacion.ud2.Calculadora en src/main/java:
Y la clase de test dam.programacion.ud2.CalculadoraTest en src/test/java:
Aquí he adelantado sintaxis de UD4 (clase propia con métodos), pero el objetivo es solo que veas cómo JUnit encaja. Lo importante ahora:
- La clase de test termina en
Testpor convención. - Cada método de test lleva la anotación
@Test. assertEquals(esperado, real)comprueba que dos valores son iguales.assertThrows(TipoExcepcion.class, () -> ...)comprueba que se lanza una excepción.
7.3. Ejecutar los tests
- En IntelliJ: clic derecho sobre la clase
CalculadoraTest→ "Run 'CalculadoraTest'". - Desde terminal:
mvn test.
Si todo va bien, verás una barra verde y un mensaje indicando que los 6 tests pasaron. Si algún test falla, verás una barra roja con el detalle.
7.4. El panel de Maven en IntelliJ
El panel lateral "Maven" de IntelliJ te muestra:
- La jerarquía de dependencias del proyecto (incluidas las transitivas).
- Las fases del ciclo de vida (Life cycle).
- Los plugins instalados.
Es tu centro de control para todo lo relacionado con Maven. Acostúmbrate a consultarlo.
8. Diagrama del flujo de trabajo con Maven
flowchart TD
A["Necesito una libreria"] --> B["Buscar en mvnrepository.com"]
B --> C["Copiar fragmento XML"]
C --> D["Pegar en pom.xml dentro de dependencies"]
D --> E["Guardar pom.xml"]
E --> F["IntelliJ detecta el cambio<br/>(icono de recarga)"]
F --> G["Recargar proyecto Maven"]
G --> H["Maven descarga la libreria<br/>+ dependencias transitivas"]
H --> I["La libreria esta disponible<br/>para tu codigo"]
I --> J["import y usar"]
J --> K["Compilar / Test / Package<br/>con mvn o IntelliJ"]
style A fill:#1565c0,color:#fff,stroke:#0d47a1
style B fill:#1565c0,color:#fff,stroke:#0d47a1
style D fill:#ef6c00,color:#fff,stroke:#e65100
style H fill:#2e7d32,color:#fff,stroke:#1b5e20
style K fill:#6a1b9a,color:#fff,stroke:#4a148c
9. Errores comunes
| Error | Qué pasa | Cómo evitarlo |
|---|---|---|
Olvidar recargar Maven tras editar el pom.xml |
IntelliJ no ve la nueva dependencia y marca errores | Pulsa el icono de recarga (esquina sup. derecha) o usa Ctrl+Shift+O |
| No tener conexión a internet la primera vez | Maven no puede descargar la dependencia | Conéctate la primera vez; luego queda cacheada en ~/.m2 |
| Mezclar versiones incompatibles de librerías | Errores en tiempo de ejecución (ClassNotFoundException, NoSuchMethodError) |
Usa versiones estables recientes; revisa el árbol de dependencias en IntelliJ |
Poner la dependencia fuera de <dependencies> |
No se reconoce | Respeta la estructura: <dependencies> contiene varios <dependency> |
Olvidar el <scope>test</scope> para JUnit |
JUnit se empaqueta en el .jar final, innecesariamente |
Marca como test todo lo que solo uses en tests |
Borrar target/ con Maven en ejecución |
Errores de bloqueo de archivos | Ejecuta mvn clean antes de borrar manualmente |
Confundir groupId con artifactId al añadir dependencia |
Maven no encuentra la librería | Copia el fragmento XML directamente de mvnrepository |
| Usar una versión SNAPSHOT | Comportamiento inestable (es una versión en desarrollo) | Para producción, usa versiones sin SNAPSHOT |
Editar archivos en target/ |
Se pierden al recompilar | target/ es generada; nunca edites su contenido |
10. Resumen
| Concepto | Idea clave |
|---|---|
| Maven | Herramienta de construcción y gestión de dependencias para Java |
pom.xml |
Descriptor del proyecto: identidad, propiedades, dependencias |
| Coordenadas GAV | groupId + artifactId + version identifican un proyecto/librería |
| Maven Central | Repositorio público con cientos de miles de librerías |
| Repositorio local | ~/.m2/repository, caché local de todo lo descargado |
| Dependencias transitivas | Maven las descarga automáticamente |
<scope> |
Cuándo está disponible una dependencia: compile, test, provided, runtime |
| Estructura de carpetas | src/main/java, src/main/resources, src/test/java, src/test/resources |
| Fases del ciclo de vida | validate, compile, test, package, verify, install, deploy |
mvn clean |
Borra target/ para empezar de cero |
| JUnit 5 | Framework de pruebas; se declara con <scope>test</scope> |
@Test, assertEquals, assertThrows |
Anotación y utilidades básicas de JUnit |
| Panel Maven de IntelliJ | Centro de control de dependencias y ciclo de vida |
11. Cuestionario de autoevaluación
Preguntas
-
¿Qué problema resuelve Maven? ¿Qué ocurriría sin él?
-
¿Qué significan las siglas GAV y qué representa cada una?
-
Si dos librerías se llamaran igual y tuvieran la misma versión, ¿cómo las distinguiría Maven?
-
¿Qué etiqueta del
pom.xmldefine la versión de Java del compilador? -
¿Para qué sirve el elemento
<scope>en una dependencia? Nombra dos valores posibles y su significado. -
¿Dónde almacena Maven las librerías descargadas localmente?
-
Si ejecutas
mvn package, ¿qué fases se ejecutan antes depackage? -
¿Para qué sirve
mvn clean? ¿Se pierde código fuente al ejecutarlo? -
¿En qué carpeta debe estar el código fuente principal y en cuál el de tests?
-
¿Por qué JUnit se declara con
<scope>test</scope>? -
¿Qué anotación marca un método como test en JUnit 5?
-
¿Cómo se comprueba en JUnit que dos valores son iguales? ¿Y que un método lanza una excepción?
-
Si añades una dependencia al
pom.xmly IntelliJ no la reconoce, ¿qué debes hacer? -
¿Qué es una dependencia transitiva? ¿Quién la descarga?
-
¿Por qué no se recomienda editar archivos en la carpeta
target/?
Soluciones
-
Maven automatiza la descarga y gestión de librerías externas y sus dependencias. Sin Maven, tendrías que buscar manualmente cada
.jaren internet, descargarlo, colocarlo en el proyecto, configurar el classpath, y repetir el proceso para cada dependencia transitiva. Sería inviable para proyectos reales con decenas de librerías. -
GAV son las siglas de GroupId, ArtifactId, Version. Identifican unívocamente a un proyecto o librería en el ecosistema Maven.
groupIdidentifica a la organización,artifactIdal proyecto concreto, yversiona la versión específica. -
Por el
groupId, que identifica a la organización. Aunque dos librerías se llamen igual (artifactId) y tengan la misma versión, si tienengroupIddistinto, son librerías distintas. -
maven.compiler.source(versión del código fuente) ymaven.compiler.target(versión del bytecode generado). Para Java 25, ambos a25. Se definen dentro de la sección<properties>. -
<scope>indica cuándo está disponible una dependencia. Valores: compile(por defecto): disponible en compilación, tests y ejecución.test: solo durante los tests.provided: en compilación y tests, pero el entorno lo proporciona en ejecución.-
runtime: solo en tests y ejecución, no en compilación. -
En el repositorio local:
~/.m2/repositoryen Linux/Mac,%USERPROFILE%\.m2\repositoryen Windows. -
validate,compileytest. Maven ejecuta todas las fases anteriores en orden antes depackage. Si los tests fallan, no se llega a empaquetar. -
mvn cleanborra la carpetatarget/, que contiene los compilados (.class), el.jary los informes de tests. No se pierde código fuente:target/es generada por Maven y se puede regenerar en cualquier momento compilando de nuevo. -
Código fuente principal:
src/main/java. Tests:src/test/java. Recursos:src/main/resourcesysrc/test/resources. -
Porque JUnit solo se usa durante los tests, no en el código de producción. Marcarlo como
testevita que se empaquete en el.jarfinal que entregas, reduciendo tamaño y evitando confusiones. -
@Test, del paqueteorg.junit.jupiter.api. Se coloca justo encima del método. -
Para igualdad:
assertEquals(esperado, real). Para excepciones:assertThrows(TipoExcepcion.class, () -> metodoQueDeberiaLanzar()). -
Recargar el proyecto Maven. En IntelliJ, hay un icono de recarga en la esquina superior derecha del editor cuando detecta cambios en el
pom.xml. También puedes usarCtrl+Shift+Oo abrir el panel Maven y pulsar el botón de recarga. -
Una dependencia transitiva es una librería que tu dependencia directa necesita para funcionar. Por ejemplo, si añades Jackson, este a su vez necesita otras librerías. Maven descarga automáticamente todas las dependencias transitivas; no tienes que declararlas.
-
Porque
target/es generada por Maven cada vez que compilas o empaquetas. Cualquier cambio que hagas en sus archivos se pierde en la próxima compilación.target/no es código fuente, es producto de la compilación.
Evaluación del cuestionario
| Aciertos | Nivel |
|---|---|
| 14-15 | Dominas la sección. Adelante con la siguiente. |
| 10-13 | Bien, repasa los puntos fallados. |
| 6-9 | Repasa la sección, especialmente el ciclo de vida y la estructura de carpetas. |
| Menos de 6 | Vuelve a leer con calma y crea un proyecto Maven desde cero en IntelliJ siguiendo los pasos. |
12. Información ampliada y próximos pasos
- Maven Central (buscador oficial): https://search.maven.org/
- MvnRepository (interfaz más amigable): https://mvnrepository.com/
- Documentación oficial de Maven: https://maven.apache.org/guides/
- Documentación de JUnit 5: https://junit.org/junit5/docs/current/user-guide/
Próximos pasos:
- Practica añadiendo una dependencia. Busca en MvnRepository la librería "Apache Commons Lang" (útil para operaciones con strings), añádela al
pom.xmly usa alguna de sus clases en un programa. Comprueba que Maven la descarga y que tu código compila. - Ejecuta el ciclo de vida completo. Desde la terminal, en la carpeta del proyecto, ejecuta
mvn clean test,mvn clean packageymvn install. Observa la salida de Maven y entiende qué hace en cada paso. - Escribe tus propios tests. Crea una clase
Validadorcon métodos simples (esEmailValido,esMayorDeEdad) y tests en JUnit para verificar su comportamiento. Aunque profundizaremos en tests más adelante, este primer contacto te dará confianza. - Avanza a la Sección 10 de UD2. Ejercicios y actividades: actividades con
String,Math,RandomyLocalDate, informe de texto conStringBuilder, generador de contraseñas y preparación para la prueba objetiva RA2. Es la sección que cierra la unidad y consolida lo aprendido.