No value specified for 'Date'的解決辦法

問題現(xiàn)象

最近公司內(nèi)部一個(gè)運(yùn)行已久的產(chǎn)品,在最近一次上線后操作出現(xiàn)了“No value specified for 'Date'”的錯(cuò)誤,異常堆棧如下:

Caused by: org.apache.commons.beanutils.ConversionException: No value specified for 'Date'
at org.apache.commons.beanutils.converters.AbstractConverter.handleMissing(AbstractConverter.java:310)
at org.apache.commons.beanutils.converters.AbstractConverter.convert(AbstractConverter.java:136)
at org.apache.commons.beanutils.converters.ConverterFacade.convert(ConverterFacade.java:60)
at org.apache.commons.beanutils.BeanUtilsBean.convert(BeanUtilsBean.java:1078)
at org.apache.commons.beanutils.BeanUtilsBean.copyProperty(BeanUtilsBean.java:437)
at org.apache.commons.beanutils.BeanUtilsBean.copyProperties(BeanUtilsBean.java:286)
at org.apache.commons.beanutils.BeanUtils.copyProperties(BeanUtils.java:137)

通過修改記錄并沒有發(fā)現(xiàn)關(guān)于BeanUtils以及源目標(biāo)模型的修改。

問題分析

通過異常堆棧和BeanUtils的copyProperties源碼分析來看,問題的根源是要copy的源模型中的存在“Date”類型的屬性,但其值為null。查看源模型類源碼的修改記錄和數(shù)據(jù)庫(kù)中的字段和值,發(fā)現(xiàn)近期均未變化,也就是說在本次上線前,這種情況的源模型是可以使用BeanUtils來copy屬性的。
百度一下,大多數(shù)給出的解決方案都是在使用BeanUtils的copyProperties之前注冊(cè)一個(gè)DateConverter:

// 增加注冊(cè)DateConverter代碼,設(shè)置默認(rèn)值為null。
ConvertUtils.register(new DateConverter(null), java.util.Date.class); 

BeanUtils.copyProperties(...);

增加這句代碼可以解決這個(gè)問題,但是我們上線之前沒有這句代碼也是可用的,換google檢索一下,最終在StackOverflow上查到了問題的根本原因,這個(gè)問題是beanutils 1.8.x版本上才會(huì)出現(xiàn),由于beanutils 1.8.x版本上修改了這個(gè)copyProperties方法,如果要轉(zhuǎn)換的類型是Date、Calendar或其他一些類型時(shí),當(dāng)值為null且沒有配置默認(rèn)值時(shí)會(huì)拋出異常。1.9.0及之后的版本修復(fù)了這個(gè)問題。
查看我們上線之前服務(wù)器上的beanutils的版本為1.9.3,而本次上線包中的beanutils的版本是1.8.3,顯然是打包時(shí)某些依賴間接依賴了低版本的beanutils進(jìn)而影響了打包結(jié)果。

問題原因

apache的BeanUtils 1.8.x版本的copyProperties修改了Date類型的null值的處理邏輯,改為了無默認(rèn)值值拋出異常。1.9.0之后的版本修復(fù)了該問題。

beanutils關(guān)于該bug的記錄:https://issues.apache.org/jira/browse/BEANUTILS-454

解決辦法

以下幾種方案選其一即可。

pom.xml中固化使用的beanutils的版本

在pom.xml中使用dependency:tree檢查依賴的beanutils的版本,可以通過強(qiáng)制指定beanutils依賴的方式來固定使用的beanutils的版本。

增加DateConverter轉(zhuǎn)換器(百度上的通用解決方案)

在程序的初始化代碼中增加DateConverter轉(zhuǎn)換器類:

// 增加注冊(cè)DateConverter代碼,設(shè)置默認(rèn)值為null。
ConvertUtils.register(new DateConverter(null), java.util.Date.class); 

使用java.sql.Date取代java.util.Date(未驗(yàn)證)

模型中日期屬性的類型使用java.sql.Date而不是java.util.Date。

使用spring的BeanUtils工具類(未驗(yàn)證)

spring中提供了一個(gè)org.springframework.beans.BeanUtils工具類,跟apache的BeanUtils功能差不多一樣。
注意:如果之前使用的是apache的BeanUitls,不建議采用該方法。一是改動(dòng)量太大,二是spring的BeanUitls一樣存在各種各樣的坑。

參考資料

  1. How to ask BeanUtils to ignore null values
  2. copyProperties() throws conversion exception for null Date
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容