FormData is missing when using Content-Type: 'application/x-www-form-urlencoded' in Spring 2.5.3 - spring

Based on the answer from: Content type 'application/x-www-form-urlencoded;charset=UTF-8' not supported for #RequestBody MultiValueMap
I'm have write post method:
#PostMapping (value = "test_3d_gmo", consumes = {MediaType.APPLICATION_FORM_URLENCODED_VALUE})
public ResponseData<String> returnUrlCall(#RequestParam Map<String, String> param, MultiValueMap<String, String> body) {
LOGGER.info("request param {}", param.toString());
LOGGER.info("request body {}", body.toSingleValueMap());
ResponseData<String> res = new ResponseData<>();
res.setAppData("Test");
return res;
}
I'm send request to this API using postman:
curl --location --request POST 'localhost:8080/api/cc/test_3d_gmo?message=a' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'param1=g1' \
--data-urlencode 'param2=g2' \
--data-urlencode 'param3=g3'
But my body always missing, param and body only have query string message. How i can fix this ?

Related

Java springboot POST request giving 404

I am trying a POST request in POSTMAN but even though its reaching the tomcat server node, I get following error in my localhost_access.log file
"POST /app/MyService/myControllerMethod HTTP/1.1" 404 1010
My Controller class is something like this :
#Controller("myServicecontroller")
#RequestMapping({"/MyService"})
public class MyServiceController {
#RequestMapping(value = {"myControllerMethod"}, method = {RequestMethod.POST})
public String myControllerMethodBackgroundCallBack(HttpServletRequest httpReq,
#RequestBody String request) {
// rest piece of code
}
}
Now my postman curl I am trying with empty data (tried with some value also) but get above 404 error response
curl --location --request POST 'http://my-ip-address:8080/app/MyService/myControllerMethod' \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--header 'My-Header-One: lskdnansdlknalkasndl' \
--header 'My-Header-Two: sadasdsa' \
--data-raw '{}'
What am I doing wrong? (app in above url is my service which works fine in other requests)
Same thing when I try with following code it is able to hit the api 200
HttpClient httpClient = new HttpClient();
PostMethod postMethod = new PostMethod(url);
postMethod.setRequestBody(requestString);
httpClient.setConnectionTimeout(httpReadTimeOut);
httpClient.executeMethod(postMethod);
I have successfully replicated this issue and found the root cause.
Root Cause
#ResponseBody annotation is missing in myControllerMethodBackgroundCallBack method.
Fix
#RequestMapping(value = {"myControllerMethod"}, method = {RequestMethod.POST})
#ResponseBody
public String myControllerMethodBackgroundCallBack(HttpServletRequest httpReq,
#RequestBody String request) {
// rest piece of code
}
}
Why?
#ResponseBody annotation is required with #Controller annotation and if use #RestController annotation then #ResponseBody annotation is not required.
In Short-
#RestController = #Controller + #ResponseBody
You can read more about #Controller and #RestController here https://medium.com/#akshaypawar911/java-spring-framework-controller-vs-restcontroller-3ef2eb360917

Spring Integration - http inbound

