Gestión de dependencias

8 min

Tabla de contenidos


1 — ¿Qué es una dependencia?

Una dependencia es una biblioteca externa que tu proyecto necesita para compilar o ejecutarse. En lugar de reescribir código (análisis JSON, acceso a base de datos, pruebas…), se reutilizan bibliotecas contrastadas.

Maven gestiona estas dependencias automáticamente: las declaras en el pom.xml, y Maven las descarga y las coloca en el classpath.

Sin MavenCon Maven
Descargar cada .jar a manoDeclarar 3 líneas en pom.xml
Gestionar el classpath manualmenteMaven lo construye automáticamente
Encontrar las bibliotecas compatiblesResolución transitiva automática

Una dependencia también se identifica por sus coordenadas GAV (groupId:artifactId:version), exactamente como tu propio proyecto. Así es como Maven sabe qué descargar.

↑ Volver arriba


2 — Declarar una dependencia

Las dependencias se declaran en el bloque <dependencies> del pom.xml. Cada dependencia es una etiqueta <dependency> con sus coordenadas GAV.

xml
<dependencies>

    <!-- Biblioteca Gson de Google para manipular JSON -->
    <dependency>
        <groupId>com.google.code.gson</groupId>
        <artifactId>gson</artifactId>
        <version>2.10.1</version>
    </dependency>

</dependencies>

Para encontrar las coordenadas correctas de una biblioteca, se consulta Maven Central (search.maven.org), que ofrece el bloque XML listo para copiar.

bash
# Tras añadir una dependencia, se dispara la descarga
mvn compile

# O descargar de forma explícita sin compilar
mvn dependency:resolve
ElementoRol
<groupId>La organización que publica la biblioteca
<artifactId>El nombre de la biblioteca
<version>La versión deseada

Maven pone las bibliotecas en caché en ~/.m2/repository. Una biblioteca ya descargada no se vuelve a descargar: por eso los builds siguientes son rápidos.

🔧 Mini-ejercicio — Declara la dependencia Gson (com.google.code.gson:gson:2.10.1) en un bloque <dependency>.

✅ Ver una solución
xml
<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.10.1</version>
</dependency>

↑ Volver arriba


3 — Los alcances (scopes)

El alcance (scope) de una dependencia indica cuándo y dónde está disponible: en la compilación, en las pruebas, en la ejecución, o la proporciona el entorno. Se precisa con <scope>.

xml
<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter</artifactId>
    <version>5.10.2</version>
    <scope>test</scope>   <!-- disponible solo para las pruebas -->
</dependency>
ScopeDisponible en la compilaciónDisponible en las pruebasDisponible en la ejecuciónIncluido en el artefacto
compile (por defecto)
test
provided❌ (lo aporta el servidor)
runtime

Ejemplos concretos:

BibliotecaScope típicoPor qué
JUnittestSolo sirve para ejecutar las pruebas
API ServletprovidedEl servidor (Tomcat) ya la aporta
Controlador JDBCruntimeRequerido en ejecución, no en la compilación
GsoncompileSe usa en todo el código

Poner JUnit en compile en lugar de test es un error frecuente: embarca inútilmente la biblioteca de prueba en tu entregable final. Elige siempre el scope más restrictivo que convenga.

🔧 Mini-ejercicio — Declara una dependencia JUnit Jupiter (5.10.2) en alcance test en el pom.xml.

✅ Ver una solución
xml
<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter</artifactId>
    <version>5.10.2</version>
    <scope>test</scope>
</dependency>

↑ Volver arriba


4 — Los repositorios (repositories)

Maven descarga las dependencias desde repositorios (repositories). Hay tres niveles:

Tipo de repositorioDescripción
Repositorio localCaché en tu máquina: ~/.m2/repository
Maven CentralEl repositorio público mundial, fuente por defecto
Repositorio privadoServidor de empresa (Nexus, Artifactory) para bibliotecas internas

Para añadir un repositorio privado, se declara en el pom.xml:

