Crear un JAR con dependencias con Apache Maven
¿Qué es un JAR con dependencias? Un requisito típico de los proyectos es agregar la salida junto con sus dependencias, módulos y otros archivos en…
En este artículo, examinaremos a fondo los archivos pom.xml y settings.xml en Apache Maven, incluyendo ejemplos prácticos y explicaciones detalladas de sus componentes. Si trabajas con Java o cualquier lenguaje basado en la JVM, comprender estos dos archivos es esencial para gestionar tus proyectos de forma eficiente.
Maven utiliza una filosofía de convención sobre configuración: con una estructura de directorios estándar y un archivo pom.xml bien definido, Maven sabe cómo compilar, empaquetar, probar y distribuir tu proyecto sin necesidad de especificar cada paso manualmente. El archivo settings.xml, por su parte, complementa esta configuración con parámetros específicos del entorno donde se ejecuta Maven.
pom.xml)El archivo POM (Project Object Model) es el archivo XML central en Maven que define el proyecto, su configuración y sus dependencias. Se encuentra en la raíz de cada proyecto Maven y es el punto de partida que Maven lee para ejecutar cualquier operación.
Cada vez que ejecutas un comando como mvn clean install, Maven parsea el pom.xml para determinar qué dependencias descargar, qué plugins ejecutar y cómo empaquetar el resultado final.
Las coordenadas Maven son el conjunto mínimo de elementos que identifican de forma única un artefacto en el ecosistema Maven. Todo pom.xml debe definir al menos estas tres coordenadas:
modelVersion: Especifica la versión del modelo de objetos de proyecto que se está utilizando. Actualmente, el valor estándar es 4.0.0.groupId: Identifica de forma única la organización o grupo al que pertenece el proyecto, utilizando la notación de nombre de dominio inverso (por ejemplo, com.miempresa).artifactId: Es el nombre del proyecto. Junto con el groupId, forma el identificador único del artefacto.version: Define la versión del proyecto. Maven distingue entre versiones estables (por ejemplo, 1.0.0) y versiones en desarrollo con el sufijo -SNAPSHOT (por ejemplo, 1.0.0-SNAPSHOT), lo que afecta directamente cómo se resuelven y cachean las dependencias.Estas tres coordenadas (groupId, artifactId y version) se conocen comúnmente como las coordenadas GAV y son el mecanismo que utiliza Maven para localizar cualquier artefacto en un repositorio.
Además de las coordenadas, el POM puede incluir metadatos descriptivos:
packaging: Especifica el tipo de empaquetado del proyecto (por ejemplo, jar, war, ear, pom). Si no se especifica, el valor por defecto es jar.name: Un nombre legible para el proyecto, utilizado en la documentación generada.description: Una descripción breve del propósito del proyecto.url: La URL del sitio web del proyecto.Estos son los bloques que controlan el comportamiento real del proyecto:
properties: Define las propiedades que se pueden utilizar en el archivo POM como variables. Son especialmente útiles para centralizar versiones de dependencias y configuraciones repetidas. Se referencian con la sintaxis ${nombre.propiedad}.dependencies: Contiene la lista de dependencias del proyecto. Cada dependencia se define con sus propias coordenadas Maven (groupId, artifactId y version).parent: Define la relación padre-hijo en proyectos multi-módulo. El POM hijo hereda configuraciones, dependencias y plugins del padre.modules: En proyectos multi-módulo, lista los submódulos del proyecto principal. Maven los construye en el orden correcto según sus interdependencias.dependencyManagement: Permite centralizar las versiones de las dependencias en un POM padre sin agregarlas directamente al classpath. Los módulos hijos solo necesitan declarar groupId y artifactId, y la versión se hereda automáticamente.El elemento scope dentro de cada dependencia define el alcance de su disponibilidad en el classpath. Maven soporta los siguientes scopes:
| Scope | Descripción | Ejemplo típico |
|---|---|---|
compile |
Disponible en compilación, pruebas y ejecución. Es el scope por defecto. | Spring Framework, Apache Commons |
provided |
Disponible en compilación y pruebas, pero NO en ejecución (el contenedor lo provee). | Servlet API, Lombok |
runtime |
NO disponible en compilación, pero sí en pruebas y ejecución. | Drivers JDBC (MySQL, PostgreSQL) |
test |
Solo disponible durante la fase de pruebas. | JUnit, Mockito |
system |
Similar a provided, pero requiere especificar la ruta al JAR manualmente. |
JARs propietarios locales |
import |
Solo se usa dentro de dependencyManagement para importar un BOM (Bill of Materials). |
Spring Boot Dependencies BOM |
El bloque build contiene la configuración de la construcción del proyecto:
plugins: Define los plugins del proceso de construcción. Los plugins son el mecanismo principal de Maven para ejecutar tareas concretas (compilar, empaquetar, ejecutar pruebas, generar documentación, etc.).pluginManagement: Similar a dependencyManagement, pero para plugins. Define configuraciones de plugin a nivel de proyecto padre que los módulos hijos pueden heredar.executions: Dentro de un plugin, configura objetivos (goals) específicos y las fases del ciclo de vida a las que se vinculan.configuration: Define la configuración específica del plugin, como parámetros de compilación, versión de Java, entre otros.El siguiente ejemplo muestra un pom.xml completo de un proyecto multi-módulo que utiliza la mayoría de los elementos descritos anteriormente:
<?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>
<!-- Coordenadas del proyecto -->
<groupId>com.miempresa</groupId>
<artifactId>mi-aplicacion</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>pom</packaging>
<!-- Metadatos -->
<name>Mi Aplicación</name>
<description>Aplicación de ejemplo con Maven</description>
<url>https://www.miempresa.com/mi-aplicacion</url>
<!-- Módulos del proyecto -->
<modules>
<module>modulo-core</module>
<module>modulo-web</module>
<module>modulo-api</module>
</modules>
<!-- Propiedades centralizadas -->
<properties>
<java.version>17</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring.version>6.1.4</spring.version>
<junit.version>5.10.2</junit.version>
</properties>
<!-- Gestión centralizada de dependencias -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</dependencyManagement>
<!-- Dependencias comunes a todos los módulos -->
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.12</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<!-- Configuración de build -->
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.12.1</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.2.5</version>
<executions>
<execution>
<id>unit-tests</id>
<phase>test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<includes>
<include>**/*Test.java</include>
</includes>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
En este ejemplo podemos observar cómo se integran los distintos elementos: las properties centralizan versiones que luego se referencian con ${}, el bloque dependencyManagement define versiones que los módulos hijos heredan, las dependencies incluyen ejemplos de distintos scopes (runtime, provided, test), y el bloque build configura plugins con sus respectivas ejecuciones.
settings.xmlMientras que el pom.xml viaja con el proyecto (se comparte entre todos los desarrolladores vía control de versiones), el archivo settings.xml contiene configuraciones específicas del entorno donde se ejecuta Maven. Este archivo nunca debe incluirse en el repositorio del proyecto, ya que puede contener credenciales y configuraciones locales.
Maven busca el archivo settings.xml en dos ubicaciones, y las combina si ambas existen:
<MAVEN_HOME>/conf/settings.xml — Aplica a todos los usuarios del sistema.~/.m2/settings.xml — Aplica solo al usuario actual. Si existe un conflicto entre ambos, la configuración del usuario tiene prioridad.localRepository: Especifica la ubicación del repositorio local de Maven. Por defecto es ~/.m2/repository. Aquí Maven almacena todas las dependencias descargadas para evitar descargarlas nuevamente.offline: Activa el modo offline de Maven (true/false). Cuando está activado, Maven no intenta descargar dependencias de repositorios remotos y solo utiliza las que ya están en el repositorio local.proxies: Define la configuración del servidor proxy. Es esencial en entornos corporativos donde el acceso a internet pasa por un proxy.servers: Define las credenciales para repositorios con autenticación. Las credenciales se vinculan al repositorio mediante un id que debe coincidir con el id del repositorio declarado en el pom.xml.mirrors: Permite redirigir solicitudes a repositorios específicos. Un uso común es redirigir todo el tráfico de Maven Central hacia un repositorio corporativo interno como Nexus o Artifactory.profiles: Define perfiles activables según condiciones específicas (sistema operativo, propiedades del sistema, etc.). Permiten adaptar la configuración de Maven a distintos entornos sin modificar el pom.xml.activeProfiles: Lista los perfiles que deben activarse por defecto en cada ejecución de Maven.settings.xmlEl siguiente ejemplo muestra un settings.xml con los componentes principales configurados:
<?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.2.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.2.0
http://maven.apache.org/xsd/settings-1.2.0.xsd">
<!-- Repositorio local personalizado -->
<localRepository>/home/usuario/.m2/repository</localRepository>
<!-- Modo offline desactivado -->
<offline>false</offline>
<!-- Configuración de proxy corporativo -->
<proxies>
<proxy>
<id>proxy-corporativo</id>
<active>true</active>
<protocol>https</protocol>
<host>proxy.miempresa.com</host>
<port>8080</port>
<username>usuario</username>
<password>contraseña</password>
<nonProxyHosts>localhost|*.miempresa.com</nonProxyHosts>
</proxy>
</proxies>
<!-- Credenciales para repositorios privados -->
<servers>
<server>
<id>nexus-releases</id>
<username>deploy-user</username>
<password>deploy-password</password>
</server>
<server>
<id>nexus-snapshots</id>
<username>deploy-user</username>
<password>deploy-password</password>
</server>
</servers>
<!-- Mirror de Maven Central hacia Nexus interno -->
<mirrors>
<mirror>
<id>nexus-central</id>
<mirrorOf>central</mirrorOf>
<name>Nexus Corporativo</name>
<url>https://nexus.miempresa.com/repository/maven-central/</url>
</mirror>
</mirrors>
<!-- Perfiles de entorno -->
<profiles>
<profile>
<id>entorno-desarrollo</id>
<repositories>
<repository>
<id>nexus-snapshots</id>
<url>https://nexus.miempresa.com/repository/maven-snapshots/</url>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
</profile>
<profile>
<id>entorno-produccion</id>
<repositories>
<repository>
<id>nexus-releases</id>
<url>https://nexus.miempresa.com/repository/maven-releases/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
</profile>
</profiles>
<!-- Perfil activo por defecto -->
<activeProfiles>
<activeProfile>entorno-desarrollo</activeProfile>
</activeProfiles>
</settings>
En este ejemplo se puede ver cómo el settings.xml configura un entorno corporativo típico: el proxy permite el acceso a internet, las credenciales de servers autorizan el despliegue a Nexus, el mirror redirige las descargas de Maven Central al repositorio interno, y los perfiles permiten alternar entre configuraciones de desarrollo y producción.
settings.xmlLos archivos pom.xml y settings.xml trabajan en conjunto para proporcionar una configuración completa. Entender cómo se combinan es clave para diagnosticar problemas de configuración:
pom.xml define la configuración específica del proyecto: qué dependencias necesita, cómo se construye, qué plugins utiliza.settings.xml define la configuración del entorno: desde dónde se descargan las dependencias, qué credenciales usar, qué proxy atravesar.settings.xml del usuario sobre el global.Cuando necesitas ver la configuración final resultante de combinar el pom.xml de tu proyecto, el POM padre (si existe), y el settings.xml, Maven proporciona el comando:
mvn help:effective-pom
Este comando muestra el POM efectivo: el resultado final de resolver toda la herencia, interpolación de propiedades y configuraciones externas. Es una herramienta invaluable para depurar problemas de configuración, ya que te permite ver exactamente qué valores está utilizando Maven en cada elemento.
De forma similar, puedes ver la configuración efectiva del settings.xml con:
mvn help:effective-settings
Los archivos pom.xml y settings.xml son componentes fundamentales de Apache Maven que permiten una gestión de proyectos eficiente y flexible. El pom.xml es el corazón de tu proyecto — define qué construir y con qué dependencias, mientras que el settings.xml adapta Maven al entorno donde se ejecuta. Su comprensión profunda permite a los desarrolladores aprovechar al máximo las capacidades de Maven para construir, gestionar y distribuir proyectos de software de manera efectiva.
¿Quieres profundizar más en Maven? Te invito a explorar nuestro curso completo «Apache Maven: Construcción de proyectos de cero a avanzado», donde cubrimos estos temas en mayor detalle.
¿Te ha resultado útil esta guía? Compártela con tus compañeros desarrolladores y no olvides visitar nuestra página de cursos online para ver la lista completa de cursos que tenemos disponibles.