0

My code is as below from where I am calling REST API

 List<String> a =  [b]
MultiValueMap<String, Object> requestParam = new LinkedValueMap<>();
requestParam.add('a', a);
restTemplate.postForObject(URL, requestparam,String.class);

On receiving end code is as

ResponseEntity<Object> functionName(
@Requestparam(value='a', required=true) List<String> a
){
for(int i = 0; i < a.size(); i++){
Sysout(a.get(i));
}


}

It print as ["b"] and in query parameter used as ["b"] while it should be as b

dkb
  • 4,389
  • 4
  • 36
  • 54
Rajanikant Shukla
  • 841
  • 2
  • 8
  • 11
  • is your request is of type `curl --location --request POST 'localhost:8080/so/2987755?a=b,c,d' \ --header 'Content-Type: application/json'`? – dkb Jun 16 '21 at 05:45

1 Answers1

1

There are multiple problems with your question

  1. '' is characters in java and "" is String
  2. There is no mention of request type GET/POST, inferred this from postForObject
  3. If you are using POST call then instead of passing arguments as RequestParam, you can pass it as BodyParam as mention here, but still, RequestParam can be used with POST call.

Solution 1: Considering POST call with @RequestBody

Controller:

@PostMapping(value = "/so/2987755", produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
ResponseEntity<List<String>> functionName(@RequestBody List<String> a){
    for(int i = 0; i < a.size(); i++){
        System.out.println(a.get(i));
    }
    return new ResponseEntity<>(a, HttpStatus.OK);
}

Client:

List<String> a = Collections.singletonList("b");
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);

final HttpEntity<String> request = new HttpEntity<String>(objectMapper.writeValueAsString(a), headers);
return restTemplate.postForObject("http://localhost:8080/so/2987755", request,String.class);

Solution 2: POST call with @RequestParam

Controller:

@PostMapping(value = "/so/2987755", produces = MediaType.APPLICATION_JSON_VALUE)
ResponseEntity<List<String>> functionName(@RequestParam(value = "a") List<String> a){
    for(int i = 0; i < a.size(); i++){
        System.out.println(a.get(i));
    }
    return new ResponseEntity<>(a, HttpStatus.OK);
}

Client 1:

import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.web.client.RestTemplate;

import java.util.HashMap;
import java.util.Map;


Map<String, String> requestParam = new HashMap<>();
final String requestParamKey = "a";
requestParam.put(requestParamKey, "b,c,d");
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);

final HttpEntity<String> request = new HttpEntity<String>(headers);
return restTemplate.postForObject("http://localhost:8080/so/2987755?a={" + requestParamKey + "}", request, String.class, requestParam);

Client 2: Another flavor of Client using UriComponentsBuilder

MultiValueMap<String, String> requestParam = new LinkedMultiValueMap<>();
final String requestParamKey = "a";
List<String> a = Arrays.asList("b", "c", "d");
requestParam.put(requestParamKey, a);

UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl("http://localhost:8080/so/2987755");
builder.queryParams(requestParam);

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(headers);

return restTemplate.postForObject(builder.build().encode().toUri(), request, String.class);

This both client call prints at the controller

b
c
d

The reason RequestParam is printed as ["b"] because you are using List<String> in LinkedValueMap instead if you use just MultiValueMap<String, String>, things will work as you expected.
What you observed is while deserializing List it will become ["b"] but if you use UriComponentsBuilder you will not face such issues.

dkb
  • 4,389
  • 4
  • 36
  • 54