Search code examples
grailsgroovyslf4j

Private static field not accessible from a nested closure


Say I have the following classes:

@Slf4j
class MySuperclass {

    public void testMethod() {
        def test = [1, 2, 3]
        test.each {it ->
            log.info("gab" + it)
            def test2 = [4,5,6]
            test2.each {
                log.info("" + it)
            }
        }
    }
}

And then:

class MySubclass extends MySuperclass {

    public void process() {
        testMethod()
    }
}

When I call mySubclass.process(), I get an error:

No such property log for class: com.ingenuity.app.kang.batch.MySubclass

The error is thrown only for the line inside the test2 closure. If I declare a public log field, it works fine. It also works fine if I add a @Slf4j annotation in the subclass.

I don't understand what happens here. Is this a groovy bug? I found this issue which might be related, but it is not the same behaviour: Groovy closure not work with static final field from super class


Solution

  • One way to deal with it is to reference the log property as a static member on the class. The project at https://github.com/jeffbrown/logissue demonstrates that.

    https://github.com/jeffbrown/logissue/blob/d089c296c102980855a88061275e52485965e4ab/src/main/groovy/logdemo/MySuperclass.groovy

    package logdemo
    
    import groovy.util.logging.Slf4j
    
    @Slf4j
    class MySuperclass {
    
        void testMethod() {
            def test = [1, 2, 3]
            test.each {it ->
                log.info("gab" + it)
                def test2 = [4,5,6]
                test2.each {
                    MySuperclass.log.info("" + it)
                }
            }
        }
    }
    

    That works.

    ~ $ git clone [email protected]:jeffbrown/logissue.git
    Cloning into 'logissue'...
    remote: Enumerating objects: 22, done.
    remote: Counting objects: 100% (22/22), done.
    remote: Compressing objects: 100% (15/15), done.
    remote: Total 22 (delta 0), reused 22 (delta 0), pack-reused 0
    Receiving objects: 100% (22/22), 53.62 KiB | 1.28 MiB/s, done.
    ~ $ cd logissue/
      $ ./gradlew run
    
    > Task :run
    16:41:19.022 [main] INFO  logdemo.MySuperclass - gab1
    16:41:19.027 [main] INFO  logdemo.MySuperclass - 4
    16:41:19.027 [main] INFO  logdemo.MySuperclass - 5
    16:41:19.027 [main] INFO  logdemo.MySuperclass - 6
    16:41:19.027 [main] INFO  logdemo.MySuperclass - gab2
    16:41:19.027 [main] INFO  logdemo.MySuperclass - 4
    16:41:19.027 [main] INFO  logdemo.MySuperclass - 5
    16:41:19.027 [main] INFO  logdemo.MySuperclass - 6
    16:41:19.027 [main] INFO  logdemo.MySuperclass - gab3
    16:41:19.027 [main] INFO  logdemo.MySuperclass - 4
    16:41:19.027 [main] INFO  logdemo.MySuperclass - 5
    16:41:19.027 [main] INFO  logdemo.MySuperclass - 6
    
    BUILD SUCCESSFUL in 2s
    2 actionable tasks: 2 executed