英文:
Custom object mapper bean changing the default properties of open Feign Client / auto configured objectMapper bean
问题
我有类似以下的Spring的Open Feign客户端配置:
public class AppFeignConfiguration
{
@Bean
public ErrorDecoder errorDecoder()
{
return new FeignErrorDecoder();
}
@Bean
public Logger.Level logger()
{
return Logger.Level.FULL;
}
@Bean
public Request.Options options()
{
return new Request.Options( 30000, 30000 );
}
}
然后我将其作为配置提供给@FeignClient
,如下所示:
@FeignClient ( value = "apigateway-service", configuration = AppFeignConfiguration.class)
我相信FeignClient
有其默认的响应反序列化配置(可能是带有某些属性的ObjectMapper
)。
到目前为止都还好。一切都按预期工作。
然后我创建了一个自定义的ObjectMapper
,并将其作为一个bean返回,如下所示:
@Configuration
public class ObjectMapperConfig
{
@Bean ( name = "plainObjectMapper")
public ObjectMapper plainObjectMapper()
{
return new ObjectMapper();
}
}
问题是,现在这个自定义的ObjectMapper
正在干扰FeignClient
的默认反序列化配置。
也就是说,在没有自定义的plainObjectMapper
的情况下,它过去可以正常工作,没有任何JSON解析错误。但是在创建了自定义的plainObjectMapper
作为bean之后,FeignClient
抛出异常,表示某些未知的属性或其他内容。
异常内容如下:
nested exception is org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Unrecognized field "xyz" (class abc.def.ghi.class), not marked as ignorable; nested exception is com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException
我通过移除自定义的plainObjectMapper
来确认了这一点,然后它可以像以前一样正常工作。
这看起来很奇怪!我已经给bean起了一个自定义的名称,不应该干扰由Spring Boot创建的bean。
我该如何解决这个冲突?
英文:
I have spring's open feign client configurations like the following:
public class AppFeignConfiguration
{
@Bean
public ErrorDecoder errorDecoder()
{
return new FeignErrorDecoder();
}
@Bean
public Logger.Level logger()
{
return Logger.Level.FULL;
}
@Bean
public Request.Options options()
{
return new Request.Options( 30000, 30000 );
}
}
and I provide it as a configuration in the @FeignClient
as the following
@FeignClient ( value = "apigateway-service", configuration = AppFeignConfiguration.class)
I believe FeignClient has its default configuration for deserializing the response (maybe an ObjectMapper with some properties).
All good so far. Everything was working as expected.
Then I created a custom object mapper and returned it as a bean like the following:
@Configuration
public class ObjectMapperConfig
{
@Bean ( name = "plainObjectMapper")
public ObjectMapper plainObjectMapper()
{
return new ObjectMapper();
}
}
The problem now is, this is messing with the default deserializing configurations of FeignClient
.
Meaning, without the custom plainObjectMapper
, it used to work fine without any json parsing errors. But after creating the custom plainObjectMapper
as a bean, FeignClient
is throwing exceptions saying some unknown properties or something.
nested exception is org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Unrecognized field "xyz" (class abc.def.ghi.class), not marked as ignorable; nested exception is com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException
I confirmed this by removing the custom plainObjectMapper
and it worked fine just as it used to before.
This seems to be strange! I have given the bean a custom name which should not mess with the bean created by springboot.
How can I overcome this conflict?
答案1
得分: 1
这并不是完全正确的。
如果你查看 FeignClientsConfiguration
的源代码,你会发现它的编码器依赖于 HttpMessageConverters
类。
接着,HttpMessageConvertersAutoConfiguration
(源代码)本身依赖于 JacksonAutoConfiguration
。
后者只有在上下文中没有手动创建的对象映射器时才会创建默认的 ObjectMapper
Bean(参见对应方法上的 @ConditionalOnMissingBean
注解链接)- 在这种情况下,不同的 Bean 名称并不重要。
因此,Feign 在隐式地依赖于这个自动配置的 ObjectMapper
,但仅在你创建自己的对象映射器之前如此。在那之后,它会开始使用你自己的对象映射器。对许多其他 Spring Bean 也是如此。
如果你真的需要有自己的 ObjectMapper
Bean,那么你需要正确地进行配置。但是你也可以通过配置属性来自定义自动配置的对象映射器 - 参见文档。
英文:
This is not completely correct.
If you look at FeignClientsConfiguration
source, you can see that its encoders rely on HttpMessageConverters
class.
Then, HttpMessageConvertersAutoConfiguration
(source) itself depends on JacksonAutoConfiguration
.
The latter creates the default ObjectMapper
bean only if there is no manually created object mapper in context (see @ConditionalOnMissingBean
on the corresponding method) - the different bean name doesn't matter in this case.
So, it happens that Feign is implicitly relying on this auto-configured ObjectMapper
but only until you create your own. Then it starts to use yours. Same with many other spring beans.
If you really need to have your own ObjectMapper
bean, then you need to configure it properly. But you can customize the auto-configured one instead via configuration properties - see docs.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论