Chapter 11. Interactive Development
11.1. Introduction
Immutant provides two methods for connecting to an application's runtime with a REPL: Swank (for emacs) and nREPL (for any nREPL client).
Each REPL service runs on a unique port, allowing you to have REPLs into multiple applications within the same Immutant, or mutltiple REPLs within the same application.
REPL services can be started at application deploy time, or dynamically from application code. REPLs started dynamically can be also be shutdown dynamically. REPLs started at deploy time and any dynamically started REPLs that are not shut down by the application will be shut down when the application is undeployed.
11.1.1. Binding To An Interface
AS7 is setup to use multiple network interfaces, and allows you to specify
different interfaces for your server: public, management, and unsecure.
By default, these interfaces are all the same - 127.0.0.1. But you can
specify different addresses for each named interface, aiding in the security
setup of your management ports.
By default, the repl services started by Immutant bind to the management interface.
11.2. Swank
Swank is the server protocol for SLIME (The Superior Lisp Interactive Mode for Emacs), and Clojure Swank & SLIME support are provided by swank-clojure & clojure-mode, respectively.
11.2.1. Starting Swank
You can start a Swank service using one (or both) of two methods: specifying
a :swank-port option in your configuration, or by calling
immutant.repl/start-swank from application code. No matter which method
you use, there can only be one Swank service running for an application.
11.2.1.1. Starting Swank Via :swank-port
To have Immutant start a Swank service on your behalf, you can specify
an open port for it to bind to using the :swank-port configuration
option. When using this option, Immutant will automatically
bind to the management interface.
11.2.1.2. Starting Swank Programatically
You can also start a Swank service from your own code, which is useful if you need to start it in response to a runtime event or bind to an interface other than the management interface. To do so, simply call immutant.repl/start-swank:
;; bind to the given port on the management interface (clojure.repl/start-swank 4242) ;; bind to the given port and interface (clojure.repl/start-swank 4242 "127.0.0.1")
11.2.2. Connecting to Swank
Installing SLIME under emacs to work with Clojure can be a painful and
confusing process if done manually. The easiest way to do it is to follow
the clojure-jack-in instructions from swank-clojure, and "jack in" to
any Leiningen project. This will trigger clojure-mode to download and
install a version of SLIME that is compatible with swank-clojure.
Once you have jacked in at least once, you can then connect to the Swank
service within your Immutant application via the slime-connect emacs
function (M-x slime-connect RET).
11.2.3. Shutting Down Swank
Immutant will automatically shutdown the Swank service for you when your application is undeployed, but if you need to do so before undeploy you can do so using the immutant.repl/stop-swank function:
;; no arg needed since only one Swank server can exist for the application (clojure.repl/stop-swank)
11.3. nREPL
nREPL is a client/server protocol that provides a Clojure across a network. It is relatively new, but has several clients built around it.
11.3.1. Starting nREPL
You can start a nREPL service using one (or both) of two methods: specifying
an :nrepl-port option in your configuration, or by calling
immutant.repl/start-nrepl from application code.
11.3.1.1. Starting nREPL Via :swank-port
To have Immutant start a nREPL service on your behalf, you can specify
an open port for it to bind to using the :nrepl-port configuration
option. When using this option, Immutant will automatically
bind to the management interface.
11.3.1.2. Starting nREPL Programatically
You can also start a nREPL service from your own code, which is useful
if you need to start it in response to a runtime event or bind to an
interface other than the management interface. To do so, simply
call immutant.repl/start-nrepl. nREPL allows you to have multiple
services in the same runtime, so you need to save the return value of
start-nrepl if you want to shut down the nREPL service yourself:
;; bind to the given port on the management interface, and ;; save the service handle for later (def nrepl (clojure.repl/start-nrepl 4242)) ;; bind to the given port and interface (clojure.repl/start-swank 4242 "127.0.0.1")
11.3.2. Connecting to nREPL
Installing SLIME under emacs to work with Clojure can be a painful and
confusing process if done manually. The easiest way to do it is to follow
the clojure-jack-in instructions from swank-clojure, and "jack in" to
any Leiningen project. This will trigger clojure-mode to download and
install a version of SLIME that is compatible with swank-clojure.
Once you have jacked in at least once, you can then connect to the nREPL
service within your Immutant application via the slime-connect emacs
function (M-x slime-connect RET).
11.3.2.1. Connecting via reply
reply is an enhanced REPL for Clojure, and supports connecting to an
nREPL service. Currently, the simplest way to install reply is to
clone the git repository and follow the intructions in its README.
Once you have reply installed, you can connect to your remote nREPL:
# connect to an nREPL bound to port 4242 on localhost $ reply --skip-default-init --attach 4242 # connect to an nREPL bound to port 4242 on 10.0.0.10 $ reply --skip-default-init --attach 10.0.0.10:4242
Note that we are passing the --skip-default-init option above. reply
attempts to load some libraries that won't exist in the application's
runtime within Immutant, and also creates handy quit & exit functions
that map to System/exit, which will shutdown the entire application server.
Passing the --skip-default-init option prevents reply from attempting
to load those missing libraries and prevents the definition of quit and
exit.
11.3.2.2. Connecting via vimclojure
Coming soon.
11.3.2.3. Connecting via Counterclockwise
Coming soon.
11.3.3. Shutting Down nREPL
Immutant will automatically shutdown any nREPL services for you when your
application is undeployed, but if you need to do so before undeploy you
can do so using the immutant.repl/stop-nrepl function. You'll need to
pass it the service handle returned by the start-nrepl call:
(clojure.repl/stop-nrepl nrepl)
Since you need the service handle to stop an nREPL service, you can only
manually stop nREPL's you start yourself. If you start an nREPL service
via the :nrepl-port configuration option, your only recourse is to
allow Immutant to shut it down for you on undeploy.