I'm trying to include a binary executable in my uberjar so that I can shell out to it from within the uberjar. When running jar tvf, I can see that the binary is in the jar... but I can't get to the path of the binary when running the program. Anybody have any tips? I've only found stack over flow suggestions for reading in text files
(def PARSER-PATH (str
(.getPath (<http://clojure.java.io/resource|clojure.java.io/resource> "parser"))
"/bin/parser"))
This works when running a repl in cider, but my println returns this when running the uberjar with java:
"PARSER PATH IS ----------------- " "file:/Users/tees/Projects/firn/firn/target/uberjar/firn-0.1.0-SNAPSHOT-standalone.jar!/parser/bin/parser"
@tees classpath resources can be loaded by the java process, but not by the OS
at least not directly
you need to write out the parser from the resource onto a filesystem before the OS will execute it
@tees something like (io/copy (io/resource "parser/bin/parser") (io/file "/tmp/bin/parser"))
ahhh.
Thanks @noisesmith. Trying now.
oh you'll need to flip the exec bit too (dunno if there's a way to do that with io/file...)
there we go https://docs.oracle.com/javase/7/docs/api/java/io/File.html#setExecutable(boolean)
(.setExecutable f true)
Great, will give that a shot.
nb don't use spit
as that will try to do text-encoding stuff that will break the executable
Hmm, running into
1. Unhandled java.lang.IllegalArgumentException
No method in multimethod 'do-copy' for dispatch value: [<http://java.net|java.net>.URL
<http://java.io|java.io>.File]
when running the io/copy.
try (io/input-stream (io/resource "parser/bin/parser"))
I should have tested that
(ins)user=> (io/copy (io/input-stream (io/resource "clojure/core.clj")) (io/file "core.clj"))
nil
(ins)user=> (count (slurp "core.clj"))
263653
user=> (subs (slurp "core.clj") 0 100)
"; Copyright (c) Rich Hickey. All rights reserved.\n; The use and distribution terms for this soft"
Works! Amazing. Thanks @noisesmith.