Advertencia de SLF4J: la ruta de clase contiene varios enlaces SLF4J

1. Información general

Cuando usamos SLF4J en nuestras aplicaciones, a veces vemos un mensaje de advertencia sobre múltiples enlaces en el classpath impreso en la consola.

En este tutorial, intentaremos comprender por qué vemos este mensaje y cómo resolverlo.

2. Comprensión de la advertencia

Primero, veamos una advertencia de muestra:

SLF4J: Class path contains multiple SLF4J bindings. SLF4J: Found binding in [jar:file:.../slf4j-log4j12-1.7.21.jar!/org/slf4j/impl/StaticLoggerBinder.class] SLF4J: Found binding in [jar:file:.../logback-classic-1.1.7.jar!/org/slf4j/impl/StaticLoggerBinder.class] SLF4J: See //www.slf4j.org/codes.html#multiple_bindings for an explanation. SLF4J: Actual binding is of type [org.slf4j.impl.Log4jLoggerFactory]

Esta advertencia nos dice que SLF4J ha encontrado dos enlaces. Uno está en slf4j-log4j12-1.7.21.jar y el otro en logback-classic-1.1.7.jar .

Ahora, entendamos por qué vemos esta advertencia.

La fachada de registro simple para Java (SLF4J) sirve como fachada o abstracción simple para varios marcos de registro. Por lo tanto, nos permite conectar nuestro marco de registro deseado en el momento de la implementación.

Para lograr esto, SLF4J busca enlaces (también conocidos como proveedores) en el classpath. Los enlaces son básicamente implementaciones de una clase SLF4J en particular que se pretende extender para conectar un marco de registro específico.

Por diseño, SLF4J solo se vinculará con un marco de registro a la vez. En consecuencia, si hay más de un enlace en la ruta de clase, se emitirá una advertencia .

Vale la pena señalar que los componentes integrados, como bibliotecas o marcos, nunca deben declarar una dependencia en ningún enlace SLF4J. Esto se debe a que cuando una biblioteca declara una dependencia en tiempo de compilación de un enlace SLF4J, impone ese enlace al usuario final. Obviamente, esto niega el propósito básico de SLF4J. En consecuencia, solo deberían depender de la biblioteca slf4j-api .

También es importante tener en cuenta que esto es solo una advertencia. Si SLF4J encuentra múltiples enlaces, seleccionará un marco de registro de la lista y se enlazará con él. Como se puede ver en la última línea de la advertencia, SLF4J ha elegido Log4j utilizando org.slf4j.impl.Log4jLoggerFactory para el enlace real.

3. Encontrar los JAR en conflicto

La advertencia enumera las ubicaciones de todos los enlaces que encuentra. Por lo general, esta información es suficiente para identificar la dependencia sin escrúpulos que atrae transitivamente un enlace SLF4J no deseado en nuestro proyecto.

Si no es posible identificar la dependencia a partir de la advertencia, podemos usar el objetivo de dependency: tree maven:

mvn dependency:tree

Esto mostrará el árbol de dependencia del proyecto:

[INFO] +- org.docx4j:docx4j:jar:3.3.5:compile [INFO] | +- org.slf4j:slf4j-log4j12:jar:1.7.21:compile [INFO] | +- log4j:log4j:jar:1.2.17:compile [INFO] +- ch.qos.logback:logback-classic:jar:1.1.7:compile [INFO] +- ch.qos.logback:logback-core:jar:1.1.7:compile 

Estamos usando Logback para iniciar sesión en nuestra aplicación. Por lo tanto, hemos agregado deliberadamente el enlace Logback, presente en el JAR clásico de logback . Pero, la dependencia docx4j también ha incluido otro enlace con el JAR slf4j-log4j12 .

4. Resolución

Ahora que conocemos la dependencia ofensiva, todo lo que tenemos que hacer es excluir el JAR slf4j-log4j12 de la dependencia docx4j :

 org.docx4j docx4j ${docx4j.version}   org.slf4j slf4j-log4j12   log4j log4j   

Dado que no vamos a utilizar Log4j, podría ser una buena idea excluirlo también.

5. Conclusión

En este artículo, vimos cómo podemos resolver la advertencia que se ve con frecuencia sobre múltiples enlaces emitidos por SLF4J.

El código fuente que acompaña a este artículo está disponible en GitHub.