Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Rest API validation

I have a Spring 3.2 application and I've created a REST API following this example based on Spring MVC. Now I am experiencing some issues while trying to validate some data for different http methods (e.g.: POST and PUT methods).

This would be a pretty simplified example:

public class myItem{

    @NotEmpty
    private String foo;

    @NotEmpty
    private String bar;

    public myItem(String foo){
        this.foo = foo;
        this.bar = "";
    }

    public myItem(String foo, String bar){
        this.foo = foo;
        this.bar = bar;
    }

    /* getters & setters omitted */

}

This POJO is reused in the different request methods.

This would be my simplified controller:

@Controller
@RequestMapping("/api/item")
public class myItemController{

    @RequestMapping(value="/", method=RequestMethod.POST)
    @ResponseStatus(HttpStatus.CREATED) 
    public @ResponseBody myItem createItem(@Valid @RequestBody myItem item){
        /* do some stuff */
        return item; //inserted item returned
    }

    @RequestMapping(value="/", method=RequestMethod.PUT)
    @ResponseStatus(HttpStatus.NO_CONTENT)
    public @ResponseBody myItem createItem(@Valid @RequestBody myItem item){
        /* do some stuff */
        return item //updated item returned
    }
}

In the POST method I only expect foo field to be set, so this request would fail with the before above annotations. In the PUT method I expect both foo and bar fields to be set, so this request would be completed successfully.

What is the correct approach to deal with this kind of situations: in a certain request method you don't expect all fields to be filled up (some fields may have default values, hence you don't want to check all them, aka create), and in another method you must check all the fields (aka update).

like image 338
jarandaf Avatar asked Jul 03 '13 16:07

jarandaf


1 Answers

Use validation groups:

public interface ValidateOnCreate {}
public interface ValidateOnUpdate {}

.

public class myItem{ 
    @NotEmpty(groups = { ValidateOnCreate.class, ValidateOnUpdate.class })
    private String foo;

    @NotEmpty(groups = ValidateOnUpdate.class)
    private String bar;
    ...
}

.

@RequestMapping(value="/", method=RequestMethod.POST)
@ResponseStatus(HttpStatus.CREATED) 
public @ResponseBody myItem createItem(
    @Validated(ValidateOnCreate.class) @RequestBody myItem item) { ... }

@RequestMapping(value="/", method=RequestMethod.PUT)
@ResponseStatus(HttpStatus.NO_CONTENT)
public @ResponseBody myItem createItem(
    @Validated(ValidateOnUpdate.class) @RequestBody myItem item) { ... }

Note that you need Spring-specific @Validated in this case, because @Valid doesn't allow you to specify groups.

See also:

  • JSR 303: Bean Validation 4.1.2. groups
like image 191
axtavt Avatar answered Oct 04 '22 06:10

axtavt