I want to create simple form which will display errors if input is not proper means if validation fails. I am using spring 3.0 annotations.
I did following things
1 : Created JSP
2 : Created Controller
3 : Created DTO
4 : Created org.springframework.validation.Validator
(write an implementation the necessary methods)
int error = bindingResult.getErrorCount() returning the error count and even my page is not being submitted which is expected but my JSP is not showing error messages
I have write on JSP.
Please guide me how to do this.
If i miss on something please let me know i will paste it.
Have a look at this answer for the structure of the controller. The important think is to have a paramter BindingResult and if this binding result contains an error you must return the same view (not redirect) again.
In the jsp code you can use the spring errors tag.
#see Spring Reference chapter 16.2.4.14 The errors tag -- there is an example
I have solved this i have just mentioned dto object name in #ModelAttribute
public void myMethod(#Valid #ModelAttribute**("myDto")** MyDTO myDTO,
BindingResult bindingResult, ActionResponse response,
SessionStatus sessionStatus)
Related
Im able to add validation to page with single form and it works great. Now, on my page i have 2 forms.
Filling first one and submitting redirects us to one page, filling seconds redirects to another page. When i add validation only for one form it works, when i do same for another, now both are throwing exception.
Thats my controller class:
https://i.stack.imgur.com/A8jWe.png
Thats my form code:
https://i.stack.imgur.com/d9CQP.png
the second form is just same but instead of th:object="${planPreferencesDTO}" it has planPreferences
The error im getting while subbmitting first form:
Caused by: java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'preferencesDTO' available as request attribute
java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'preferencesDTO' available as request attribute
Submitting second form throws same exception bit with planPreferencesDTO instead of preferencesDTO in stack trace
The dtos have #Data annotation from lombok.
It looks like a problem with model and binding result, but i wasn't able to find the solution for many hours, does anyone know what is wrong here?
Does Spring throw HttpRequestMethodNotSupportedException when a request body is not valid and #Valid (or #Validated) is used? I really expected MethodArgumentNotValidException.
Details: I have a small REST server built on Spring-Boot version 2.2.4. One of the methods looks like this:
#PostMapping("/yapp")
public Yapp kickYapp(#Validated #RequestBody YappDescriptor yappDescriptor) {
logger.debug("kickYapp descriptor {}", yappDescriptor);
doWork(yappDescriptor);
}
The YappDescriptor has annotations like "required" but nothing for valid values, ranges, etc. When I POST a well-formed JSON object with values for all the required fields as defined in the YappDescriptor POJO, the Spring controller method is found and invoked as expected.
I tried a couple error scenarios:
1) If I POST a well-formed JSON object that has only null values for the expected fields, the method is found and entered as expected.
2) If I POST a well-formed JSON object with a key that does not match any of the POJO's fields, the method is NOT found and entered. In watching class org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler I see the exception is HttpRequestMethodNotSupportedException and the server answers 405 "Request method 'POST' not supported".
In this controller class, kickYapp is the only POST-mapped method at the specified path, so I think that answer is pretty confusing. Altho I'm definitely sending a bad request (unexpected data), I am surprised my POST-mapped method is not found and invoked.
This post Validating if request body in HTTP POST request is null in Spring Boot controller suggests I should be seeing HttpMessageNotReadableException which would be helpful, but I never get that exception.
Many other questions on SO seem to be about enabling validation of request bodies, like Spring 4.1.7 validate request body , but I seem to be past that.
Thanks in advance for helping me understand this behavior and maybe improve the server to help my users discover their errors more easily (which saves me time :). Thought I could maybe extend that method to accept a BindingResult parameter and report errors that way, but that's a non-starter if the controller method is never entered.
Update to respond to comments: yes I could have used #Valid. In my tests annotation #javax.validation.Valid and #org.springframework.validation.annotation.Validated have the same effect, both turned on validation of the RequestBody parameter.
why not use #Valid?
like so:
public ResponseEntity<SalaryDto> update(#Valid #RequestBody SalaryDto subject)
and don't forget to use javax.validation validation annotations in your request body object
I am using #ParamValue annotation in my controller (Spring MVC).
Say My valid URL's are:
www.temp.com/test/a,
www.temp.com/test/b and
www.temp.com/test/c
So, my RequestMapping is:
#RequestMapping(value = "/test/{value}", method = RequestMethod.GET)
Now, my problem is that if anyone types a wrong URL like this :
www.temp.com/test/youarebroken
then I have to manually handle such a case in my controller to show 404 or not found.
Isn't there something inbuilt that sends a "not found or 404" notification to server that I can use directly ?
The simplest solution is to define a custom exception handler and to throw the custom exception when a validation fails within your controller. That would require that you manage the conditions manually as you stated you do not want to do.
A different solution is to use a global exception handler and define it to deal with the HTTP errors that are handled by Spring built-in.
In this link you can see both approaches: http://www.journaldev.com/2651/spring-mvc-exception-handling-exceptionhandler-controlleradvice-handlerexceptionresolver-json-response-example
However, from your question I understand you would like to return automatically an exception when certain condition in your param value does not meet, and you do not want to validate this manually within your controller. For this, you can add custom validation for an specific class and then set #Valid before the #ParamValue.
You can check this link for DataBinding http://docs.spring.io/spring/docs/current/spring-framework-reference/html/validation.html
And this link for specific validation on param attributes: Spring Web MVC - validate individual request params
So, in plain a solution would be to define a custom validator that throws a custom exception when fails. To set #Valid for the parameters (check link) and to adjust the custom exception to handle HTTP errors (e.g. HttpStatus.NOT_FOUND).
You can use a regex in your #RequestMapping URL. Example:
#RequestMapping(value = "/test/{value:[a-z]}", method = RequestMethod.GET)
I've got an ArticleFormModel containing data sent by normal html form which is injected by Spring using #ModelAttribute annotation, i.e.
#RequestMapping(value="edit", method=RequestMethod.POST)
public ModelAndView acceptEdit(#ModelAttribute ArticleFormModel model,
HttpServletRequest request, BindingResult errors)
{
//irrelevant stuff
}
Everything works perfectly fine up to some point. The problem is that the ArticleFormModel contains a double field (protected, set using normal setter). Everything works fine as long as data sent by user is a number. When they type a word, all I get is 400 Bad Request Http Error.
I've already registered a WebDataBinder for this controller
#InitBinder
protected void initBinder(WebDataBinder binder) throws ServletException
{
binder.setValidator(validator);
}
where validator is an instance of a custom class implementing org.springframework.validation.Validator interface
but I don't know what to do next. I'd like to be able to parse the model, get valid HTTP response and display error message in the form. The initBinder() method is called and I can call validator.validate() from it but it doesn't change the error (for that wrong data).
I'm aware that I could use a setter to parse the string, check if it's a number, if not, store that info in a variable, then retrieve that variable during validation, but that seems to be too much work. There has to be an easier way to force a type on the field without getting an error. Also, the issue is in data binding, not validation, so I feel that it should be placed in the respective code layer.
I was also thinking about implementing java.beans.PropertyEditor and calling binder.registerCustomEditor(), but I'm lacking a reliable knowledge source.
Client-side validation (checking if data is number via JavaScript) isn't a possibility.
TL;DR:
How can I force a field to be of specific type for a #ModelAttribute item without getting 400 Bad Request Http Error?
You can use <form:errors> for a binding error.
It looks like this:
Controller:
#RequestMapping(value="edit", method=RequestMethod.POST)
public ModelAndView acceptEdit(#ModelAttribute ArticleFormModel model,
BindingResult errors, HttpServletRequest request)
{
if (errors.hasErrors()) {
// error handling code goes here.
}
...
}
errors parameter is needed to be placed on the right after the model.
See below for details (Example 17.1):
http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/mvc.html#mvc-ann-methods
jsp:
<form:form modelAttribute="articleFormModel" ... >
...
<form:errors path="price" />
</form:form>
message properties file:
typeMismatch.articleFormModel.price=customized error message
I have ajax requests that come into my controller and my validation is working great. In the controller I call a failure jsp page if there is a failure. The only problem is that I have no idea how I can output the errors to the user on the failure.jsp page. I don't have access to the form tags of spring obviously. What should you do in this scenario?
Edit: All I really want to know is how I can access the binding errors on a JSP page when I'm using an AbstractCommandController.
What I've done in the past is use HTTP headers to send back messages to the AJAX requester (the XMLHTTPRequest object). You will not get a full binding and validation support this way, but it's a simple way to pass messages.
Another option that will give you the full power of Spring binding and validation is as follows. I'm assuming you're submitting a form via AJAX. You could do the standard spring binding and validation, and in the case of an error, send back and replace the form with the exception messages next to the problem input. This way you can leverage the full power of Spring binding and validation while getting the AJAX goodness that you want. This would require you to separate your form into a separate JSP page, so you could just return that form on AJAX submission and error.
In response the comment
My issue is just how to access the
BindingErrors from a JSP if I'm using
an AbstractCommandController. Ajax
isn't really that important in the
equation. I just didn't want to use a
formController because it didn't make
sense.
I think you can simply set a variable in your model like this:
ModelAndView.addObject(this.getCommandName(), errors)
This would be done in AbstractCommandController's
protected abstract ModelAndView handle(
HttpServletRequest request,
HttpServletResponse response,
Object command,
BindException errors)
throws Exception
method. Be sure the name of the model attribute is the name of your command (set in the setCommandName method).
This is untested and from memory.
You can check the BindException object for errors (and also catch and handle exceptions), and return information about them in your Ajax response. If you're using JSON, you could pair a list of error information with an "errors" key. The front-end would then need to check for and display these errors.