Lucene和jackson冲突
今天在使用lucene的时候,想直接在Controller中返回json对象,于是在Spring中配置了JackSon的converter:
<bean id="jacksonMessageConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean> <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"> <property name="messageConverters"> <list> <ref bean="jacksonMessageConverter"/> </list> </property> </bean>
配置好后,就可以直接在Controller中返回容器对象,如map、list等,jackson会自动的将对象转为JSON对象返回,方便前端使用。在几个索引库中使用都没有问题,正常工作,但是当我使用到歌曲索引库的时候出问题了,一直报错,如下:
Caused by: java.lang.IllegalArgumentException: Conflicting getter definitions for property "match": org.apache.lucene.search.ComplexExplanation#getMatch(0 params) vs org.apache.lucene.search.ComplexExplanation#isMatch(0 params) at org.codehaus.jackson.map.introspect.POJOPropertyBuilder.getGetter(POJOPropertyBuilder.java:167) at org.codehaus.jackson.map.introspect.POJOPropertyBuilder.getAccessor(POJOPropertyBuilder.java:116) at org.codehaus.jackson.map.ser.BeanSerializerFactory.removeIgnorableTypes(BeanSerializerFactory.java:705) at org.codehaus.jackson.map.ser.BeanSerializerFactory.findBeanProperties(BeanSerializerFactory.java:562) at org.codehaus.jackson.map.ser.BeanSerializerFactory.constructBeanSerializer(BeanSerializerFactory.java:434) at org.codehaus.jackson.map.ser.BeanSerializerFactory.findBeanSerializer(BeanSerializerFactory.java:347) at org.codehaus.jackson.map.ser.BeanSerializerFactory.createSerializer(BeanSerializerFactory.java:291) at org.codehaus.jackson.map.ser.StdSerializerProvider._createUntypedSerializer(StdSerializerProvider.java:782) at org.codehaus.jackson.map.ser.StdSerializerProvider._createAndCacheUntypedSerializer(StdSerializerProvider.java:735) ... 64 more
Google了一下这个错误,发现是jackson在将map转化为JSON对象时,需要调用相应的get方法,而在org.apache.lucene.search.ComplexExplanation类中,有如下两个方法。
boolean |
isMatch() |
这两个方法返回值都为boolean类型,并且名字都是match,所以导致jackson类不知道该使用哪一个获取match的值,所以报了confict错误。
那么再去查jackson的文档,如下:
We have defined both isVoided() and getVoided() methods in BaseOpenmrsData (and isRetired() and getRetired() in BaseOpenmrsMetadata), which is technically not right according to bean specifications. The Jackson JSON library bombs on this, like: Caused by: java.lang.IllegalArgumentException: Conflicting getter definitions for property "voided": org.openmrs.BaseOpenmrsData#isVoided(0 params) vs org.openmrs.BaseOpenmrsData#getVoided(0 params) Selected approach (per the Design Forum on 15-Aug-2012): Go through the API and find all methods with the signature "Boolean isXyz()", and for each of them: Verify we have a correct "Boolean getXyz()" method Deprecate the incorrect isXyz() method, saying to use the getXyz() method instead Add the @JsonIgnore annotation to the incorrect isXyz method It may be possible to salvage Saptarshi's attached patch here, but given the amount of time that has passed since he wrote it, it may be easier to just re-do the work against trunk.
从上述文档中可以看出,如果返回值相同,并且ismatch和getmatch同时存在时就会引发conflict异常,要么删除其中一个方法,或者在不需要使用的方法上加上@的annotation。但是为了这个小问题去修改lucene的源码,代价有点高,后期也不太好维护。
那么就继续想办法,突然发现,我并不需要返回match这个值啊,我也没有主动调用获取这个值,那么究竟是哪块使用到了match这个值呢?
继续看代码,将问题定位到如下一段代码:
Explanation explanation = indexSearcher.explain(query, docID);
这个是用来调试查询结果的,里面包含了lucene打分的结果。
所以可以把这个去掉,那么在我的map中就不会调用getmatch或者ismatch方法了,也就解决了冲突,去掉后再运行,没有报错,完美运行~~
作者