Difference between revisions of "Opentaps 2 Service Validation"

From Opentaps Wiki
Jump to navigationJump to search
(New page: There are currently two level of validations, one at the service level which validates the parameters given, and one at the persistence level. == General Concept == Validation at those l...)
 
m (Protected "Opentaps 2 Service Validation": Sysop page [edit=sysop:move=sysop])
 
(No difference)

Latest revision as of 14:50, 30 January 2012

There are currently two level of validations, one at the service level which validates the parameters given, and one at the persistence level.

General Concept

Validation at those levels is implemented using Bean Validation (JSR-303), which simply consist of annotations on a POJO's properties or accessors. There are numerous online articles to learn more about it, eg: http://java.dzone.com/articles/bean-validation-made-simple

Some validators are quite simple, like javax.validation.constraints.NotNull, and it is also very easy to define your own, like for example org.opentaps.validation.contraints.NotEmpty.

A Validator can also be set on a class itself when complex validation involving multiple properties is needed.

Validation on Entities

JPA supports Bean Validation internally so an entity which is annotated will only be persisted if it is valid.

Validation in the Services

Validation in the Services is done in a similar manner, the Input and Output objects are annotated and the service implementation is responsible for calling the validator.

For this the validation.api bundle defines a ValidationService which is provided by the validation.impl bundle which itself simply expose the implementation given by Geronimo.

A typical pattern in the service implementation can be seen in org.opentaps.notes.services.impl.CreateNoteServiceImpl and is basically:

 Set<ConstraintViolation<MyServiceInput>> inputViolations = validationService.getValidator().validate(input);
 if (inputViolations.size() > 0) {
   throw new ServiceValidationException("My service failed.", (Set) inputViolations);
 }
 
 try {
   // do something involving  persistence
   ...
 } catch (ConstraintViolationException e) {
   throw new ServiceValidationException("My service failed.", e);
 } catch (PersistenceException e) {
   throw new ServiceException("My service failed.", e);
 }
 
 // populate the output
 MyServiceOutput out = new MyServiceOutput();
 ...
 
 Set<ConstraintViolation<MyServiceOutput>> outputViolations = validationService.getValidator().validate(out);
 if (outputViolations.size() > 0) {
   throw new ServiceValidationException("My service failed.", (Set) outputViolations);
 }

Sending Validation Errors to the Client

As an example the Note rest service `org.opentaps.notes.rest.NoteResource` simply extends `org.opentaps.rest.ServerResource` which implements an exception handler that translates a `ServiceValidationException` into a JSON structure.

Part of the JSON response includes a `errorDetail` object which is an array of `ServiceValidationException.FieldError` which contains 3 fields:

  • field which is the field name in the service interface that was not valid
  • message which is the error message returned by the validator
  • value which was the value given that failed validation

The client can then read that response to present the errors to the user.