Learn how to seamlessly integrate external Java libraries into your Clojure projects using dependencies in project.clj or deps.edn, and explore examples of calling code from popular Java libraries.
As experienced Java developers, you are likely familiar with the vast ecosystem of Java libraries available for various tasks, from data processing to web development. One of the strengths of Clojure is its seamless interoperability with Java, allowing you to leverage these libraries within your Clojure projects. In this section, we’ll explore how to add external Java libraries to your Clojure projects using two popular dependency management tools: Leiningen and tools.deps. We’ll also provide examples of calling code from popular Java libraries to illustrate these concepts.
Before diving into the specifics of adding Java libraries, it’s important to understand how dependency management works in Clojure. Clojure projects typically use either Leiningen or tools.deps to manage dependencies. Both tools allow you to specify the libraries your project depends on, automatically downloading and including them in your project’s classpath.
project.clj)Leiningen is a build automation tool for Clojure that uses a project.clj file to define project settings, including dependencies. Here’s a basic structure of a project.clj file:
(defproject my-clojure-project "0.1.0-SNAPSHOT"
  :description "A simple Clojure project"
  :dependencies [[org.clojure/clojure "1.10.3"]
                 [org.some/library "1.2.3"]])
:dependencies: This vector contains the list of dependencies, each specified as a vector with the library’s group ID, artifact ID, and version.deps.edn)tools.deps is a more recent addition to the Clojure ecosystem, providing a flexible way to manage dependencies using a deps.edn file. Here’s an example of a deps.edn file:
{:deps {org.clojure/clojure {:mvn/version "1.10.3"}
        org.some/library {:mvn/version "1.2.3"}}}
:deps: This map contains the dependencies, with each key being the library’s coordinate and the value specifying the version.Now that we understand the basics of dependency management, let’s explore how to add external Java libraries to your Clojure project using both Leiningen and tools.deps.
To add a Java library using Leiningen, you simply need to include it in the :dependencies vector in your project.clj file. For example, let’s add the popular Apache Commons Lang library:
(defproject my-clojure-project "0.1.0-SNAPSHOT"
  :description "A simple Clojure project with Apache Commons Lang"
  :dependencies [[org.clojure/clojure "1.10.3"]
                 [org.apache.commons/commons-lang3 "3.12.0"]])
Once you’ve added the dependency, run lein deps to download and include it in your project’s classpath.
With tools.deps, you add a Java library by specifying it in the :deps map in your deps.edn file. Here’s how you can add Apache Commons Lang:
{:deps {org.clojure/clojure {:mvn/version "1.10.3"}
        org.apache.commons/commons-lang3 {:mvn/version "3.12.0"}}}
After updating your deps.edn file, use the clj command to resolve and download the dependencies:
clj -Stree
This command will show the dependency tree, confirming that the library has been added successfully.
Once you’ve added a Java library to your project, you can call its code directly from Clojure. Let’s explore how to do this with some examples.
Suppose you want to use the StringUtils class from Apache Commons Lang to check if a string is empty. Here’s how you can do it in Clojure:
(ns my-clojure-project.core
  (:import [org.apache.commons.lang3 StringUtils]))
(defn is-empty? [s]
  (StringUtils/isEmpty s))
;; Usage
(println (is-empty? ""))  ; true
(println (is-empty? "Clojure"))  ; false
:import: This directive is used to import Java classes into your Clojure namespace.StringUtils/isEmpty: Calls the static isEmpty method from the StringUtils class.Google Guava is another popular Java library that provides utilities for collections, caching, and more. Let’s use Guava’s Joiner class to join a list of strings:
(ns my-clojure-project.core
  (:import [com.google.common.base Joiner]))
(defn join-strings [separator strings]
  (-> (Joiner/on separator)
      (.join strings)))
;; Usage
(println (join-strings ", " ["Clojure" "Java" "Scala"]))  ; "Clojure, Java, Scala"
Joiner/on: Creates a Joiner instance with the specified separator..join: Joins the strings using the Joiner instance.To highlight the differences and similarities between Java and Clojure, let’s compare the above examples with their Java counterparts.
import org.apache.commons.lang3.StringUtils;
public class Example {
    public static void main(String[] args) {
        System.out.println(StringUtils.isEmpty(""));  // true
        System.out.println(StringUtils.isEmpty("Clojure"));  // false
    }
}
import com.google.common.base.Joiner;
public class Example {
    public static void main(String[] args) {
        Joiner joiner = Joiner.on(", ");
        System.out.println(joiner.join("Clojure", "Java", "Scala"));  // "Clojure, Java, Scala"
    }
}
To deepen your understanding, try modifying the examples above:
To better understand how dependencies are managed in Clojure, let’s visualize the process using a diagram.
    graph TD;
	    A[Define Dependencies] --> B[Leiningen: project.clj];
	    A --> C[tools.deps: deps.edn];
	    B --> D[Download Dependencies];
	    C --> D;
	    D --> E[Classpath Setup];
	    E --> F[Use Java Libraries in Clojure];
Diagram Description: This flowchart illustrates the process of adding external Java libraries to a Clojure project. It starts with defining dependencies in either project.clj or deps.edn, followed by downloading the dependencies and setting up the classpath, allowing you to use Java libraries in your Clojure code.
For more information on dependency management and Java interoperability in Clojure, consider exploring the following resources:
deps.edn file, such as specifying a local path or a Git repository for dependencies.Now that we’ve explored how to add external Java libraries to your Clojure projects, you’re well-equipped to enhance your applications with powerful Java tools and libraries.