Reify in macro woes

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

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.