Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring MVC 3.0: How to validate path variable that is global to all request mappings efficiently?

I'm trying to get my feet wet with Spring MVC 3.0, and while I can get it to work, I can't seem to handle this particular scenario efficiently.

I have a controller with that handles "/{studyName}/module" prefix, and it looks something like this:-

@Controller
@RequestMapping(value = "/{studyName}/module")
public class ModuleController {

    @RequestMapping(...)
    public ModelAndView getA(@PathVariable String studyName, ...) {
        if (!validStudy(studyName)) { return bad request; }
        ...
    }

    @RequestMapping(...)
    public ModelAndView getB(@PathVariable String studyName, ...) {
        if (!validStudy(studyName)) { return bad request; }
        ...
    }

    @RequestMapping(...)
    public ModelAndView getC(@PathVariable String studyName, ...) {
        if (!validStudy(studyName)) { return bad request; }
        ...
    }

    @RequestMapping(...)
    public ModelAndView getD(@PathVariable String studyName, ...) {
        if (!validStudy(studyName)) { return bad request; }
        ...
    }
}

The problem with this code is, I have the studyName validation scattered all over the methods and possibly in other Controllers' methods too. Is there a way I can perform validation on studyName path variable all in one spot without using something like AOP? How do you handle validation like this?

Thanks.

like image 341
limc Avatar asked Jan 14 '11 14:01

limc


People also ask

How do you validate a path variable?

Validating a PathVariable Just as with @RequestParam, we can use any annotation from the javax. validation. constraints package to validate a @PathVariable. The default message can be easily overwritten by setting the message parameter in the @Size annotation.

What is difference between @PathParam and @PathVariable?

The @PathVariable annotation is used for data passed in the URI (e.g. RESTful web services) while @RequestParam is used to extract the data found in query parameters. These annotations can be mixed together inside the same controller. @PathParam is a JAX-RS annotation that is equivalent to @PathVariable in Spring.

What is difference between @RequestParam and @PathVariable?

2) @RequestParam is more useful on a traditional web application where data is mostly passed in the query parameters while @PathVariable is more suitable for RESTful web services where URL contains values.


2 Answers

Right now, it's a little tricky to make this happen automatically, but it is possible. You should use a Bean validation (JSR-303) provider that implements appendix C. Currently that's Apache BeanValidation or Hibernate Validator 4.2 (which is in beta).

Add your chosen bean validation implementation to the classpath. This will be the implementation of JSR-303 that Spring MVC uses.

Second, annotate the method parameter with @Valid and any constraint annotations, like @NonNull.

This will look something like:

public ModelAndView getB(@Valid @NonNull @PathVariable String studyName, ...) {

That should work. You'd then need to check your Spring errors for any problems.

Alternatively, if you don't make use of any other Spring parameters, you can register a validator with an InitBinder like so:

@InitBinder
public void initBinder(WebDataBinder binder) {
  binder.setValidator(new StudyNameValidator());
}
like image 175
GaryF Avatar answered Oct 02 '22 22:10

GaryF


Create a class StudyName then have a WebArgumentResolver registered for StudyName and have your validation take place there.

   public ModelAndView getA(@PathVariable StudyName studyName){
      ...
   }

   public class StudyNameResolver implements WebArgumentResolver{
      //have resolveArgument method do validation if resolved to a StudyName
   }
like image 41
Eric Winter Avatar answered Oct 02 '22 22:10

Eric Winter