最近在中台組件一次版本迭代中,網關組件升級版本后其它業務線集成網關組件后項目啟動失敗,
出現了
Caused by: java.lang.NoClassDefFoundError: Could not initialize class org.hibernate.validator.internal.engine.ConfigurationImpl at org.hibernate.validator.HibernateValidator.createGenericConfiguration(HibernateValidator.java:33) ~[hibernate-validator-6.0.16.Final.jar:6.0.16.Final] at javax.validation.Validation$GenericBootstrapImpl.configure(Validation.java:296) ~[validation-api-2.0.1.Final.jar:na] at org.springframework.boot.validation.MessageInterpolatorFactory.getObject(MessageInterpolatorFactory.java:53) ~[spring-boot-2.0.9.RELEASE.jar:2.0.9.RELEASE] at org.springframework.boot.context.properties.ConfigurationPropertiesJsr303Validator$Delegate.<init>(ConfigurationPropertiesJsr303Validator.java:69) ~[spring-boot-2.0.9.RELEASE.jar:2.0.9.RELEASE] at org.springframework.boot.context.properties.ConfigurationPropertiesJsr303Validator.<init>(ConfigurationPropertiesJsr303Validator.java:42) ~[spring-boot-2.0.9.RELEASE.jar:2.0.9.RELEASE] at org.springframework.boot.context.properties.ConfigurationPropertiesBinder.getJsr303Validator(ConfigurationPropertiesBinder.java:109) ~[spring-boot-2.0.9.RELEASE.jar:2.0.9.RELEASE] at org.springframework.boot.context.properties.ConfigurationPropertiesBinder.getValidators(ConfigurationPropertiesBinder.java:99) ~[spring-boot-2.0.9.RELEASE.jar:2.0.9.RELEASE] at org.springframework.boot.context.properties.ConfigurationPropertiesBinder.bind(ConfigurationPropertiesBinder.java:80) ~[spring-boot-2.0.9.RELEASE.jar:2.0.9.RELEASE] at org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor.bind(ConfigurationPropertiesBindingPostProcessor.java:107) ~[spring-boot-2.0.9.RELEASE.jar:2.0.9.RELEASE] at org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor.postProcessBeforeInitialization(ConfigurationPropertiesBindingPostProcessor.java:93) ~[spring-boot-2.0.9.RELEASE.jar:2.0.9.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:416) ~[spring-beans-5.0.13.RELEASE.jar:5.0.13.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1686) ~[spring-beans-5.0.13.RELEASE.jar:5.0.13.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:573) ~[spring-beans-5.0.13.RELEASE.jar:5.0.13.RELEASE] ... 78 common frames omitted Process finished with exit code 1
這種錯誤。
開始排查問題:
首先根據錯誤提示,看了一下組件源碼中org.hibernate.validator.internal.engine.ConfigurationImpl這個類是否存在,
在hibernate-valifator-6.0.16-Final包中可以看到這個class文件。
繼續排查是否打包的過程中出現錯誤致使該文件不存在,業務線自己排查fatJar包中有hibernate-valifator的包並且版本一致,
而且沒有其它版本的hibernate-valifator的包,不存在多個版本依賴沖突的問題。
開始源碼探索之路:
打開ConfigurationImpl源碼,看里面是否有某些類沒有被依賴到造成該類本身不能被實例化,在ConfigurationImpl中沒有發現問題。
但是其中有一段代碼:
private static final Log LOG = LoggerFactory.make( MethodHandles.lookup() );
為什么關注它?因為中台所有技術組件都按照要求排除了所有的日志實現,只保留slf4j本身的API去供技術組件使用,
而這個LoggerFactory並不是slf4j本身的,是屬於hibernate本身的。打開之后發現:
package org.hibernate.validator.internal.util.logging; import java.lang.invoke.MethodHandles.Lookup; import org.jboss.logging.Logger; /** * @author Hardy Ferentschik * @author Kevin Pollet <kevin.pollet@serli.com> (C) 2012 SERLI * @author Sanne Grinovero */ public final class LoggerFactory { public static Log make(final Lookup creationContext) { final String className = creationContext.lookupClass().getName(); return Logger.getMessageLogger( Log.class, className ); } // private constructor to avoid instantiation private LoggerFactory() { } }
import org.jboss.logging.Logger一行是紅色的,沒有這個Logger類,依賴樹一看果然沒有jboss-logging這個包。
果然在這次升級的過程中jboss-logging的包被排除了,其實這個hibernate-valifator包的org.hibernate.validator.internal.util.logging下多個
類都出現錯誤,都是使用了jboss-logging中的依賴。
所以出現了以上錯誤。加上jboss-logging依賴,項目正常啟動。
-------------------------------------------------------------------------------------------
至於springboot為什么引入hibernate-valifator,這個是干嘛用的? 去查一下Jsr-303,順便可以看下springboot中屬性綁定ConfigurationPropertiesBinder中的
getValidators方法就知道了。