编写插件时如何排除 leiningen 引入的依赖项? [英] How do I do exclusions for dependencies that are pulled in by leiningen when writing a plugin?

查看:18
本文介绍了编写插件时如何排除 leiningen 引入的依赖项?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为 Leiningen 编写一个自定义插件,这将有助于部署用 Clojure 编写的 AWS Lambda 函数.我正在使用 aws-java-sdk-lambda 版本 1.11.145,它依赖于 Jackson 2.6.x,特别是 2.6.5 IIRC.

I'm writing a custom plugin for Leiningen that will help in deploying AWS Lambda functions written in Clojure. I'm using aws-java-sdk-lambda version 1.11.145 which has a dependency on Jackson 2.6.x, specifically 2.6.5 IIRC.

由于我将其作为插件编写,因此代码在 Leiningen 的上下文中执行(即 :eval-in-leiningen true),并且,AFAIK,受 Leiningen 本身的依赖.

Since I am writing this as a plugin, the code is executing in the context of Leiningen (i.e. :eval-in-leiningen true) and, AFAIK, is subject to the dependencies of Leiningen itself.

这是一个问题,因为我运行的 Leiningen 版本 (2.7.1) 依赖于 Cheshire 5.5.0 而后者又依赖于 Jackson2.5.3.当 AWS 开发工具包尝试调用 com.fasterxml.jackson.databind.JavaType.isReferenceType() 时,这会导致 NoSuchMethodError.AFAIK,jackson-core-2.6.5(由 AWS 引入)正试图调用 jackson-databind-2.5.3(由 Cheshire 间接引入).至少看起来是这样.

This is a problem since the version of Leiningen I am running (2.7.1) is dependent on Cheshire 5.5.0 which, in turn, is dependent on Jackson 2.5.3. This results in a NoSuchMethodError when the AWS SDK attempts to call com.fasterxml.jackson.databind.JavaType.isReferenceType(). AFAIK, jackson-core-2.6.5 (pulled in by AWS) is attempting to call into jackson-databind-2.5.3 (pulled in, indirectly, by Cheshire). At least that is what appears to be happening.

第一个问题:这是一个已知问题吗?我无法在 SO、Google 或 Leiningen 的 GitHub 页面上的第一页问题上找到任何直接引用它的内容(我没有在那里进行详尽的搜索).第二:有人对解决这个问题有什么建议吗?:exclusions 似乎是显而易见的选择,但我不确定如何为 Leiningen 本身作为依赖项引入的内容指定排除项.

First question: is this a known issue? I was not able to find anything directly referencing it on SO, Google or the first page of issues on Leiningen's GitHub page (I did not do an exhaustive search there). Second: Does anyone have any suggestions for working around this problem? :exclusions seems like the obvious choice but I'm not sure how one would specify an exclusion for something that Leiningen itself is pulling in as a dependency.

下面,我包含了简单的项目规范来重现错误:

Below, I have included simple project specifications to reproduce the error:

插件的project.clj:

(defproject aws-plugin "0.1.0-SNAPSHOT"
  :description "FIXME: write description"
  :url "http://example.com/FIXME"
  :license {:name "Eclipse Public License"
            :url "http://www.eclipse.org/legal/epl-v10.html"}
  :dependencies [[com.amazonaws/aws-java-sdk-lambda "1.11.145"]]
  :eval-in-leiningen true)

插件的源代码:

(ns leiningen.aws-plugin
  (:import (com.amazonaws.services.lambda AWSLambdaClient
                                          AWSLambdaClientBuilder)))

(def aws-lambda-client (-> (AWSLambdaClient/builder) (.build)))

(defn aws-plugin
  "I don't do a lot, or anything at all."
  [project &]
  (println "Create Lambda"))

插件用户的project.clj

(defproject aws-plugin-user "0.1.0-SNAPSHOT"
  :description "FIXME: write description"
  :url "http://example.com/FIXME"
  :license {:name "Eclipse Public License"
            :url "http://www.eclipse.org/legal/epl-v10.html"}
  :dependencies [[org.clojure/clojure "1.8.0"]]
  :target-path "target/%s"
  :plugins [[aws-plugin "0.1.0-SNAPSHOT"]]
  :profiles {:uberjar {:aot :all}})

设置完成后,从插件目录运行 lein install,然后从插件用户目录运行 lein aws-plugin.这应该尝试创建 AWSLambdaClient 的实例,这将反过来触发错误.

Once this is setup, run lein install from the plugin directory and then run lein aws-plugin from the plugin users directory. This should attempt to create an instance of AWSLambdaClient which will, in turn, trigger the error.

推荐答案

第一个问题:这是一个已知问题吗?

First question: is this a known issue?

这是一个已知问题,许多编写 Leiningen 插件的人都会面临这个问题.根本原因是 Leiningen 构建了一个包含所有依赖项的 uberjar,而这些依赖项不是 阴影.这意味着如果 Jackson 类之间有任何冲突,将始终选择 Leiningen 的类.使这特别狡猾的是,您不会收到任何有关冲突依赖项的警告,因为 JAR 不会冲突,但它们的内容会冲突.

This is a known issue, and one that many people writing Leiningen plugins face. The root cause is that Leiningen builds an uberjar with all of its dependencies, and those dependencies are not shaded. This means that if there is any collision between Jackson classes, Leiningen's one will always be chosen. What makes this especially devious is that you won't get any warnings about conflicting dependencies, as the JARs don't conflict, but the contents of them do.

以下是此问题的几个示例:https://github.com/s3-wagon-private/s3-wagon-private/issues/38, https://github.com/technomancy/leiningen/issues/2215.

Here's a few examples of this problem: https://github.com/s3-wagon-private/s3-wagon-private/issues/38, https://github.com/technomancy/leiningen/issues/2215.

第二:有人对解决这个问题有什么建议吗?

Second: Does anyone have any suggestions for working around this problem?

Clojure 与同一库的不同主要版本之间的相互依赖问题 对一般情况有一些建议,尽管当 Lein 的依赖关系非常糟糕时,它会变得有点棘手.

Issues with Clojure inter-dependency with different major versions of the same library has some suggestions for the general case, although it gets a little trickier when Lein's dependencies are uberjarred.

我认为此时最好的办法是屏蔽 Jackson 依赖项和 AWS SDK.

I think your best bet at this point would be to shade the Jackson dependency and the AWS SDK.

Leiningen master 不再依赖于柴郡,当是 2.8 时.发布了,你应该会少一些问题.

Leiningen master no longer depends on Cheshire though, and when 2.8.0 is released you should have less problems.

这篇关于编写插件时如何排除 leiningen 引入的依赖项?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