spring-cloud / spring-cloud/spring-cloud-openfeign
FeignHttpMessageConverters concurrency issue
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 1.3k
- Forks
- 838
- Avg merge
- 2d 11h
- Merged PRs (30d)
- 13
Description
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;
}
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reading FeignHttpMessageConverters#getConverters and the constructor usage shown in the workaround. Reproduce concurrent calls before initialization and inspect whether incomplete or null converters can be returned. Done means concurrent request and response processing no longer produces the reported converter exceptions, with coverage for initialization under concurrency.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java, spring
- Domain
- api, backend
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 57/100