Search code examples
spring-mvcgroovyslf4jresttemplategroovy-grape

Why does SLF4J with slf4j-nop output the StaticLoggerBinder warning when using a Groovy script with @Grab


I have a Groovy script which specifies dependencies using the Grape @Grab annotation. The dependencies specified are spring-web to use RestTemplate, and a dependency on slf4j-nop to avoid the Failed to load class "org.slf4j.impl.StaticLoggerBinder" warning.

#!/usr/bin/env groovy

@Grab('org.springframework:spring-web:5.3.18')
@Grab('org.slf4j:slf4j-nop:1.7.36')
import org.springframework.web.client.RestTemplate

new RestTemplate().getForObject('http://www.example.com', String)

However, despite this, I am still getting the SLF4J warning:

$ ./restTemplateLoggingTest.groovy 
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.

Given that it's a script, it's important that it not output extraneous noise, as the script output may be used and manipulated programmatically.

What can I do to prevent this logging warning from being output when I run my script?


Solution

  • Experimentation has shown that attaching the dependencies to the system classloader using @GrabConfig(systemClassLoader=true) causes the logs to no longer be emitted:

    #!/usr/bin/env groovy
    
    @GrabConfig(systemClassLoader=true)
    @Grab('org.springframework:spring-web:5.3.18')
    @Grab('org.slf4j:slf4j-nop:1.7.36')
    import org.springframework.web.client.RestTemplate
    
    new RestTemplate().getForObject('http://www.example.com', String)
    

    I don't know for sure why this is the cause, though I have some vague guesses.

    Note that despite addressing the issue, this isn't a use that's described by the Javadocs for GrabConfig#systemClassLoader:

    Set to true if you want to use the system classloader when loading the grape. This is normally only required when a core Java class needs to reference the grabbed classes, e.g. for a database driver accessed using DriverManager.