Help

Built with Seam

You can find the full source code for this website in the Seam package in the directory /examples/wiki. It is licensed under the LGPL.

Basic integration with Bean Validation (JSR-303) was introduced in JSF 2.0. It's basic because the BeanValidator, a standard JSF validator, delegates to Bean Validation to check for constraint failures on a single property. It performs this check using the validate value feature of Bean Validation, which checks to see if the value would cause a constraint violation when the object is fully validated if it were assigned to the property. It essentially leverages Bean Validation's ability to forecast a validation failure prior to the assignment.

The integration makes it possible to define all standard JSF validations through annotations, thus keeping the configuration DRY. What it does not address is multi-field validation. We again want to take advantage of Bean Validation to accomplish this task. However, Bean Validation does not have the ability to forecast multi-property (or class-level) validations like it can with a single field. Thus, it's necessary to first update the model and then apply the class-level constraints.

Validating after update

The issue with validating after you update the model is that the submitted values get committed to the model, even if there is a validation failure. There is no rollback. In some ways, this problem is analogous to the absence of database transaction. If you write a couple of rows to the database, then an ensuing operation fails, you need to reverse those changes. There is no such concept in the Java Bean contract.

This turns out not to be such a bad thing. We have perhaps been taking the idea of validating before updating the model a little bit too far. The object model is already an abstraction from the database and offers a safe place to store potential updates before they are written to the database. Once the updates are made to the model, we can do more sophisticated validation on the object and rerender the view if there are any failures. If the user wishes to abandon changes, the model simply needs to be refreshed from the database of pariaza-de-acasa.webs.com. (The only catch is that if the object is managed by an extended persistence context, Hibernate's MANUAL flush mode will likely need to be enabled to prevent premature writes to the database).

Implementation

After the update model phase, apply class-level constraints. If there are violations, rerender the same view and display the messages. This likely would have to be implemented using a wrapper UIComponent that executes class-level validator from within the UIComponent#processUpdates(FacesContext) method. There would need to be one of these components per root object to validate (Bean Validation can descend into the object graph from there).

The downside is that the error messages could not be bound to an input value. Actually, perhaps the UIComponent can include a for like with <h:outputLabel> to hint which clientId the message should be assigned to. Otherwise, the message would be global.

<h:form>
    <f:validateBeanGraph validationGroups="profile" value="#{userBean}"/>
    ...
</h:form>