记一次项目整合后的maven报错问题

516 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第1天,点击查看活动详情

现象

问题发生在整合了一个开源项目到原项目中后,项目启动时有如下报错。

An attempt was made to call the method org.quartz.Scheduler.getListenerManager()Lorg/quartz/ListenerManager; but it does not exist. Its class, org.quartz.Scheduler, is available from the following locations

clipboard.png 大意是尝试调用org.quartz.Scheduler.getListenerManager()方法,但是它不存在,列出了方法所在类路径,和加载的jar包。建议更正项目的classpath,使它包含唯一且兼容的org.quartz.Scheduler版本。

初步分析

报错的Scheduler类在quartz包中,而quartz是一个大家熟知的定时任务框架,令我有点疑惑的是,无论是原项目还是整合进来的开源项目,其pom文件中均没有定义quartz依赖。

idea项目中,在maven的dependency列表下没quartz依赖,而在项目的External Library中可以看到org.quartz-Scheduler.quartz-2.3.2和quartz.quartz-1.5.1,这两个jar包中都包含有org.quartz.Scheduler,区别是前者的类里包含有getListenerManager方法,后者的类中不包含。这两个依赖的groupId不同,而artifactId都是quartz,查了下,网上大部分使用quartz框架引入的依赖,groupId都用的是org.quartz-Scheduler。

报错应该是因为有2个相同名称的类,加载了错误的类。

探索尝试

既然不是显示引入的,那可能是间接引入,它可能是依赖的依赖,先来看看它在哪里被用到了。最直观的想法是在项目里全局搜索一下,得到的结果如下。

druid中

druid中用了quartz,但是它的scope是provided,也就是正式编译后的Druid的jar包中,是不包含quartz依赖的,所以报错应该和它无关。

clipboard (1).png

ehcache中

ehcache中有用到quartz,EhCache 是一个纯Java的进程内缓存框架,是Hibernate中默认的CacheProvider,引入的开源项目,持久层框架就是Hibernate。但是ehcache中没找到pom文件的定义,只在META-INF\MANIFEST.MF文件的Export-Package部分,找到了quartz相关的包名,但是并没有版本信息,可能是一种我不了解的打包方式吧。

clipboard (3).png

一个好用的命令

现在的关键就在于找到quartz的依赖是如何被引入的,那么maven有没有提供这样的命令呢,查了一下,还真有。 这个命令就是mvn dependency:tree,可以用来查看maven依赖树。

clipboard (4).png

clipboard (5).png

可以清晰的看到,org.quartz-Scheduler.quartz-2.3.2是shiro-quartz引入的,而quartz.quartz-1.5.1是jcaptcha的依赖引入的。

问题的解决

报错应该是因为这两个jar包间接引入了quartz包的多个不同版本,造成版本冲突。这时候我们应该让classpath下的org.quartz.Scheduler类唯一,使用一个能够兼容的版本。通过exclude配置来解决这个问题。

<dependency>
    <groupId>com.octo.captcha</groupId>
    <artifactId>jcaptcha-all</artifactId>
    <version>1.0-RC6</version>
    <exclusions>
        <exclusion>
            <artifactId>spring</artifactId>
            <groupId>org.springframework</groupId>
        </exclusion>

        <!-- 排除quartz低版本依赖-->
        <exclusion>
            <groupId>quartz</groupId>
            <artifactId>quartz</artifactId>
        </exclusion>
    </exclusions>
</dependency

总结

项目的依赖有时只通过pom文件,并不能直观的看清楚,这时候可以使用mvn dependency:tree命令查看依赖树,定位版本冲突的问题。笔者对maven的了解还不够深入,需要加强。