19

I have a FeignClient like this

@RequestLine("POST /enroll")
@Headers({ "header1: {header1}", "header2: {header2}", "Content-Type: application/json" })
ResponseDto enroll(@Param("header1") String header1,@Param("header1") String header1, RequestDto requestDto)throws MyCustomException;

` I am not using spring cloud netflix. But I am keep getting the below exception.

Caused by: java.lang.IllegalStateException: Body parameters cannot be used with form parameters.
at feign.Util.checkState(Util.java:128)
at feign.Contract$BaseContract.parseAndValidateMetadata(Contract.java:112)
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)

I am instantiating my client like this.

return Feign.builder()
        .encoder(new JacksonEncoder())
        .decoder(new JacksonDecoder())
        .logger(new Slf4jLogger())
        .logLevel(Logger.Level.FULL)
        .target(RegularFeignClient.class, url);
Seetha
  • 980
  • 1
  • 8
  • 27

4 Answers4

28

Wow this a tricky one. The order of parameters matter here.

@RequestLine("POST /enroll")
@Headers({ "header1: {header1}", "header2: {header2}", "Content-Type: application/json" })
ResponseDto enroll(RequestDto requestDto, @Param("header1") String header1,@Param("header1") String header1)throws MyCustomException;

This works!!!

Thanks to my senior developer. He found it.

Seetha
  • 980
  • 1
  • 8
  • 27
  • So you moved `RequestDto requestDto` from the last parameter to the first and that did the trick? – Tim Büthe Apr 17 '18 at 14:42
  • 1
    Hmm, oddly, changing the order of params worked for me too. In my case, there was no problems like the ones mentioned in other answers, so I tried this trick (made request body object as 1st param) & it started working. Still digging, if I find any other reason, I'll post it. – human Jan 01 '20 at 18:43
  • I think it's related to this issue https://github.com/OpenFeign/feign/issues/561, I thought they fixed in newer release, but it seems not. – ascetic652 Mar 23 '20 at 22:59
10

Order of parameters in feign should not matter as stated by spencergibb in this issue : https://github.com/spring-cloud/spring-cloud-netflix/issues/1915. If you don't use form parameters alongside body parameters you should search why one of your parameters is interpreted as a form parameter.

My specific problem, using spring @RequestMapping annotation was that feign was misinterpreting one of my param anotations because of a typo, in my case I provided a request path value /path/{pathParam} and mistype spring annotation with @PathVariable("pathparam") with lower case typo.

Eric Aya
  • 69,473
  • 35
  • 181
  • 253
NicolasG
  • 171
  • 1
  • 6
2

If anybody is still coming here like me, there is another possible case. I had the same exception when defining path params with query params and request body as follows:

    @RequestLine("POST /namespaces/{namespace}/releases/{release}")
    Response createRelease(ReleaseBody releaseBody,
                           @Param("namespace") String namespace,
                           @Param("release") String release,
                           @Param("plan") String planName);

I recieved the exception IllegalStateException: Body parameters cannot be used with form parameters. even after updating to latest feign.

Explicitly defining query params in request line helped:

    @RequestLine("POST /namespaces/{namespace}/releases/{release}?plan={plan}")
    Response createRelease(ReleaseBody releaseBody,
                           @Param("namespace") String namespace,
                           @Param("release") String release,
                           @Param("plan") String planName);
Zavael
  • 2,383
  • 1
  • 32
  • 44
1

I has same error , but not because of order of parameter. Upon investigation found that the problem was in my swagger definition. I had defined parameter definition that was missing missing in path. ie:

     /someapi/bla/{parm1}/bla/
       parameters:
          - $ref: '#/parameters/parm1'
          - $ref: '#/parameters/parm2'

Changed to:

     /someapi/bla/{parm1}/bla/
       parameters:
          - $ref: '#/parameters/parm1'

solved the issue. Hope it helps some one with same issue.

amit
  • 337
  • 1
  • 11