mongo driver类加载导致的错误

来源:互联网 发布:漱口水 酒精 知乎 编辑:程序博客网 时间:2024/05/17 02:28

摘要

一次类加载导致的错误,之所以要记录下来,是因为错误的发现不是在本地开发环境或者预部署环境,而是在生产环境。这应该是个易于重现的问题,但是不知道为什么直到生产环境部署时才报错。

问题

Unsatisfied dependency expressed through constructor parameter 3: Could not convert argument value of type [com.mongodb.AuthenticationMechanism] to required type [[C]: Failed to convert value of type [com.mongodb.AuthenticationMechanism] to required type [char[]]; nested exception is java.lang.IllegalArgumentException: Cannot convert value of type [com.mongodb.AuthenticationMechanism] to required type [char]: PropertyEditor [org.springframework.beans.propertyeditors.CharacterEditor] returned inappropriate value of type [com.mongodb.AuthenticationMechanism]

分析

<bean id="mongoCredentialList" class="java.util.ArrayList">            <constructor-arg>                <list>                    <bean id="mongoCredential" class="com.mongodb.MongoCredential">                        <constructor-arg                                value="#{T(com.mongodb.AuthenticationMechanism).SCRAM_SHA_1}"/>                        <constructor-arg value="test"/>                        <constructor-arg value="test"/>                        <constructor-arg value="1234"/>                    </bean>                </list>            </constructor-arg>        </bean>
  1. 直接原因就是创建mongoCredential bean时出错。第四个参数(从0开始,所以parameter 3就是第四个参数)
  2. 这个通常就是依赖的类版本不对,再开发环境应该就会报出来的。所以开始没朝这方面思考,总是怀疑生产环境的web 容器有什么不对导致。

root cause
MongoCredential 这个类(同包,同名)在工程中不同的jar中存在。一个是被其他人封装了,换了个jar名字。所以maven检测不出来的,maven只能在artifact检测是否存在不同版本的jar,然后根据规则选择加载某个版本。这种不同jar的同一个类处理不了。

如下图,mongo-java-driver-2.14是官方的driver类。里面没有上述的构造器方法。
mongodb-driver-3.2.1是别人打包的。是有上述构造器方法。这个jar顺序是之前在开发环境,测试环境打包的顺序,这样没有问题。java加载器会先load mongodb-driver-3.2.1的MongoCredential类。

这里写图片描述

但是不知道为什么,打包到线上环境时,顺序变成了下面这样,打包时对”-“的解析不同。如果是按照ASCII顺序,“-”ASCII值是47,比字母要小,应该是在最上面的。但是不知道为什么会到下面。造成了这样的错误。

这里写图片描述

总结

  • 包命名一定要规范,不要和官方的,通用的整成一样,非常愚蠢的错误。
原创粉丝点击