Spring MVC - Calling a rest service from inside another rest service

34,773

A HTTP415 means Unsupported Media Type. What that means is that isUsernameAvailable expects input in JSON format, but that isn't what it is getting.

Try explicitly adding Content-Type: application/json header to your HTTP request by doing the following:

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);

HttpEntity<String> entity = new HttpEntity<String>(requestJson,headers);
restTemplate.put(uRL, entity);
Share:
34,773
Rob
Author by

Rob

Updated on September 21, 2020

Comments

  • Rob
    Rob over 3 years

    I'm currently having a really weird issue with calling one REST service from inside another one and I could really use a hand in working out what I'm doing wrong.

    So first off, a bit of context:

    I have a webapp which calls off to a REST service to create a user account (for the sake of this explanation, the endpoint is localhost:8080/register). Earlier in the user journey I've called a different service to create the user's login credentials localhost:8090/signup but I need to check a few things in the call to /register so inside the call I'm calling out to a different endpoint on 8090 to get this information (localhost:8090/availability). Long story short, the webapp calls localhost:8080/register which in turn calls localhost:8090/availability.

    When I call the availability endpoint directly, from either a REST client or the webapp itself, everything works as expected, but for some strange reason, when I call it from inside the call to the register endpoint I get a HTTP415. Anyone have any insight into what's going wrong?

    The register controller looks like this:

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

    And the availability controller looks like this:

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

    Full disclosure - in practice, what I've shown as the contents of createUser() are actually several calls up the call stack, using the same class as I use to call the services from the webapp (which works perfectly well in that context), and I'm not actually just returning true in isUsernameAvailable (because that would be silly) but this is the simplest version of the code that replicates the issue.

    My current assumption is that I'm doing something that I'm going to kick myself over when I see it but I've been staring at this code too long to be able to see it any more.

    Edit Vikdor's comment below solved this problem for me. I changed the createUser method to:

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