En Maven, la conifguración de repositorios remotos es crucial para acceder a dependencias. El repositorio central predeterminado se especifica en el archivo de modelo POM, ubicado en el JAR de construcción de Maven:
Archivo: $M2_HOME/lib/maven-model-builder-3.3.3.jar
Ruta: org/apache/maven/model/pom-4.0.0.xml
Contenido de configuración del repositorio:
<repositories>
<repository>
<id>central</id>
<name>Repositorio Central</name>
<url>https://repo.maven.apache.org/maven2</url>
<layout>default</layout>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
Las dependencias en Maven pueden ser transitivas, lo que implica que si el módulo A depende de B, y B depende de C, entonces A hereda la dependencia de C. En caso de rutas de dpeendencia múltiples, Maven selecciona la más corta para evitar conflictos; si las rutas tienen la misma longitud, se aplica el orden de declaración en el POM.
A continuación, se presenta un ejemplo práctico de un proyecto multi-módulo que demuestra estos conceptos. Se crearán dos módulos: uno para el acceso a datos y otro para la lógica de servicio.
Creación del módulo de acceso a datos:
Este módulo, llamado datos-usuario, utiliza MyBatis y log4j. Su estructura incluye clases para entidades, inetrfaces DAO y archivos de configuración.
Archivo POM del módulo datos-usuario:
<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.ejemplo.usuario</groupId>
<artifactId>datos-usuario</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.9</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.17.1</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Interfaz para el acceso a datos:
package com.ejemplo.usuario.dao;
import com.ejemplo.usuario.modelo.Cliente;
public interface ClienteAccesoDatos {
public Cliente buscarPorCredenciales(Cliente cliente);
}
Clase de entidad:
package com.ejemplo.usuario.modelo;
public class Cliente {
private Integer identificador;
private String nombreUsuario;
private String clave;
public Integer getIdentificador() {
return identificador;
}
public void setIdentificador(Integer identificador) {
this.identificador = identificador;
}
public String getNombreUsuario() {
return nombreUsuario;
}
public void setNombreUsuario(String nombreUsuario) {
this.nombreUsuario = nombreUsuario;
}
public String getClave() {
return clave;
}
public void setClave(String clave) {
this.clave = clave;
}
}
Archivo de mapeo MyBatis:
<?xml version="1.0" encoding="UTF-8" ?>
<mapper namespace="com.ejemplo.usuario.dao.ClienteAccesoDatos">
<select id="buscarPorCredenciales" parameterType="Cliente" resultType="Cliente">
SELECT * FROM tabla_clientes WHERE nombreUsuario=#{nombreUsuario} AND clave=#{clave}
</select>
</mapper>
Configuración de log4j:
log4j.rootLogger=INFO, Consola
log4j.appender.Consola=org.apache.log4j.ConsoleAppender
log4j.appender.Consola.layout=org.apache.log4j.PatternLayout
log4j.appender.Consola.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n
Archivo de configuración MyBatis:
<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
<typeAliases>
<package name="com.ejemplo.usuario.modelo"/>
</typeAliases>
</configuration>
Para que otros módulos puedan usar este, se debe instalar en el repositorio local mediante el comando mvn install, lo que generará un archivo JAR en el directorio target.
Creación del módulo de servicio:
Este módulo, llamado servicio-usuario, depende del módulo anterior e integra Spring Framework para la inyección de dependencias y gestión de transacciones.
Archivo POM del módulo servicio-usuario:
<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.ejemplo.usuario</groupId>
<artifactId>servicio-usuario</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.15</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.15</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.7</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.ejemplo.usuario</groupId>
<artifactId>datos-usuario</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
Interfaz de servicio:
package com.ejemplo.usuario.servicio;
import com.ejemplo.usuario.modelo.Cliente;
public interface ServicioCliente {
public Cliente autenticar(Cliente cliente);
}
Implementación del servicio con Spring:
package com.ejemplo.usuario.servicio.impl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ejemplo.usuario.dao.ClienteAccesoDatos;
import com.ejemplo.usuario.modelo.Cliente;
import com.ejemplo.usuario.servicio.ServicioCliente;
@Service("servicioCliente")
public class ServicioClienteImpl implements ServicioCliente{
@Autowired
private ClienteAccesoDatos accesoDatos;
public Cliente autenticar(Cliente cliente) {
return accesoDatos.buscarPorCredenciales(cliente);
}
}
Configuración de Spring para el módulo de servicio:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<context:component-scan base-package="com.ejemplo.usuario.servicio" />
<bean id="fuenteDatos" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/base_usuarios"/>
<property name="username" value="admin"/>
<property name="password" value="secreta"/>
</bean>
<bean id="sesionSql" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="fuenteDatos" />
<property name="mapperLocations" value="classpath:com/ejemplo/usuario/mappers/*.xml"></property>
<property name="configLocation" value="classpath:mybatis-config.xml"></property>
</bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.ejemplo.usuario.dao" />
<property name="sqlSessionFactoryBeanName" value="sesionSql"></property>
</bean>
<bean id="gestorTransacciones" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="fuenteDatos" />
</bean>
<tx:advice id="consejoTx" transaction-manager="gestorTransacciones">
<tx:attributes>
<tx:method name="insertar*" propagation="REQUIRED" />
<tx:method name="actualizar*" propagation="REQUIRED" />
<tx:method name="buscar*" propagation="REQUIRED" read-only="true" />
<tx:method name="*" propagation="REQUIRED" read-only="true" />
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="operacionServicio" expression="execution(* com.ejemplo.usuario.servicio.*.*(..))" />
<aop:advisor advice-ref="consejoTx" pointcut-ref="operacionServicio" />
</aop:config>
</beans>
Este ejemplo ilustra cómo configurar repositorios, gestionar dependencias transitivas y estructurar proyectos multi-módulo en Maven.