Once you learn Clojure (or any programming language) well enough to tackle a large project, you are going to run into lifecycle, dependency, and state management issues.
Two great resources for handling lifecycles, dependency, and state in Clojure apps are Mount and Component. I use Mount for my projects, but both are popular solutions. This post is about tolitius/Mount.
Create a Clojure Servlet project with the following command.
1
leinnewluminusmy-clj-servlet+war
The important parts of the command are ‘luminus’, which is the framework used to create the Servlet, and ‘+war’, which adds uberwar and Servlet routes to the project. This creates a file called ‘handler.clj’ that replaces the traditional Java Servlet file. The configurations for the Clojure Servlet are found in ‘project.clj’ in the
:uberwar section of the configurations.
By default the lein command above creates a project that will build a WAR file called my-clj-servlet.war, and when deployed will deploy in the my-clj-servlet context, meaning on a default installation of Tomcat you would find the link at http://localhost:8080/my-clj-servlet/
It is important to note that the resulting project from the above lein command actually won’t work as a Servlet, yet. But, we’ll fix that below. The project is configured in the hopes that you can run it from a Servlet container or as a standalone app, and with some massaging, you could. However, this tutorial only focuses on how to get the project compiling as a Java Servlet written in Clojure. If there is enough interest, I’ll write another tutorial on how to get the default project working as a standalone app, and a Servlet.
As mentioned in my other post about plaintext emails, I recommend using the Apache Commons Email library when sending email from Clojure apps. First up, you need to add the dependency to ‘project.clj’
1
2
3
4
:dependencies[
[org.clojure/clojure"1.10.1"]
[org.apache.commons/commons-email"1.5"]
]
Next, your HTML email has both an HTML version and the alternative plaintext version of the email. Notice, all you have to do is create an instance of HtmlEmail and then call the set and send methods on it using ‘doto’. Pretty easy.
I recommend using the Apache Commons Email library when sending email from Clojure apps. Here’s a simple example.
First up, you need to add the dependency to ‘project.clj’
1
2
3
4
:dependencies[
[org.clojure/clojure"1.10.1"]
[org.apache.commons/commons-email"1.5"]
]
Next, your code would look something like the following. Caution, … This will send emails, so configure it to send the emails to a personal email address for testing purposes.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
(nsemail-example.core
(:import(org.apache.commons.mailSimpleEmail)))
(defn-main
"I send plaintext emails using the Apache Commons Email library."
[&args]
(println"Email the World ...")
;; for more methods, such as for authentication, look at the manual...
When saving datetimes to databases like MySQL, it is best to save them as UTC instead of using your local timezone. That way, if your company, or IT department, or servers move to a new timezone, you won’t have to worry about adjusting every time stored in the database to match the new timezone. The trick is that you always return UTC times in your APIs, and then expect the clients or tools using your APIs to convert the provided UTC time to their local timezone for display.
This leads to a common question. How do I get the current datetime in UTC when using Clojure?
1
2
3
4
5
6
7
8
9
10
11
12
(defnutc-now
"Get now in UTC for use in a datetime for a database."
Migratus is a great migration tool for Clojure enterprise projects. Migrations allow you to do and undo changes to a database very quickly. The best use case for Migratus is update of a database for your enterprise project or setting up a new database for a development environment. Setting up the database can be on a production server or your local development environment.
Eventually one of your migrations is going to have an SQL exception. Normally, SQL exceptions aren’t a big deal. You just fix it, and run the migration again. However, Migration gets into an :ignore state and gives you an exception reading …
1
Migrationreservedbyanotherinstance
… and then refuses to run another migration no matter what you do.
The fix is to go into your ‘schema_migrations’ table in your database and remove the row that has an id of -1.
That’s really a simple fix for your favorite Clojure migration tool.
1
;-) Remember, ... keep your anonymous closures recursively tailed.
The book, Structure and Interpretation of Computer Programs, is considered one of the top necessary reads for software engineers. It is a fairly expensive book to buy hard copies of. Luckily, the authors generously provide a PDF version for free. Currently, you can download the free version from the sicp-pdf on GitHub. Also, MIT offers a free download at https://web.mit.edu/alexmv/6.037/sicp.pdf.
Structure and Interpretation of Computer Programs is written in Scheme, but is all applicable to Clojure. Functional programming is taught thoroughly, along with lazy sequences and higher order functions.
Structure and Interpretation of Computer Programs doesn’t ignore the other side of the fence. It also goes over objects, state, and mutable data.
This is a Computer Science book, so expect some deep thinking and descriptions. But, if you’re looking to improve your software engineering skills, give reading this book a go.
When coming from other languages, devs often think the best way to check for an empty vector or other sequence in Clojure is to either check the
count is less than one or check for
(not(empty?some-seq)) . Both will work, but are not idiomatic, meaning “Your newbness is showing.” Continue reading “Checking for Empty Seqs in Clojure”→
Clojure developers coming from Object Oriented backgrounds know how useful it is to separate implementation details from functions and methods that are supposed to be used by other coders. Java has public and private methods. This allows devs to limit usage and visibility of functions that are not meant to be used directly.
There are two options in Clojure for keeping functions private. First, you can use a special macro,
defn- .
defn- works just like
defn , except that the function is only visible inside the current namespace. This makes the function private in the Java sense to the term. Continue reading “Private Functions in Clojure”→