问题
TL;DR - Is there a way to throw an error from a registered type converter during the MVC databinding phase such that it will return a response with a specific HTTP status code? I.e. if my converter can't find an object from the conversion source, can I return a 404?
I have a POJO:
public class Goofball {
private String id = "new";
// others
public String getName () { ... }
public void setName (String name) { ... }
}
and am using a StringToGoofballConverter to create an empty object when "new".equals(id)
or try to load a Goofball from the database if it exists:
public Goofball convert(String idOrNew) {
Goofball result = null;
log.debug("Trying to convert " + idOrNew + " to Goofball");
if ("new".equalsIgnoreCase(idOrNew))
{
result = new Goofball ();
result.setId("new");
}
else
{
try
{
result = this.repository.findOne(idOrNew);
}
catch (Throwable ex)
{
log.error (ex);
}
if (result == null)
{
throw new GoofballNotFoundException(idOrNew);
}
}
return result;
}
That converter is used by spring when the request matches this endpoint:
@RequestMapping(value = "/admin/goofballs/{goofball}", method=RequestMethod.POST)
public String createOrEditGoofball (@ModelAttribute("goofball") @Valid Goofball object, BindingResult result, Model model) {
// ... handle the post and save the goofball if there were no binding errors, then return the template string name
}
This all works quite well insofar as GET requests to /admin/goofballs/new
and /admin/goofballs/1234
work smoothly in the controller for both creating new objects and editing existing ones. The hitch is that if I issue a request with a bogus id, one that isn't new
and also doesn't exist in the database I want to return a 404. Currently the Converter is throwing a custom exception:
@ResponseStatus(value= HttpStatus.NOT_FOUND, reason="Goofball Not Found") //404
public class GoofballNotFoundException extends RuntimeException {
private static final long serialVersionUID = 422445187706673678L;
public GoofballNotFoundException(String id){
super("GoofballNotFoundException with id=" + id);
}
}
but I started with a simple IllegalArgumentException as recommended in the Spring docs. In either case, the result is that Spring is returning a response with an HTTP status of 400.
This makes me think I'm misusing the Converter interface but that approach appears to be recommended by the @ModelAttribute docs.
So, again the question: is there a way to throw an error from a registered type converter during the databinding phase such that it will return a response with a specific HTTP status code?
回答1:
Answering my own question:
Change StringToGoofballConverter
to simply return null
for the unfound entity instead of throwing IllegalArgumentException
or a custom exception. The @Controller
method will then be given a Goofball
object that has a null
id (e.g. the id is not "new" nor the path element value). At that point I can throw a GoofballNotFoundException
or any other @ResponseStatus
exception from there, within the controller method to affect the response status code.
来源:https://stackoverflow.com/questions/25254730/spring-mvc-using-a-converter-to-load-object-from-path-variable-but-need-to-retu