J'éprouve actuellement un problème très étrange à appeler un service REST à partir d'un autre service et je pourrais vraiment m'employer à comprendre ce que je fais de travers.
Alors tout d'abord, un peu de contexte:
J'ai une application Web qui appelle un service REST pour créer un compte utilisateur (pour cette raison, le point de terminaison est localhost: 8080/register). Plus tôt dans la vie de l'utilisateur, j'ai appelé un autre service pour créer les informations de connexion de l'utilisateur localhost:8090/signup
, mais je dois vérifier quelques éléments de l'appel et vous enregistrer afin que, dans cet appel, j'appelle vers un autre point de terminaison sur 8090 pour obtenir cette information (localhost:8090/availability
). En résumé, la webapp appelle localhost: 8080/register qui appelle à son tour localhost:8090/availability
.
Lorsque j'appelle le point de terminaison de disponibilité directement, à partir d'un client REST ou de l'application Web elle-même, tout fonctionne comme prévu, mais pour une raison étrange, lorsque je l'appelle de l'intérieur de l'appel du point de terminaison du registre, je reçois un message. HTTP415. Quelqu'un a une idée de ce qui ne va pas?
Le contrôleur de registre ressemble à ceci:
@RequestMapping(method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseStatus(HttpStatus.OK)
public UserModel createUser(@RequestBody UserModel userModel) throws InvalidSignupException {
// a load of business logic that validates the user model
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<Boolean> response = restTemplate.postForEntity("http://localhost:8090/availability",
userModel.getUsername(), Boolean.class);
System.out.println(response.getBody());
// a load more business logic
return userModel;
}
Et le contrôleur de disponibilité ressemble à ceci:
@RequestMapping(method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseStatus(HttpStatus.OK)
public Boolean isUsernameAvailable(@RequestBody String username) {
// a load of business logic that returns a boolean
return Boolean.TRUE;
}
Divulgation complète - en pratique, ce que j'ai montré comme contenu de createUser () correspond en fait à plusieurs appels de la pile d'appels, en utilisant la même classe que celle que j'utilise pour appeler les services à partir de la webapp (ce qui fonctionne parfaitement dans ce contexte) et je ne retourne pas simplement true dans isUsernameAvailable (car ce serait idiot), mais c’est la version la plus simple du code qui reproduit le problème.
Mon hypothèse actuelle est que je fais quelque chose que je vais me renverser quand je le verrai mais que je regarde ce code trop longtemps pour pouvoir le voir davantage.
Edit Le commentaire de Vikdor ci-dessous a résolu ce problème pour moi. J'ai changé la méthode createUser en:
@RequestMapping(method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseStatus(HttpStatus.OK)
public UserModel createUser(@RequestBody UserModel userModel) throws InvalidSignupException {
// a load of business logic that validates the user model
RestTemplate restTemplate = new RestTemplate();
restTemplate.setMessageConverters(Arrays.asList(new MappingJackson2HttpMessageConverter()));
ResponseEntity<Boolean> response = restTemplate.postForEntity("http://localhost:8090/availability",
userModel.getUsername(), Boolean.class);
System.out.println(response.getBody());
// a load more business logic
return userModel;
}
A HTTP415 signifie Type de support non supporté . Cela signifie que isUsernameAvailable
attend une entrée au format JSON, mais ce n’est pas ce que cela produit.
Essayez d'ajouter explicitement l'en-tête Content-Type: application/json
à votre requête HTTP en procédant comme suit:
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> entity = new HttpEntity<String>(requestJson,headers);
restTemplate.put(uRL, entity);
Utilisez RestTemplate.exchange mentionné ci-dessous:
ResponseEntity responseEntity = RestTemplate.exchange (endPointURL, HttpMethod.GET/POST/PUT/DELETE, HttpEntity/en-têtes, uriVariables)
endpointURL - SOAP URL du noeud final, que le service REST doit consommer.
HTTPMethod - Type de méthode tel que GET, PUT, POST, DELETE etc.
HTTPEntity - Soap requiert l'expéditeur/les en-têtes/{a} obligatoires. Assurez-vous de définir le nom et la valeur de votre en-tête comme paire clé-Valye dans les en-têtes HTTP.
uriVariables - (Object ... urivariables) tels que String.class, Integer.class
Vous devez également mettre le connectTimeout , isSSLDisabled , responseCached dans le constructeur lors de la génération de la demande vers restTemplate.