Spring REST input validation - spring

I'm writing a REST service using Spring Boot and JPA. I need to be able to validate some of the input fields and I want to ensure I'm using a proper pattern for doing so.
Let's assume I have the following model and I also have no control over the model:
{
"company" : "ACME"
"record_id" : "ACME-123"
"pin" : "12345"
"company_name" : ""
"record_type" : 0
"acl" : ['View','Modify']
"language" : "E"
}
The things I need to do are:
Ensure the value is not empty - This seems simple enough using the #NotEmpty annotation and I can pass a message.
Ensure the value is part of a valid list of values - The example here is the language property in the model above. I want the value to be either E,F or S. This seems possible using a custom annotation (eg #ValidValue({"E","F","S"})) but is there a better/"Springy" way to do this?
Ensure the values in a list are part of a valid list of values - The example here is the acl property. Again this seems possible with a custom annotation like #ValidListValues({"View", "Modify", "Delete", "Hide"}) but same question as above.
Set a default value - From what I read, custom validator annotations are only able to validate and not modify. I would like to do something like #DefaultValue(value=5) if the value is null. Is this possible? More on this below.
Set a default value to the return of a static method - For example if the pin field in model above isn't set, I want to set it to something like Util.getRandomDigitsAsString(5).
Use values from another property - I would like to validate that one property contains the string from another property. Using the example model, I want to ensure that record_id starts with company.
I have this setup in what I believe is a standard way with the controller -> service -> DTO -> DAO -> Model. Another option I was thinking about was creating a method in the validateCreate() that would go through all of the items above and throw an exception if needed.
Thanks.

Yes, NotEmpty is the right way
You should define a Language enum. The language field of your POJO should be of type Language
Same as 2. Define an Acl enum.
Define that in your Java code. Initialize the value of the field to 5 by default. If the JSON contains a value, Jackson will set the field value to the value in the JSON. Otherwise, it will stay as 5. Or initialize the field to null, and add a method getValueOrDefault(int defaultValue) that returns the default value you want if the value is null.
Same as 4
Define a custom validator that applies on the class itself, rather than a property of the class. In the validator chec that the two related values are correct.

Related

Thymeleaf th:value

Using SpringMVC + Thymeleaf, how does one bind an integer based model attribute, to an input field in a form using th:value or th:field, without having a value of '0' show in the field itself.
The issue is not with Thymeleaf, it is on the EL implementation of Tomcat. It doesn't respect the difference between the nullable Integer and primitive int. It is always coercing null values to 0. You can turn off this behavior using this VM argument :
-Dorg.apache.el.parser.COERCE_TO_ZERO=false
or programatically by
System.setProperty("org.apache.el.parser.COERCE_TO_ZERO", "false");
If you choose the programatic way, make sure that you invoke it during initialization of ServletContext (ServletContextListener#contextInitialized)
Just remove th:field attribute and write id and name attributes with corresponding logical name.

Analogue of #NotRquired annotation for validation

I use Hibernate Validation 4.3.1.Final and Spring 3.2.0.RELEASE
I have a form with a string attribute. This attribute is not required, but if it contains some value this value should be exactly 10 digits length.
So I need somthing like:
#NotRquired
#Length(min = 10, max = 10)
But there is no annotation like #NotRquired. How I should write validation for this case?
Not that a #NotRquired annotation would not help in this case, because all defined constraints are evaluated. So in the case where the value is not specified #Length would still be validated and fail. There are several things you could do:\
Use the #Pattern constraint and define a pattern which matters the empty string and the one of length 10 characters. Provided of course for not required case you get an empty string
Write a custom constraint, for example #EmptyOrLength which does what you want
Try working with validation groups and assign each constraint to a different group. You then need a way to target the right validation group
Revert to Hibernate Validator specific functionality and use boolean composition of constraints - http://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/#d0e3701. You still need a custom constraint though, but you can use a composition of #NotNull and #Length using #ConstraintComposition(OR)

Custom validation message

I have a problem with validating some data types.
There are int, short, DateTime and so on except string.
Suppose i have following property in my view model class
public int? LineNumber { get; set; }
When i input incorrect value i get mvc error "The value 'balblabl' is not valid for LineNumber."
But what if i want just out something like "Value incorrect"? Or what if i want to use other language? I have no idea how to do it(of course i can use string instead of int but it is painfull workaround)
i already tried dataannotationsextensions [DataAnnotationsExtensions.Integer(ErrorMessage = "Please enter a valid number.")] attribute. It is not working. I cannt to use custom validation attribute because of after binder convertation i get null value in all cases with incorrect value. I just cannt to do my own validation. I can to write my own binder but it looks like a joke. Really i think custom validation message is one of must have featerus and i cannt belive asp.net mvc doesnt has a simple way to do it.
I would like to add another, in my opinion, easy way to add and maintain custom error messages.
using the FluentValidation NuGet package.
It hooks up with mvc pretty easy have a look here
You can easily specify numerous rules for your models and display custom error messages that can use a resource file an example:
public class CreateProductCommandValidator : AbstractValidator<CreateProductCommand>
{
public CreateAgendaPointCommandValidator()
{
RuleFor(cmd => cmd.price)
.NotEmpty()
.WithMessage(Translations.CreateProduct_Price)
}
}
}
Documentation: FluentValidationDocumentation
Those errors are automatically added by the default model binder when it cannot parse the input string into its destination type. They are not like data annotations, where you can specify a resource instead of a harcoded string error message.
However you can use your own resource files, see this other question. Once you have created the resource file, you will update the global.asax for the default model binder to use it:
DefaultModelBinder.ResourceClassKey = "MyResources";
After a custom resource file has been set in the property ResourceClassKey of the default model binder, values will be resolved according to the following criteria (as per the MSDN):
If the property is not set, MVC uses the standard MVC resources.
If the property is set to an invalid class key (such as a resource
file that does not exist), MVC throws an exception.
If the property is set and the class key exists but the resource
names in the file do not exist in the application, MVC uses the
standard MVC resources.
If the property is set and the specified resources are available,
MVC uses the resources in the file.
If you need to know the key values for a particular message check this. For the message The value '{0}' is not valid for {1}., you will need to add a value with the key DefaultModelBinder_ValueInvalid

Representation of nulls in Freemarker with Spring Framework

I'm developing an application based on Spring Framerwork. As a view technology I use integrated with the framework Freemarker. Problems occur when java bean that stores data for vizualization have a null in some fields. There is no null conception in Freemarker so it considers that there is no these fields in the bean at all. I suppose problem could be solved by customization of class that copies data from the java bean to freemarker's hash object referred in template. But i haven't found what class does it in Spring. Is there such class and how is it called?
Usually you just deal with nulls directly in the template. E.g:
${person.surname!"n/a"}
which will print "n/a" in case of a null surname, or just:
${person.surname!}
which will print out the empty string (nothing) in case of a null surname.
You can use the "!" operator. Here is an example :
${your_property!""}
It will print the empty string "" if your_property is null.
If any part in your property chain can be null, you can also put parantheses around it to guard against any part being null. E.g. if you pu
${person.car.door.color!"<no value"}
you only guard against the color being null. But if it could also happen that the door, the car or the whole person is gone missing, you have to put
${(person.car.door.color)!"<no value"}

How to get the selected value of combo in Spring MVC 3?

I am using the Spring MVC <form:select> tag in my JSP and have populated the values in it.
How can I retrieve the selected value from the select box and use it for further operations?
You can obtain them in the controller to which you submit. For example:
#RequestMapping("/submit")
public String handle(#RequestParam Foo selectedFoo) {
}
This assumes you have a converter from String to Foo. Otherwise you can simply use String as argument.
If you want to get the whole form submitted to a javabean, make a bean with fields named exactly the same as the fields in your html form, and pass it as argument to the handling method.
I think this tutorial will help you:
http://www.mkyong.com/spring-mvc/spring-mvc-dropdown-box-example/
Spring MVC 3 example:
http://www.roseindia.net/tutorial/spring/spring3/web/spring-3-mvc-form-example.html
Just combine the logic from these 2 examples and you will understand hoe to do it right.

Resources