im trying to make a http inbound but when i print my message the payload its empty, what am i missing here?
#Slf4j
#Component
public class HttpInboundGateway {
#Bean
public IntegrationFlow inGate1() {
log.info("Initializing inbound gateway...");
return IntegrationFlows.from(Http.inboundChannelAdapter("/")
.requestPayloadType(PayloadObj.class))
.channel("transfer_next_channel")
.get();
}
#Bean
#ServiceActivator(inputChannel = "transfer_next_channel")
public MessageHandler handler() {
return new MessageHandler() {
#Override
public void handleMessage(Message<?> message) throws MessagingException {
System.out.println("myHandlerPayload: " + message.getPayload());
System.out.println("myHandlerHeader: " + message.getHeaders());
}
};
}
}
PayloadObj class expected:
#Data
#NoArgsConstructor
public class PayloadObj {
String name;
String job;
}
EDIT 1: As requested
Curl from Postman
curl --location --request GET 'http://localhost:9090/' \
--header 'Content-Type: application/json' \
--data-raw '{
"name":"Marcos",
"job":"Dev Jr"
}'
Print from handler:
myHandlerPayload: {} --- Payload
myHandlerHeader: {content-length=46, http_requestMethod=GET,
host=localhost:9090, http_requestUrl=http://localhost:9090/,
connection=keep-alive, id=e67aef3d-938a-7ac3-eb7d-ddaf9cd74f4e,
contentType=application/json;charset=UTF-8, accept-encoding=gzip,
deflate, br, user-agent=PostmanRuntime/7.28.4, accept=*/*,
timestamp=1642168826837}
curl --location --request GET 'http://localhost:9090/'
You do GET request. This way the body of the request is ignored.
And only request params are transferred as payload. Since you don't have those as well, that means the payload is empty Map.
Consider to use POST or PUT instead.
And learn more about an HTTP protocol and its method specifics.

springframework rest template: Method Not Allowed: [no body]

I need to recover a token from amazon cognito service.
I tried to use Spring RestTemplate, but when I request the URL in Java I got the following error:
org.springframework.web.client.HttpClientErrorException$MethodNotAllowed: 405 Method Not Allowed: [no body]
at org.springframework.web.client.HttpClientErrorException.create(HttpClientErrorException.java:117)
at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:186)
at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:125)
at org.springframework.web.client.ResponseErrorHandler.handleError(ResponseErrorHandler.java:63)
at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:819)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:777)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:711)
at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:602)
Below is my code (okay compagny and aHash were removed for this ticket):
Map<String, String> params = new LinkedHashMap<>();
params.put("grant_type", "client_credentials");
// build the url with params
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl("https://company.auth.eu-west-1.amazoncognito.com/oauth2/token");
for (Map.Entry<String, String> entry : params.entrySet()) {
builder.queryParam(entry.getKey(), entry.getValue());
}
Map<String, String> headers = new LinkedHashMap<>();
headers.put(AUTHORIZATION, "Basic aHash==");
headers.put("Content-Type", "application/x-www-form-urlencoded");
log.error("GenerateRemoteTokenURI requesting: {}", builder.toUriString());
HttpEntity<String> tokenResponseEntity = restTemplate.exchange(builder.toUriString(), HttpMethod.POST, new HttpEntity<>(headers),
String.class);
If I use a curl with that:
curl --location --request POST 'https://company.eu-west-1.amazoncognito.com/oauth2/token?grant_type=client_credentials' \ [14:28:53]
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'Authorization: Basic aHash=='
I got my access_token without any problem.
Do you know why I got this error from Spring, and how I can resolve the problem, please?
Thank you a lot and best regards

Spring Webclient Post Method `BadRequest` error for a request that works in Postman (and curl)

I'm calling an external API via WebClient to create a resource. But getting WebClientResponseException$BadRequest while testing from Postman. Here are few things I've tried without success:
Building URI path from uribuilder
Coverting entity to MultiValueMap before inserting into the request
Controller:
#PostMapping("/createMessage")
public String createMessage(#RequestBody Message request) {
return service.createMessage(request);
}
Service:
public String createMessage(Message requestBody) {
ObjectMapper mapper = new ObjectMapper();
MultiValueMap requestBodyForm = new LinkedMultiValueMap<String, Object>();
Map<String, Object> requestBodyMap = mapper.convertValue(requestBody, new TypeReference<Map<String, Object>>() {});
requestBodyForm.setAll(requestBodyMap);
String id = webClient.post()
.uri(properties.getMessageUrl())
.contentType(MediaType.APPLICATION_JSON)
.headers( headers ->
headers.setBasicAuth(user,pass))
.body(BodyInserters.fromValue(requestBodyForm))
.retrieve()
.bodyToMono(String.class)
.block();
return id;
}
Any direction where might be the problem would help a lot.
The external service is an IoT device controller API, with predefined message format:
$ curl --location --request POST 'http://external-service/message' \
--header 'Content-Type: application/json' \
--header 'Authorization: Basic xxxxxxxxxxxx' \
--data-raw '[{
"message": "Testing service reachability",
"defaulttext": "This is Message Zone",
"startDate": "2021-05-25 15:20:00",
"duration":10,
...
}]'
198

convert text form-data curl request into java code using rest template

curl --location --request POST 'some/api' \
--header 'Content-Type: multipart/form-data' \
--form 'name=testing' \
--form 'Key=testing' \
--form 'Client_Code=123' \
--form 'userid=123' \
Curl request converted using RestTemplate like below. It is not sending the form-data in the body.
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
// headers.setContentType(MediaType.MULTIPART_FORM_DATA); tried this also
MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
formData.add("MsgCode", "testing");
formData.add("Key", "testing");
formData.add("Client_Code", "123");
formData.add("userid", "123");
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(formData, headers);
try {
ResponseEntity<String> responseEntity = restTemplate
.exchange("some/api", HttpMethod.POST,
request, String.class);
old post, but was looking for something similar and saw nothing wrong other than the key you sent was
formData.add("MsgCode", "testing");
Should have been
formData.add("name", "testing");

Resources