Skip to content

FeignHttpMessageConverters concurrency issue #1307

Description

@alianman

Describe the bug
When mutiple concurrent threads call the org.springframework.cloud.openfeign.support.FeignHttpMessageConverters#getConverters method on a non-initialized class, some non-initialized converters could be returned. This leads to similar exceptions when processing requests/responses. After the class is initialized, no exceptions are thrown.

feign.codec.EncodeException: Could not write request: no suitable HttpMessageConverter found for request type [com.MyClass]
	at org.springframework.cloud.openfeign.support.SpringEncoder.encodeWithMessageConverter(SpringEncoder.java:168)
	at org.springframework.cloud.openfeign.support.SpringEncoder.encode(SpringEncoder.java:110)
	at org.springframework.cloud.openfeign.support.PageableSpringEncoder.encode(PageableSpringEncoder.java:105)
	at feign.RequestTemplateFactoryResolver$BuildEncodedTemplateFromArgs.resolve(RequestTemplateFactoryResolver.java:274)
	at feign.RequestTemplateFactoryResolver$BuildTemplateByResolvingArgs.create(RequestTemplateFactoryResolver.java:107)
	at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:48)
	at feign.ReflectiveFeign$FeignInvocationHandler.invoke(ReflectiveFeign.java:104)
	at org.springframework.cloud.openfeign.FeignCachingInvocationHandlerFactory$1.proceed(FeignCachingInvocationHandlerFactory.java:66)
	at org.springframework.cache.interceptor.CacheInterceptor.lambda$invoke$0(CacheInterceptor.java:54)
	at org.springframework.cache.interceptor.CacheAspectSupport.invokeOperation(CacheAspectSupport.java:424)
	at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:410)
	at org.springframework.cache.interceptor.CacheInterceptor.invoke(CacheInterceptor.java:64)
	at org.springframework.cloud.openfeign.FeignCachingInvocationHandlerFactory.lambda$create$0(FeignCachingInvocationHandlerFactory.java:53)
	at jdk.proxy2/jdk.proxy2.$Proxy166.list(Unknown Source)
	... 189 filtered

java.lang.IllegalArgumentException: 'messageConverters' must not contain null elements
	at org.springframework.util.Assert.noNullElements(Assert.java:436)
	at org.springframework.web.client.HttpMessageConverterExtractor.<init>(HttpMessageConverterExtractor.java:78)
	at org.springframework.web.client.HttpMessageConverterExtractor.<init>(HttpMessageConverterExtractor.java:71)
	at org.springframework.cloud.openfeign.support.SpringDecoder.decode(SpringDecoder.java:56)
	at org.springframework.cloud.openfeign.support.ResponseEntityDecoder.decode(ResponseEntityDecoder.java:62)
	at feign.optionals.OptionalDecoder.decode(OptionalDecoder.java:38)
	at feign.InvocationContext.decode(InvocationContext.java:121)
	... 201 more
Wrapped by: <#64f634dc> feign.codec.DecodeException: 'messageConverters' must not contain null elements
	at feign.InvocationContext.decode(InvocationContext.java:125)
	at feign.InvocationContext.proceed(InvocationContext.java:94)
	at feign.ResponseHandler.handleResponse(ResponseHandler.java:69)
	at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:109)
	at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:53)
	at feign.ReflectiveFeign$FeignInvocationHandler.invoke(ReflectiveFeign.java:104)
	at org.springframework.cloud.openfeign.FeignCachingInvocationHandlerFactory$1.proceed(FeignCachingInvocationHandlerFactory.java:66)
	at org.springframework.cache.interceptor.CacheInterceptor.lambda$invoke$0(CacheInterceptor.java:54)
	at org.springframework.cache.interceptor.CacheAspectSupport.invokeOperation(CacheAspectSupport.java:424)
	at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:410)
	at org.springframework.cache.interceptor.CacheInterceptor.invoke(CacheInterceptor.java:64)
	at org.springframework.cloud.openfeign.FeignCachingInvocationHandlerFactory.lambda$create$0(FeignCachingInvocationHandlerFactory.java:53)
	at jdk.proxy2/jdk.proxy2.$Proxy166.list(Unknown Source)
	... 172 filtered

Workaround

Current workaround is declaring own converters bean and call initialization explicitly at application startup:

    @Bean
    @ConditionalOnMissingBean
    public FeignHttpMessageConverters feignHttpMessageConverters(
            ObjectProvider<HttpMessageConverter<?>> messageConverters,
            ObjectProvider<HttpMessageConverterCustomizer> customizers) {
        var feignHttpMessageConverters = new FeignHttpMessageConverters(messageConverters, customizers);
        // init converters
        feignHttpMessageConverters.getConverters();
        return feignHttpMessageConverters;
    }

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions