Hi…
Disclaimer: My macro skills are something I rarely exercis, so please bear with me :-).
When playing with helidon (http://helidon.io) today, I came up with this translation of their getting started sample:
(ns helidontry.core
(:import (io.helidon.webserver WebServer Routing ServerResponse ServerRequest Handler ServerConfiguration)))
(defn -main [& args]
(doto (WebServer/create
(-> (ServerConfiguration/builder)
(.port 8080)
(.build))
(-> (Routing/builder)
(.get "/greet" (into-array
[(reify
Handler
(^void accept
[^Handler this ^ServerRequest req ^ServerResponse res]
(.send res "Hello World")))]))
(.build)))
(.start)))
The routing handler into-array/reify looks really ugly, so I thought I use a macro here.
This is what I came up with:
(defmacro helidon-handler [[this req res] & body]
`(into-array
[(reify Handler
(~(with-meta 'accept {:tag 'void})
[~(vary-meta this assoc :tag Handler)
~(vary-meta req assoc :tag ServerRequest)
~(vary-meta res assoc :tag ServerResponse)]
~@body))]))
and use it like this:
...
(.get "/greet" (helidon-handler [this req res]
(.send res "Hello World")))
…
Looks much better IMHO, but unfortunately does not work.
The server starts up, but when exercising it with a
(slurp "http://localhost:8080/greet")
I get an error:
java.lang.AbstractMethodError: Method helidontry/core$_main$reify__1500.accept(Lio/helidon/webserver/ServerRequest;Lio/helidon/webserver/ServerResponse;)V is abstract
at helidontry.core$_main$reify__1500.accept(core.clj)
...
The reify did not create the correct access method signature it seems.
(set! *print-meta* true)
(macroexpand-1 '(helidon-handler [this req res]
(.send res "Hello World")))
yields
(clojure.core/into-array
[(clojure.core/reify
io.helidon.webserver.Handler
(^void accept
[^io.helidon.webserver.Handler this
^io.helidon.webserver.ServerRequest req
^io.helidon.webserver.ServerResponse res]
^{:line 95, :column 34} (.send res "Hello World")))])
which looks ok to me.
When I paste this exact macro expansion ihto the code replacing the macro call, it works.
Any idea what is going wrong here?
Ciao
…Jochen