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

getMatch() 
          The match status of this explanation node.

 

boolean

isMatch() 
          Indicates whether or not this Explanation models a good match.

 

 

这两个方法返回值都为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方法了,也就解决了冲突,去掉后再运行,没有报错,完美运行~~

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。