16

I have been working on java 7 so far and recently moved to java-8, one thing which was surprising is that you can add methods in java-8 interfaces.

So far so good....loved this new stuff!

Now, my problem is that logging is an essential part of any development but seems lombok.extern.slf4j won't let you add log stuffs in by interface methods as it is only allowed on classes and enums.

How do you log your interface methods (if by lombok or is this the only way?? ) ? Or is interface methods not supposed to be logged? what am i missing here?

P.S : At present i am working with System.out.println.... yeah...thats noob :)

NoobEditor
  • 15,563
  • 19
  • 81
  • 112

5 Answers5

24

Currently Lombok @Slf4j annotation is not supported on interfaces, but it can be circumvented like this

public interface MyInterface
{
    @Slf4j
    final class LogHolder
    {}

    default void action() {
        LogHolder.log.error("Error TEST");
    }
}
NoobEditor
  • 15,563
  • 19
  • 81
  • 112
Vaibhav
  • 397
  • 2
  • 10
  • 1
    Here's the closed/rejected Lombok feature request to support the logging annotations on interfaces: https://github.com/rzwitserloot/lombok/issues/2584 – M. Justin Dec 17 '20 at 20:47
  • why not use an abstract class with a method already implemented, if you really need to write some code with logging instead of searching for hacks to add logger – Dheeraj Sachan Sep 06 '22 at 20:52
19

you can add logger to your interface manually, but your logger will be public:

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

    default void action() {
        log.info("TEST");
    }
}
Alex M981
  • 2,264
  • 14
  • 24
  • will this be same as `slf4j` log? – NoobEditor Feb 13 '18 at 05:53
  • lombok slf4j is actually adding the line `Logger log = LoggerFactory.getLogger(SomIface.class);` so you avoid such a routine work. Example from my post is using slf4j – Alex M981 Feb 13 '18 at 05:55
  • With this attitude it's possible to declare a public static logger in any other class and use it, maybe through a static method, maybe with static import. There's no need for an interface and for a default method in an interface. – pcjuzer Feb 14 '18 at 12:59
  • 3
    the code checker like 'sonar' won't suggest u do this . warning 'Move constants to a class or enum.' still exist – Adams.H Jan 03 '19 at 14:33
  • Keep in mind this logger will be static, as well as any attribute defined in an interface – JohnnyB Mar 15 '20 at 13:18
  • If you don\`t want to expose Logger object(I think most people would agree), then the other answer is better for not exposing it(because the actual logger object is inside the nested class, as a private field, it is not accessible outside) – Hi computer Mar 09 '23 at 09:38
7

Logging is an implementation detail, so an interface shouldn't deal with it. If logging is considered as the responsibility of the interface that will lead to several problems. For example:

  • If there are more than one class implementations, you don't know which is used because they log with the same name. It's also not possible to fine-tune their log levels by their names in config.
  • Default methods are public which means they can be called from the outside. This is not very desirable for logging methods.
  • Logging methods would just pollute the interface. What would one say if 'Map' interface would contain such kind of default methods? 'logDebug' or so. It's just confusing and leads to unnecessary questions. An interface should be a clean API for the intended purpose.

What you could use instead:

  • Some kind of delegation which Lombok also has support for. (Composition over inheritance)
  • Some kind of Aspect Oriented Programming technique. There are frameworks for that but it's also possible to achieve the same by "Dynamic Proxies". This is also in connection with interfaces.
pcjuzer
  • 2,724
  • 4
  • 25
  • 34
  • I don't think you understand the concept of "implementation on the interface" in Java. Implementation here can only be static, it's not inherited by implementing classes. – Boris Schegolev Oct 15 '20 at 16:19
  • How do you mean 'static' and 'not inherited'? Constants in interfaces are static, that's right. But 'default' method is not static. It can be called on instances of implementation classes, so it's inherited. – pcjuzer Oct 16 '20 at 13:32
0

We can add an abstract method getLogger in interface. And ask the implementer to pass the logger object.

public interface CustomRepo{
 
    Logger getLogger();

    default void processData(Data data){
        // Do something 
        getLogger().info("Processing");
        // Do something
    }

}

@Slf4j
public RepoImplementer implements CustomRepo {

   @Override
   public Logger getLogger(){
      return log;
   }
}
Anand
  • 1
  • 1
0

With Java 9+ you could use private methods to prevent logger from being public static

public interface SomeInterface {
    private Logger log() {
        return LoggerFactory.getLogger(SomeInterface.class);
    }

    default void action() {
        log().info("TEST");
    }
}