Is it possible to attach metadata to a Clojure gen-class?
I am trying to implement a server that uses a library that requires Java annotations added to classes.
From Chas Emerick's, et al., forthcoming book "Programming Clojure" (section 9.7.3), adding annotations to gen-class methods is easy, but there is no mention of adding class-level annotations.
An optional :gen-class directive can be used in the ns declaration to generate a named class corresponding to a namespace. (:gen-class … ), when supplied, defaults to :name corresponding to the ns name, :main true, :impl-ns same as ns, and :init-impl-ns true.
Basically, General Education (or Gen Ed for short) is required curriculum that makes up the foundation of an undergraduate degree. This set of standard classes goes by many other names, including Core Curriculum and Shared Experience.
In Clojure we can do that using the special form new or using a dot ( . ) notation. The new special form has the class name of the Java class we want to create an instance of as argument followed by arguments for the Java class constructor. With the dot notation we place a .
Yes it is, I found a great example here:
https://github.com/clojure/clojure/blob/master/test/clojure/test_clojure/genclass/examples.clj
Here's some code inlined so it doesn't disappear in the future:
(gen-class :name ^{Deprecated {}
SuppressWarnings ["Warning1"] ; discarded
java.lang.annotation.Target []}
clojure.test_clojure.genclass.examples.ExampleAnnotationClass
:prefix "annot-"
:methods [[^{Deprecated {}
Override {}} ;discarded
foo [^{java.lang.annotation.Retention java.lang.annotation.RetentionPolicy/SOURCE
java.lang.annotation.Target [java.lang.annotation.ElementType/TYPE
java.lang.annotation.ElementType/PARAMETER]}
String] void]])
I don't think it is possible at this point.
Rich Hickey mentions adding annotations support in this thread https://groups.google.com/group/clojure/browse_thread/thread/d2128e1505c0c117 but as far as I can see this is only for deftype / defrecord. I could be wrong of course.
Both of these
(ns genclass.example
(:gen-class ^{:doc "example class"}))
and
(ns genclass.example)
(with-meta
(gen-class
:name genclass.example.ClassA
:methods [[hello [] void]])
{:doc "Example class"})
fail to compile for me. From the exception
Exception in thread "main" java.lang.IllegalArgumentException: Metadata can only be applied to IMetas (example.clj:4)`
It sounds like this is not possible.
To add additional information to this because I can't find it documented anywhere else it's possible to add annotations to constructors as well.
You can add annotations to constructors by adding meta data to the first array of the constructor pair. Like this:
(gen-class
:name "FooClass"
:init "init"
:constructors {^{Inject {}} [Configuration] []}
:state "state"
:implements [FooInterface]
:prefix "ref-")
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With