Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for javax.validation annotations on @PathVariable, @RequestHeader, @RequestParam [SPR-6380] #11041

Open
spring-issuemaster opened this issue Nov 17, 2009 · 26 comments

Comments

@spring-issuemaster
Copy link
Collaborator

@spring-issuemaster spring-issuemaster commented Nov 17, 2009

Gerrit Brehmer opened SPR-6380 and commented

I thought this was already done, because support for controller method-parameter validation should be available for all parameters.

I there a reason to exclude annotated (@RequestParam, etc.) method parameters? Is it not possible to validate primitive values?

Simple example:
For Paging-Support i need two request parameters: "start" & "size". "start" must have a positive value or 0 and "size" must have a positive value and also a maximum set.


Affects: 3.0 RC2, 4.0.5

Issue Links:

  • #14473 Support JSR 303 @Valid on @PathVariable

75 votes, 80 watchers

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Nov 18, 2009

Juergen Hoeller commented

The problem here is that JSR-303 is only really defined for bean classes: The constraint annotations are expected to sit on the target model class. As a consequence, @Valid on a parameter with primitive type doesn't mean anything since the primitive type doesn't contain any constraint annotations... Instead, we'd have to support constraint annotations like @NotNull, @Size etc themselves as parameter annotations. We can certainly consider that.

Juergen

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Nov 24, 2009

Gerrit Brehmer commented

Thats sounds good, because I think same programming approach (by Annotations) for validation of input values is quite useful. Also, it would be great to be able to use SpEL-Expressions inside this validation annotations.

You could change(correct) the enhancement summary to "Support of javax.validation.*-Annotations for @PathVariable, etc.", because usage of @Valid is limited to bean classes.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Nov 30, 2009

Roel van Dijk commented

And also: the JSR-303 @Valid annotation cannot be used on method parameters:

@Target(value={METHOD,FIELD})
@Retention(value=RUNTIME)
public @interface Valid ..

The current RC2 documentation (section 5.7.4.1) still uses this as an example, but that wouldn't work, right?

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Nov 30, 2009

Juergen Hoeller commented

Well, in the published version of the JSR-303 API that we're using, @Valid looks as follows:

@Target({ METHOD, FIELD, CONSTRUCTOR, PARAMETER })
@Retention(RUNTIME)
public @interface Valid {
}

So it can be used on method parameters... Which version of the API are you looking at there?

Juergen

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Nov 30, 2009

Roel van Dijk commented

Ah sorry about that. I was looking at the version I had extracted locally, which is the CR1 version. I hadn't realized that the final spec was released and that different from CR1. The new spec looks great, thanks, and the example in the manual is valid.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Feb 5, 2010

Andrew Ebaugh commented

I understand the limitation of validating beans vs "primitive" types, like String.
However, it currently does not appear to work for beans when using @PathVariable either.

I'd like to annotate a @Controller method like so:

@RequestMapping(value = "/user/{guid}", method = RequestMethod.GET)
public User getByGuid(@Valid @PathVariable GuidString guidString) {
}

I have already registered a converter from String->GuidString and a JSR-303 global validator that processes the GuidString validation annotations. But the validation does not appear to be done prior to invoking my handler method. It looks like the web data binder validation is only performed for method parameters annotated with @ModelAttribute.

I can see in the HandlerMethodInvoker.resolveHandlerArguments code that for this PathVariable parameter, the "validate" boolean is true because the @Valid annotation has been processed, but no validation logic is performed.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Feb 7, 2010

Kenny MacLeod commented

