0

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 of Faces.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.

Nimantha
  • 6,405
  • 6
  • 28
  • 69
Rokko_11
  • 837
  • 2
  • 10
  • 24
  • what is 'bean validation' for you? Seems like you mean programmatic validation in a backing bean instead of declarative with e.g. annotations (JSR-303)? – Kukeltje Nov 10 '15 at 16:20
  • Your question is confusing. JSF has transparent support for Bean Validation (JSR303; `@NotNull` and friends) and it just runs gently during validations phase without messing up the JSF lifecycle. Nonetheless, collecting invalid input fields with the purpose to highlight them is already fleshed out several times before. Which one do you accept as dupe? http://stackoverflow.com/q/14452594, http://stackoverflow.com/q/13781928 and http://stackoverflow.com/a/33635193 – BalusC Nov 10 '15 at 18:01
  • As per your edit, the validation during invoke application is not performed by JSF but by JPA. You're asking the question from the wrong angle. Disabling all the validation in JSF side makes indeed no sense. Better reframe the question to eleborate about the technical problem you faced when validation is performed in JPA, so that one can simply answer it (or simply ask a new question, the current question has already an answer and I'm sure the answerer isn't happy that the answer in its current form makes no sense anymore considering the question in its current form). – BalusC Nov 30 '15 at 09:35

1 Answers1

0

If you don't want to use client side validators, then you can add in your backing bean set of booleans (1 per each field), set up it during validation, and use it for field style displaying:

<h:outputLabel id="cardNumLabel" for="cardnum" value="*#{msg.cardNumLabel}"  
    styleClass="#{registrationBean.cardNumberValid ? '' : 'error'}" />
<h:inputText id="cardnum" 
    value="#{registrationBean.cardNumber}" label="#{msg.cardNumLabel}" size="35"
    styleClass="#{registrationBean.cardNumberValid ? '' : 'error'}" />

Where error style is like

.error { color: #ed1c24; }
Vasil Lukach
  • 3,658
  • 3
  • 31
  • 40