MovieMe
MovieMe

Reputation: 133

How do I write my REST API call when expecting two types of return Objects

I've written a REST endpoint using Spring.

@RequestMapping(value = "/staticdata/userPreference/extUserId/{extUserId}/type/{type}", method = RequestMethod.GET)
public ResponseEntity<List<UserPreference>> getData(
        @PathVariable String extUserId,
        @PathVariable String type) {

    List<UserPreference> userPreferences = null;
    userPreferences = staticDataService.getUserPreference(extUserId, type);
    return new ResponseEntity<List<UserPreference>>(userPreferences, HttpStatus.OK);
}

@ExceptionHandler(RuntimeException.class)
public ResponseEntity<String> handleError(HttpServletRequest req, Exception exception) {
    return new ResponseEntity<String>(exception.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
}

When the getData() method is able to successfully get the data, it needs to return the List<>. However when there is an exception. The message is to be returned. This is handled by the handleError() method. This method returns a String.

My question is: How should the call to this rest service look like using the restTemplate offered by Spring? The return of the method can either be a List or a String based on success of failure respectively.

Upvotes: 3

Views: 746

Answers (1)

Wilson
Wilson

Reputation: 11619

You can try RestTemplate#exchange to execute a request and get the response as ResponseEntity and then obtain the List<UserPreference> by ResponseEntity#getBody.

If there is an error, you can obtain the error response from HttpStatusCodeException.getResponseBodyAsString.

Following is an example:

try {
    HttpHeaders headers = new HttpHeaders();
    // add some headers
    HttpEntity<String> request = new HttpEntity<String>(headers);    
    ResponseEntity<List<UserPreference>> response = restTemplate.exchange(
        YOUR_URL, HttpMethod.GET, request, new ParameterizedTypeReference<List<UserPreference>>() {});
    List<UserPreference> userPerference = response.getBody();
} catch (HttpStatusCodeException e) {
    String errorBody = e.getResponseBodyAsString();
}

If you need some more special handling on the error, you can try to implement a custom ResponseErrorHandler.

Edited:

Following is a code example for demonstration:

A test RestController have a RequestMapping which will throw an exception if request path is "/test?error=true". Otherwise, return a List<String> response:

@RestController
public class TestController {

    @RequestMapping(value = "/test", method = RequestMethod.GET)
    public ResponseEntity<List<String>> getData(@RequestParam(value = "error", required = false) String error) {
        if (error != null && error.equals("true")) {
            throw new HttpClientErrorException(HttpStatus.NOT_FOUND);
        } else {
            List<String> list = new ArrayList<>();
            list.add("test");
            return new ResponseEntity<List<String>>(list, HttpStatus.OK);
        }
    }

    @ExceptionHandler(RuntimeException.class)
    public ResponseEntity<String> handleError(HttpServletRequest req, Exception exception) {
        return new ResponseEntity<String>("Exception Message", HttpStatus.INTERNAL_SERVER_ERROR);
    }
}

A test configuration:

@SpringBootApplication
public class TestConfig {

}

The integration test that have 2 test cases. One is to test to get a List response, another is to test to get a message body from error response:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = TestConfig.class)
@WebIntegrationTest
public class IntegrationTest {

    @Value("${local.server.port}")
    int port;

    final RestTemplate template = new RestTemplate();

    @Test
    public void testGetListResponse() {
        String url = "http://localhost:" + port + "/test";
        ResponseEntity<List<String>> response = template.exchange(
                url, HttpMethod.GET, null, new ParameterizedTypeReference<List<String>>() {});
        List<String> list = response.getBody();
        Assert.assertEquals(list.size(), 1);
        Assert.assertEquals(list.get(0), "test");
    }

    @Test
    public void testGetErrorResponse() {
        String url = "http://localhost:" + port + "/test?error=true";
        String errorBody = null;
        try {
            ResponseEntity<List<String>> response = template.exchange(
                    url, HttpMethod.GET, null, new ParameterizedTypeReference<List<String>>() {
                    });
        } catch (HttpStatusCodeException e) {
            errorBody = e.getResponseBodyAsString();
        }
        Assert.assertEquals(errorBody, "Exception Message");
    }
}

Hope this can help.

Upvotes: 2

Related Questions