xml
<repositories>
    <repository>
        <id>nexus-entreprise</id>
        <url>https://nexus.monentreprise.com/repository/maven-public/</url>
    </repository>
</repositories>
bash
# Forzar la actualización de las dependencias desde los repositorios
mvn clean install -U

# Vaciar la caché de una biblioteca para forzar su nueva descarga
# (supresión manual de la carpeta correspondiente en ~/.m2)
CasoRepositorio usado
Biblioteca open-source públicaMaven Central
Biblioteca casera de la empresaRepositorio privado (Nexus/Artifactory)
Biblioteca ya descargadaCaché local ~/.m2

Las empresas usan a menudo un repositorio privado como espejo de Maven Central: acelera las descargas y permite controlar qué bibliotecas están autorizadas.

↑ Volver arriba


5 — La resolución transitiva

Una dependencia puede a su vez depender de otras bibliotecas: son las dependencias transitivas. Maven las descarga automáticamente — no tienes que listarlas.

Declaras una dependencia, Maven resuelve decenas:

xml
<!-- Una sola declaración... -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>3.2.5</version>
</dependency>
<!-- ...trae automáticamente spring-web, jackson, tomcat, etc. -->

Para visualizar el árbol completo:

bash
# Muestra el árbol de dependencias (directas + transitivas)
mvn dependency:tree

Salida típica:

com.exemple:mon-app:jar:1.0.0
+- org.springframework.boot:spring-boot-starter-web:jar:3.2.5:compile
|  +- org.springframework:spring-web:jar:6.1.6:compile
|  +- com.fasterxml.jackson.core:jackson-databind:jar:2.15.4:compile
|  \- org.apache.tomcat.embed:tomcat-embed-core:jar:10.1.20:compile

Cuando dos caminos traen dos versiones distintas de la misma biblioteca, Maven aplica la regla del «más cercano en el árbol» (nearest wins): gana la versión más cercana a tu proyecto.

La resolución transitiva es una de las mayores fuerzas de Maven: declaras tus intenciones de alto nivel, y Maven ensambla todo el puzle de dependencias por ti.

🔧 Mini-ejercicio — Escribe el comando que muestra el árbol completo de dependencias (directas y transitivas).

✅ Ver una solución
bash
mvn dependency:tree

↑ Volver arriba


6 — Diagnosticar y excluir

A veces, una dependencia transitiva da problemas (conflicto de versión, biblioteca indeseada). Maven ofrece herramientas para diagnosticar y corregir.

Para excluir una dependencia transitiva no deseada:

xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>3.2.5</version>
    <exclusions>
        <exclusion>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-to-slf4j</artifactId>
        </exclusion>
    </exclusions>
</dependency>

Comandos de diagnóstico útiles:

ComandoRol
mvn dependency:treeMuestra el árbol completo de dependencias
mvn dependency:analyzeDetecta dependencias no usadas o faltantes
mvn dependency:resolveDescarga todas las dependencias
bash
# Localizar las dependencias declaradas pero no usadas,
# y las usadas pero no declaradas
mvn dependency:analyze

Antes de excluir nada, lanza mvn dependency:tree para entender de dónde viene la dependencia problemática. Nunca se excluye a ciegas.

🔧 Mini-ejercicio — Escribe el comando que localiza las dependencias declaradas pero no usadas (y a la inversa).

✅ Ver una solución
bash
mvn dependency:analyze

↑ Volver arriba


7 — Quiz — Gestión de las dependencias

Question 1

¿Dónde pone Maven en caché las dependencias descargadas?

a) En target/

b) En ~/.m2/repository

c) En src/main/resources

d) En el servidor web

💡 Ver la solución

Respuesta: b) — El repositorio local ~/.m2/repository sirve de caché: una biblioteca ya descargada no se vuelve a descargar.


Question 2

¿Qué scope conviene a JUnit, una biblioteca usada solo para las pruebas?

a) compile

b) runtime

c) test

d) provided

💡 Ver la solución

Respuesta: c) — El scope test deja la dependencia disponible solo para las pruebas y la excluye del entregable final.


