Hi I'm facing some issues with respect to java interop
I've namespace myorg.helpers.fs-input-stream -Its definition is
(ns myorg.helpers.fs-input-stream)
(gen-class
:name "myorg.helpers.FsInputStream"
:extends java.io.ByteArrayInputStream
:implements [org.apache.hadoop.fs.Seekable org.apache.hadoop.fs.PositionedReadable]
:main false
:exposes {buf {:get getBuf}
pos {:get getPos}
mark {:get getMark}}
:init-impl-ns false)
I've another namespace myorg.plugin.orc-output which uses the class generated by above namespace. Its definition is -
Thanks @hiredman
but I'm stuck more on this
how can I aot compile this in deps.edn?
do I have to add (require 'myorg.plugins.helper.FsInputStream) ?
no
in general aot compilation is a separate step your build tool is usually responsible for
clj and deps.edn are not really a complete build tool, but they work together with tools.build (https://clojure.org/guides/tools_build) #tools-build
aot (a head of time) compilation in clojure means generating jvm bytecode classfiles and writing them to disk, instead of just keeping it in memory (what the clojure compiler normally does with bytecode)
if you are new to clojure, gen-class is pretty terrible to work with, in general if you can it is much better to use reify/deftype/defrecord then proxy, then if you must gen-class (a lot of people would prefer to write some stub java than use gen-class)
ohh okay
Thanks hiredman
(ns myorg.plugin.orc-output
(:import
[myorg.helpers.fs-input-stream FsInputStream]
[ URL]
[ File]
[java.nio.file Path]
org.apache.hadoop.conf.Configuration
[org.apache.orc OrcFile]
[org.apache.hadoop.fs FileSystem FileSystem$Statistics FSDataInputStream FSDataOutputStream]))
(set! *warn-on-reflection* true)
(defn to-path
[x]
{:post (instance? Path %)}
(cond
(instance? URL x) (Path. (.toURI ^URL x))
(instance? File x) (Path. (.getPath ^File x))
(string? x) (Path. ^String x)
(instance? Path x) x))
(def dummy-path (to-path "dummy"))
(def orc-header-length (count OrcFile/MAGIC))
(defn input-stream-filesystem [buffered-bytes]
(proxy [FileSystem] []
(open [_]
(FSDataInputStream. (FsInputStream. buffered-bytes)))))
(defn create-orc-reader [buffered-bytes]
(OrcFile/createReader dummy-path (doto (OrcFile/readerOptions (Configuration.))
(.maxLength (count buffered-bytes))
(.filesystem (input-stream-filesystem buffered-bytes)))))
Then I've test for namespace myorg.plugin.orc-output called myorg.plugin.orc-output-test. It has very basic test
(ns myorg.plugin.orc-output-test
(:require [clojure.test :refer :all])
(:require [myorg.plugin.orc-output :refer :all]))
(deftest orc-create
(is (= 1 1)))
When I run the test I get error
Syntax error (ClassNotFoundException) compiling at (myorg/plugin/orc_output.clj:1:1). myorg.helpers.fs-input-stream.FsInputStream Full report at: /var/folders/b_/_t677thx43n6pd8l8x0c1qjr0000gp/T/clojure-13616919898936783952.edn
The project is in https://github.com/rajcspsg/gen-class-error-demo as well.
How can I fix this?
You are not aot compiling the namespace with the gen-class in it
You also are not requiring the namespace that defines the class from the namespace that uses it
You also are not using the correct name for the class, you need to replace all - with _
The docstring for gen-class helpfully tells you it does nothing when "not compiling", but unhelpfully clojure is always compiled to bytecode, so in this case "compiling" means aot compiling