13

It's my Feign interface

@FeignClient(
        name="mpi",
        url="${mpi.url}",
        configuration = FeignSimpleEncoderConfig.class
)
public interface MpiClient {

    @RequestMapping(method = RequestMethod.POST)
    public ResponseEntity<String> getPAReq(@QueryMap Map<String, String> queryMap
    );
}

and my custom configuration

public class FeignSimpleEncoderConfig {
    public static final int FIVE_SECONDS = 5000;

    @Bean
    public Logger.Level feignLogger() {
        return Logger.Level.FULL;
    }

    @Bean
    public Request.Options options() {
        return new Request.Options(FIVE_SECONDS, FIVE_SECONDS);
    }

    @Bean 
    @Scope("prototype")
    public Feign.Builder feignBuilder() {
        return Feign.builder()
                .encoder(new FormEncoder());
    }
}

If I send request like this I see that my request send Content-Type: application/json;charset=UTF-8. But if I set content type

consumes = "application/x-www-form-urlencoded"

I've this error message

feign.codec.EncodeException: Could not write request: no suitable HttpMessageConverter found for request type [java.util.HashMap] and content type [application/x-www-form-urlencoded]
    at org.springframework.cloud.netflix.feign.support.SpringEncoder.encode(SpringEncoder.java:108) ~[spring-cloud-netflix-core-1.1.7.RELEASE.jar:1.1.7.RELEASE]

How to send POST request, I think I should make something more with Encoder. Thanks for your help.

koa73
  • 861
  • 2
  • 10
  • 27

4 Answers4

7

First of all you should change your Feign interface like this:

@FeignClient (
    configuration = FeignSimpleEncoderConfig.class
)
public interface MpiClient {
   @RequestMapping(method = RequestMethod.POST)
   ResponseEntity<String> getPAReq(Map<String, ?> queryMap);
}

Then you should set the encoder during feign configuration:

public class FeignSimpleEncoderConfig {
    @Bean
    public Encoder encoder() {
        return new FormEncoder();
    }
}
Dale K
  • 25,246
  • 15
  • 42
  • 71
koa73
  • 861
  • 2
  • 10
  • 27
  • 1
    I'm trying to use the Encoder bean in my project (spring boot 2.0.2.RELEASE and feign-form:3.4.1 & feign-form-spring:3.4.1 ) but I have a problem with FormEncoder class. The problem is that I can't import feign.form.FormEncoder. Any suggestion? Thanks – Javier C. Nov 12 '18 at 11:09
  • I don't know. I've used spring-boot 1.3.8 – koa73 Nov 13 '18 at 16:39
5

It seems to me that Map is not valid for form body. MultiValueMap works just fine.

Feign client:

@FeignClient(name = "name", url="url", configuration = FromUrlEncodedClientConfiguration.class)
public interface PayPalFeignClient {

    @RequestMapping(value = "/", method = POST, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
    @Headers("Content-Type: application/x-www-form-urlencoded")
    String foo(MultiValueMap<String, ?> formParams);
}

Config:

@Configuration
public class FromUrlEncodedClientConfiguration {

    @Autowired
    private ObjectFactory<HttpMessageConverters> messageConverters;

    @Bean
    @Primary
    @Scope(SCOPE_PROTOTYPE)
    Encoder feignFormEncoder() {
        return new FormEncoder(new SpringEncoder(this.messageConverters));
    }
}

Gradle dependencies:

compile group: 'io.github.openfeign.form', name: 'feign-form', version: '2.0.2'
compile group: 'io.github.openfeign.form', name: 'feign-form-spring', version: '2.0.5'

After that all you have to do is call it with a MultivalueMap parameter.

0

Specify the correct encoder for handle form encoded request

you can specify multi encoder example json/xml/formhttpurl encoded

@Bean
public Encoder feignEncoder() {
    ObjectFactory<HttpMessageConverters> objectFactory = () ->
            new HttpMessageConverters(new FormHttpMessageConverter());
    return new SpringEncoder(objectFactory);
}

Important FormHttpMessageConverter serialize only MultiValueMap subsclass

0

im my case it was due to outdated version of lombok, updating to 1.18.16 resolve it

jhenya-d
  • 399
  • 7
  • 19