Search code examples
springrestspring-bootresttemplaterestful-authentication

HttpClientErrorException$BadRequest: 400 null with RestTemplate 2.1.4.RELEASE


I have an SpringBoot 2.1.4.RELEASE app. that uses a third party API. With Postman Versión 6.7.4.

I authenticate with this URL:

https://bonanza.com:7688/pecador/api/v1/auth and in the body: { "username": "nunito.calzada@gmail.com","password": "sdfhhskj$(I$" }

and it works perfectly

I have implemented this method:

protected String authToken (Authentication auth) {

        // Request Header
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.add("Accept", "application/json");

        // Request Body
        MultiValueMap<String, String> parametersMap = new LinkedMultiValueMap<String, String>();
        parametersMap.add("username", auth.getName());
        parametersMap.add("password", (String)auth.getCredentials());

        // Request Entity
        HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(parametersMap, headers);

        // RestTemplate
        RestTemplate restTemplate = new RestTemplate();

        // POST Login
        ResponseEntity<String> response = restTemplate.exchange("https://bonanza.com:7688/pecador/api/v1/auth", HttpMethod.POST, requestEntity, String.class);

        HttpHeaders responseHeaders = response.getHeaders();

        List<String> list = responseHeaders.get("Authorization");
        return list == null || list.isEmpty() ? null : list.get(0);
    }

but I have this error:

2019-04-25 19:55  [http-nio-2233-exec-2] ERROR i.i.w.a.e.RestResponseEntityExceptionHandler.handleInternal(95) - 500 Status Code
org.springframework.web.client.HttpClientErrorException$BadRequest: 400 null
    at org.springframework.web.client.HttpClientErrorException.create(HttpClientErrorException.java:79)
    at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:122)
    at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:102)
    at org.springframework.web.client.ResponseErrorHandler.handleError(ResponseErrorHandler.java:63)
    at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:778)
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:736)
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:670)
    at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:579)

I also tried reple auth.getName() with "nunito.calzada@gmail.com" and (String)auth.getCredentials() with "sdfhhskj$(I$" with the same result

Testing with Postman, I set the Content-Type: application/json in the header:

enter image description here

I also tried this code with the same result:

HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.add("Accept", "application/json"); 

        //Request Body 
        MultiValueMap<String, String> parametersMap = new LinkedMultiValueMap<String, String>(); 


          parametersMap.add("username", "ricard.olle@gmail.com");
          parametersMap.add("password", "Iconofcoil100@");


          HttpEntity<?> httpEntity = new HttpEntity<Object>(parametersMap, headers);

          RestTemplate restTemplate = new RestTemplate();

          ResponseEntity<String> response =
                  restTemplate.exchange( BASE_API_URL + "auth", HttpMethod.POST, httpEntity,String.class);


          HttpHeaders responseHeaders = response.getHeaders();

          List<String> list = responseHeaders.get("Authorization"); 

          return list == null || list.isEmpty() ? null : list.get(0);

Solution

  • Your line:

    // Request Entity
    HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(parametersMap, headers);
    

    is wrong. Only is necessary to do:

    HttpEntity<?> httpEntity = new HttpEntity<Object>(parametersMap, requestHeaders);
    

    because parametersMap is a MultiValueMap but you declare also HttpEntity with a type MultiValueMap, and is not correct is this case.

    EDIT:

    Ok, MultiValueMap is for petitions "MediaType.APPLICATION_FORM_URLENCODED". Your case is "MediaType.APPLICATION_JSON". You can create a object that wrap username and password and send this object. For example:

    public class ObjectRequest {
    
        private String username;
        private String password;
    
        public String getUsername() {
            return username;
        }
        public void setUsername(String username) {
            this.username = username;
        }
        public String getPassword() {
            return password;
        }
        public void setPassword(String password) {
            this.password = password;
        }
    }
    

    And then:

    ObjectRequest obr = new ObjectRequest();
    obr.setUsername("nunito.calzada@gmail.com");
    obr.setPassword("sdfhhskj$(I$");
    

    And put this object as object in the HttpEntity:

    HttpEntity<ObjectRequest> requestEntity = new HttpEntity<ObjectRequest>(obr, headers);
    

    This will transform the object to json automatically.