Fork me on GitHub
#babashka
<
2023-06-21
>
jeroenvandijk13:06:57

Is there a way to create a mock of java classes so that Babashka does not say Unable to resolve classname when this class is not included in Babashka? 🧵

jeroenvandijk13:06:46

I’m trying to port a library to Babashka, but somewhere deep in the code java.util.concurrent.ConcurrentHashMap is being used. This class is not available in Babahska so I tried something like

(ns java.util.concurrent) 

(deftype ConcurrentHashMap [a])
But this doesn’t work it seems

jeroenvandijk13:06:57

The other option would be to adapt the library to not use this class, but I feel that this would be more work than to create a mock version of this particular class.

jeroenvandijk14:06:43

Maybe it is easier to override that particular ns instead

jeroenvandijk14:06:23

Ok still need this mocking idea I think, the next class that it doesn’t like is https://github.com/clojure/tools.deps/blob/be30a1ae275eabfd1eba571080e039451c122c69/src/main/clojure/clojure/tools/deps.clj#L21 Or I have to port tools.deps itself of course 😅

Bob B14:06:27

iirc, the mocking thing wouldn't really work, because deftype doesn't create a class in bb (because of the limitations of graal with regards to reflection)

borkdude14:06:42

I've used the same mocking trick in bb. It doesn't really matter that it's not a real class since interop stuff should also work on "fake" classes

borkdude14:06:37

you should be able to use tools deps in bb using this https://github.com/babashka/tools-deps-native but it's very experimental so be warned.

jeroenvandijk16:06:02

ah cool, i’ll try that repo

borkdude16:06:28

it's also used in this (experimental!) project https://github.com/babashka/tools.bbuild

jeroenvandijk17:06:02

Ah great, I just tried it and it does get me to a new (unrelated!) error message of a missing class. Might be tricky to port polylith

jeroenvandijk17:06:48

org.eclipse.aether.util.version.GenericVersionScheme

borkdude17:06:45

right, just found it too

jeroenvandijk17:06:13

I guess I could find a workaround here as well. Maybe for another day 🙂

borkdude18:06:26

We can add that, issue welcome, but you can probably fake it using intern right now

👍 1
jeroenvandijk18:06:29

I’ll try intern and create an issue. Thanks!

borkdude19:06:07

This wasn't what I meant. I meant:

(intern 'clojure.tools.reader 'resolve-symbol your-version-of-resolve-symbol)

jeroenvandijk19:06:33

ah I yeah I didn’t think it through properly. Not sure how to do a custom version I think

jeroenvandijk19:06:43

Something like this should work?

(intern 'clojure.tools.reader 'resolve-symbol (fn [sym] (eval sym)))

borkdude19:06:26

the return value of that function should be a symbol

borkdude19:06:12

in the var? case I would substitute just calling symbol on the var directly:

user=> (symbol #'inc)
clojure.core/inc

borkdude19:06:19

instead of the interop

jeroenvandijk19:06:20

resolve-symbol also contains resolve-ns which has other dependencies. Not sure if this is right. Since the parser should not load code from the polylith project itself

jeroenvandijk19:06:06

(relies on read-string )

borkdude19:06:29

read-string uses edamame in bb ;)

borkdude19:06:44

resolve-ns doesn't load code, it only does a map lookup

borkdude19:06:51

require loads, resolve doesn't

jeroenvandijk19:06:13

hmmm ok not too familiar with all of this I guess

jeroenvandijk19:06:45

I have a private project where

bb --config ../../Github/polyfy/polylith/projects/poly-bb/bb.edn  --debug -m polylith.clj.core.poly-cli.core info
works. On the polylith project itself I still get an error. Might be a missing class method

borkdude19:06:37

(defn- resolve-ns [sym]
  (or (resolve-alias sym)
      (find-ns sym)))

borkdude19:06:10

(defn- resolve-alias [sym]
  ((or *alias-map*
       (ns-aliases *ns*)) sym))

borkdude19:06:18

I'd just leave out *alias-map*

borkdude19:06:50

and note that these can return nil indeed, when something can't be resolved, so maybe log an error to see what could not be resolved

jeroenvandijk19:06:38

I went for a nil clause at var?

jeroenvandijk19:06:15

So with Edamame it works on the polylith project itself. Didn’t check if the output is the same with the normal polylith tool, but it looks like something

borkdude19:06:52

> I went for a nil clause at var? huh?

borkdude19:06:18

you can just call symbol on the var

jeroenvandijk20:06:20

Ok I guess too many things at once happening 😬

jeroenvandijk20:06:59

Thanks for your help as always 🙂

borkdude20:06:52

sure :) perhaps tools-deps-native could be replaced by shelling out using the babashka.tasks/clojure function or so, not sure.

jeroenvandijk20:06:14

ah doesn’t ring a bell yet, I’ll have a look tomorrow with fresh eyes

borkdude20:06:32

deps.clj now also has an API to get the clojure.basis - yeah ok

jeroenvandijk07:06:07

I didn’t try to replace tools-deps-native, but I did use it from the https://github.com/polyfy/polylith/commit/0cf1cb6ce1911dbe64b0c58d7460374590c258c4 For now pretty happy with the result