'How to create Java mixins: @Slf4j

I'm trying to create a Java mixin and use the @Slf4j annotation. However intellij shows an error @Slf4j is only legal for classes and enums.

import lombok.extern.slf4j.Slf4j;

@Slf4j
public interface Foo {
    default void foo() {
        log.info("Hello world");
    }
}


Solution 1:[1]

If you want to use logging for the interface you could use a constant:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public interface Foo {
    Logger log = LoggerFactory.getLogger(Foo.class);

    default void foo() {
        log.info("Hello from Foo");
    }
}

If will have some implementation for this interface and you could overwrite a logger:

public class Bar implements Foo {
    Logger log = LoggerFactory.getLogger(Bar.class);

    public void bar() {
        log.info("Hello from Bar");
    }
}

With Lombok it could be done even simpler:

@Slf4j
class Bar implements Foo {
    public void bar() {
        log.info("Hello from Bar");
    }
}

Demo code:

public class LoggerDemo {
    public static void main(String[] args) {
        Bar bar = new Bar();
        bar.foo();
        bar.bar();
    }
}

Output:

20:40:48.010 [main] INFO demo.Foo - Hello from Foo 
20:40:48.014 [main] INFO demo.Bar - Hello from Bar

Solution 2:[2]

A simple way to solve the issue is to pass the logger to the foo() method:

import org.slf4j.Logger;

public interface Foo {
    default void foo(Logger log) {
        log.info("Hello world");
    }
}

Then use the @Slf4j annotation on classes that implement Foo:

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class Bar implements Foo {
    public void bar() {
        foo(log);
    }
}

Solution 3:[3]

One option is to add a getLogger method to the interface and require the implementations to implement that method. Then the interface can call that method.

import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;

public interface Foo {

    Logger getLogger();

    default void foo() {
        getLogger().info("Hello world");
    }
}

@Slf4j
public class Bar implements Foo {

    public void bar() {
        foo();
    }

    @Override
    public Logger getLogger() {
        return log;
    }
}

Solution 4:[4]

One option is to create an inner class with a static getLogger method.

import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;

public interface Foo {

    @Slf4j
    class Log {
        public static Logger getLogger() {
            return log;
        }
    }

    default void foo() {
        Log.getLogger().info("Hello world");
    }
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Olivier
Solution 3 nanotek
Solution 4 nanotek