Home > Mobile >  SpringBoot: HttpClientErrorException$BadRequest: 400: [no body] when calling restTemplate.postforEnt
SpringBoot: HttpClientErrorException$BadRequest: 400: [no body] when calling restTemplate.postforEnt

Time:09-23

I am trying to hit a restful endpoint from my springboot application using restTemplate.exchange and restTemplate.postForEntity and I am getting 400 Bad request [no body] exception.

I tried every possible solution to figure out the issue. From the same code I used HttpURLConnection to hit the endpoint and it works fine. I am able to get valid response. I also tried hitting the endpoint from Postman and it works fine

Below is endpoint code

@RestController
@RequestMapping("auth")
@Slf4j
public class AuthController {

    @PostMapping(value = "/as/resourceOwner",
            consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
            produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<Token> getToken(@RequestParam(required = false)MultiValuedMap<?, ?> params) {
        log.info("token endpoint");
        return new ResponseEntity<>(new Token(), HttpStatus.OK);
    }
}

The below code with HttpURLConnection class works fine

public class Test {

    public static void main(String[] args) {
        try {
            URL url = new URL("http://localhost:8080/fc-services-mock-auth/fmrco/as/resourceOwner");
            HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
            urlConnection.setDoOutput(true);
            urlConnection.setRequestMethod("POST");
            urlConnection.setRequestProperty("Content-Type", MediaType.APPLICATION_FORM_URLENCODED_VALUE);
            OutputStream writer = urlConnection.getOutputStream();
            writer.write("a=a&b=b".getBytes(StandardCharsets.UTF_8));
            writer.flush();
            writer.close();
            BufferedReader reader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
            String line = null;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }
        } catch (Exception e) {
            System.out.println(e);
        }
    }

}

But the below code with restTemplate does not work

try {
        

    HttpEntity httpEntity = new HttpEntity<>(createBody(), createHeaders());
    ResponseEntity<String> response = restTemplate.exchange(new URI(endpointConfig.getTokenServiceUrl()),
            HttpMethod.POST, httpEntity, String.class);
            
    HttpEntity<MultiValueMap<String, String>> request =
            new HttpEntity<>(createBody(), createHeaders());

    ResponseEntity<TokenResponse> tokenResponse = restTemplate.postForEntity(
            new URI(endpointConfig.getTokenServiceUrl()),
            request,
            TokenResponse.class);

    logger.debug(" token process completed");
    return tokenResponse.getBody();
} catch (Exception e) {
    throw new TokenException(" token error: ", e);
}
    
    
private HttpHeaders createHeaders() {
    HttpHeaders headers = new HttpHeaders();
    headers.add("Content-Type", MediaType.APPLICATION_FORM_URLENCODED_VALUE);
    return headers;
}

private  MultiValueMap createBody() {
    MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
    map.add("client_id", applicationConfig.getTokenClientId());
    map.add("client_secret", applicationConfig.getTokenClientSecret());
    map.add("grant_type", "password");
    map.add("username", applicationConfig.getTokenUsername());
    map.add("password", applicationConfig.getTokenPassword());

    return map;
}

Can anyone please tell me what is wrong here?

Additionally I have written another GET restful endpoint like below and while hitting the endpoint using exchange I still get the same error.

@GetMapping(value = "test", produces =  MediaType.TEXT_PLAIN_VALUE)
    public ResponseEntity<String> test() {
        return new ResponseEntity<>("Hello", HttpStatus.OK);
    }

try {
            HttpHeaders headers = new HttpHeaders();
            headers.setAccept(Arrays.asList(MediaType.TEXT_PLAIN));
            HttpEntity<MultiValueMap<String, String>> entity =
                    new HttpEntity<>(null, headers);
            ResponseEntity<String> response = restTemplate.exchange(
                    "http://localhost:8080/context/path",
                    HttpMethod.GET, entity, String.class);
        } catch (Exception e) {
            System.out.println(e);
        }

Also, intentionally I tried making a POST call to the get endpoint to see if it returns 405 Method not allowed. But to my wonder it still returned 400 Bad Request no body.

CodePudding user response:

I finally figured it out. The restTemplate is configured to use a proxy. I removed the proxy and it is working fine now.

CodePudding user response:

You can try something like:-

public void fetchAuthenticationToken() {

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        headers.setAccept(List.of(MediaType.APPLICATION_JSON));
        
        MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
        map.add("client_id", applicationConfig.getTokenClientId());
        map.add("client_secret", applicationConfig.getTokenClientSecret());
        map.add("grant_type", "client_credentials");
        map.add("username", applicationConfig.getTokenUsername());
        map.add("password", applicationConfig.getTokenPassword());
        
        HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<>(map, headers);
        String tokenEndPoint = "{your endpoints URL}";
        ResponseEntity<TokenResponse> responseEntity = testRestTemplate.exchange(tokenEndPoint,
                HttpMethod.POST, entity, TokenResponse.class, new HashMap<String, String>());
                
        assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK);
        TokenResponse token = responseEntity.getBody();
        assertThat(token).isNotNull();
        System.out.println("Auth Token value is "  token)
                
    }
  • Related