javax.validation.constraints.#Max not working as request param - spring

Tried to add #Max validation for the sizes request parameter. However, it seems whatever value I put in will be valid.
A simple controller method in a spring boot application.
#GetMapping("/all")
public String getAll(#RequestParam #Max(value=20, message = "should be less than 20") int sizes) {
if (sizes > 20) {
return "Pass but not valid";
}
return "Valid";
}
when request param sizes is 21, I get Pass but not valid rather error message
http://localhost:8080/all?sizes=21
Any advice? Thanks

dit you put #Validated above you class?

I found the following answer (Spring Controller: RequestParam not validated despite #Valid and #Size) helpful for exactly this question.
Basically, it says that:
MethodValidationPostProcessor needs to be added to a configuration.
#Validated annotation needs to be added on top of the controller class.
Possibly some exceptions like ConstraintViolationException or MethodArgumentNotValidException will need to be handled if customized responses are wanted.
For this setup to run, I had to add spring-boot-starter-validation like it's said in this answer: "The Bean Validation API is on the classpath but no implementation could be found" preventing startup

Related

javax regex validation of path variables in Spring

I have validation working for the beans and request parameters, however, my path variables fail to get validated:
#PathVariable #Pattern(regexp = "[A-Za-z0-9]+") String protocol
When I provide path var as ab!ab it doesn't fail the request with 400 status code but lets it pass with the value assigned to the argument.
I have also validated my regex online and it is valid and should be working fine.
Also, my rest controller does have #Validated annotation.
What am I missing here?
================UPDATE=============
I have tried other constraint annotations and none of them work, so it must something to do with the path variable validation. But what??
Make sure you have
hibernate-validator
dependency and add following bean:
#Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
return new MethodValidationPostProcessor();
}

POST / GET Request Param Validation in Spring Boot

I am using spring boot. I want to validated the POST request params. So I have gine through #Validated annotation but this require creating a different class for Every API. How should I write my code?
As for example, this is my api
#RequestMapping("/tags/{tagId}/{tagParentId}")
public Response<Demo> a(#PathVariable int tagId, #PathVariable int tagParentId){
... code
}
#RequestMapping("/data/{courseId}/{instId}")
public Response<Demo> b(#PathVariable int courseId, #PathVariable int instId){
... code
}
How should I change my code to add params validation for there API's such that I do not need to create two different validation class? Just one class and then I can add different functions for different API's.
#Validated should be used, to check that a parameter is syntactical correct.
As you are using int values, this is already done by spring.
If tagId is not a valid int, the client will already receive a Http error code.
The validation, whether there is a tag with the given tagId is implicitly done in your code, you do not need an additional validator for that.
If you read tags for example from the database, and you cannot find a tag for the tagId, you should
return new ResponseEntity(HttpStatus.NOT_FOUND);
from your controller method.
You may need to change the return type of your controller method to a common superclass or just to Object, to allow returning the ResponseEntity.
Its also possible to throw exceptions in the controller methods and to configure spring to return a regarding HttpStatus.
See exception-handling-for-rest-with-spring

Spring MVC + Hibernate validator : how can I override/internationalize the default error messages?

