Spring MVC Validation error - java

I have a Spring controller that accepts one of my business objects as an argument, that spring is automatically building from form data. One of the attributes of the object is an enum that comes from a select dropdown in the form. I am also using the #Valid notation to do validation on the object, using an implementation of the Spring Validator interface.
In testing, I manually added a selection to the dropdown (using the browser inspector) that is not valid, since it can't be converted to an enum. I would have thought that Spring would just leave the enum attribute as null, and the validator would catch the error, but I actually get a runtime error:
javax.el.ELException: Cannot convert CC of type class java.lang.String to class com.app.enums.States
Any ideas on how to handle this?

We need more details on what you want to happen when this occurs. You could tell Spring how to convert that String into an instance of States by using a Converter (see this page for details).

Related

Are Spring Model objects (and their attributes) tied to their respective controller endpoints / templates?

I'm just starting with spring so please bear with me. I've just solved a bug in my code that was coming from my assumption that once an attribute is added to any Model object, it would also be available to the templating implementation at other endpoints.
#GetMapping("/user_page")
public String getUserPage( Model model ) {
Page page = new Page();
model.addAttribute("user_page", page);
return "user_page";
In my Thymeleaf template I was able to use this attribute fine at user_page.html. Now at another endpoint and template I was also trying to use this user_page attribute. Note that it was throwing some errors:
Exception evaluating SpringEL expression:
and
Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1007E: Property or field 'name' cannot be found on null
It looks like Thymeleaf couldn't find the user_page attribute.
but I also hadn't added a Model parameter to the controller that handled this other endpoint. After adding a Model to the method parameters and adding the page again model.addAttribute("user_page", page);, this time to the controller handling the different endpoint, the problem went away.
Is Spring autowiring non-singleton Model objects to these controllers? Why did I have to add the same page instance to the model twice? So are these Models tied specifically to the template (maybe even endpoint) that their respective controller returns?
Read Dispatcher Servlet Processing Sequence.
Are Spring Model objects (and their attributes) tied to their respective controller endpoints / templates?
There is no such a thing, as "Model's respective controller"; rather, a fresh instance of the Model's implementation gets instantiated each time, any handler method gets invoked.
When an HTTP request hits dispatcher servlet, and the latter passes the servlet request-response objects into the corresponding handler method, Spring MVC's infrastructure looks up the signature of corresponding handler method and passes a fresh instance of the Model (along with many others), if it is expected.
You can also use modelAttribute element in your template's form, and this way, you will directly bind the data to the handler method's Model parameter, having the argument being pre-filled with the form data. In this case, you can also enable Bean Validation.

Default globalErrors in Spring

I want to know if there are any default globalErrors in Spring framework. I need to create my own custom validator by implementing org.springframework.validation.Validator interface. And there I add a globalError by errors.reject().
In controller class I have to catch this custom validation error If it's occurred. My plan is to catch it by using getGlobalErrors method. But if there any default globalErrors in spring, they will be also caught by getGlobalErrors method.
So I really need to know if there are any default globalErrors in Spring framework.
Well, actually I think there is just one type of errors - when object or some of its fields cannot be mapped to Java object.
For example - when you are trying to set null value from your front-end for LocalDateTime - it's gonna give you an error.
I really believe there are no other errors you can have.
getGlobalErrors method is there in the Spring. Here is the URL -
https://docs.spring.io/autorepo/docs/spring-framework/3.2.8.RELEASE/javadoc-api/org/springframework/validation/AbstractBindingResult.html#getGlobalErrors()

Spring form validation for plain HTML form

I need to validate some simple forms in my application. In these forms I have one or two input text to validate so I'd like to not create a specific ModelAttribute class for every form. I'd like to use instead plain HTML form and use #RequestParam annotations to handle POST parameters.
Is there a way to use Spring form validation in this situation (without using model attribute) or should I implement a backing-form object and a validator for each form?
Currently it is not possible to use #Valid on individual #RequestParam, #PathVariable etc. to trigger validation. This is the relevant feature request on the Spring Issue Tracker. Let's cross our fingers for Spring 4.1!
In your case, you will either have to use #ModelAttribute, or perform custom validation inside the controller (or maybe a Spring interceptor if you want the same validation to apply to multiple endpoints)
I think you can do this with Annotation. You can specifie for your parameters annotation like :
#Size(min=3, max=5)
#NotNull
#NotEmpty
...
Without a model attribute, Spring form Validation is not possible. Because Spring Form Validation depends on Spring Form Binding, which is a linkage between form elements and Model Attribute. So how small the form may be, create a DTO(Model Attribute), bind it to form and Perform Validations.
Definitely not possible using Spring's validation API (Errors object):
java.lang.IllegalStateException: An Errors/BindingResult argument is expected to be declared immediately after the model attribute, the #RequestBody or the #RequestPart arguments to which they apply
You could instantiate a model object, fill it with the data from the plain form and validate that object programmatically.

Spring and JSR303

I need to validate an XML coming from a vendor and saving it as XML type in oracle....
Now i need a process to trigger a validation engine... which is going to validate it and save the value in indicator as 'YES' or 'NO' example if the address in XML doesn't exist in our dB make the address indicator as 'NO' [which we correct in another process...]
I already used JSR303 in Spring 303, which is very effective and easy to use....but it uses a form backing object and #valid.....
Can I use it here in my design...
Or let me put it this way -
Is it possible for Spring's JSR-303 implementation to validate object fields that are not from form input?
I know its a very vague question...so please let me know if I need to explain more
Most of the work for object's validation performed by JSR-303 provider (hibernate-validator in most cases). Spring's role in this process is minimal -- it just parses user's data, binds it to the object and passes this object to validator. Also, during application startup, Spring creates Validator instance.
So, you can interfere in this proccess: create object, which will be validated, manually, get Validator instance and pass object to him. As result you will get a Set of ConstraintViolation which represents errors of each fields.
In this scheme main problem is that JSR-303 validator works with object, while you operates with XML document. You may deserialize XML document to object, validate it and, if it doesn't have errors, serialize it back to XML and writes to DB.
I recommend to read the following part of Hibernate Validator manual: 2.2. Validating constraints It describe Validator interface and a few useful methods: validate(), validateProperty() and validateValue().
One benefit from Spring here is that you won't need to create Validator by yourself with Validation.buildDefaultValidatorFactory().getValidator(): just #Autowire it as all other Spring beans:
#Autowired
private Validator validator;

How to handle in spring validation of json request / bean if the json cannot be converted to the bean?

I have classic Spring MVC application.
I want to validate a Form using a corresponding Java Bean, annotated with JSR-303 validation annotation.
The form data is sent by an ajax call using JSON. This Json is converted to the target Java Bean with Jackson - automatically by spring:
#RequestMapping(value = ControllerConstants.CALCULATION_MAPPING_SUBMIT_FORM,method = RequestMethod.POST)
public String submitForm(#Valid #RequestBody MyFormBean bean, final BindingResult result) {
...
}
Problem is for example if I have an Integer field in my bean but, in JSON the values is not a number. In this case it cannot create the target bean, that cannot be validated. This situation cannot be solved with custom property editors, since there is no way to convert a a text that not represents an Integer to Integer.
It seems that this is solved in Grails, we get errors from validator (errors is domain object) which has to be created during the data binding. So I assume spring supports this, thus Grails just uses Spring's support)
So how to elegantly solve this situation to handle this "validation" error?
UPDATE
Actually I figured out, that is this is supported by spring if we use simple form submit. The problem is with integration of Jackson deserialized. It does not fills errors. Still how to solve this?
I see two options...
Have client side validation that would not allow the form to be submitted if the there are formatting issues.
On the server side you will have to have a mechanism of handling the exception that would catch it and report the problem back to client.
Hope that helps.
EDIT:
Well not having client side validations may not be a good user experience. Users do not want to be reminded about validation errors after they have made a server round trip. However, if this is still a constraint have a look at following url and it gives elegant way of handling such issues and reporting informative error messages.
http://www.mkyong.com/spring-mvc/spring-3-mvc-and-jsr303-valid-example/

Categories

Resources