Skip to main content

Java Validation standard JSR-303

Every application needs to do some validation, and it varies from simple checking on values to complex business rules, like verifying if the user bill has been paid and payment received before we are able to call the print bill API.

 So the java people have created a standard for us under the number JSR-303 that creates a pretty nice way to validate our entities. javax.validatio, inside the validation-api.jar, is the API package for this standard.

The most popular implementation for that API is Hibernate-validator gradle dependencies : compile 'org.hibernate:hibernate-validator:5.0.1.Final'




What mainly is in the validation-api jar are the constraints and the generic interface ConstraintValidator, these are what I'm going to work with here.

there are two methods in this interface the one that does the work is the isValid method, this what will be called, and this what we need to implement  if we need a custom validation rule.

the standard rules are the following :
AssertFalse, AssertTrue, DecimalMax, DecimalMin, Digits, Future, Max, Min, NotNull, Null, Past,
Pattern, Size.

and they are used like this

class MyClass {

@NotNull
private String id;

}

this is the simplest way of using the validation API, you dont have to do more, just put the hibernate validator in the class path, and instantiate your validator and use it, see this very basic example :
[ it's important that you understand the very basics about validation to continue]
http://hibernate.org/validator/documentation/getting-started/

but in most cases we need to tweak things a bit for our business needs. and what we need more is also integrating this to be an autonomous process, and not call validator in every method, unless there is an explicit need for that.

so the way to do that is by using aspects, and the way I like it is on business logic APIs, but it is up to you to choose where you need to put that and I'll explain two ways, but first let's delegate the validator instantiation to the Spring framework

Spring supports the hibernate validator out of the box (the spring jar for this is spring-context.jar)

in our container configuration we add the following:


this will handle creating the validator instance for us.
the messageSource( ) is my custom messages source for i18n purposes, but it's not required by every one since hibernate validator already provide default messages, you can check them out here:

anyway let's proceed with the two possible locations where we can use the validation

1- If we are using Spring dispatcher servlet, we can out of the box put validation on our Rest/MVC controllers

2- On the business logic beans api.



General preparation:

now we add the validation rules to the user entity:


This what you will think at first will be enough, but actually there are couple of problems in this approach..

You see, now the business objects like the User object is no longer a dummy object just to hold data, it has business logic and that logic is in the validation annotations..it's now part of the API itself so we should use it that way and the best way I found to do that is to create a Business object for each call..

 otherwise, there may be conflicts in validation rules, like in the update method we don't want to validate the password again, it shouldn't be in the user object in the first place, another thing is that we may add another field : passwordConfirmation and validate that it match the password field.

so to correctly place our logic, I prefer to create a Business object for different APIs, example for create API:


and for the update API BO :


this is better, each API has it's own validation rule and does one thing, and does it right.
it's not repetition as it may seem, these are totally different APIs and each has it's own work, but it all comes down to your business logic.

To implement the rule that the password and passwordConfirmation should be the same, we should do that with custom validation annotation.




and the validator :



and based on this our BO :



Note that the last rule is put on the validated class instead of the field and the constraint validator takes Object as the class parameter.


Now regarding where to tell Spring to validate an object or not:


Option #1 - validate on web tier

Spring people like everything to be done on the controller level and they have their reasons and I can think one reason like:

what to do if business services call each other, should we validate or assume we are working with validated data?

Assume our controller will look like this without validation:



Reminder: make sure you provide the validator( ) bean with the same name, don't change it to something like : beanValidator( ) since Spring won't be happy.

What we need to do to tell spring to validate the objects is to add @Valid annotation



Spring will throw MethodArgumentNotValidException [ this is a custom spring exception ] in case of invalid objects, you can handle this exception using @ExceptionHandler annotation, I'll do another blog about ExceptionHandling.

Option#2- Validation on BL


To validate on Business layer API we need use aspects, to do that we need to register a bean MethodValidationPostProcessor :










and to trigger the validation we need to do 2 things

1- add @Valid annotation to the method parameters
2- add @Validated to the class/interface we are calling


this will throw ConstraintViolationException [original exception by validation-api]

here is how I handle this and convert it into my custom object :



Notes:

Database validation

You can use the custom ConstraintValidator to communicate with spring beans, it will do that by default if you use validation on Controller layer, but in case of method validator [BL layer], make sure to register the beans correctly.

here is an example of my code using bean to validate object:


Rules Order can be defined by the annotation @GroupSequence



and that's all you can gracefully start using the validation-api JSR-303

Comments

  1. Thank you for this great article.

    I just have a problem with MethodValidationPostProcessor: if my Controller calls a bean annotated with @Transactional, the annotation is no longer handled and no transaction is created.

    It is an annoying side effect, do you have a work around ?

    Thanks !

    ReplyDelete

Post a Comment

Popular posts from this blog

Android RecyclerView - Adding Empty View

So RecyclerView was introduced to replace List view and it's optimized to reuse existing views and so it's faster and more efficient as stated in the documentation:

https://developer.android.com/training/material/lists-cards.html

While using it, I faced the issue of missing a useful functionality that is implemented in ListView.
that feature is setting an empty view in case there was no records.

In ListView it was as simple as this

View emptyView = findViewById(R.id.mylist_empty_view);
ListView  myList = ....
myList.setEmptyView(emptyView);

but this method doesn't exist for recycler view so we need a work around until android team fixes this.


and here are the screen shots of both list view and recycler view fix

List view :

Recycler view :



here is how I fixed it:



here is the content of empty_view, it can be anything.



Enjoy.

Android - Multiple themes for one application

Sometimes you want to have multiple themes for your app
one strong example is having the ability to switch between dark and light themes because during night, a white bright screen can really be annoying for users eyes

Android will do most of the work for you but it may be required to change icons between themes to fit colors
In this blog I'll show a simple app with both dark and light themes and how to change icons without having to do that from code and keep things clean and centralized.
first of all let's create our activity, it will look something like this :


In /rest/values/styles.xml, we inherit Theme.AppCompat
 <!--
        Base application theme, dependent on API level. This theme is replaced
        by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
    -->
    <style name="AppBaseTheme" parent="Theme.AppCompat">
        <!--
            Theme customizations available in newer API levels can go in
            res/values…

Creating your own OAuth2 server and clients using spring security - part 1

In this series of posts, I'll try to put together a simple working example on how to create your own OAuth2 server.

if you want to know more on OAuth2 and when to use it as authentication and authorization protocol then you can search about it on google and i'll put some URLs later.

Now I assume you are familiar with java web applications using Spring and maven.

to get started we need to create the server side with all dependencies required and i'll list them here, i'll use maven 2 to ease downloading dependencies for us.


Steps:

1- Create new maven project with arch type webapp:



2- Add the required depenedencies for spring, spring security, spring-oauth2, hibernate & other libraries (required for this tutorial only you can use other libraries if you like)

https://gist.github.com/anonymous/d33a31ddc3ba84375cf3

3- I used hibernate to automate the creation of the schema required by spring OAuth2 to manage tokens (it's required to have schema created in db if you a…