Cris
Cris

Reputation: 339

How to respond with HTTP status code in a Spring MVC @RestController @ResponseBody class returning an object?

I'm trying to have a @RestController which takes a @PathVariable return a specific object in JSON format, along with proper status code. So far the way the code is, it will return the object in JSON format because it is using Spring 4 built in Jackson library by default.

However I do not know how to make it so it will give a message to the user saying we want an api variable, then JSON data, then Error code (Or success code depending if all went well). Example output would be:

Please enter api value as parameter (NOTE this can be in JSON as well if needed)

{"id": 2, "api": "3000105000" ... } (NOTE this will be the JSON response object)

Status Code 400 (OR proper status code)


The url with parameter look like this

http://localhost:8080/gotech/api/v1/api/3000105000

The code I have so far:

@RestController
@RequestMapping(value = "/api/v1")
public class ClientFetchWellDataController {

    @Autowired
    private OngardWellService ongardWellService;

    @RequestMapping(value = "/wells/{apiValue}", method = RequestMethod.GET)
    @ResponseBody
    public OngardWell fetchWellData(@PathVariable String apiValue){
        try{
            OngardWell ongardWell = new OngardWell();
            ongardWell = ongardWellService.fetchOneByApi(apiValue);
    
            return ongardWell;
        }catch(Exception ex){
            String errorMessage;
            errorMessage = ex + " <== error";
            return null;
        }
    }
}

Upvotes: 31

Views: 82128

Answers (2)

Sotirios Delimanolis
Sotirios Delimanolis

Reputation: 279970

A @RestController is not appropriate for this. If you need to return different types of responses, use a ResponseEntity<?> where you can explicitly set the status code.

The body of the ResponseEntity will be handled the same way as the return value of any @ResponseBody annotated method.

@RequestMapping(value = "/wells/{apiValue}", method = RequestMethod.GET)
public ResponseEntity<?> fetchWellData(@PathVariable String apiValue){
    try{
        OngardWell ongardWell = new OngardWell();
        ongardWell = ongardWellService.fetchOneByApi(apiValue);

        return new ResponseEntity<>(ongardWell, HttpStatus.OK);
    }catch(Exception ex){
        String errorMessage;
        errorMessage = ex + " <== error";
        return new ResponseEntity<>(errorMessage, HttpStatus.BAD_REQUEST);
    }
}

Note that you don't need @ResponseBody on a @RequestMapping method within a @RestController annotated class.

Upvotes: 64

Affe
Affe

Reputation: 47974

The idiomatic way would be to use an exception handler instead of catching the exception in your regular request handling method. The type of exception determines the response code. (403 for security error, 500 for unexpected platform exceptions, whatever you like)

@ExceptionHandler(MyApplicationException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public String handleAppException(MyApplicationException ex) {
  return ex.getMessage();
}

@ExceptionHandler(Exception.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public String handleAppException(Exception ex) {
  return ex.getMessage();
}

Upvotes: 32

Related Questions