Fork me on GitHub
#clojure-dev
<
2020-11-30
>
andy.fingerhut04:11:47

I'm chatting with someone who is trying to use Java interop on a class where there is 1 method in a class with a particular name and 1 parameter, and it extends an abstract class that has several more methods with the same name and 1 parameter (different types for that parameter). When he is trying to call a method on an instance of the child class, but the method he wants to call is in the abstract parent class, Clojure reflection seems to prefer non-bridge methods over bridge methods, and all of the methods in the parent class are bridge methods in the child class. Even with an explicit type hint on the 1 parameter in the Clojure interop call, it gives a ClassCastException at Java interop call time, because it cannot cast the type of the parameter in the interop call to the type of a different method than the one the developer is trying to call. More details in thread.

andy.fingerhut04:11:52

Here is a link to the discussion (I hope, if I am doing this correctly):

andy.fingerhut04:11:48

Minimal repro is to fire up a REPL using the deps.edn file in the root dir of that repo, then evaluate these two expressions:

(require '[ventures.fierce.pdfbox.core :as c])
(in-ns 'ventures.fierce.pdfbox.core)

andy.fingerhut04:11:00

then eval the expression in the comment block at the end of the core.clj source file.

andy.fingerhut04:11:27

OK, maybe not minimal repro, but at least very quick to get to the exception.

andy.fingerhut04:11:29

and that one is the one that the Clojure Reflector code seems to find, even though it has the wrong type. The others are in the abstract parent class here: https://github.com/apache/pdfbox/blob/fffad2fe3ff74eaca909fce65cf1dd4191ceb036/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/PDAbstractContentStream.java#L76

andy.fingerhut04:11:46

I am not sure if this is a case that Clojure reflection is intended to handle correctly, or not.

Alex Miller (Clojure team)14:11:22

reminds me of an old issue with reflection and bridge methods, let me see if I can find it.

andy.fingerhut15:11:00

Thanks for the links, Alex! The description makes it sound like it could very well be exactly that issue. The workaround mentioned by one commenter is one that I mentioned to @U3FKR3KDF - define a small class in Java that calls only the java methods that you need. Make everything you need public, and then if it works, use Java interop to call those methods. A pain, but probably effective.

stuartrexking06:12:59

Thanks for that. I’ve created a class to manage the interop.