Is there a way to replace/patch/alter a single dependency namespace? I'm doing a http-kit server that's meant to run in both bb and clj, but keep running into errors when loading ring.util.response , which is a transitive dep of a lot of ring middleware.
----- Error --------------------------------------------------------------------
Type: clojure.lang.ExceptionInfo
Message: Unable to resolve classname: java.net.JarURLConnection
Data: {:type :sci/error, :line 277, :column 1, :file "ring/util/response.clj", :phase "analysis"}
Location: ring/util/response.clj:278:20
Phase: analysis
----- Context ------------------------------------------------------------------
274: path
275: (str path "/")))
276:
277: (defn- jar-directory? [^java.net.JarURLConnection conn]
278: (let [jar-file (.getJarFile conn)
^--- Unable to resolve classname: java.net.JarURLConnection
279: entry-name (.getEntryName conn)
280: dir-entry (.getEntry jar-file (add-ending-slash entry-name))]
281: (and dir-entry (.isDirectory dir-entry))))
282:
283: (defn- connection-content-length [^java.net.URLConnection conn]
----- Stack trace --------------------------------------------------------------
ring.util.response/let - ring/util/response.clj:278:20
ring.util.response - ring/util/response.clj:278:3
clojure.core/let - <built-in>
ring.util.response/fn - ring/util/response.clj:278:3
clojure.core/fn - <built-in>
... (run with --debug to see elided elements)
ring.util.response - ring/util/response.clj:277:1
ring.util.response - ring/util/response.clj:277:1
ring.middleware.resource - ring/middleware/resource.clj:3:3
invoker - /Users/filipesilva/repos/personal/invoker/src/invoker.clj:3:3
user - <expr>:1:10
This is similar to https://clojurians.slack.com/archives/CLX41ASCS/p1682919417008599will that replace my global bb install via homebrew or?
ah no I see that it got installed to /tmp/bb, nice
I can confirm that wrap-resource works now in my original usage (serving files on bb using http-kit)!
filipesilva@m4 ~/r/p/invoker (master)> curl localhost/file.txt
foo
nice!
thank you for taking the time to fix this 🙏
heya, sorry to bother you again, but about clojure.lang.Ref... there's a couple of places in clojure-plus that try to use it, like this in clojure+.test
(defn- inc-report-counter [name]
(condp instance? test/*report-counters*
clojure.lang.Ref
(dosync (commute test/*report-counters* update name (fnil inc 0)))
as far as I can tell it's kinda there in bb, but can't be resolved?
user=> (require '[clojure.test :as test])
nil
user=> (test/deftest foo (println (type test/*report-counters*)))
#'user/foo
user=> (test/run-tests)
Testing user
clojure.lang.Ref
Ran 1 tests containing 0 assertions.
0 failures, 0 errors.
{:test 1, :pass 0, :fail 0, :error 0, :type :summary}
user=> clojure.lang.Ref
Could not resolve symbol: clojure.lang.Ref [at <repl>:7:-16]
do you have any suggestions on what to do in this case? I could check the str instead of using instance?
user=> (test/deftest foo (println (= "class clojure.lang.Ref" (str (type test/*report-counters*)))))
#'user/foo
user=> (test/run-tests)
Testing user
true
Ran 1 tests containing 0 assertions.
0 failures, 0 errors.
{:test 1, :pass 0, :fail 0, :error 0, :type :summary}
user=>yes, I can add it. shall we use a different thread so we don't bother niki with all the details? let's take it one by one. please make a github issue
sgtm, thank you
let me just add clojure.lang.Ref right now, no need for a gh issue
@tonsky tried adding babashka support to clj-reload here https://github.com/tonsky/clj-reload/pull/25, gonna look at all the clojure+ stuff now
@filipematossilva I already have some WIP here for clj-reload as well: https://github.com/borkdude/clj-reload
but I'm still working on SCI improvements to retain types defined with deftype and defclass even after you remove the namespaces. You will see that not working like JVM Clojure when you run the tests in babashka
more notes here: https://github.com/babashka/babashka/issues/1839
oh shoot, I think you linked me that already but I completely forgot
well I needed a working version of clj-reload anyway to run the clojure+ tests so it wasn't wasted time
with that minimal change, at least the code runs. but it just doesn't work fully for the defclass/deftype stuff. so maybe a good start
Removed stuff from clojure+ until I could get the remaining tests passing in a bb env, it looks a bit like this:
• hashp and error install need .doReset , which looks like it could be replaced with an atom anyway
• print install needed .addMethod on MultiFn
• print has lots of java imports that don't work, and error tests also rely on print readers
• hashp, print, and error tests are all down
• then it's a bunch of smaller stuff that looks like it can be worked around
• there's a couple of macros around clojure version support that look like they could be used for babashka support/not support
If you're curious what it looks like, https://github.com/filipesilva/clojure-plus/commit/82d5b69bb8607e1741067fdd39ac25b71cbec00f
> hashp and error install need .doReset , which looks like it could be replaced with an atom anyway
this is about vars. you can use alter-var-root instead.
I never quite understood why some codebases prefer to store state in vars and alter them, is it just preference or are some cases where the atom won't work?
I don't know but alter-var-root does what you want if you want to stay close to the original
@filipematossilva I decided to just add everything to bb that's needed to run clojure+.hashp unmodified. The only thing that could be improved now is the line number stuff. But you can already run it with the newest bb I believe
awesome!
let me try
filipesilva@m4 ~> bb --version
babashka v1.12.208
filipesilva@m4 ~> rlwrap bb
Babashka v1.12.208 REPL.
Use :repl/quit or :repl/exit to quit the REPL.
Clojure rocks, Bash reaches.
user=> (deps/add-deps '{:deps {io.github.tonsky/clojure-plus {:mvn/version "1.6.3"}}})
nil
user=> (require 'clojure+.hashp)
nil
user=> (clojure+.hashp/install!)
java.lang.IllegalArgumentException: No matching method doReset found taking 1 args for class sci.lang.Var [at clojure+/hashp.clj:123:4]
user=>
hm I think there's still something wrong... I guess it's a different type of problem though, because it's on the install fnoh yes, you're right.... I forgot about .doReset. This can be changed in alter-var-root + constantly
(I sound like an LLM now...)
you're absolutely right! XD
Guys, if at any point you need anything changed in clojure+ itself, just open a PR. Will be happy to help
@tonsky fyi this is the thread related to https://github.com/babashka/babashka/issues/1853, I tagged you on the issue with the results of trying to install the rest of the clojure+ ns's
I'm already talking with @tonsky on this. I'll send a PR based on the code in the issue. But one thing that wasn't working that well is showing the location of the #p in the output, was trying to improve on that still
I could also send a PR without the improvements first so at least it's working on bb
ah sorry, didn't mean to get in the way, it's just that I was trying to install all the others and thought I should put down what happens in case the whole thing was a bit of a fools errand
thanks! it's appreciated
I added Compiler/demunge to bb. I'll make a PR to remove TaggedLiteral interop in favor of tagged-literal in core. These changes should at least make things work
I'm in no rush myself really... I just happened to be trying it out, and since there were no issue reports on it I thought I'd make some, then eventually if other people tried there was some help and context
thanks :) I might have done a PR on weavejester's hashp at some point maybe
(no I didn't)
you had https://github.com/weavejester/hashp/issues/21, but I think it still suffers from the location issue
it shows
filipesilva@m4 ~/r/p/invoker (master) [SIGINT]> invoker http
#p[clojure.core/apply:667] req => {:args [],
:async-channel #<org.httpkit.server.AsyncChannel@51c7a210 /[0:0:0:0:0:0:0:1]:80<->/[0:0:0:0:0:0:0:1]:54325>,
:body #<org.httpkit.BytesInputStream@4d90c592 BytesInputStream[len=3]>,
:character-encoding "utf8",
for
(defn http-invoke [{:as req, :keys [var args opts]}]
(try
#p req
...
should I close that issue?
Your issue is about how the location isn't accurate, which is still true, so I'd say no. https://github.com/weavejester/hashp/pull/25 aimed to fix how it didn't work at all in clojure 1.12, but that's been fixed already.
I don't really know if the middleware I'm trying to use right now (`ring.middleware.resource`) would work at all if I managed to get past this particular error... but a couple of weeks ago I hit the same issue with another middleware, and at any rate ring.util.responses has lots of useful helpers that are ubiquitous in ring apps, like
(defn not-found
"Returns a 404 'not found' response."
{:added "1.1"}
[body]
{:status 404
:headers {}
:body body})
(defn response
"Returns a skeletal Ring response with the given body, status of 200, and no
headers."
[body]
{:status 200
:headers {}
:body body})
btw java.net.JarURLConnection was added in 1.12.206 (2025-07-16)
if you can upgrade, we can see if there's other things to add/fix
borkdude you are a gem ❤️
Sorry for the delay confirming it works, it seems to have a problem and I was debugging it.
Well I can confirm the require goes through, but ring.middleware.resource doesn't work. It seems to be related to https://github.com/ring-clojure/ring/blob/8fcd3b6594fc66c156e7c4e5f66a55c6acf952f6/ring-core/src/ring/util/response.clj#L309-L312, that gets called in the fns below it.
Specifically this piece of code behaves differently between bb and clj:
(-> (.getContextClassLoader (Thread/currentThread))
(.getResources "public")
(enumeration-seq))
here's a repro:
mkdir repro
cd repro
echo '{:paths ["src" "resources"]}' > bb.edn
cp bb.edn deps.edn
mkdir -p resources/public
touch resources/public/file.txt
then in clj we see the folder
filipesilva@m4 ~/r/s/bb-resources> clj -M -e '(-> (.getContextClassLoader (Thread/currentThread)) (.getResources "public") (enumeration-seq))'
(#object[java.net.URL 0x772485dd "file:/Users/filipesilva/repos/sandbox/bb-resources/resources/public"])
but in bb we do not
filipesilva@m4 ~/r/s/bb-resources> bb -e '(-> (.getContextClassLoader (Thread/currentThread)) (.getResources "public") (enumeration-seq))'
maybe it's just a matter of using the right class loader in the middleware opts
ok, nice repro. can you file an issue for this, then I'll have a look
do you actually have the resources folder on your classpath in bb?
in bb.edn
oh yes, you have sorry
uhm I assume echo '{:paths ["src" "resources"]}' > bb.edn did that, maybe I am wrong
I'll print the file in the repo to demonstrate that
thank you
yeap there
filipesilva@m4 ~/r/s/bb-resources> clj -M -e '( "public/file.txt")'
#object[java.net.URL 0x44e3760b "file:/Users/filipesilva/repos/sandbox/bb-resources/resources/public/file.txt"]
filipesilva@m4 ~/r/s/bb-resources> bb -e '( "public/file.txt")'
#object[java.net.URL 0x72531f93 "file:/Users/filipesilva/repos/sandbox/bb-resources/resources/public/file.txt"]
lol https://github.com/babashka/babashka/issues/1851 and https://github.com/babashka/babashka/issues/1839 are things I wanted to test too 😄
nice, they are still active to do :)
feel free to bump those issues with a thumbs up
clj-reload is the first thing I want to fix. it basically already works except not with deftype/defrecord stuff yet
out of curiosity have you tried https://github.com/tonsky/clojure-plus?tab=readme-ov-file#clojurehashp ? I think atm it doesn't work
filipesilva@m4 ~/r/s/bb-resources [SIGINT]> rlwrap bb
Babashka v1.12.207 REPL.
Use :repl/quit or :repl/exit to quit the REPL.
Clojure rocks, Bash reaches.
user=> (require '[babashka.deps :as deps])
nil
user=> (deps/add-deps '{:deps {io.github.tonsky/clojure-plus {:mvn/version "1.6.3"}}})
Downloading: io/github/tonsky/clojure-plus/1.6.3/clojure-plus-1.6.3.pom from clojars
Downloading: io/github/tonsky/clojure-plus/1.6.3/clojure-plus-1.6.3.jar from clojars
nil
user=> (require 'clojure+.hashp)
java.lang.Exception: Unable to resolve classname: clojure.lang.TaggedLiteral [at clojure+/hashp.clj:7:3]
the original hashp seems fine though
user=> (deps/add-deps '{:deps {dev.weavejester/hashp {:mvn/version "0.4.0"}}})
nil
user=> (require 'hashp.preload)
nil
user=> #p "hello"
#p[babashka.impl.repl/repl:84] "hello"
"hello"
the original works fine. I haven't tried clojure+
add an issue for it, I can take a look
issue for wrap-resource https://github.com/babashka/babashka/issues/1852
issue for clojure+.hashp https://github.com/babashka/babashka/issues/1853
👍 I'll see what I can do
@filipematossilva This issue is fixed on master. https://github.com/babashka/babashka/issues/1852 You can try it out with:
bash <(curl ) --dev-build --dir /tmp
when CI is finished. Should be in 10 minutes or soThere's going to be a bb-and-clj-kondo-related talk at the #clojure-conj this year!