JBoss.orgCommunity Documentation

Chapter 5. Application Initialization & Configuration

5.1. Introduction

The initialization and configuration of applications deployed to Immutant can potentially involve multiple files:

Each of these files have the opportunity to contribute to the configuration or initialization of the application.

5.2. The Initialization Process

When an Immutant detects a Clojure deployment (either a deployment descriptor or an Immutant archive), it begins the application initialization process:

  1. If the deployment is a descriptor file, this file is loaded in a global Clojure runtime to parse the map from the file. The :root entry from that map is then used to determine the actual root of the application, and can refer to the application directory or the path to an Immutant archive. Any additional configuration information from the descriptor is stored for later merging with data from other configuration sources.
  2. If the deployment is an archive, or the :root from the descriptor points to an archive, the archive is expanded on disk to a temporary directory.
  3. Once the application root has been determined, Immutant looks for a Leiningen project.clj in the root. If present, the project file is loaded and if an :immutant key is preset in the resulting project, it is merged with the configuration data from the descriptor with the configuration from the descriptor taking precedence. If the deployment was not an archive file, Leiningen is used to resolve the dependencies present in the project via Maven (this behavior can be overridden - see :resolve-dependencies.
  4. If a lib/ directory is present in the application root, any jars within it are merged with the dependencies calculated in the previous step. Each of these jars are added to the isolated classpath for the application, along with source and resource directories within the application root (see Dependencies & Resources for more information).
  5. At this point, Immutant creates a Clojure runtime for the application. Runtimes in Immutant are isolated from each other, and can each load their own versions of Clojure or any other jar.
  6. If an initialization function was specified in either the descriptor or the :immutant hash in the project (via the :init key), it is loaded and invoked within the application's runtime (see :init for more details). If no init function was specified, Immutant looks in the application root for a file named immutant.clj and loads that file. See immutant.clj for more information on using this initialization method. At this point, the application is fully initialized.

5.3. Configuration Options

The following configuration options can appear in the deployment descriptor or (with the exception of :root) the :immutant hash of project.clj.

  • :root - specifies the path to the 'root' of the application. This can either be the path to the application directory, or the path to an Immutant archive. :root is only valid in a deployment descriptor, and is ignored if specified in project.clj.
  • :resolve-dependencies - determines if dependencies defined in project.clj will be resolved via Pomegranate. This resolution process downloads and installs any missing dependencies to $M2_REPO (~/.m2/repository by default). If not specified, :resolve-dependencies defaults to true for dir-based deployments, and false for Immutant archives. See Dependencies & Resources for more details on the dependency resolution process.
  • :swank-port & :nrepl-port - Immutant can provide a per-application repl, either via Swank or nREPL. Immutant will automatically start a repl for you if you specify an unused port using either :swank-port or :nrepl-port. See Interactive Development for more details.
  • :init - specifies a function to call to initialize your application. This can be used as an alternative to an immutant.clj file. It can be either a namespace qualified symbol (my.app/do-something) or string (="my.app/do-something"=).
  • :context-path - overrides the default web context path that is generated based on the deployment name. See Web - Context Paths for more details.

A sample deployment descriptor:

;; :root is the only required option
{:root "/the/path/to/my/app"
 :resolve-dependecies false
 :swank-port 4242
 :nrepl-port 4343
 :init my.app/init
 :context-path "/" }

5.4. Files Used In Configuration & Initialization

5.4.1. Deployment Descriptor

A deployment descriptor is simply a Clojure source file containing a map of configuration options that is placed in Immutant's deployment directory to trigger the deployment of an application. It must contain a :root entry (see above), but any other configuration is optional. Any configuration specified here overrides configuration from project.clj. See the deployment descriptor section for more details.

5.4.2. project.clj

project.clj is the standard configuration file used by the Leiningen build tool. If a project.clj exists at the root of the application, Immutant will parse it and use it to determine dependencies and resource paths, as well as read Immutant specific configuration from the :immutant map. Here is a sample project.clj including all of the Immutant options that are usable in that file:

(defproject my-app "1.2.3"
            :dependencies [[org.clojure/clojure "1.3.0"]
                           [noir "1.2.0"]]
            :immutant {:init my-app.core/initialize
                       :resolve-dependencies true
                       :context-path "/"
                       :swank-port 4111
                       :nrepl-port 4112})

5.4.3. immutant.clj

immutant.clj provides an alternate initialization mechanism to the :init function. If no :init function is specified, Immutant will load immutant.clj if present at the application root. Typically, this file is used to start Immutant specific services, like so:

(ns my-app.init
  (:require [immutant.daemons   :as daemons]
            [immutant.jobs      :as jobs]
            [immutant.messaging :as messaging]
            [immutant.web       :as web]
            [immutant.repl      :as repl]
            [noir.server        :as server]
            [my-app.core        :as core]))

;; point noir to the right place for views
(server/load-views (str (web/src-dir) "/my_app/views"))

;; start a web endpoint
(web/start "/" (server/gen-handler {:mode :dev :ns 'my-app}))

;; spin up a repl
(repl/start-swank 4321)

;; schedule a job
(jobs/schedule "my-job" "*/5 * * * * ?" 
               my-app.core/process-tps-reports)

;; start a daemon
(deamons/start "my-daemon" core/daemon-start core/daemon-stop)

;; create a queue
(messaging/start "/queue/foo")

The services started in the above example are documented elsewhere in this manual.

5.5. Dependencies & Resources

Immutant generates a unique classpath for each deployed application based upon dependencies and source & resource directories defined in project.clj and any jars found in the lib/ at the application root.

The lib/ directory can be used to bundle dependencies with your application, and can be useful in the following situations:

  • you want to verify an application through a QA process without any external dependencies, can resolve dependencies
  • you don't have the option of resolving dependencies at deploy time
  • you have dependencies that aren't published to a maven repository
  • you're project doesn't use Leiningen

When dependency resolution is enabled for an application, Immutant uses Pomegranate (via leiningen-core) to resolve the dependencies against a local Maven repository. If the dependencies aren't available in the local repository, they are downloaded into it. The local repository is located based on the value of $M2_REPO, and defaults to ~/.m2/repository/.

The enablement of dependency resolution depends upon the value of the :resolve-dependencies option and the type of deployment.

5.5.1. Dependency Resolution In Directory Based Deployments

When deploying an application as a directory, dependencies are resolved by default, but resolution can be disabled by setting :resolve-dependencies to false.

5.5.2. Dependency Resolution In Archive Based Deployments

When deploying an application as an archive, dependencies are not resolved by default, but resolution can be enabled by setting :resolve-dependencies to true.

Immutant 0.1.0