This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2023-12-18
Channels
- # adventofcode (12)
- # asami (2)
- # babashka (95)
- # beginners (17)
- # biff (5)
- # calva (1)
- # clojure (90)
- # clojure-europe (15)
- # clojure-nl (1)
- # clojure-norway (8)
- # clojure-uk (6)
- # clojuredesign-podcast (2)
- # clojurescript (34)
- # clr (1)
- # community-development (42)
- # cursive (11)
- # data-science (1)
- # datomic (13)
- # graalvm (5)
- # hoplon (2)
- # hyperfiddle (32)
- # off-topic (1)
- # pathom (6)
- # releases (1)
- # shadow-cljs (25)
- # squint (4)
- # xtdb (10)
How do I force this to happen even without need?:
Clojure tools not yet in expected location: /home/app/.deps.clj/1.11.1.1413/ClojureTools/clojure-tools-1.11.1.1413.jar
Downloading to /home/app/.deps.clj/1.11.1.1413/ClojureTools/clojure-tools.zip
Unzipping /home/app/.deps.clj/1.11.1.1413/ClojureTools/clojure-tools.zip ...
Successfully installed clojure tools!
Use case: I need this setup to happen early on in a Dockerfile
, to avoid doing the setup over and over again at a later step (triggered by COPY
).
Thanks!In this Docker image, do you intend to run an application with dependencies in bb.edn? I think the best way to do this is to produce an uberjar first and then run the uberjar
Thanks.
In this case I'm fetching the dependencies when building the docker image (the user triggers build), and using bb prepare
. The problem is that the clojure tools setup always run when there are changes to the source code files of the user (triggered with COPY
). I want this setup to happen only in the first build, thus a step before the COPY
Made available the code in a branch for better context: https://github.com/ccfontes/faas-bb/blob/setup-clj-tools/template/bb/Dockerfile#L24
To be fair, this only happens when function/bb.edn
changes, which is a bit more rare than other source files.
bb prepare should also do Clojure tools not yet in expected location:
when you are building the docker image.
But you have to preserve the ~/.deps.clj directory into the image for it not to happen again
I don't see how the clojure tools setup would run multiple times, even with bb.edn changes
if you can make a repro Dockerfile I could have another look, not sure what to do about it now
It's here. https://github.com/ccfontes/faas-bb/blob/setup-clj-tools/template/bb/Dockerfile#L24 Thanks
My ys
program is written in clojure, evals with sci, compiled to binary with native-image...
like bb is
> ys
is installed as a symlink to ys-0.1.28
which is the real binary file
I want to have a couple subcommands that invoke a bash script say ys-sh
that is installed in same dir as ys
I don't know if I should make ys
the bash thing that calls the binary ys-0.1.28
Or if I can shell out from the compiled ys-0.1.28
to ys-sh
I would want the binary to invoke the sh script using the same directory it was in (not a PATH lookup)
using babashka.process, you can do an exec call (which is a true OS exec call) which might help. not sure about the rest of the trade-offs
that's awesome and another question that I had, so thanks I was just going to use https://clojuredocs.org/clojure.java.shell/sh but how do I get the abs path of my binary program at runtime
clojure.java.shell does not let you do an exec call btw it will create another child process
of course
This is how you can get the binary name of the invoked process:
$ bb -e '(-> (java.lang.ProcessHandle/current) .info .command .get)'
"/Users/borkdude/dev/babashka/bb"
thanks! I'll try it.
it's preferable for me for the binary to call or exec the bash after it does the CLI option parsing, so I don't have to repeat that in bash
I'm getting
Method info on class java.lang.ProcessHandleImpl not allowed!
when I call basically
(sci/eval-string "(-> (java.lang.ProcessHandle/current) .info .command .get)"
{:classes {'java.lang.ProcessHandle java.lang.ProcessHandle}})
in the repl, not with graal...
check the bb classes.clj file, it has a function called public-class which cases the Impl class back to the public class
You're right. I don't need this in SCI for what I'm trying to do here. Thanks for noticing that!
I graal compiled ys with it in there and it gets the install path right. \o/
when not graal compiled it gives /usr/lib/jvm/java-17-openjdk-amd64/bin/java
though
I'll probably just default to a PATH lookup in that case since I want to be able to test without a full native-image compile.
@U04V15CAJ I ended up going with babashka.process
to get https://yamlscript.org/posts/advent-2023/dec-20/ machinery working.
https://github.com/yaml/yamlscript/commit/9d0c2dac87aa013fdc12e0b1f7ab26376bf9824f#diff-320f19934fd7d03ab26a1a99137a67e759faa60c287dc3ef144ca56b24fb5781R171-R174
Is it possible to add an import to a Babashka script?
I would like to use the com.deepbeginnings/eximia
dependency from Babashka, but I get the following error:
----- Error --------------------------------------------------------------------
Type: java.lang.Exception
Message: Unable to resolve classname: javax.xml.stream.XMLInputFactory
Location: eximia/core.clj:21:3
----- Context ------------------------------------------------------------------
17:
18: CDATA blocks can also be read and written as [[CData]] records, processing instructions as [[ProcessingInstruction]]s
19: and comments as [[Comment]]s."
20: (:refer-clojure :exclude [read])
21: (:import [javax.xml.stream XMLInputFactory XMLStreamReader XMLStreamWriter XMLStreamConstants XMLOutputFactory]
^--- Unable to resolve classname: javax.xml.stream.XMLInputFactory
22: [javax.xml.namespace QName]
23: [javax.xml XMLConstants]
24: [java.io Reader Writer InputStream OutputStream StringReader StringWriter]
25: [clojure.lang IPersistentMap]))
26:
----- Stack trace --------------------------------------------------------------
eximia.core - eximia/core.clj:21:3
xml-utils2 - /tools/dataset-utils/xml_utils2.clj:6:3
Doesn't Babashka already include the javax.xml
dependencies?
I would like to use eximia
instead of data.xml
because it's faster with large files.
This is the code:
(require '[babashka.deps :as deps])
(deps/add-deps '{:deps {com.deepbeginnings/eximia {:mvn/version "0.1.3"}}})
(ns xml-utils2
(:require [eximia.core :as exml]
[clojure.java.io :as io]))
(defn read-xml
"Reads the xml from a file"
[file]
(try
(->
(with-open [input (io/input-stream file)]
(exml/read input {:tag-fn exml/qname->unq-keyword})))
(catch Exception e
(println (str "Could not read xml file '" file "': " e))
(System/exit 1))))
None of the jaxax.xml classes are currently exposed in babashka, but you can use clojure.data.xml instead
I'll have a look later if we can exposes those javax.xml classes, but I doubt that eximia will be faster when running in bb due to interpretation overhead, but it's worth testing. Do you have any examples of big XML files + clojure.data.xml + eximia example that compares speeds?
if you can prepare a repository that I can clone locally and just run with both, that would be a nice start
Yes, I do, I have tried it already with data.xml and it is slower parsing and specially updating. Currently they are company files, but I'll see if I can generate some similar ones. XML files are around several MB.
if you want to experiment yourself, you can add the javax.xml classes here: https://github.com/babashka/babashka/blob/master/src/babashka/impl/classes.clj and then compile bb locally
build instructions are here: https://github.com/babashka/babashka/blob/master/doc/build.md
Would it be as simple as adding it to https://github.com/babashka/babashka/blob/53d16eb9a02ee7dbc39243ff7d2b73049f7fda63/src/babashka/impl/classes.clj#L254? or does it involve more?
you could try to first run with the JVM-version of bb to see if it works:
clj -M:babashka/dev my_script.clj
this gives you faster feedback
(where babashka/dev is an alias which points to your local clone of bb)Hi again, I added the javax.xml
classes to babashka as you suggested. It compiled with no problems.
Now, when I run the script to read an xml file I don't get the Unable to resolve classname
error anymore, but now I get the following error:
Method setProperty on class com.sun.xml.internal.stream.XMLInputFactoryImpl not allowed!
Is there a way to solve this?Add to the :public-fn
casts:
(instance? javax.xml.stream.XMLInputFactory v)
javax.xml.stream.XMLInputFactory
Yes!, the error message disappeared, but now I get the error:
Method close on class com.sun.org.apache.xerces.internal.impl.XMLStreamReaderImpl not allowed!
I suppose I have to do the same with the javax.xml.stream.XMLStreamReader
class?It worked! Thanks!! I will add and test the functions to write xml files, I might have to add some more classes to the :public-class.
Trying to write an XML file, I got an error:
Type: java.lang.NoSuchFieldException
Message: close
I'm not sure if this is the same case as before.I Does write the xml file but stops almost at the end, its incomplete and invalid xml, the file is not that big (541KB).
at least .close
is called on something but the .close
method isn't available in the native image . perhaps you can track down which class this is
It shows this in the error:
----- Context ------------------------------------------------------------------
25: (defn save-xml
26: "Saves the xml to a file"
27: [xml path]
28: (let [opts {:tag-fn exml/keyword->qname}]
29: (exml/write xml (io/output-stream path) opts)))
^--- close
This does work:
$ bb -e '(with-open [out (java.io.StringWriter.)] (.write out "foo") (str out))'
"foo"
don't know. I think it would be useful to clone eximia locally and insert some printlns etc to see where exactly this is happening and then make a repro to fix
I debugged eximia, and putting a (.close out)
after https://github.com/nilern/Eximia/blob/d57c6268eb3ee4a5c3f5baad7336a02693662ae0/src/eximia/core.clj#L135
generates the whole xml file, but the error remains.
Unfortunately no :(, here are some quick benchmarks: There was no transformation to the xml it only wrote back the xml that was read from the file. reading eximia babashka file size: 541K "Elapsed time: 236.811919 msecs" reading clojure.data.xml babashka file size: 541K "Elapsed time: 0.562374 msecs" writing eximia babashka file size: 541K "Elapsed time: 374.571785 msecs" writing clojure.data.xml babashka file size: 541K "Elapsed time: 117.879349 msecs" --- reading eximia babashka file size: 14M "Elapsed time: 5233.275265 msecs" reading clojure.data.xml babashka file size: 14M "Elapsed time: 0.565281 msecs" writing eximia babashka file size: 14M "Elapsed time: 8450.353057 msecs" writing clojure.data.xml babashka file size: 14M "Elapsed time: 3803.034851 msecs" --- reading eximia clj file size: 541K "Elapsed time: 49.630511 msecs" reading clojure.data.xml clj file size: 541K "Elapsed time: 19.460798 msecs" writing eximia clj file size: 541K "Elapsed time: 87.266801 msecs" writing clojure.data.xml clj file size: 541K "Elapsed time: 432.58637 msecs" --- reading eximia clj file size: 14M "Elapsed time: 284.419659 msecs" reading clojure.data.xml clj file size: 14M "Elapsed time: 19.567271 msecs" writing eximia clj file size: 14M "Elapsed time: 497.282376 msecs" writing clojure.data.xml clj file size: 14M "Elapsed time: 2173.910879 msecs"
Well, it was a nice experiment. I think I'll try my scripts with babashka and clojure.data.xml. Thanks for your time!
perhaps it's useful to make a PR with it, then we can close it, but at least we have the code how to add those xml classes in case we do need it at some point
Here is a git patch with the changes I made, if it's quicker:
diff --git a/src/babashka/impl/classes.clj b/src/babashka/impl/classes.clj
index 5c2e808d..25998d78 100644
--- a/src/babashka/impl/classes.clj
+++ b/src/babashka/impl/classes.clj
@@ -553,7 +553,16 @@
~(symbol "[Ljava.util.regex.Pattern;")
~(symbol "[Lclojure.core$range;")])
~@(when features/yaml? '[org.yaml.snakeyaml.error.YAMLException])
- ~@(when features/hsqldb? '[org.hsqldb.jdbcDriver])]
+ ~@(when features/hsqldb? '[org.hsqldb.jdbcDriver])
+ ;; for eximia (xml parser)
+ javax.xml.stream.XMLInputFactory
+ javax.xml.stream.XMLStreamReader
+ javax.xml.stream.XMLStreamWriter
+ javax.xml.stream.XMLStreamConstants
+ javax.xml.stream.XMLOutputFactory
+ javax.xml.namespace.QName
+ javax.xml.XMLConstants
+ ]
:constructors [clojure.lang.Delay
clojure.lang.LineNumberingPushbackReader
java.io.EOFException]
@@ -675,6 +684,15 @@
java.lang.ProcessHandle
(instance? java.lang.ProcessHandle$Info v)
java.lang.ProcessHandle$Info
+ ;; for eximia (xml parser)
+ (instance? javax.xml.stream.XMLInputFactory v)
+ javax.xml.stream.XMLInputFactory
+ (instance? javax.xml.stream.XMLStreamReader v)
+ javax.xml.stream.XMLStreamReader
+ (instance? javax.xml.stream.XMLOutputFactory v)
+ javax.xml.stream.XMLOutputFactory
+ (instance? javax.xml.stream.XMLStreamWriter v)
+ javax.xml.stream.XMLStreamWriter
;; added for calling .put on .environment from ProcessBuilder
(instance? java.util.Map v)
java.util.Map