Take also the scenario where you have a bound model object passed in as a @RequestParam (e.g. @RequestParam MyModel model). If MyModel is annotated with JSR-303 annotations, it should be simple to pass the MyModel instance through the validator (in HandlerMethodInvoker.resolveRequestParam.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Jan 18, 2011

Gerrit Brehmer commented

Hibernate Validator added this functionality (MethodValidator) in version 4.2.0-BETA1 http://opensource.atlassian.com/projects/hibernate/browse/HV-347

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Jul 13, 2011

Thad West commented

" Instead, we'd have to support constraint annotations like @NotNull, @Size etc themselves as parameter annotations. We can certainly consider that."...yes please!

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Dec 5, 2012

Johan Kindgren commented

I've started to look into this feature, would it be okay to assume that "primitive" arguments are annotated with javax.validation-annotations? (More precisely, annotated with annotations that themselves are annotated with javax.validation.Constraint.)
"Complex" arguments (which internally are annotated with javax.validation-annotations) should be annotated with @Valid or @Validated?

I also assume that the solution can't reference classes/interfaces from javax.validation?

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Dec 5, 2012

Johan Kindgren commented

I was perhaps a bit enthusiastic about the solution. The upcoming release of Validation-api 1.1 could help a lot, but then again maybe it isn't possible to bump the validation-api version right away.

Another possible solution could be to use a bytecode modifier to create a class with the correct annotations, but that seems somewhat like a hack?

My attempted solution would add a "validate" method called from AbstractNamedValueMethodArgumentResolver.resolveArgument, seems like it could handle @RequestParameter, @RequestHeader and @PathVariable.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Apr 7, 2014

Jan Held commented

Is this topic still on the possible roadmap? I have the same problem, and fixed it for my case. I think a similar solution that Johan Kindgren proposed. Nevertheless I would prefer if this will be supported as a standard spring feature, so I can remove my workaround an simply provide custom validation Annotations and Classes.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Apr 12, 2014

Benjamin M commented

+1

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Jul 1, 2014

Rossen Stoyanchev commented

The underlying implementation for this, i.e. the ability to validate method parameters, has run into unexpected challenges. For a proper resolution unfortunately we'll have to revisit in 4.2, after #16519 is resolved (see comments there for further detail).

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Aug 21, 2015

roll tide commented

Is this still on roadmap?

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Apr 27, 2016

Michael Pratt commented

+1, would love to see this as well.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Oct 12, 2016

Rutvij Ravi commented

In Spring 4.3, constraint annotations work on @PathVariable, @RequestHeader, and @RequestParam parameters when the Controller class is annotated with @Validated and a MethodValidationPostProcessor is registered as a Spring bean in the DispatcherServlet's application context.

Is this issue for achieving this functionality without @Validated and MethodValidationPostProcessor?

Since this functionality is usually needed in most projects, i think it makes sense for any constraints on these parameters to be validated by default.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Dec 7, 2016

Dmitry Bedrin commented

MethodValidationPostProcessor doesn't work if Controller implements any interfaces. Unless you force proxyTargetClass behavior in Spring AOP of course.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Feb 16, 2017

Juergen Hoeller commented

Along with the InvocableHandlerMethod revision for #19792, I intend to revisit this one for 5.0. We still don't have a Bean Validation API for validating individual values, however, we have the BV 1.1 ExecutableValidator API available by default now and we can probably do some smart invocation for all method arguments, triggered by a method-level @Validated annotation or possibly even just by the mere presence of parameter-level constraint annotations.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Feb 28, 2017

Thibaud Lepretre commented

Using MethodValidationPostProcessor within Spring 4.x following constraint validation works perfectly

@RestController
@Validated
@RequestMapping(path = "/api/v1/users")
class UserController {

    private final UserService userService;

    public UserController(UserService userService) {
        this.userService = userService;
    }

    @GetMapping(path = "/")
    public CompletableFuture<Slice<UserResponse>> getUsers(
            @Min(value = 0) @RequestParam(value = "page", defaultValue = "0") int page,
            @Min(value = 1) @RequestParam(value = "limit", defaultValue = "50") int limit) {
        Pageable pageable = new PageRequest(page, limit);
        return userService.findAll(pageable)
                          .thenApply(users -> users.map(UserResponse::new));
    }

}

So is there something missing on current version of Spring? (except if Controller implements any interfaces see above)

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Feb 28, 2017

Juergen Hoeller commented

This works fine for the time being indeed. I'd just like to make it more first-class, without the need for a separate post-processor and without the need for an AOP proxy to begin with. Since we directly dispatch to MVC handler methods, we can also trigger method validation directly, not having to go through a generated proxy for that purpose.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Feb 28, 2017

Thibaud Lepretre commented

Ok is clear now. Thank for information.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Jul 23, 2018

caipivara commented

Any update on this?

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Nov 22, 2018

Stephano apiolaza tapia commented

It doesn´t work on websphere 8.5.11 with spring framework 4.3.20.RELEASE , the output is 

Caused by: java.lang.NoClassDefFoundError: org.hibernate.validator.method.MethodConstraintViolationException

There is a space on https://www.ibm.com/developerworks/community/forums/html/topic?id=ee47f46e-c56c-44e9-81be-0f94d4d3f1c5&ps=100&tags=&query=&filter=&sortBy=&order=asc, but the only solution that expose was https://www.ibm.com/developerworks/community/blogs/Dougclectica/entry/Spring_MVC_JSR_303_Validation_and_WebSphere?lang=en_us  

 The trouble is that websphere has bean validation 1.0 and use MethodConstraintViolationException from hibernate 4 (It was deprecated), It was changed by ConstraintViolationException on hibernate 5, I Must activate bean validation 1.1 on was https://www.ibm.com/support/knowledgecenter/en/SSAW57_liberty/com.ibm.websphere.liberty.autogen.nd.doc/ae/rwlp_feature_beanValidation-1.1.html

 

Websphere 9 is compatible with this feature

Note: I used @validated on controller

 

@oberlies

This comment has been minimized.

Copy link

@oberlies oberlies commented Feb 27, 2019

Thibaud Lepretre commented
So is there something missing on current version of Spring?

Yes, the status code in case of validation errors on @PathVariable, @RequestHeader, and @RequestParam parmeters is incorrect: With the described solution, there is a 500. This is different from an invalid @RequestBody, which correctly results in a 400.

@membersound

This comment has been minimized.

Copy link

@membersound membersound commented Aug 6, 2019

I'm having the same issue with @RestController @Validated and @GetMapping... @RequestParam. Resulting in a 500 instead of expected 400.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
3 participants
You can’t perform that action at this time.