Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Programmatically change http response status using spring 3 restful

I have a controller like below

@Controller("myController")
@RequestMapping("api")
public class MyController {

     @RequestMapping(method = RequestMethod.GET, value = "/get/info/{id}", headers = "Accept=application/json")
    public @ResponseBody
    Student getInfo(@PathVariable String info) {
.................
}




    @ExceptionHandler(Throwable.class)
    @ResponseStatus( HttpStatus.EXPECTATION_FAILED)
    @ResponseBody
    public String handleIOException(Throwable ex) {
        ErrorResponse errorResponse = errorHandler.handelErrorResponse(ex);
        return errorResponse.toString();
    }

}

The controller has an error handling mechanism, in the error handling option it always return expectation fail status code 417. But I need to set a dynamic error Http status code like 500, 403 etc depending on type of error. How do I do this?

like image 421
1Sundorbon_bangla Avatar asked Nov 19 '13 08:11

1Sundorbon_bangla


People also ask

How do I change the response type dynamically in Spring REST?

This is done by setting the Accept header to the required type(s). So in the case where the consumer expects a response type as JSON an Accept header should be configured with "application/json" or "application/xml" for XML (or any specific variation of each such as "application/xhtml+xml" and alike).

How do I change the response code on a Spring REST controller?

Spring provides a few primary ways to return custom status codes from its Controller classes: using a ResponseEntity. using the @ResponseStatus annotation on exception classes, and. using the @ControllerAdvice and @ExceptionHandler annotations.

How do I send response status in Spring?

The very basic way of sending response status is to use ResponseEntity object, which is returned by a controller. Controller can set a specific response status in the Response. Alternatively, we can use @ResponseStatus annotation to specify the desired status code.


3 Answers

You need to change the type of the output value ResponseEntity. Answer here: How to respond with HTTP 400 error in a Spring MVC @ResponseBody method returning String?

like image 123
MartenCatcher Avatar answered Oct 19 '22 12:10

MartenCatcher


I get a solution and going to share this and also like to know any good suggestions.

@Controller("myController")
@RequestMapping("api")
public class MyController {

    @RequestMapping(method = RequestMethod.GET, value = "/get/info/{id}", headers = "Accept=application/json")
    public @ResponseBody
    Student getInfo(@PathVariable String info) {
        // ...
    }

}


// ...    
    @ExceptionHandler(Throwable.class)
    //@ResponseStatus( HttpStatus.EXPECTATION_FAILED)<<remove this line
    @ResponseBody
    public String handleIOException(HttpServletResponse httpRes,Throwable ex){ // <<Change this 
        if (some condition) {
            httpRes.setStatus(HttpStatus.BAD_GATEWAY.value());
        } else {
            httpRes.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
        }                 
        ErrorResponse errorResponse = errorHandler.handleErrorResponse(ex);
        return errorResponse.toString();
    }

Expected out in rest client :

502 Bad Gateway
{
    "status":"BAD_GATEWAY",
    "error":"java.lang.UnsupportedOperationException",
    "message":"Some error message"
}

Thanks for your replies. I still need pointers for good practices.

like image 25
1Sundorbon_bangla Avatar answered Oct 19 '22 14:10

1Sundorbon_bangla


Going by the code above, you need to be more careful about which exceptions you are throwing and handling. Setting up an exception handler for Throwable seems overly broad.

The way I do this is to create an ErrorMessage class with my XML/JSON marshalling annotations.

@XmlRootElement(name = "error")
public class ErrorMessage {
    private Throwable exception;
    private String message;
    public ErrorMessage() {
        this.message = "";
    }
    public ErrorMessage(String message) {
        this.message = message;
    }
    public ErrorMessage(Throwable exception) {
        this.exception = exception;
        this.message = exception.getLocalizedMessage();
    }
    @XmlTransient
    @JsonIgnore
    public Throwable getException() {
        return exception;
    }
    public void setException(Throwable exception) {
        this.exception = exception;
    }
    @XmlElement(name = "message")
    public String getMessage() {
        return message;
    }
    public void setMessage(String message) {
        this.message = message;
    }
}

With that in place, I tend to create my own application exceptions and then create my exception handler methods such as:

@ExceptionHandler(ResourceNotFoundException.class)
@ResponseBody
@ResponseStatus(HttpStatus.NOT_FOUND)
public ErrorMessage handleResourceNotFoundException(ResourceNotFoundException e, HttpServletRequest req) {
    return new ErrorMessage(e);
}

@ExceptionHandler(InternalServerErrorException.class)
@ResponseBody
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public ErrorMessage handleInternalServerErrorException(InternalServerErrorException e, HttpServletRequest req) {
    return new ErrorMessage(e);
}

With those in place, I just need to throw appropriate exceptions from my controller methods. For instance, if I throw a ResourceNotFoundException, then Spring will redirect that to my handleResourceNotFoundException method, which returns a 404, and that will also return JSON or XML representing the error.

like image 24
Steve Avatar answered Oct 19 '22 13:10

Steve