Moments of validation
Bean-Validation (Validation via Annotations, JSR 303) happens in two different phases of the JSF-Lifecycle:
In the PROCESS_VALIDATIONS
-Phase
- Trivial validators like
@Size(max = 1024)
or@NotNull
get invoked in this Phase. If the validation fails, you can't get one Phase further.
In the INVOKE_APPLICATION
-Phase
- In this phase trivial validators get invoked a second time. But also more complex validators (see Cross field validation-Post) get executed in this phase. These validators cannot run earlier, because they require
UPDATE_MODEL_VALUES
-Phase.
Problem
When working on complex forms it is annoying to have two (or with client-side validation) three moments of validation. If you add
<context-param>
<param-name>javax.faces.validator.DISABLE_DEFAULT_BEAN_VALIDATOR</param-name>
<param-value>true</param-value>
</context-param>
to your web.xml
, you can skip the first validation-phase in order to validate everything on INVOKE_APPLICATION
. But now there happens something terrible:
JSF looses the connection between the UI-component and the properties referenced in the facelets. So if the validation for <p:inputText value="#{myBean.entity.price}"/>
fails, JSF does not know anymore, that the attribute price
of the object entity
located in the @Named MyBean
. A message get's displayed, that something failed, but the user does not get a hint of the invalid field.
Approaches
The first approach was to implement a PhaseListener which invokes
visitTree
-Method ofFaces.getViewRoot()
. In the given callback I iterate over all components and try to map all validation-messages to the specified UIComponent. This approach is error-prone: I need a convention for ids of the components in the facelet. This also not works for composite-components without an extra class which maps Strings to component-IDs. That sucks!Another approach is to save the relation UIComponent <-> Target Property at the moment, the values get assigned. This happens in
UPDATE_MODEL_VALUES
. So I do not have to guess the UIComponents any more.
Questions
Do you have any idea of how to do this? I have no idea, if this approach is realistic and could be successful.
Previous Post
I have an application which runs with a webapp (JSF), a Rest-API and (perhaps) a JavaFX-app. That's the reason why I prefer bean validation over view-based JSF-validation to keep the code dry.
So I skip the validation-phase and throw validation exceptions after updateModels-phase.
This works very well so far, but I have trouble to dye the input-fields after a failed validation. (btw. is "to dye" the right Englisch word for "making input-fields red"?) At the moment I use a convention for naming my ids and a mapper who maps the invalid object-fields to the ids of the input-fields.
This is kind of messy and I would like to clean this up.