Question

I have created a new project with

lein new jar-clash-test
cd jar-clash-test/

I have put the following in project.clj

(defproject jar-clash-test "0.1.0-SNAPSHOT"
  :dependencies [[org.clojure/clojure "1.5.0"]
                 [io.pedestal/pedestal.service "0.1.2"]
                 ...]
  :main ^{:skip-aot true} jar-clash-test.core
)

I have put the following in jar-clash-test/src/jar_clash_test/core.clj

(ns jar-clash-test.core
  (:require [io.pedestal.service.http :as bootstrap]))

When I run this with

lein repl

I get the following error:

CompilerException java.lang.RuntimeException: No such var: content-type/content-type-response, compiling:(io/pedestal/service/http/ring_middlewares.clj:46:3)

When I look at:

/.m2/repository/io/pedestal/pedestal/0.1.2/pedestal.service-0.1.2/io/ring_middlewares.clj

On line 46 I see:

  (leave-interceptor ::content-type-interceptor content-type/content-type-response opts))

Which is defined in the requirements as:

[ring.middleware.content-type :as content-type]

Which means it is trying to bring in the ring-middleware jar.

My hypothesis is that there is a jar version clash for the ring middleware implementation.

This is based on:

  1. [compojure "1.1.3"] [has a dependency]2 on [ring/ring-core "1.1.5"]
  2. [io.pedestal/pedestal.service "0.1.2"] [has a dependency on]3 [ring/ring-core "1.2.0-beta1"]

When I look at:

/.m2/repository/ring/ring-core/1.2.0-beta1/ring-core-1.2.0-beta1/ring/middleware/content_type.clj

The function

(defn content-type-response

exists. When I look at:

/.m2/repository/ring/ring-core/1.1.5/ring-core-1.1.5/ring/middleware/content_type.clj

The function doesn't exist.

My question is - how do I know which version lein has picked up? I can 'assume' it has picked up the earlier one - but how I can know for certain?

My second question is - how can I guarantee which one lein will pick?

Was it helpful?

Solution

You can say lein classpath to get a printout of the computed value of the classpath for your project. Earlier jars win. Another approach: examine the value of (System/getProperty "java.class.path") at the REPL.

If you want to pick a version of an indirect dependency by hand, make it direct, that is, add it to your project.clj; this entry will then override the dependencies' choices in the context of this project. Alternatively, you could add :exclusions to all but one of your dependencies which cause the indirect dependency to be pulled in.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top