Thanks,

We were just discussing this in our video call last week. It was also pointed 
out that there are advantages to Log4j using its own Supplier although I cannot 
remember what they were.

Of course, the Log4j Supplier could be modified to extend j.u.f.Supplier, 
although I don’t know what the point of that would be.

Adding new methods that use j.u.f.Supplier almost certainly would just create a 
mess and require casting all over the place.

Ralph

> On May 12, 2022, at 9:00 AM, Chris Hegarty <chegar...@gmail.com> wrote:
> 
> 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