Skip to content

Setup for production

Sebastian edited this page Dec 15, 2017 · 1 revision

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.

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.

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

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

LEIN_NO_DEV

Start the server.

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.

(ns sample
  (:require [ring.adapter.jetty :refer [run-jetty]])
  (:gen-class))

(defn handler [request]
  {:status  200
   :headers {"Content-Type" "text/text"}
   :body    "Hello world"})

(defn -main [& args]
  (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.

(defproject lein-ring "0.1.0-SNAPSHOT"
  :dependencies [[org.clojure/clojure "1.8.0"]
                 [ring/ring-core "1.6.3"]
                 [ring/ring-jetty-adapter "1.6.3"]
                 [ring/ring-devel "1.6.3"]]
  :profiles{
    :uberjar{
      :aot :all
      :main sample}})

Build using Boot

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

(set-env!
  :resource-paths #{"src"}
  :dependencies '[[org.clojure/clojure "1.8.0"]
                  [ring/ring-core "1.6.3"]
                  [ring/ring-jetty-adapter "1.6.3"]
                  [ring/ring-devel "1.6.3"]])

(deftask build
  "Builds an uberjar of this project that can be run with java -jar"
  []
  (comp
   (aot :namespace #{'sample})
   (uber)
   (jar :file "project.jar" :main 'sample)
   (sift :include #{#"project.jar"})
   (target)))

Run the server

Execute the Jar File with an optional port.

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