Custom object mapper bean changing the default properties of open Feign Client / auto configured objectMapper bean

huangapple go评论79阅读模式
英文:

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.

huangapple
  • 本文由 发表于 2020年4月8日 22:41:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/61103415.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定