Hi,

I want to pick up an old thread [1], for which I cannot find a conclusion. Apologies if this has already been discussed, but I cannot find it anywhere (and I have looked!).

It relates to the potential of dropping o.a.l.log4j.util.Supplier in favour of the standard j.u.f.Supplier. I think that such is a great idea, but I want to ensure that some details are not overlooked.

log4j.Supplier shows up in public API methods like, say, Logger.info(Supplier<?>). If this, and others, were migrated to say, Logger.info(util.Supplier<?>), then this would be a,

  - source compatible change, but a
  - binary incompatible change

Source compatible, since type inference will infer the similarly shaped util.Supplier method variant when recompiling the consuming call sites against the new method signature.

Binary incompatible, since existing classes compiled against the existing info(log4j.Supplier) will have method descriptors in their byte code referencing the log4j.Supplier signature variant, which will not be resolvable at runtime.

For clarity, here is a brief, somewhat contrived, minimal example:

// Fake Logger interface
$ cat Logger.java
public interface Logger {
    void info(org.apache.logging.log4j.util.Supplier<?> messageSupplier);
}

// Fake LogManager: factory for loggers that log to stdout
$ cat LogManager.java
public class LogManager {
    public static Logger getLogger() {
        return new Logger() {
            @Override
public void info(org.apache.logging.log4j.util.Supplier<?> messageSupplier) {
                System.out.println(messageSupplier.get());
            }
        };
    }
}

// Compile these
$ javac -cp log4j-api-2.17.1.jar Logger.java LogManager.java


// Minimal app that does some logging
$ cat Main.java
public class Main {
    public static void main(String... args) {
        LogManager.getLogger().info(() -> "log msg");
    }
}

$ javac -cp log4j-api-2.17.1.jar:. Main.java
$ java -cp log4j-api-2.17.1.jar:. Main
log msg


// Now migrate the logging framework to util.Supplier

$ cat Logger.java
public interface Logger {
    void info(java.util.function.Supplier<?> messageSupplier);
}
$ cat LogManager.java
public class LogManager {
    public static Logger getLogger() {
        return new Logger() {
            @Override
public void info(java.util.function.Supplier<?> messageSupplier) {
                System.out.println(messageSupplier.get());
            }
        };
    }
}

// recompile the logging framework
$ javac Logger.java LogManager.java

// Now rerun the app code (without recompiling) - binary incompatible

$ java -cp log4j-api-2.17.1.jar:. Main
Exception in thread "main" java.lang.NoSuchMethodError: 'void Logger.info(org.apache.logging.log4j.util.Supplier)'
        at Main.main(Main.java:4)

// Recompile the app code - source compatible
$ javac Main.java
$ java Main
log msg

-Chris.

[1] https://www.mail-archive.com/dev@logging.apache.org/msg07967.html

Reply via email to