Setup for production

There are many options to setup a lein ring project for production.

  • Deploy a WAR-archive to a Servlet engine like Tomcat or Jetty.
  • The plugin lein-ring and ring-server
  • Embedded Jetty Server
  • Embedded Jetty Server as part of a module system
  • Use one of the 第三方库(Third Party Libraries)

WAR archive

A WAR archive is the standard packaging to copy an application to an existing Tomcat or Jetty servlet engine.

It is a ZIP file with a specific structure containing the clojure code and all libraries.

Create the archive using the following command.

  1. lein ring uberwar

Deploy the created archive to your servlet engine.

Lein-ring plugin

You need to add the lein-ring plugin to your profile.clj.

  1. :plugins [[lein-ring "0.12.1"]]
  2. :ring {:handler sample/handler}

In addition disable hot reloading and random port selection using the enviroment option.

  1. LEIN_NO_DEV

Start the server.

  1. LEIN_NO_DEV=true lein ring server-headless

More infos: https://github.com/weavejester/ring-server

Embedded Jetty server

We create a JAR file containing the already compiled Clojure code and all libraries.

Steps

  • src/sample.clj entrypoint of JAR
  • build configuration
    Use ring.adapter.jetty to start Jetty with your handler.
  1. (ns sample
  2. (:require [ring.adapter.jetty :refer [run-jetty]])
  3. (:gen-class))
  4.  
  5. (defn handler [request]
  6. {:status 200
  7. :headers {"Content-Type" "text/text"}
  8. :body "Hello world"})
  9.  
  10. (defn -main [& args]
  11. (run-jetty handler {:port (Integer/valueOf (or (System/getenv "port") "3000"))}))

It is important to use :gen-class with AOT compiling.

The next step depends on the build tooling.

Build using Leiningen

We need to add :aot and :main to the project.clj.

  1. (defproject lein-ring "0.1.0-SNAPSHOT"
  2. :dependencies [[org.clojure/clojure "1.8.0"]
  3. [ring/ring-core "1.6.3"]
  4. [ring/ring-jetty-adapter "1.6.3"]
  5. [ring/ring-devel "1.6.3"]]
  6. :profiles{
  7. :uberjar{
  8. :aot :all
  9. :main sample}})

Build using Boot

A simple build.boot containing a task to create an uberjar.

  1. (set-env!
  2. :resource-paths #{"src"}
  3. :dependencies '[[org.clojure/clojure "1.8.0"]
  4. [ring/ring-core "1.6.3"]
  5. [ring/ring-jetty-adapter "1.6.3"]
  6. [ring/ring-devel "1.6.3"]])
  7.  
  8. (deftask build
  9. "Builds an uberjar of this project that can be run with java -jar"
  10. []
  11. (comp
  12. (aot :namespace #{'sample})
  13. (uber)
  14. (jar :file "project.jar" :main 'sample)
  15. (sift :include #{#"project.jar"})
  16. (target)))

Run the server

Execute the Jar File with an optional port.

  1. port=2000 java -jar target/project.jar

Embedded Jetty Server as part of a module system

Have a look at the page about module lifecycle libraries Interactive Development