89

I am using methods like this

@RequestMapping(method = RequestMethod.GET)
public ResponseEntity<UserWithPhoto> getUser(@RequestHeader(value="Access-key") String accessKey,
                                     @RequestHeader(value="Secret-key") String secretKey){
    try{
        return new ResponseEntity<UserWithPhoto>((UserWithPhoto)this.userService.chkCredentials(accessKey, secretKey, timestamp),
                new HttpHeaders(),
                HttpStatus.CREATED);
    }
    catch(ChekingCredentialsFailedException e){
        e.printStackTrace();
        return new ResponseEntity<UserWithPhoto>(null,new HttpHeaders(),HttpStatus.FORBIDDEN);
    }
}

And I want to return some text message when exception occurs but now I just return status and null object. Is it possible to do?

3
  • 13
    Change your return type to a ResponseEntity<Object> or to a ResponseEntity<?>. Instead of passing a null argument for your error case, pass in a String. Spring is smart enough to see the String and write it as text to the response body. Alternatively, provide a @ExceptionHandler that will handle the exception itself and have your handler throw the exception. Commented Sep 7, 2015 at 15:25
  • 1
    @SotiriosDelimanolis, wondering why don't you create answer? Commented Sep 7, 2015 at 16:19
  • 4
    @lkrnac I've answered similar questions in the past. I don't find them necessarily interesting anymore. But I couldn't find a duplicate, so I still wanted to give something. Commented Sep 8, 2015 at 14:26

5 Answers 5

160

As Sotirios Delimanolis already pointed out in the comments, there are two options:

Return ResponseEntity with error message

Change your method like this:

@RequestMapping(method = RequestMethod.GET)
public ResponseEntity getUser(@RequestHeader(value="Access-key") String accessKey,
                              @RequestHeader(value="Secret-key") String secretKey) {
    try {
        // see note 1
        return ResponseEntity
            .status(HttpStatus.CREATED)                 
            .body(this.userService.chkCredentials(accessKey, secretKey, timestamp));
    }
    catch(ChekingCredentialsFailedException e) {
        e.printStackTrace(); // see note 2
        return ResponseEntity
            .status(HttpStatus.FORBIDDEN)
            .body("Error Message");
    }
}

Note 1: You don't have to use the ResponseEntity builder but I find it helps with keeping the code readable. It also helps remembering, which data a response for a specific HTTP status code should include. For example, a response with the status code 201 should contain a link to the newly created resource in the Location header (see Status Code Definitions). This is why Spring offers the convenient build method ResponseEntity.created(URI).

Note 2: Don't use printStackTrace(), use a logger instead.

Provide an @ExceptionHandler

Remove the try-catch block from your method and let it throw the exception. Then create another method in a class annotated with @ControllerAdvice like this:

@ControllerAdvice
public class ExceptionHandlerAdvice {

    @ExceptionHandler(ChekingCredentialsFailedException.class)
    public ResponseEntity handleException(ChekingCredentialsFailedException e) {
        // log exception
        return ResponseEntity
                .status(HttpStatus.FORBIDDEN)
                .body("Error Message");
    }        
}

Note that methods which are annotated with @ExceptionHandler are allowed to have very flexible signatures. See the Javadoc for details.

Sign up to request clarification or add additional context in comments.

5 Comments

I have been doing something similar to the second example here. I can't test it properly though. Do you know how to test the controller response using this method. Seems to work when you don't return your own ResponseEntity, but just use \@ResponseStatus and \@ResponseBody alongside \@ExceptionHandler.
Should the class with the @ControllerAdvice try to handle all possible exceptions? For example if I throw a "weak password" exception, should I try catch it in the service method, or should I handle it in the exception handler class? How do we separate which exceptions are being handled by who? I know it's pretty subjective, but is there a standard practice?
To avoid a Raw use of parameterized class 'ResponseEntity warning, use ResponseEntity<?> as your method return type.
what happens if you have Strong type object? eg ResponseEntity<Product> , then you cant throw error
It would be useful to have public class ExceptionHandlerAdvice extends ResponseEntityExceptionHandler. (See this.)
18

Here is an alternative. Create a generic exception that takes a status code and a message. Then create an exception handler. Use the exception handler to retrieve the information out of the exception and return to the caller of the service.

http://javaninja.net/2016/06/throwing-exceptions-messages-spring-mvc-controller/

public class ResourceException extends RuntimeException {

    private HttpStatus httpStatus = HttpStatus.INTERNAL_SERVER_ERROR;

    public HttpStatus getHttpStatus() {
        return httpStatus;
    }

    /**
     * Constructs a new runtime exception with the specified detail message.
     * The cause is not initialized, and may subsequently be initialized by a
     * call to {@link #initCause}.
     * @param message the detail message. The detail message is saved for later retrieval by the {@link #getMessage()}
     *                method.
     */
    public ResourceException(HttpStatus httpStatus, String message) {
        super(message);
        this.httpStatus = httpStatus;
    }
}

Then use an exception handler to retrieve the information and return it to the service caller.

@ControllerAdvice
public class ExceptionHandlerAdvice { 

    @ExceptionHandler(ResourceException.class)
    public ResponseEntity handleException(ResourceException e) {
        // log exception 
        return ResponseEntity.status(e.getHttpStatus()).body(e.getMessage());
    }         
} 

Then create an exception when you need to.

throw new ResourceException(HttpStatus.NOT_FOUND, "We were unable to find the specified resource.");

2 Comments

what happens if you have Strong type object? eg ResponseEntity<Product> , then you cant throw error
So we have to perform a bunch of voodoo just to override spring boot's override.
1

I´m not using the RepsoneEntitiy as return element because it destroys json format of the body. I found at this time of my posting this solution:

        throw new ResponseStatusException(
      HttpStatus.BAD_REQUEST, "ErrorMessage", optionalCauseExeption);

found here: https://www.baeldung.com/spring-response-status-exception

1 Comment

This works great, you can additionally just define a handler to catch ResponseStatusExceptions and return a Map of errors. Thanks @Van.
-1

Evaluating the error response from another service invocated...

This was my solution for evaluating the error:

try {
        return authenticationFeign.signIn(userDto, dataRequest);
    }catch(FeignException ex){

        //ex.status();

        if(ex.status() == HttpStatus.UNAUTHORIZED.value()){
            System.out.println("is a error 401");
            return new ResponseEntity<>(HttpStatus.UNAUTHORIZED);
        }
        return new ResponseEntity<>(HttpStatus.OK);

    }

Comments

-6
return new ResponseEntity<>(GenericResponseBean.newGenericError("Error during the calling the service", -1L), HttpStatus.EXPECTATION_FAILED);

1 Comment

Where does GenericResponseBean come from?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.