Welcome! Please see the About page for a little more info on how this works.

+1 vote
in Compiler by

more context in slack: https://clojurians.slack.com/archives/C03S1KBA2/p1728938240053429

I'm using the MessageSupplier interface (https://logging.apache.org/log4j/2.x/javadoc/log4j-api/org/apache/logging/log4j/util/MessageSupplier.html) with log4j. And i'm coding like so:

❯ clj -Sdeps '{:deps {org.apache.logging.log4j/log4j-api {:mvn/version "2.23.1"} org.clojure/clojure {:mvn/version "1.12.0"}}}'
Clojure 1.12.0
user=> (let [^org.apache.logging.log4j.util.MessageSupplier supplier
      (fn [_]
        (org.apache.logging.log4j.message.MapMessage. {"stuff" "value"}))]
  (.fatal (org.apache.logging.log4j.LogManager/getLogger)
          supplier))
2024-10-14T20:45:25.707016Z main ERROR Log4j2 could not find a logging implementation. Please add log4j-core to the classpath. Using SimpleLogger to log to the console...
Execution error (ClassCastException) at user/eval134 (REPL:4).
class user$eval134$supplier__135 cannot be cast to class org.apache.logging.log4j.util.MessageSupplier (user$eval134$supplier__135 is in unnamed module of loader clojure.lang.DynamicClassLoader @2d7e1102; org.apache.logging.log4j.util.MessageSupplier is in unnamed module of loader 'app')

I was hoping to be able to use a function and take advantage of the new sugar in 1.12. The following does work for me though,

(let [^org.apache.logging.log4j.util.MessageSupplier supplier
      (reify org.apache.logging.log4j.util.MessageSupplier
        (get [_]
          (org.apache.logging.log4j.message.MapMessage. {"stuff" "value"})))]
  (.fatal (org.apache.logging.log4j.LogManager/getLogger)
          supplier))
nil
;; and in terminal
2024-10-14 21:37:41,491 FATAL user$eval189307 :: stuff="value"

2 Answers

+1 vote
by

In this version of log4j, the MessageSupplier class does not extend Supplier or have the @FunctionalInterface annotation:

user=> (.isAnnotationPresent org.apache.logging.log4j.util.MessageSupplier java.lang.FunctionalInterface)
false

So that's why it's not being adapted.

+1 vote
by
(~/clojure)-(!2011)-> clj -Sdeps '{:deps {org.apache.logging.log4j/log4j-api {:mvn/version "2.23.1"}}}'
Clojure 1.12.0
user=> (.isAnnotationPresent org.apache.logging.log4j.util.MessageSupplier java.lang.FunctionalInterface)
false
user=>

(~/clojure)-(!2012)-> clj -Sdeps '{:deps {org.apache.logging.log4j/log4j-api {:mvn/version "2.24.0"}}}'
Clojure 1.12.0
user=> (.isAnnotationPresent org.apache.logging.log4j.util.MessageSupplier java.lang.FunctionalInterface)
true

So, I would expect this to fail with 2.23.1 but work with 2.24.0.

...