Question 3

¿Qué son las dependencias transitivas?

a) Dependencias que hay que listar a mano

b) Las dependencias de tus dependencias, resueltas automáticamente por Maven

c) Dependencias temporales

d) Dependencias de prueba

💡 Ver la solución

Respuesta: b) — Una dependencia declarada trae sus propias dependencias; Maven las descarga automáticamente.


Question 4

¿Qué comando muestra el árbol completo de dependencias?

a) mvn list

b) mvn dependency:tree

c) mvn show-deps

d) mvn package

💡 Ver la solución

Respuesta: b)mvn dependency:tree muestra las dependencias directas y transitivas, útil para diagnosticar conflictos.


Question 5

¿Qué scope elegir para la API Servlet, que aporta el servidor Tomcat?

a) compile

b) test

c) provided

d) runtime

💡 Ver la solución

Respuesta: c)provided: la biblioteca hace falta para compilar, pero el entorno de ejecución (el servidor) ya la aporta.

Corrigé

  1. b — El caché local está en ~/.m2/repository.
  2. c — JUnit va en scope test y no entra en el entregable.
  3. b — Las transitivas son las dependencias de tus dependencias, resueltas por Maven.
  4. b — mvn dependency:tree muestra el árbol completo.
  5. c — La API Servlet es provided porque Tomcat ya la aporta.

↑ Volver arriba


8 — Práctica — Añadir dependencias

Consigna

En un proyecto existente, añade dos dependencias: Gson (com.google.code.gson:gson:2.10.1) en alcance compile para manipular JSON, y JUnit Jupiter (org.junit.jupiter:junit-jupiter:5.10.2) en alcance test. Luego verifica el árbol de dependencias.


Corrección — Bloque <dependencies> esperado

xml
<dependencies>

    <!-- Gson: usada en todo el código (scope compile por defecto) -->
    <dependency>
        <groupId>com.google.code.gson</groupId>
        <artifactId>gson</artifactId>
        <version>2.10.1</version>
    </dependency>

    <!-- JUnit: solo pruebas -->
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter</artifactId>
        <version>5.10.2</version>
        <scope>test</scope>
    </dependency>

</dependencies>

Verificación:

bash
# Descargar y mostrar el árbol de dependencias
mvn dependency:tree

Resultado esperado:

com.exemple:mon-app:jar:1.0.0-SNAPSHOT
+- com.google.code.gson:gson:jar:2.10.1:compile
\- org.junit.jupiter:junit-jupiter:jar:5.10.2:test
   +- org.junit.jupiter:junit-jupiter-api:jar:5.10.2:test
   +- org.junit.jupiter:junit-jupiter-params:jar:5.10.2:test
   \- org.junit.jupiter:junit-jupiter-engine:jar:5.10.2:test

Fíjate en que junit-jupiter trae automáticamente -api, -params y -engine: son sus dependencias transitivas. Solo declaraste una línea, Maven resolvió el resto.

↑ Volver arriba


9 — Síntesis

Puntos a recordar

  1. Una dependencia es una biblioteca externa, identificada por sus coordenadas GAV.
  2. Se declara en <dependencies>; Maven la descarga y la pone en caché en ~/.m2.
  3. Los alcances (compile, test, provided, runtime) controlan cuándo está disponible la dependencia.
  4. Los repositorios: local (~/.m2), Maven Central (público), privado (Nexus/Artifactory).
  5. La resolución transitiva trae automáticamente las dependencias de las dependencias; mvn dependency:tree permite inspeccionarla.

A continuación

Lección 04 — Ciclo de vida y fases: entender las fases (compile, test, package, install, deploy) que orquestan la construcción.

↑ Volver arriba


Todos los derechos reservados. Toda reproducción, difusión, uso o adaptación de este curso, en todo o en parte, está estrictamente prohibida sin la autorización escrita previa del Dr. Haythem REHOUMA.

Curso creado por Dr. Haythem REHOUMA — Desarrollo y despliegue de soluciones de datos