6

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.

Ralph
  • 31,584
  • 38
  • 145
  • 282

3 Answers3

24

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]])
Daniel Kaplan
  • 62,768
  • 50
  • 234
  • 356
1

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-")
zachncst
  • 11
  • 2
1

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.

Paul
  • 7,836
  • 2
  • 41
  • 48
  • 1
    I have started to use `deftype` instead of `gen-class` for my JAX-RS REST Server, following the example in Chas's book. It appears to be "cleaner". – Ralph Oct 10 '11 at 11:01
  • You might also like the following flowchart, also by Chas: http://cemerick.com/2011/07/05/flowchart-for-choosing-the-right-clojure-type-definition-form/ It could be in his book, I don't have it yet... – Paul Oct 10 '11 at 12:00
  • I saw the flowchart when it first showed up on twitter. Pretty nice! Thanks. – Ralph Oct 10 '11 at 12:43
  • @Ralph could you be so kind and mark the other answer as the accepted one, as nowadays it _is possible_ to attach annotations via `gen-class`. – Jakub Holý May 27 '19 at 15:27