dnang
dnang

Reputation: 939

Spring MVC: How to return different type in ResponseEntity body

In my request handler I want to do some validation and based on the outcome of validation check I will return different response (success/error). So I create a abstract class for the response object and make 2 subclasses for failure case and successful case. The code looks something like this, but it doesn't compile, complaining that errorResponse and successResponse cannot be converted to AbstractResponse.

I'm quite new to Java Generic and Spring MVC so I don't know of a simple way to solve this.

@ResponseBody ResponseEntity<AbstractResponse> createUser(@RequestBody String requestBody) {
    if(!valid(requestBody) {
        ErrorResponse errResponse = new ErrorResponse();
        //populate with error information
        return new ResponseEntity<> (errResponse, HTTPStatus.BAD_REQUEST);
    }
    createUser();
    CreateUserSuccessResponse successResponse = new CreateUserSuccessResponse();
    // populate with more info
    return new ResponseEntity<> (successResponse, HTTPSatus.OK);
}

Upvotes: 18

Views: 38926

Answers (2)

gadget
gadget

Reputation: 1978

There are two problems here:-

  • Your return type has to be changed to match the two response subclasses ResponseEntity<? extends AbstractResponse>

  • When you instantiate your ResponseEntity you cannot use the simplified <> syntax you have to specify which response class you are going to use new ResponseEntity<ErrorResponse> (errResponse, HTTPStatus.BAD_REQUEST);

     @ResponseBody ResponseEntity<? extends AbstractResponse> createUser(@RequestBody String requestBody) {
         if(!valid(requestBody) {
             ErrorResponse errResponse = new ErrorResponse();
             //populate with error information
             return new ResponseEntity<ErrorResponse> (errResponse, HTTPStatus.BAD_REQUEST);
         }
         createUser();
         CreateUserSuccessResponse successResponse = new CreateUserSuccessResponse();
         // populate with more info
         return new ResponseEntity<CreateUserSuccessResponse> (successResponse, HTTPStatus.OK);
     }
    

Upvotes: 26

Ruben
Ruben

Reputation: 521

Another approach would be using error handlers

@ResponseBody ResponseEntity<CreateUserSuccessResponse> createUser(@RequestBody String requestBody) throws UserCreationException {
    if(!valid(requestBody) {
        throw new UserCreationException(/* ... */)
    }
    createUser();
    CreateUserSuccessResponse successResponse = new CreateUserSuccessResponse();
    // populate with more info
    return new ResponseEntity<CreateUserSuccessResponse> (successResponse, HTTPSatus.OK);
}

public static class UserCreationException extends Exception {
    // define error information here
}

@ExceptionHandler(UserCreationException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ResponseBody
public ErrorResponse handle(UserCreationException e) {
    ErrorResponse errResponse = new ErrorResponse();
    //populate with error information from the exception
    return errResponse;
}

This approach enables the possibility of returning any kind of object, so an abstract super class for the success case and the error case (or even cases) is no longer necessary.

Upvotes: 12

Related Questions