BVARecommendations

mariok edited this page Sep 20, 2012 · 2 revisions

In the following we want to introduce and discuss some recommendations from project experiences and best practices and give a few samples on how to make use of the BVA possibilities in a Java project.

Table of Contents

Principles

Write once use multiple

- The Single Source principle -

Early Validation

  • Use different validation rules for different tasks.
  • Give user early feedback to improve usability

Integrate everything with build

- under construction -

Usage Scenarios

Programmatic call of a Validator

This is the simples use of the Bean Validation API: in the application each time you want to validate some objects you retrieve a Validator from its factory and call the validate() Method to validate the objects you pass.

Sample:

 ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
 Validator validator = factory.getValidator();
 Set<ConstraintViolation<Object>> constraintViolations = validator.validateValue(myObject);

Disadvantage: You are validating "ad hoc" and can never assume, that validation is done in all caes you want the application to do it.


Java Server Faces

In JSF 2.0 Bean Validation is used by a SPI without a configuration. This means, if JSF finds any JSR-303 implementation in the classpath of the container, is is used to validate input.

This works for input fields which are connected to bean properties with BVA annotations (not for user defined data types, which have to be connected by the means of JSF Converters).

Use the f:validateBean tag to define validation groups.


EJB 3.0

Validierung durch einen Interceptor

 @Stateless
 @Local(SomeService.class)
 @Interceptors({SomeValidationInterceptor.class})
 public class SomeServiceImpl implements ISomeService {
    ...
 }

Java Persistence API and Hibernate

Hibernate provides its own implementation of the Bean Validation API, called "Hibernate Validator", which is the reference implementation of the JSR-303.

To use validation in the persistence lawer, some listeners pre-persist, pre-remove and pre-update are registered performing a validation check in advance of a database operation.

Sample:

 @Entity
 @EntityListeners(class=SomeValidator.class)
 public class User {
     @Id 
     private Integer id;
     private String name;
     ...

See:


Web Services

- under construction


Spring and BVA

The Spring Framework makes use of BVA in various ways:

  • Use aspects to use BVA validations with Spring Services. The aspect performs a validation and is configured that it is called before and after the execution of a service method.
  • Spring 3 supports the JSR-303 and provides its own validation factory for validators that can even parse the Spring Expression Language.
See:

Data Binding in UI Design

To complete seamless use of BVA in our application we made integrate a validator into the data binding of our framework.

To realize a binding of gui elements like input fields to the properties of a domain object we use a set of connectors. These are implemented as bidirectional listeners between our model and the ui control:

  • listening on user input to update the domain when typing
  • listening to property changes of the domain objects to update the gui
In addition the panel in which contains the control holds a reference to dhe domain object and manages all required references to update the view when the user passes a new domain object to the panel in order to display the new content.

The illustration shows the collaboration of the involved classes.

A simple example shows how simple it is to bind a text field to a String attribute of a domain class:

     /** Construction */
     public UserPanel() {
         // initialize the GUI here
         ...
     }
  
     /** initialize connectors etc. */
     public void onInit() {
         super.onInit();
         addConnector(new StringConnector(field, getDomain(), "name");
     }
 }

The following sequence diagram gives some more details:

The sequence diagram explains the different interaction steps:

  1. Construction of the connector. The connector registers itself as focus listener of the text field and as property change istener of the domain object
  2. The users edits the contents of the text field. On "focus lost" the connector is called, which reads the entered text and passes it to the setter mthod of the domain object.
  3. The value of the property in the domain object is changed. The connector reads the value and passes its string representation to the text field to display the new value.
  4. Finally the user replaces the displayed domain object in the panel by calling its setDomain() method. The connector stops listening to the old domain property changes and registers to the property of the new domain object.
In addition the Connectors are designed as type converter. For example, if you consider to display and/or edit a Date property in a text field you will need to parse/format the String/Date to update the domain/field.

Implementations for the basic types like Date, Float, Integer, Short, Double, BigDecimal are provided. The used parser is the most important validator here: if you entered some text that can't be parsed to the valid destination class, the domain object's property can not be updated.

To allow users to interact on validation exceptions the application can become some validation listener of the connectors. So the connector broadcasts a validation violation event to the listener e.g. when you type the word "yesterday" as a date.

Now we want to use our annotations. These can be read by an "external validator" we can add to our connector, which is able to read the annotations for the property in the domain class and validates the entered contents of the ui control against these rules, sending violation messages to the registered listeners.

Links and References

  • "Türsteher für Bohnen", Bean Validation mit domänenspezifischen Typen in der Praxis von Oliver Ochs und Simon Zambrovsky, Java Magazin 4/2011
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Press h to open a hovercard with more details.