Sample SpringBoot project using spring-boost
When run normally, it does not load and run the Clojure code.
Clojure code is enabled only when the dev profile is activated
Note: There is no reason it should be so. If you are adventurous enough (or believe in Clojure), get rid of the @Profile("dev") annotation in the ~DevWorx~ class.
SPRING_PROFILES_ACTIVE=dev ./gradlew clean bootRun
#or
./gradlew clean bootRun --args='--spring.profiles.active=dev'Output looks something like
> Task :bootRun . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.7.0) [2022-05-21 00:18:07,877] INFO [main] org.springframework.boot.StartupInfoLogger::logStarting Starting SpringCljApplication using Java 17.0.3 on tachyon-mac-2.local with PID 43464 (/Users/jaju/github/spring-clj/build/classes/java/main started by jaju in /Users/jaju/github/spring-clj) [2022-05-21 00:18:07,879] DEBUG [main] org.springframework.boot.StartupInfoLogger::logStarting Running with Spring Boot v2.7.0, Spring v5.3.20 [2022-05-21 00:18:07,880] INFO [main] org.springframework.boot.SpringApplication::logStartupProfileInfo The following 1 profile is active: "dev" [2022-05-21 00:18:09,144] INFO [main] org.msync.spring_boost.application_context$_component_init::invokeStatic Initializing the ClojureComponent [2022-05-21 00:18:09,986] INFO [main] org.msync.spring_boost.Boost::startNrepl nREPL server started on port = 8190 [2022-05-21 00:18:09,986] INFO [main] org.msync.spring_boost.Boost::setInitSymbol Initializing clojure code: org.msync.spring-clj.core/main [2022-05-21 00:18:11,275] INFO [main] jdk.internal.reflect.NativeMethodAccessorImpl::invoke0 [spring-clj] Initializing clojure app... [2022-05-21 00:18:11,543] INFO [main] org.springframework.boot.StartupInfoLogger::logStarted Started SpringCljApplication in 4.278 seconds (JVM running for 4.491) <===========--> 85% EXECUTING [17s] > :bootRun
(ns org.msync.spring-clj.core
(:require [org.msync.spring-boost :as boost]
[compojure.core :refer :all]
[compojure.route :refer [not-found]]
[clojure.string]
[clojure.pprint :refer [pprint]])
(:import [java.util.logging Logger]
[org.springframework.context ApplicationContext]))
(defonce logger (Logger/getLogger (str *ns*)))
(defroutes app
"Root hello-world GET endpoint, and another echo end-point that handles both GET and POST.
The :body entry in the request-map comes in either as a map for JSON requests, or as a String
for other types."
(GET "/" [:as {query-string :query-string}]
(str "<h1>Hello World.</h1>"
(if-not (clojure.string/blank? query-string) (str "We received a query-string " query-string))))
(GET "/echo/:greeter" [greeter]
{:status 200
:headers {:content-type "application/json"}
:body {:greeting (str "Hello, " greeter)}})
(POST "/echo/:greeter" [greeter :as request]
{:status 200
:headers {:content-type "application/json"}
:body {:greetings (str "Hello, " greeter)
:echo (:body request)}})
(not-found "<h1>Page not found</h1>"))
(defn web-socket-handler [session]
(pprint session)
;; Use the session as you wish - to create session-specific handlers
(fn [^String message]
(str "*Hello*, " (.toUpperCase message))))
(defn main
"Set this as your entry-point for the Clojure code in your spring-boot app.
Gets the ApplicationContext object as an argument - which you are free to ignore or use."
[^ApplicationContext application-context]
(.info logger (str "[spring-clj] Initializing clojure app..."))
(boost/set-handler! app)
(boost/set-websocket-handler! web-socket-handler))
(comment
(require '[org.msync.spring-boost.application-context :as ac])
(ac/get-application-context)
(def boost-configuration (get components "boostConfiguration"))
(map str (.getMethods (class boost-configuration)))
(.getMethod (class boost-configuration) "setInitSymbol" (into-array Class [String]))
(ac/beans-with-annotation org.springframework.stereotype.Component)
(->> (ac/beans-with-annotation org.springframework.stereotype.Component)
vals
(map class)))