I'm working on a Spring MVC project in which I'm using Hibernate Validator to validate input fields from a form. As my project is Maven-based, I added this dependency:
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator-annotation-processor</artifactId>
<version>4.1.0.Final</version>
</dependency>
The form validation process works fine but now, I would like to override or internationalize the default error messages.
For instance, by default, using the #NotEmpty annotation will yield the message "may not be empty". How I can replace this message by my own message? I've tried several solutions:
defining a Spring bean with id "messageSource" and setting its "basenames" property
creating ValidationMessages.properties file in the project classpath
But the default messages are still displayed...
Any hint?
Thx in advance.
Yes you can do that. You can load the error message from the properties files. But you need to have the key in a proper format. Like NotEmpty.ClassName.fieldName=fieldName Can not be empty.
You just need to specify your exact class name and property name in your properties files. Everything other is looking just perfect in your case.
You can also have a common error message for a particular type of validation annotation for all the fields having that annotation. Like javax.validation.constraints.NotNull=Notnull erro happened!
Hope this helps you. Cheers.
This is a bit explanation that how you can find the exact property name behind every annotation given or used for validation. See below mentioned steps.
#Size(min = 1, max = 50, message = "Email size should be between 1 and 50")
Now remove { message = "Email size should be between 1 and 50" } from validation tag.
After doing this your annotation will be like this.
#Size(min = 1, max = 50)
Now at controller side debug the method which is being called upon when submitting the form. Below is my method which is receiving the request when user hits submit.
public static ModelAndView processCustomerLoginRequest(IUserService userService,LoginForm loginForm,
HttpServletRequest request, HttpSession session, BindingResult result, String viewType, Map<String, LoginForm> model)
Now place a debug point at very first line of the method and debug the argument "result".
BindingResult result
While dubugging you will find a string like this in codes array.
Size.loginForm.loginId
Now define this string in your properties file and a message against that string. Compile and execute. That message will be displayed whenever that annotation wouldn't be validated.
Size.loginForm.loginId=email shouldn't be empty.
Basically spring makes its own string as key to its property file message. In above key
Size(#Size) = validation annotation name
loginForm = My Class Name
loginId = Property name in LoginForm class.
The Beauty of this method is it also runs fine while you will be using Spring Internationalization. It automatically switches the messages file as language changes.

Non JSR303 equivalent of #Valid annotation in Spring 3.x?

Plain and simple issue:
I would like to annotate my method parameter with some sort of annotation that would fire regular spring validation mechanism (based on Validator interface)
I don't want to include JSR303 dependency
Any ideas? I looked on #Validated but it seems that it was not created for this purpose.
Right now I do it like this:
public String req(#ModelAttribute SomeRequest request, BindingResult errors) {
validator.validate(request, errors); // This can be avoided
if (!errors.hasErrors()) {
// Valid request
return ...
} else {
// There were errors
return ...
}
}
In that case you need to create custom annotation using #interface and then use that instead of standard #Valid annotation and at runtime identify it and validate your fields accordingly. Hope this helps you. Cheers.

Spring Framework validate request parameter or path variable

I know I can validate forms in Spring, but can I apply similar validate to URL parameters? For example, I have a method in my controller as follows:
public String edit(#PathVariable("system") String system,
#RequestParam(value="group") String group,
ModelMap model) throws DAOException {
Can I validate the values of system and group before the method is called, to ensure they are of a certain value or match a certain regex?
Thanks
You may be able to use Spring Asserts for this. The Assert api (http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/util/Assert.html) runs a supplied expression against the specified parameters and if the expression equates to false then it throws an exception.
Ex:
Assert.isTrue(system.equals("ValidSystemName"), "You must supply a valid system");
It also contains functions to check that parameters are not null or are not empty strings, etc.
Create an annotation that marks parameters that should be validated. This annotation needs a #Retention of RUNTIME and a #Target of ElementType.PARAMETER.
Create a validator implemented as an AspectJ Aspect.
Wrap calls to controllers with this validator.
A sample annotation:
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.PARAMETER)
#Documented
public #interface ValidSystemParameter {
}
A sample validator:
#Aspect
public class ValidSystemParameterValidator {
#Pointcut("TODO: write your pointcut expression")
public void controllerMethodWithValidSystemParameter();
#Before(pointcut = "controllerMethodWithValidSystemParameter()")
public void validateSystemParameter(String systemParameter) {
// validate the parameter (throwing an exception)
}
}
To learn about the AspectJ pointcut expression language see: http://www.eclipse.org/aspectj/doc/released/progguide/language-joinPoints.html
To learn about AspectJ integration in Spring see: http://static.springsource.org/spring/docs/current/spring-framework-reference/html/aop.html#aop-ataspectj
I might be a little late, but with Spring 3.0 you have the option of using JSR-303 validation with the #Valid annotation. There are also some more specific annotations as #DateTimeFormat and #NumberFormat. More details here: http://static.springsource.org/spring/docs/3.0.5.RELEASE/reference/validation.html#validation-mvc
As I see it you have two options:
Define your request parameters as objects and user JSR-303
validation.
Use the Assert api as mentioned above.
If you just want to make a simple validation on a single value, I would go with the latter (that's what I did when I had simple int values to check for max value).

Resources