Clojure Tutorial II — Packaging

joydeep bhattacharjee
Technology at Nineleaps
5 min readJul 19, 2017

Till now you have been using lein repl to explore the intricacies of the Clojure code you have seen so far. In the real world, you make actual applications and then ship/release those applications. More often than not those applications will sit alongside some legacy Java applications that have already been built and are running on the JVM in production. So, in this section, you will learn how to create effective production code and ship it. This tutorial assumes that you have leiningen installed and running. In case you don’t, please refer Clojure Tutorial I.

  1. How to create an application using lein.
  2. How to write test cases for the application and ensure that the application is production grade.
  3. How to create a jar for the application so that it can be deployed to JVM.
  4. How to interact with applications that are created in Java and achieve Java interop through the JVM.

Create an application

To create an application, you have the following options for commands.

lein new app my-first-clojure-app

which gives the following output -

lein new app my-first-clojure-app
Generating a project called my-first-clojure-app based on the 'app' template.

and

lein new my-first-clojure-app1

The above command gives the following output.

➜  clojure_blog lein new my-first-clojure-app1
Generating a project called my-first-clojure-app1 based on the 'default' template.
The default template is intended for library projects, not applications.
To see other templates (app, plugin, etc), try `lein help new`.

There is another template provided which is the plugin template. The directory structure that is generated in all of them is almost the same.

➜  my-first-clojure-app tree .
.
├── CHANGELOG.md
├── doc
│ └── intro.md
├── LICENSE
├── project.clj
├── README.md
├── resources
├── src
│ └── my_first_clojure_app
│ └── core.clj
└── test
└── my_first_clojure_app
└── core_test.clj
6 directories, 7 files

Once your directory structure is created, copy paste the code shown below to my-first-clojure-app/src/my_first_clojure_app/core.clj . This is the core file where the main code for running the Clojure app should be present. Clojure community encourages a high amount of abstraction, so you should be creating a lot of such libraries with a small amount of code in the core.clj file.

Take a look at the code shown. There is the main function that calls the binomial function, executes it and prints it. The binomial function is a pure function and just returns the value based on the input given.

You can execute this code. Go back to the project root and then type the following command.

➜  my_first_clojure_app cd ../../..
➜ clojure_blog ls -ltr
total 8
drwxrwxr-x 6 joy joy 4096 Jul 10 12:48 my-first-clojure-app
drwxrwxr-x 6 joy joy 4096 Jul 10 12:48 my-first-clojure-app1
➜ clojure_blog cd my-first-clojure-app
➜ my-first-clojure-app ls -ltr
total 40
-rw-rw-r-- 1 joy joy 491 Jul 10 12:48 README.md
-rw-rw-r-- 1 joy joy 387 Jul 10 12:48 project.clj
drwxrwxr-x 2 joy joy 4096 Jul 10 12:48 doc
drwxrwxr-x 3 joy joy 4096 Jul 10 12:48 src
drwxrwxr-x 3 joy joy 4096 Jul 10 12:48 test
-rw-rw-r-- 1 joy joy 11219 Jul 10 12:48 LICENSE
-rw-rw-r-- 1 joy joy 794 Jul 10 12:48 CHANGELOG.md
drwxrwxr-x 2 joy joy 4096 Jul 10 12:48 resources
➜ my-first-clojure-app
➜ my-first-clojure-app lein run
(binomial 5 3): 10
(binomial 10042 111): 490683895750681449466337775283661634279920945976497785986873571425849866652769464638191990344596658199164342716253389845859043982357640103767897175853473645345706556778496338557820478748178314846156008309671682804824359157818666487159757179543983405334334410427200
➜ my-first-clojure-app

This should execute the code.

Unittests

Now that you have written a production function you should also have tests for that function. You should see that the following file is created in your project directory.

➜  my-first-clojure-app ls -ltr test/my_first_clojure_app/core_test.clj 
-rw-rw-r-- 1 joy joy 192 Jul 10 12:48 test/my_first_clojure_app/core_test.clj

Open this file and paste the following code there.

Lein will help you run the tests as well.

➜  my-first-clojure-app lein testlein test my-first-clojure-app.core-testRan 1 tests containing 1 assertions.
0 failures, 0 errors.

Create a jar

You have written your application and have tested it as well. Now, you will need to distribute this application so that your clients can plug it in their JVM processes and run the application. You can do this by creating a jar file. To create a jar, you need to pass the uberjar argument.

➜  my-first-clojure-app lein uberjar
➜ my-first-clojure-app cd target/uberjar
➜ uberjar ls -ltr
total 3632
drwxrwxr-x 2 joy joy 4096 Jul 10 13:25 stale
drwxrwxr-x 4 joy joy 4096 Jul 10 13:25 classes
-rw-rw-r-- 1 joy joy 15611 Jul 10 13:25 my-first-clojure-app-0.1.0-SNAPSHOT.jar
-rw-rw-r-- 1 joy joy 3690828 Jul 10 13:25 my-first-clojure-app-0.1.0-SNAPSHOT-standalone.jar
➜ uberjar
➜ uberjar java -jar my-first-clojure-app-0.1.0-SNAPSHOT-standalone.jar
(binomial 5 3): 10
(binomial 10042 111): 490683895750681449466337775283661634279920945976497785986873571425849866652769464638191990344596658199164342716253389845859043982357640103767897175853473645345706556778496338557820478748178314846156008309671682804824359157818666487159757179543983405334334410427200

After that send this jar to your clients and they will be able to run the app as a jar file.

➜  cd target/uberjar 
➜ uberjar java -jar my-first-clojure-app-0.1.0-SNAPSHOT-standalone.jar
(binomial 5 3): 10
(binomial 10042 111): 490683895750681449466337775283661634279920945976497785986873571425849866652769464638191990344596658199164342716253389845859043982357640103767897175853473645345706556778496338557820478748178314846156008309671682804824359157818666487159757179543983405334334410427200

Calling Clojure from Java

But sometimes you need to call Clojure functions from Java. People usually use Clojure because they have huge applications written in Java. They probably want to extend that application and create the new feature in Clojure. Clojure’s many advantages of speed and crispness of code make it an ideal candidate to be integrated into your code base. I am assuming you will encounter the same situation making you want to create the new feature as a Clojure function and call the function in Java. Clojure provides the required classes to call the Clojure code in your Java app and then run it. The Clojure code will run through an interpreter as a side effect in Java and then the results can be imported and analyzed.

To do that, create a directory clojure-java-interop. Download the latest Clojure jar to that folder. Also, copy the earlier code to the directory and then rename it to binomial.clj. Then, create a file called Binomial.java where you will be calling the Clojure code.

➜  ls -ltr
total 3552
-rw-r----- 1 joy joy 3622815 Jul 10 14:29 clojure-1.8.0.jar
-rw-rw-r-- 1 joy joy 469 Jul 10 14:29 binomial.clj
-rw-rw-r-- 1 joy joy 643 Jul 10 14:36 Binomial.java

Now, write the Java code.

For this tutorial, you can just call the function and then print it out. You will need two classes to help you out with that as is shown in the code below.

You will now need to compile the Java code and then run it.

➜  javac -cp "clojure-1.8.0.jar:." Binomial.java
➜ java -cp "clojure-1.8.0.jar:." Binomial
10
490683895750681449466337775283661634279920945976497785986873571425849866652769464638191990344596658199164342716253389845859043982357640103767897175853473645345706556778496338557820478748178314846156008309671682804824359157818666487159757179543983405334334410427200

In the next tutorial you will learn about the basic data structures and some interesting properties and use cases about them.

--

--