Spring-MVC using a Converter to load object from path variable, but need to return 404 for unfound

帅比萌擦擦* 提交于 2019-12-10 22:58:05

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!