Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.4k views
in Technique[技术] by (71.8m points)

android - Could not write request: no suitable HttpMessageConverter found for request type [org.json.JSONObject] and content type [application/json]

I'm digging myself in trying to send a POST request with a JSON payload to a remote server.

This GET curl command works fine:

curl -H "Accept:application/json" --user [email protected]:aaa "http://www.aaa.com:8080/aaa-project-rest/api/users/1" -i

And this POST one works fine too:

curl -H "Accept:application/json" -H "Content-Type: application/json" "http://www.aaa.com:8080/aaa-project-rest/api/users/login" -X POST -d "{ "email" : "[email protected]", "password" : "aaa" }" -i

And so I'm trying to mimic it in my Android app.

The app works fine on the first GET request but gives a 400 Bad Request on the second POST one.

Here is the code that works for the GET request:

  RestTemplate restTemplate = new RestTemplate();
  restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
  HttpHeaders httpHeaders = Common.createAuthenticationHeaders("[email protected]" + ":" + "aaa");
  User user = null;
  ResponseEntity<User> responseEntity = restTemplate.exchange("http://" + REST_HOST + ":8080/aaa-project-rest/api/users/" + 1L, HttpMethod.GET, new HttpEntity<Object>(httpHeaders), User.class);

Here is the source code for the POST request:

RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
User user = null;
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
httpHeaders.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
JSONObject jsonCredentials = new JSONObject();
jsonCredentials.put("email", REST_LOGIN);
jsonCredentials.put("password", REST_PASSWORD);
ResponseEntity<User> responseEntity = restTemplate.exchange("http://" + REST_HOST + ":" + REST_PORT + "/" + REST_APP + "/api/users/login",
        HttpMethod.POST, new HttpEntity<Object>(jsonCredentials, httpHeaders), User.class);

But it gives the message:

Could not write request: no suitable HttpMessageConverter found for request type [org.json.JSONObject] and content type [application/json]

Here is the Spring REST controller:

@RequestMapping(value = RESTConstants.SLASH + RESTConstants.LOGIN, method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public ResponseEntity<UserResource> login(@Valid @RequestBody CredentialsResource credentialsResource, UriComponentsBuilder builder) {
    HttpHeaders responseHeaders = new HttpHeaders();
    User user = credentialsService.checkPassword(credentialsResource);
    userService.clearReadablePassword(user);
    if (user == null) {
        return new ResponseEntity<UserResource>(responseHeaders, HttpStatus.NOT_FOUND);
    } else {
        tokenAuthenticationService.addTokenToResponseHeader(responseHeaders, credentialsResource.getEmail());
        responseHeaders.setLocation(builder.path(RESTConstants.SLASH + RESTConstants.USERS + RESTConstants.SLASH + "{id}").buildAndExpand(user.getId()).toUri());
        UserResource createdUserResource = userResourceAssembler.toResource(user);
        ResponseEntity<UserResource> responseEntity = new ResponseEntity<UserResource>(createdUserResource, responseHeaders, HttpStatus.CREATED);
        return responseEntity;
    }
}

@RequestMapping(value = RESTConstants.SLASH + "{id}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public ResponseEntity<UserResource> findById(@PathVariable Long id, UriComponentsBuilder builder) {
    HttpHeaders responseHeaders = new HttpHeaders();
    User user = userService.findById(id);
    if (user == null) {
        return new ResponseEntity<UserResource>(responseHeaders, HttpStatus.NOT_FOUND);
    } else {
        UserResource userResource = userResourceAssembler.toResource(user);
        responseHeaders.setLocation(builder.path(RESTConstants.SLASH + RESTConstants.USERS + RESTConstants.SLASH + "{id}").buildAndExpand(user.getId()).toUri());
        ResponseEntity<UserResource> responseEntity = new ResponseEntity<UserResource>(userResource, responseHeaders, HttpStatus.OK);
        return responseEntity;
    }
}

The CredentialsResource class code:

public class CredentialsResource extends ResourceSupport {

    @NotEmpty
    @Email
    private String email;
    @NotEmpty
    private String password;

    public CredentialsResource() {
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Quite late to reply, though I've just hitten the same problem and took me some time to solve it. So, I think I'd better share it and keep track of my solution.

Actually, the exception thrown is totally misleading. Turned out the problem is not that the MappingJackson2HttpMessageConverter didn't know how to marshall my object -which sounded strange, being JSON-, but a configuration of the underlying ObjectMapper.

What I did is to disable the property SerializationFeature.FAIL_ON_EMPTY_BEANS like that

restTemplate = new RestTemplate();
MappingJackson2HttpMessageConverter jsonHttpMessageConverter = new MappingJackson2HttpMessageConverter();
jsonHttpMessageConverter.getObjectMapper().configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
restTemplate.getMessageConverters().add(jsonHttpMessageConverter);

and everything started working as expected.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...