Para versão em português, clique aqui.
Although the title emphasises the word validation, this article is actually about the JSF life cycle. That’s because I believe that one of the easiest ways to truly understand the life cycle is by making something we do all the time: validating user input.
In general, understanding the so called JSF Life Cycle is what sets apart junior developers, who mostly copy and paste everything they see in front of them, and the senior ones who are able to “wing it” when facing uncommon scenarios without compromising code quality.
Usually when I’m interviewing somebody who claims to have years of experience with JSF and seems to have no knowledge of the life cycle, I take it as a bad sign 🙂
If you ever read a book about JSF in your life, you have probably seen the image below:
This image shows all the phases in the life cycle. With respect to what we’re interested in for this article, three of them will be most useful to us: Process Validations, Update Model Values and Invoke Application.
Let’s suppose a hypothetical application where we register users. In it, we’re gonna ask the user for his name and age:
In order to “process” the form above we would probably need two artifacts: A Managed Bean to take requests and a entity object representing the Person being registered:
We’re then left with two main approaches to validate the “age” field:
- Inside the “save()” method in our Managed Bean class. (less recommended)
- Using a JSF Validator. (recommended)
I insisted on using the terms “less recommended” and “recommended” to emphasise that is not a crime to validate user input outside of the Process Validations phase. We are often faced with scenarios where the “happy path” is just not achievable. The crime would be doing it without any idea of what’s going on!
The explanation comes next.
Not Like This
The approach I classified as “less recommended” would be validating the “age” field inside our Managed Bean, in the logic contained by the “save()” method. When the user clicks “Submit”, the JSF life cycle kicks in and invokes the “save()” method right at the Invoke Application phase (note that this is AFTER the Process Validations phase):
To get a grasp of why this might be bad we need to understand what takes place in each of the JSF life cycle phases, and also keeping in mind that the Invoke Application phase happens after Process Validations and Update Model Values. To summarize it, it means that the “save()” method will only be invoked after the Person object already had its “age” property updated by the JSF life cycle:
Looking at the image above you probably noticed that by the time our “save()” method gets called, the JSF life cycle already set an inconsistent value in the “age” property of our domain class, the Person object. So is this a problem?
Yes, it might be. Since our domain classes most of the time are managed by JPA, invalid values like these might end up going to the database without us even realizing it. From my personal experience, I’ve come to the conclusion that such mistakes are more common when using “extended persistence contexts”, that is, JPA contexts that spans multiple request/response cycles. Nowadays this is more commonly done by using “conversation contexts”, like the ones in CDI or in the now deceased JBoss Seam.
Now we’re talking
Ideally we should validate our input using a JSF Validator. Notice that it doesn’t necessarily mean creating a separate class just for the validation logic, it does mean we have to trigger the validation at the right phase, Process Validations:
- We could create a validator class, annotated with @FacesValidator.
- Or create a validation method inside our Managed Bean class.
Like I said, the main thing to focus on is validating at the right phase no matter how that validation is made. There are still a couple different ways to validate input, for instance Bean Validation.
Hope you guys enjoyed it. Comments and questions can be left below. Till next time!