Marcus Junius Brutus
Marcus Junius Brutus

Reputation: 27286

compile Clojure *.clj into *.class, some functions are not generated

I am following the instructions from here and am trying to generate a Java class from clj sources by invoking lein jar.

However, when I edited the code a little to add a test function of my own:

(ns some.Example
  (:gen-class))

(defn -main
  [greetee]
  (println (str "Hello " greetee "!")))

(defn -foo []
  "foo bar")

.. and then proceeded to generate a Java class file with lein jar (I append the project.clj at the end of the post) I found that the generated jar contains the methods as inner classes:

$ jar tvf example-1.0.0.jar 
    76 Sun Feb 17 20:56:24 EET 2013 META-INF/MANIFEST.MF
  1225 Sun Feb 17 20:56:24 EET 2013 META-INF/maven/some/example/pom.xml
    87 Sun Feb 17 20:56:24 EET 2013 META-INF/maven/some/example/pom.properties
  2697 Sun Feb 17 20:56:24 EET 2013 some/Example__init.class
  1499 Sun Feb 17 20:56:24 EET 2013 some/Example$loading__4784__auto__.class
  1035 Sun Feb 17 20:56:24 EET 2013 some/Example$_main.class
   565 Sun Feb 17 20:56:24 EET 2013 some/Example$_foo.class
  1771 Sun Feb 17 20:56:24 EET 2013 some/Example.class
   162 Sun Feb 17 18:03:12 EET 2013 project.clj
   129 Sun Feb 17 19:23:54 EET 2013 some/Example.clj

and that the some.Example class contains only the main method but not the foo:

$ javap some.Example
public class some.Example {
  public static {};
  public some.Example();
  public java.lang.Object clone();
  public int hashCode();
  public java.lang.String toString();
  public boolean equals(java.lang.Object);
  public static void main(java.lang.String[]);
}

So the question is: how can we specify a clj Clojure file that generates a Java class with a number of static and instance methods with the aim of calling these methods from Java code?

project.clj used for the *lein jar* operation

(defproject some/example "1.0.0"
  :description "A sample project"
  :dependencies [[org.clojure/clojure "1.4.0"]]
  :aot [some.Example]
  :source-paths ["."]
  )

Upvotes: 1

Views: 847

Answers (1)

Cubic
Cubic

Reputation: 15683

You need to declare the methods that your class is going to have:

(ns some.Example
  (:gen-class
     :methods [[foo [] String]]))

Note that this declares foo as a non-static method so it also needs to take a this parameter:

(defn -foo [this]
  "foo bar")

If you want the method to be static, you need to attach some metadata:

(ns some.Example
      (:gen-class
         :methods [#^{:static true}[bar [] int]]))
(defn -bar []
  3)

Try reading this, it gets somewhat faster to the point.

Upvotes: 2

Related Questions