Aviso do SLF4J: o caminho da classe contém várias ligações do SLF4J

Aviso do SLF4J: o caminho da classe contém várias ligações do SLF4J

1. Visão geral

Quando usamos o SLF4J em nossos aplicativos, às vezes vemos uma mensagem de aviso sobre várias ligações no caminho de classe impresso no console.

Neste tutorial, tentaremos entender por que vemos essa mensagem e como resolvê-la.

2. Compreendendo o aviso

Primeiro, vamos ver um exemplo de aviso:

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 http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [org.slf4j.impl.Log4jLoggerFactory]

Este aviso está nos dizendo que o SLF4J encontrou duas ligações. Um está emslf4j-log4j12-1.7.21.jar e o outro emlogback-classic-1.1.7.jar.

Agora, vamos entender por que vemos esse aviso.

OSimple Logging Facade for Java (SLF4J) serve como uma fachada simples ou abstração para vários frameworkslogging. Assim, nos permite conectar nossa estrutura de log desejada no momento da implantação.

Para conseguir isso, o SLF4J procura ligações (também conhecidas como provedores) no caminho de classe. As ligações são basicamente implementações de uma classe SLF4J específica que deve ser estendida para conectar uma estrutura de log específica.

Por design, o SLF4J será vinculado apenas a uma estrutura de log por vez. Consequentemente,if more than one binding is present on the classpath, it will emit a warning.

Vale ressaltar que os componentes incorporados, como bibliotecas ou estruturas, nunca devem declarar dependência de nenhuma ligação do SLF4J. Isso ocorre porque quando uma biblioteca declara uma dependência em tempo de compilação de uma ligação SLF4J, ela impõe essa ligação ao usuário final. Obviamente, isso nega o propósito básico de SLF4J. Consequentemente, eles devem depender apenas da bibliotecaslf4j-api.

Também é importante paranote that this is only a warning. Se SLF4J encontrar várias ligações, ele escolherá uma estrutura de registro da lista e se ligará a ela. Como pode ser visto na última linha do aviso, SLF4J escolheu Log4j usandoorg.slf4j.impl.Log4jLoggerFactory para a vinculação real.

3. Encontrando os JARs conflitantes

O aviso lista os locais de todas as ligações que encontra. Geralmente, essas são informações suficientes para identificar a dependência inescrupulosa que atrai transitivamente uma ligação SLF4J indesejada para o nosso projeto.

Se não for possível identificar a dependência do aviso, podemos usar a meta de mavendependency:tree:

mvn dependency:tree

Isso exibirá a árvore de dependência do projeto:

[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 o Logback para fazer login em nosso aplicativo. Portanto, adicionamos a ligação Logback, presente no JARlogback-classic, deliberadamente. Mas, a dependênciadocx4j também puxou outra ligação com o JARslf4j-log4j12.

4. Resolução

Agora que sabemos a dependência ofensiva, tudo o que precisamos fazer é excluir oslf4j-log4j12 JAR da dependênciadocx4j:


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

Como não vamos usar o Log4j, pode ser uma boa ideia excluí-lo também.

5. Conclusão

Neste artigo, vimos como podemos resolver o aviso frequentemente visto sobre várias ligações emitidas pelo SLF4J.

O código-fonte que acompanha este artigo está disponívelover on GitHub.