JSR-303 and conditional validation with self-validation POJOs
The JSR-303 validation is great. Yes, really. But sometimes it is just too great. Imagine yourself having to do some complex validation on a single data-transfer POJO. Maybe you are collecting the data from a web-form and you need to show an error somewhere, but the default validation rules just don't fit, your to-be-enforced constraints are just too complex to be enforced using default constraints. It can be as simple as having to check for a string to be submitted, if, and only if, a checkbox is selected, but yet it is too complex to achieve using the default rules.
Yes, you can define a custom annotation, write a validator, a unit-test for validator, then define a message for the validation error in your Validation.properties file and so on.
Do you really have to do all that? If you are going to reuse the code – yes. But if it is really just a one-time shot? Then a simple short-cut can do the trick: just define a method in your POJO class that will do the validation, then annotate it with an @AssertTrue.
public class YourDataTransferObject {
// … your fields, getters and setters
@AssertTrue(message="Your custom validation message")
public boolean isValid() {
//...do your non-standard validation stuff here
//and return true if the object is valid
}
}
And, assuming you have a Spring form with an instance of YourDataObject as your command object (form object), your JSP can contain the following code.
YourSpringWebForm.jsp:
…
<form:errors path="valid">
<!-- Put it wherever you like: next to an input field, in the header, etc. -->
No boilerplate code. It's that simple. You might need to write a unit test for your method (you probably do), but it's still a lot simpler than setting up a whole bunch of mock objects to test a custom validator object.
This approach can save you some effort, if you don't really plan to reuse the code. If you ever need to reuse the validation logic – the refactoring is very simple: you just move the validation code from your POJO to a validator object.
P.S. Disclaimer: this is just a quick-and-dirty solution for one-time validation scenarios. I don't suggest using this approach in all and every case, but in my experience, it can save some time now and then.
Yes, you can define a custom annotation, write a validator, a unit-test for validator, then define a message for the validation error in your Validation.properties file and so on.
Do you really have to do all that? If you are going to reuse the code – yes. But if it is really just a one-time shot? Then a simple short-cut can do the trick: just define a method in your POJO class that will do the validation, then annotate it with an @AssertTrue.
public class YourDataTransferObject {
// … your fields, getters and setters
@AssertTrue(message="Your custom validation message")
public boolean isValid() {
//...do your non-standard validation stuff here
//and return true if the object is valid
}
}
And, assuming you have a Spring form with an instance of YourDataObject as your command object (form object), your JSP can contain the following code.
YourSpringWebForm.jsp:
…
<form:errors path="valid">
<!-- Put it wherever you like: next to an input field, in the header, etc. -->
No boilerplate code. It's that simple. You might need to write a unit test for your method (you probably do), but it's still a lot simpler than setting up a whole bunch of mock objects to test a custom validator object.
This approach can save you some effort, if you don't really plan to reuse the code. If you ever need to reuse the validation logic – the refactoring is very simple: you just move the validation code from your POJO to a validator object.
P.S. Disclaimer: this is just a quick-and-dirty solution for one-time validation scenarios. I don't suggest using this approach in all and every case, but in my experience, it can save some time now and then.
Comments
Post a Comment