How to post request with spring boot web-client for Form data for content type application/x-www-form-urlencoded
We can use BodyInserters.fromFormData
for this purpose
webClient client = WebClient.builder()
.baseUrl("SOME-BASE-URL")
.defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE)
.build();
return client.post()
.uri("SOME-URI)
.body(BodyInserters.fromFormData("username", "SOME-USERNAME")
.with("password", "SONE-PASSWORD"))
.retrieve()
.bodyToFlux(SomeClass.class)
.onErrorMap(e -> new MyException("messahe",e))
.blockLast();
Spring Boot - Content type 'application/x-www-form-urlencoded;charset=UTF-8' not supported
As @Sunil Dabburi suggests debugging the readWithMessageConverters
method in the AbstractMessageConverterMethodArgumentResolver
sheds light on this issue, which turns out to be pretty simple once understood. Spring has about 15 default message converters, which are responsible for converting the content of an incoming request to a RequestEntity
or HttpEntity
. If the request has body, the converter reads it and converts it to the object type it is responsible for. Depending on the incoming request's Media Type, each converter decides whether it can read the request. In the case of the application/x-www-form-urlencoded
Media Type none of the default Spring converters can process such a request. Therefore, the above mentioned error occurs.
Adding a custom converter for the application/x-www-form-urlencoded
Media Type to the list of Spring's http message converters would solve the issue. In the example below the custom converter is responsible only for reading requests and only for requests with the desired Media Type.
** These reads help understanding the media type itself and how does spring work with it, thus how should the custom converter convert the incoming request:
- About the media type
- Default Spring handling and why does it work with MultiValueMap as only parameter
- The needed request body object type (MultiValueMap<String, String>) for Spring to create RequestEntity/HttpEntity for this media type
Here is an example of such custom http message converter:
@Component
public class FormUrlencodedHttpMessageConverter extends
AbstractGenericHttpMessageConverter<MultiValueMap<String, String>> {
private static final MediaType CONVERTER_MEDIA_TYPE = MediaType.APPLICATION_FORM_URLENCODED;
public FormUrlencodedHttpMessageConverter() {
super(CONVERTER_MEDIA_TYPE);
}
@Override
public MultiValueMap<String, String> read(Type type, Class<?> contextClass, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException {
String urlEncodedData = new BufferedReader(
new InputStreamReader(inputMessage.getBody(), StandardCharsets.UTF_8)).readLine();
String[] keyValuePairs = urlEncodedData.split("&");
MultiValueMap<String, String> keyValuePairsMap = new LinkedMultiValueMap<>();
for (String keyValuePair : keyValuePairs) {
String[] pairElements = keyValuePair.split("=");
String key = pairElements[0];
String value = pairElements[1];
keyValuePairsMap.add(key, value);
}
return keyValuePairsMap;
}
@Override
protected boolean canRead(@Nullable MediaType mediaType) {
return CONVERTER_MEDIA_TYPE.includes(mediaType);
}
@Override
protected boolean canWrite(@Nullable MediaType mediaType) {
return CONVERTER_MEDIA_TYPE.includes(mediaType);
}
@Override
protected void writeInternal(MultiValueMap<String, String> t, Type type, HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableException {
throw new RuntimeException("Method 'writeInternal' in " + this.getClass().getSimpleName() + " is not implemented");
}
@Override
protected MultiValueMap<String, String> readInternal(Class<? extends MultiValueMap<String, String>> clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException {
throw new RuntimeException("Method 'readInternal' in " + this.getClass().getSimpleName() + " is not implemented");
}
Related Topics
Source Folder Is Not on the Java Build Class Path, Creating Java Package
How to Pass Intent in Adapter Class
Why Is Git Bash Not Using the Correct Java Path as Defined in the Path Environment Variable
Newline Character in Jlabel.Settext()
Safely Generate Random Numbers Between Some Range in Java
Generate Any Random Number of Any Length in Java
Calculating and Printing the Nth Prime Number
How to Reconnect Kafka Producer Once Closed
This Program Is About String Compression in Java
Splitting a String Containing Special Characters in to Individual Characters
Java Program to Check for Similar Digits
Cannot Get Jedis Connection; Could Not Get a Resource from the Pool
Can a @Manytoone JPA Relation Be Null
Android Classnotfoundexception: Didn't Find Class on Path
Reading Only the Integers from a Txt File and Adding the Value Up for Each Found