2015-02-26 10 views
7

Ich versuche mich selbst zu versuchen, eine POST-Anfrage mit JSON-Nutzdaten an einen Remote-Server zu senden .Anforderung konnte nicht geschrieben werden: kein passender HttpMessageConverter für Anforderungstyp [org.json.JSONObject] und Inhaltstyp [application/json] gefunden

Dieser curl Befehl GET funktioniert:

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

Und die POST ein Werk zu fein:

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 

Und so versuche ich es in meinem Android-App zu imitieren.

Die App funktioniert gut auf die erste GET-Anfrage, aber gibt eine 400 Bad Anfrage auf dem zweiten POST.

Hier ist der Code, der für die GET-Anforderung funktioniert:

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); 

Hier ist der Quellcode für die POST-Anfrage:

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); 

Aber es gibt die Meldung:

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

Hier ist der 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; 
    } 
} 

Der CredentialsResource Klassencode:

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; 
    } 

} 
+0

Können Sie die Definition des REST-Controllers auf dem Server anzeigen? –

+0

@SergeyYamshchikov Ich habe den Controller hinzugefügt. Auch ich bemerke jetzt die Antwort ist ein 401 Nicht autorisierte – Stephane

+0

Die Curl-Anfrage ist Benutzer/1, aber die android ist Benutzer/Login –

Antwort

2

Ich hatte ein paar Dinge zu tun, um diese Funktion zu erhalten.

Zuerst hatte ich die JSONObject in einen String, wie in konvertieren:

sein
HttpEntity<String> entityCredentials = new HttpEntity<String>(jsonCredentials.toString(), httpHeaders); 

Der Grund, dass es keinen Konverter für die JSONObject Klasse-Mapping-Nachricht ist, während es eine für die String-Klasse ist.

Zweitens musste ich einen Restwert an den RestTemplate-Konstruktor übergeben. Andernfalls würde ich eine 400 Bad Request bekommen.

RestTemplate restTemplate = new RestTemplate(true); 

Der wahre Wert weist die Restvorlage an, die Standardkonverter zu verwenden. Wenn jemand weiß, warum das so ist, würde ich mich freuen, mehr darüber zu erfahren.

Third ich den nicht benötigten Jackson Konverter entfernt:

restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter()); 

Mit diesen Dingen getan, arbeitet die Anfrage einfach gut.

Hier ist der vollständige Code:

RestTemplate restTemplate = new RestTemplate(true);  
User user = null; 
HttpHeaders httpHeaders = new HttpHeaders(); 
httpHeaders.setContentType(MediaType.APPLICATION_JSON); 
httpHeaders.setAccept(Arrays.asList(MediaType.APPLICATION_JSON)); 
try { 
    JSONObject jsonCredentials = new JSONObject(); 
    jsonCredentials.put("email", REST_LOGIN); 
    jsonCredentials.put("password", REST_PASSWORD); 
    Log.e(Constants.APP_NAME, ">>>>>>>>>>>>>>>> JSON credentials " + jsonCredentials.toString()); 
    HttpEntity<String> entityCredentials = new HttpEntity<String>(jsonCredentials.toString(), httpHeaders); 
    ResponseEntity<User> responseEntity = restTemplate.exchange("http://" + REST_HOST + ":" + REST_PORT + "/" + REST_APP + "/api/users/login", 
      HttpMethod.POST, entityCredentials, User.class); 
    if (responseEntity != null) { 
     user = responseEntity.getBody(); 
    } 
    return user; 
} catch (Exception e) { 
    Log.e(Constants.APP_NAME, ">>>>>>>>>>>>>>>> " + e.getLocalizedMessage()); 
} 
return null; 

ich vermute, es eine Möglichkeit sein könnte, explizit einen Jackson-Wandler zu verwenden, und den wahren Wert im Rest Vorlage Konstruktor überspringen, aber das ist nur eine Vermutung.

5

Ziemlich spät zu antworten, obwohl ich gerade das gleiche Problem getroffen habe und nahm mir etwas Zeit, es zu lösen. Also, ich denke, ich teile es besser und behalte meine Lösung im Auge.

Eigentlich ist die Ausnahme völlig irreführend. Es stellte sich heraus, das Problem ist nicht, dass die MappingJackson2HttpMessageConverter nicht wusste, wie ich mein Objekt marshall - was seltsam klang, JSON-, sondern eine Konfiguration der zugrunde liegenden ObjectMapper.

Was ich getan habe ist disable die Eigenschaft SerializationFeature.FAIL_ON_EMPTY_BEANS wie die

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

und alles begann wie erwartet funktioniert.

0

Die Ausnahme "kein passender HTTPMessageConverter gefunden" wird ausgelöst, wenn keine JSON-Implementierung im Klassenpfad vorhanden ist. Werfen Sie einen Blick auf RestTemplate Quellcode:

public RestTemplate() { 
    this.messageConverters.add(new ByteArrayHttpMessageConverter()); 
    this.messageConverters.add(new StringHttpMessageConverter()); 
    this.messageConverters.add(new ResourceHttpMessageConverter()); 
    this.messageConverters.add(new SourceHttpMessageConverter<Source>()); 
    this.messageConverters.add(new AllEncompassingFormHttpMessageConverter()); 

    if (romePresent) { 
     this.messageConverters.add(new AtomFeedHttpMessageConverter()); 
     this.messageConverters.add(new RssChannelHttpMessageConverter()); 
    } 

    if (jackson2XmlPresent) { 
     this.messageConverters.add(new MappingJackson2XmlHttpMessageConverter()); 
    } 
    else if (jaxb2Present) { 
     this.messageConverters.add(new Jaxb2RootElementHttpMessageConverter()); 
    } 

    if (jackson2Present) { 
     this.messageConverters.add(new MappingJackson2HttpMessageConverter()); 
    } 
    else if (gsonPresent) { 
     this.messageConverters.add(new GsonHttpMessageConverter()); 
    } 
} 

eine JSON-Implementierung auf Ihren Klassenpfad hinzufügen. Beispiel:

implementation "com.fasterxml.jackson.core:jackson-databind:2.9.0" 
Verwandte Themen