Guidelines for using Clojure with Spring Framework
(ns ...
(:require [cheshire.core :as json]))
and then return using
(json/generate-string {:a 1 :b 2})
When using annotations like @PathVariable, @RequestParam etc., specify the value
attribute as the debugging information is not available. The value attribute can be dash-case.
Otherwise the following error will occur: Name for argument type [java.lang.String] not available, and parameter name information not found in class file either.
We cannot require another namespace or import a class in (ns :gen-class )
. The code emitted by ns macro calls :gen-class
before calling any of the :require
or :import
.
Thus the required namespace/class or not compiled when :gen-class
is called. We can use fully qualified names to solve this, but that would be ugly.
A Better solution is to call (gen-class ...)
after (ns ...)
Method arguments types and return types still need to be fully qualified (except java.lang.*)
Method names should be camelCase instead of dash-case due to Java restrictions
If you prefer, you can return CompletableFuture from the controller method to be asynchronous with the following macro
(ns ...
(:import (java.util.concurrent CompletableFuture)
(java.util.function Supplier)))
(defmacro async
"Wraps the given `body` inside a CompletableFuture."
[& body]
`(CompletableFuture/supplyAsync
(reify
Supplier
~(list 'get '[this] (cons 'do body)))))
and then use it like
(async
(println "Async Controller method")
(+ 3 5))
(ns com.clojurespring.controller
(:require [cheshire.core :as json])
(:import (org.springframework.web.bind.annotation RestController GetMapping PathVariable)))
(gen-class
:name ^{RestController {}} com.clojurespring.SampleController
:methods [[^{GetMapping {:value ["/hello"]
:produces ["application/json;charset=UTF-8"}}
hello [^{PathVariable {:value "name"}} String] java.util.concurrent.Future]])
(defn -hello
[this name]
(async
(println "Inside async controller...")
(json/generate-string {:a 1
:message (str "Hello " name " from Clojure controller"))))
curl -X GET -H "Accept: application/json;charset=UTF-8" "http://server.name/hello/rich"
{
"a": 1,
"message": "Hello rich from Clojure controller"
}
Nothing written in this guide is set in stone. It's my desire to work together with everyone interested in Clojure coding style, so that we could ultimately create a resource that will be beneficial to the entire Clojure community.
Feel free to open tickets or send pull requests with improvements. Thanks in advance for your help!