spring-cloud / spring-cloud-openfeign

Support for using OpenFeign in Spring Cloud apps
Apache License 2.0
1.17k stars 756 forks source link

provide ignore annotation to programmatically ignore method parameter #996

Closed XhstormR closed 3 months ago

XhstormR commented 4 months ago

Is your feature request related to a problem? Please describe.

Currently following interface method:

ResponseEntity<ModelSO> getSubscriptionInformation(
       @RequestBody @ApiParam(name = "request", value = "The body of the request", required = true) 
       ModelSO model, // body 1
       WebRequest webRequest); // body2 ?

can't be used as Feign Client:

java.lang.IllegalStateException: Method has too many Body parameters: public abstract org.springframework.http.ResponseEntity com.daimler.daivb.vts.snap.SubscriptionInformationSI.getSubscriptionInformation(java.lang.String,java.lang.String,java.lang.String,java.lang.String,com.daimler.daivb.vts.snap.SubscriptionRequestSO,java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String,org.springframework.web.context.request.WebRequest)
    at feign.Util.checkState(Util.java:128)
    at feign.Contract$BaseContract.parseAndValidateMetadata(Contract.java:114)
    at org.springframework.cloud.netflix.feign.support.SpringMvcContract.parseAndValidateMetadata(SpringMvcContract.java:131)
    at feign.Contract$BaseContract.parseAndValidatateMetadata(Contract.java:64)
    at feign.ReflectiveFeign$ParseHandlersByName.apply(ReflectiveFeign.java:146)
    at feign.ReflectiveFeign.newInstance(ReflectiveFeign.java:53)
    at feign.Feign$Builder.target(Feign.java:209)
    at feign.Feign$Builder.target(Feign.java:205)

Describe the solution you'd like We should provide ignore annotation like @FeignIgnore to programmatically ignore some method parameter. For example:

ResponseEntity<ModelSO> getSubscriptionInformation(
       @RequestBody @ApiParam(name = "request", value = "The body of the request", required = true) 
       ModelSO model, // body 1
       @FeignIgnore
       WebRequest webRequest); // ignored

Describe alternatives you've considered I have tried add @RequestParam(required=false), but it will add toString() value to url as get parameters, and server will respond cannot convert string to target object.

For example :

Caused by: feign.FeignException$BadRequest: [400] during [GET] to [http://text-masker-mgmt/api/phrase?assembler=org.springframework.data.web.PagedResourcesAssembler%4010b3ea72&pageable=INSTANCE&pageRequest=PageRequest%28page%3D0%2C%20size%3D10%2C%20sort%3DcreatedAt%29&value=FOR_UPDATE&enabled=false&page=0&size=10&sort=createdAt&offset=0] [PhraseApi#getPhraseList(PagedResourcesAssembler,Pageable,Predicate,PageRequest,Map)]
    at feign.FeignException.clientErrorStatus(FeignException.java:213) ~[feign-core-11.10.jar:na]
    at feign.FeignException.errorStatus(FeignException.java:194) ~[feign-core-11.10.jar:na]
    at feign.FeignException.errorStatus(FeignException.java:185) ~[feign-core-11.10.jar:na]
    at feign.codec.ErrorDecoder$Default.decode(ErrorDecoder.java:92) ~[feign-core-11.10.jar:na]
    at feign.AsyncResponseHandler.handleResponse(AsyncResponseHandler.java:98) ~[feign-core-11.10.jar:na]
    at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:141) ~[feign-core-11.10.jar:na]
    at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:91) ~[feign-core-11.10.jar:na]
    at feign.ReflectiveFeign$FeignInvocationHandler.invoke(ReflectiveFeign.java:100) ~[feign-core-11.10.jar:na]
    at com.sun.proxy.$Proxy109.getPhraseList(Unknown Source) ~[na:na]
    at io.github.xhstormr.masker.web.api.phrase.PhraseApi.getPhraseList(PhraseApi.kt:113) ~[main/:na]
    at java.base/java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:710) ~[na:na]
    at feign.DefaultMethodHandler.invoke(DefaultMethodHandler.java:141) ~[feign-core-11.10.jar:na]
    at feign.ReflectiveFeign$FeignInvocationHandler.invoke(ReflectiveFeign.java:100) ~[feign-core-11.10.jar:na]
    at com.sun.proxy.$Proxy109.getPhraseList(Unknown Source) ~[na:na]
    at io.github.xhstormr.masker.Application.mgmtApi$lambda$2(Application.kt:43) ~[main/:na]
    at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:756) ~[spring-boot-2.7.18.jar:2.7.18]
    ... 14 common frames omitted

Currently i implemented @FeignIgnore by myself, but i think official repos should provide this feature. It will also resolve https://github.com/spring-cloud/spring-cloud-netflix/issues/2540.

annotation class FeignIgnore

class FeignIgnoreParameterProcessor : AnnotatedParameterProcessor {

    override fun getAnnotationType() = FeignIgnore::class.java

    override fun processArgument(
        context: AnnotatedParameterProcessor.AnnotatedParameterContext,
        annotation: Annotation,
        method: Method
    ) = true
}

class ExampleFeignConfig {

    @Bean
    fun feignIgnoreParameterProcessor() = FeignIgnoreParameterProcessor()
}

Then add ExampleFeignConfig to @FeignClient

@FeignClient(...., configuration = [ExampleFeignConfig::class])
OlgaMaciaszek commented 3 months ago

Hello @XhstormR, Swagger annotations have never been supported. Spring Cloud OpenFeign is now in maintenance only mode (we're suggesting migrating over to Spring interface clients). We are not planning to work on new features in this project.