mongo driver类加载导致的错误

摘要

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

问题

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,比字母要小,应该是在最上面的。但是不知道为什么会到下面。造成了这样的错误。

这里写图片描述

总结

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

猜你喜欢

转载自blog.csdn.net/fs1360472174/article/details/75708257