AdSense Mobile Ad

Showing posts with label validation. Show all posts
Showing posts with label validation. Show all posts

Sunday, April 11, 2010

JSR 303 - Overview, part 3

Table of contents:
Introduction

The JSR 303 API

The JSR 303 API is made of the following functional subsets:
  • The bootstrap SPI
  • The validator API (which itself is made up the client API and the validation routine)
  • Important helper classes and interfaces used during the validation process such as the ConstraintViolation class and the message interpolators.
  • The constraint metadata request API

The API a JSR 303 will be most interested in is probably the validation API, which is the API used to trigger the validation process.

The bootstrap process: how to obtain a Validator

During the bootstrap process the service provider which implements the JSR 303 is discovered, configured and initialized. I won't cover the details of the bootstrapping API and if you're interested, you can check the specification. From an user standpoint, this API is important because it's the entry point to the validation API. After discovering and configuring all the available providers, you'll use the Validation class to obtain an instance of a ValidatorFactory.

ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();

The validator API

The validator API defines a series of interfaces which let an user programmatically trigger the validation process on a bean of a given class. The Validator interfaces is the following:

public interface Validator {
  <T> Set<ConstraintViolation<T>> validate(T object, Class<?>... groups);
  <T> Set<ConstraintViolation<T>> validateProperty(T object, String propertyName, Class<?>... groups);
  <T> Set<ConstraintViolation<T>> validateValue(Class<T> beanType, String propertyName, Object value, Class<?>... groups);
  BeanDescriptor getConstraintsForClass(Class<?> clazz);
}

The first three methods of this interfaces trigger the validation process on an object of type T whose logic was described in Part 2. While the first method triggers the complete validation process, the other two methods can be used to validate just a property. The third is a convenience methods which trigger the validation of a bean's property if its value were the object passed as parameter. This way you'll be able to validate a property beforehand and, most importantly, without triggering any side effect of the property change or in the case the property were read only.

No matter which validate method you choose it will return a set of contraint violations for the type T. A constraint violation is a type which is part of the JSR 303 API whose purpose is describing the errors found during the validation process. Such a type will be described later on.

The last method of the Validator interface is used to retrieve a BeanDescriptor, which is a structure which describes the constraints applied to a specific class' instances. You usually won't use this method in your daily life with a JSR 303 implementation unless you are building sophisticated logic which has to rely to such information at runtime.

Also, you won't be using the validator API directly when using API which can automatically validate beans. Such APIs are, for example, JPA and JSF with CDI beans and those are the use cases I'll be focusing on.

Defining a constraint

To define a constraint the first thing you need to do is defining the constraint annotation you're going to use. For example, let's define an annotation to validate a String instance representing an email address.

package es.reacts.validators;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.validation.Constraint;
import javax.validation.Payload;

/**
 *
 * @author http://thegreyblog.blogspot.com/
 */
@Documented
@Constraint(validatedBy = EmailValidator.class)
@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface EmailAddress {

    String message() default "{email.invalid}";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};
}

It's important to note the following:
  • The @Constraint annotation is used to declare that the following annotation will be used as a constraint annotation. The validatedBy attribute of the @Constraint annotation is used to declare the class of the associated constraint validator, in this case the class EmailValidator.
  • The standard @Target annotation is used to indicate which kind of element type this annotation will be used with. A JSR 303 compliant implementation will let you define and use constraint for the FIELD, METHOD and TYPE element types. In this example an email address is represented by a String instance so that TYPE is not specified in the constraint definition. If we were to define a class to represent an email address, we could define a constraint and a validator to annotate our class.
  • The required RUNTIME @Retention policy is necessary so that the JSR 303 implementation be able to read validation metadata at runtime.
  • The message() element is used to return a message in case of a validation error. The JSR 303 supports a flexible mechanism to define messages and this example uses the standard "{...}" notation to internationalize our messages in a properties resource bundle.

Defining a constraint validator

Constraint validators are instances of the ConstraintValidator<T, V> class, being T the type of the constraint and V the type of the validated objects. In this case, T is EmailAddress and V is String so that the skeleton of our validator will be:

package es.reacts.validators;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

/**
 *
 * @author http://thegreyblog.blogspot.com/
 */
public class EmailValidator implements ConstraintValidator<EmailAddress, String> {

    public void initialize(EmailAddress constraintAnnotation) {
    
    }

    public boolean isValid(String value, ConstraintValidatorContext context) {

    }
}

The initialize method is used to initialize the validator during the validation process: if you're defining attributes in your constraint, the initialize method body will scan the constraint passed as a parameter and save it in its state. The isValid method will validate the current object. Since our @EmailAddress constraint contains no attributes, the validator will only need to implement the validation logic in the isValid method and, for the sake of the current example, we'll use a standard regular expression to check if the current String instance represents a valid email address:

package es.reacts.validators;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

/**
 *
 * @author http://thegreyblog.blogspot.com/
 */
public class EmailValidator implements ConstraintValidator<EmailAddress, String> {

  private static final Pattern emailPattern = Pattern.compile("[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?");

    public void initialize(EmailAddress constraintAnnotation) {
    
    }

    public boolean isValid(String value, ConstraintValidatorContext context) {
        if (value == null) {
            return true;
        }

        Matcher match = emailPattern.matcher(value.toLowerCase());

        return match.matches();
    }
}

Since Pattern instances are thread-safe, our EmailValidator will take advantage of it by caching the regular expression used to validate email addresses. The isValid method simply checks that the String instance is not null (in which case the email address is considered to be valid, as suggested by the JSR 303 spec), and uses a Matcher instance to match it against our pattern.

Although a bit primitive, this is a sound constraint validator and you can take advantage of it immediately by annotating the fields of your beans. In my case, for example, I'm using it in a JPA entity and in a CDI bean which backs a JSF page in which users are submitting their email address. Without additional code, I'm taking advantage of JSF, JPA and JSR-303 to enforce a validation policy on both the web channel and the persistence layer of my Java EE 6 application.









Saturday, September 5, 2009

JSR 303 - Overview, part 2

Table of contents:
Introduction
In the previous post, I began introducing the concepts defined in the JSR 303 (Bean validation) specification. The first concept we dealt with was the concept of constraint. The constraint represent the validation rule you want to apply to the target of your validation process, be it a field, a method or an entire class. This post is an overview of the validation API and a brief description of the validation process you can trigger on a JavaBean of your own. The understanding of the validation routine is necessary to avoid common pitfalls when defining and applying constraint to a class or a class' fields.

A word of warning: JSR 303 API is not yet committed and might change in a future revision of the specification. At the moment, the JSR 303 is in the public draft review state.

The validation process (in a nutshell)

The validation process is always started on a bean instance and may be instructed to recursively validate the objects in the object graph starting from such bean. Although the validator API also provides methods to validate only a given field or property of the target bean (for fine grained validation process, such as it might be the case for a partially populated bean) the validation routine described here will be partially honored for such methods, too.

The validation routine performs the following tasks, for the applying groups to be validated:
  • perform all field-level constraints' validations
  • perform all method-level constraints' validations
  • perform class-level constraints' validations
  • perform cascade validations

The validation routine is a deterministic routine which also checks the following:
  • the validation routine will avoid infinite loops, keeping track of the validated object instances in the current validation process
  • the validation routine won't execute the same validation more than once for the same validation constraint, keeping track if it matched on a previous group match.

The constraint validations matching the current groups being validated are run with no deterministic order.

Constraints semantics and constraint validator visibility

The algorithm implemented by the validation routine is pretty intuitive: it starts from inside the bean and goes to the outside. First, fields are validated, then properties, then the entire bean. The first thing to grasp is what a constraint really represent, that is something you must be aware of when designing your constraints and your validation strategy.

The constraint may be thought of as a validation rule applied to an object. The context in which the constraint is applied (the root object's type) is part of the validation rules' semantics:
  • If you apply a constraint to an object's field or property, you're applying a validation rule to that field (as part of a type), but the validation routine visibility is limited to only that object. You cannot access values of other fields of your object during the validation of the fields' constraints.
  • If you apply a constraint to a type, the validation routine visibility will be able to apply class' invariants (if you've got any) and any other validation rule whose parameters may be whichever part (be it field or property) that make up your type.

Basically, you'll use field-level (resp: property-level) constraints when you want to apply the validation rule to that field (resp.: property) as part of a type. For example, a String id field may be length-bounded when part of a type, such as a Passport (A String isn't length-bounded by definition).


You'll use class-level constraints when you want to apply a validation rule to the state of a type as a whole. For example, if you define a Passport type you would apply a class level constraint to check that the id-field is coherent with the Country field.


That's why the validation routine starts from inside the bean and proceeds outwards: you would not apply validation rules to an entire class instance state if some of the class' fields were invalid.


Constraint design principles and a constraint domain

The validation routine definition and the constraints semantics outlined in the previous section have got an effect, which is visible in the way these concepts have been defined. As we saw, whether to apply a constraint to a class or to a field depends on the semantics of the constraint you defined. But a class' fields are class' instances themselves. Let's suppose we're validation a bean of class X which defines a field of type Y.

public class X {
  private Y y;
  [...]
}

Moreover, let's suppose you designed class Y as an helper class for X and that Y is seldom visible, or visible at all, in your API. When validating such type you might be tempted to apply validation rules to Y instances as field level validations in class X. The constraint validation would indeed be passed Y instance and you could get access to all of Y's fields and properties, if you needed them. Furthermore, you could argue that this way you could validate both X and Y instances in just one validation pass. Yes, but that could be a huge design flaw if the constraints you're applying in the "X context" were in reality validation rules of class Y whose scope is not restricted to the "Y as a field of X" use case.

The question you've got to answer, during the definition of every constraint you design, is the following:

What is this constraint's domain?

If you establish an analogy with a constraint validators and a set of mathematical operators, you should be asking yourself:

What is the domain of this operator?

The answer to this question will suggest you the correct way to define and apply your constraint. If the answer is "The domain of the constraint is the entire type Y" (and you own type Y), you would define constraints accordingly and apply them to type Y (and its fields, if necessary). If the answer is "The domain of the constraint is field y of type X" you would define the constraints accordingly and you'll apply them to X.id.

Obviously reality might be more complicated than this and you might, for example:
  • discover that you need both a set of constraints for the Y domain and another set for X.id domain.
  • need constraints for the Y type but it's not yours.
In the first case you would act accordingly to achieve the correct isolation of the two distinct domains while in the second case you could extend, if possible, type Y or wrap it in another type of yours.

This leads us directly to why the validation routine must execute cascading validations.

Cascading validations

Cascading validations are the means you need to cleanly implement constraints such as:

Type X is subject to the following validation rules [...] and its field y is valid in the Y domain.

To model such situation you would apply the @Valid annotation to the X.y field:

public class X {
  @Valid
  private Y y;
  [...]
}

When encountering such annotation during the validation of an X instance, the validation routine will also apply the constraint validators applied to Y in the Y domain. In other words, the validation routine would go down the object graph recursively reapplying itself to everyone of such fields (resp: properties).

What's next

In the next post I'll introduce the least (but not last) few missing concepts and then we'll start building some examples.

Thursday, September 3, 2009

JSR 303 - Overview, part 1

What was before the JSR 303?

Well, as you probably know, before the JCP promoted this specification, very little could be done and you probably ended up using non-standard validation frameworks and/or tier-specific validation frameworks (such as Spring Validator, just to make an example). Things could go even worse: you probably ended up writing your own implementation solution.

The only standard approach I can think of is the venerable (and neglected) JavaBeans specification. I won't dig into the specification details, but JavaBeans are not just classes with some getters and setters. That's just the beginning. The JavaBeans specification, although nowadays that solution might seem clumsy, would support validations in the form of event listeners processing property change events. The mechanism is powerful but won't really fit the simplest use cases, which probably are the great majority we're dealing with everyday. The JavaBeans specification was tailored to provide a object component framework, such as Microsoft's COM could be. That's why events and listeners find their place there. But in the case of your-everyday-class, I recognize there's too much boilerplate code in it. Moreover, JavaBeans' events and listeners aren't declaratively configurable and, once more, the pitfall would be building your own configuration mechanism: ending up with your own non-standard solution, once more.

The basic concept: the constraint

The JSR 303 specification introduces the concept of constraint. The beauty of a constraint is that it's a metadata which can be applied declaratively to types, methods and fields. The constraint is a simple and intuitive concept which defines:
  • How you would apply an instance of the constraint to a target. In other words, its interface.
  • Who's going to implement the validation algorithm associated to that constraint.
I'm going to make the most basic example: validating a String length. The constraint would use two configuration parameters representing the minimum and the maximum length of the string. If one of the parameters would be left unspecified it would take its default value, such as 0 for the lower bound and infinite for its upper bound. The metadata you would need to apply to a field subject to this validation rule would thus be:
  • the constraint itself, let's call it Size
  • the constraint configuration parameters: min and max.
How would your class end up? Something like:

public class YourClass {
  @Size(min=1,max=9)
  private String yourField;
...
}

Of course the specification gives us the means to inject this kind of metadata without applying annotations. Somewhere in the definition of the Size constraint there would be the link with the class which actually implements the (really basic) validation algorithm. This is one of the indirection levels formalized in the specification: the validation algorithm cleanly separates the general validation process and introduces hooks, in the same definition of a constraint, where the constraint specific algorithm would be invoked. The general validation process, for example, takes into account the objects' graph navigation and the API to discover and describe the constraints applied to a target (the constraint metadata request API).

The responsibility of the analyst programmer would then be:
  • Define his own constraints.
  • Implement his own constraints.
  • Apply constraints to validation targets.
  • Trigger the validation process when needed.


All of the validation API has been designed with simplicity and reusability in mind. As far as I've seen this API is JavaBeans-based and does not establish a dependence with any other API. Furthermore this API is not obtrusive: you can define, declare and use constraints in every tier of your Java EE application, from the EJB up, up to the JSF components and the managed beans. The validation metadata and the validation process are (finally) orthogonal to the logic of your application: the design and the implementation of a Java EE system-wide validation policy for your objects' is finally feasible and standardized.

What's next

In the next post we'll dig into the technical details of what a constraint is and how you can define and use your own.

Saturday, August 29, 2009

JSR 303 - A standard bean validation API for the Java Platform

JSR 303 (Bean validation) is making its way into being approved by the Java Community Process. The goal of this series of post is to give you a quick introduction about this specification.

What is the problem with validations?

This specification, citing the official JSR 303 Request, tries to solve a common problem. Validations are commons steps executed during the business logic of the application, although often the validations algorithm are a characteristic of the data structure being validated, rather than the bussiness logic flow they're executed within. That's why validations aren't tier dependent operations and validation algorithms might span almost all of the tiers into your system, from the front end down to the backend. Reimplementing or redistributing the same validation classes to all of the applications layers and components is error prone and adds a complexity you must deal with. Bundling validation into the data structure being validated, on the other side, generate couplings and clutters the affected types with algorithms and structures which are not part of the class. 

How does this specification solve this problem?

This specification tries to solve this problem recognizing the fundamental flaw we often encounter in validation implementations inside enterprise applications:
  • The process of validating data is part of the business logic of an application.
  • The logic executed during the validation process might not be part of the business logic. Rather, it's a characteristic of the data structure itself.
  • Hence, validations should be considered metadata of a class and...
  • ... validations should be orthogonal to both business logic and tiers in the applications.
  • Validation logic may change over time.
  • Being an API specification, validation frameworks should be pluggable and interchangeable.

The solution boils down to recognizing that validation is a process that must be driven by class metadata. By providing a sufficiently flexible metadata model and a validation API, the specification defines how to associate validation metadata to a class either by using Java annotations or XML descriptors. 

The proposed solution only leverages the JavaBeans object model: therefore, it can be used in whichever application tier without being tied to a specific programming model. Furthermore, this API is suitable to be used as a component of other APIs thus enabling JSR 303 bean validation into, for example, the persistence layer (with JPA), the bussines layer (with EJBs), and so forth.

Why do you need this spec?

I would restate this with a more general question: do you need specs? This blog post isn't about why standards (and specs) are good. While designing and implementing there aren't just standards and specs. There are algorithms (your business logic is not a standard, it's just as unique as your fingerprint), patterns, best practices and unique application requirements. There's common sense, too (sometimes). The value of standards and specs is the value of having a standard solution to a well stated class of problems. If it fits your requirements, it's generally good: someone else, probably more skilled than you in that particular field, would have produced an implementation you can just take and use.

Being the JSR 303 a service provider standard (also) sort of guarantees you that you may choose the implementation that works best for you and that integrates best with the environment you have. There won't only Hibernate Validator after this specification is approved. It's very likely you could choose between a bunch of implementations which, because of this spec's characteristics, will fit into the other frameworks and APIs you use, such as EJB, JPA, JSF, Bean Bindings, put-your-favorite-here. Indeed, the JSR 303 will be required by JSR 316: the upcoming Java Enterprise Edition version 6.

The lack of a standard validation API, or even well established validation patterns, had as an effect that many application reinvented a validation framework: this process usually starts providing a solution to the first identified requirements, which seem too few or simple to require another validation framework, and then, as development proceeds, starts to grow according to the new requirements. There you ends with your own validation framework which, I bet most of the case, will not be a state-of-the-art, encapsulated and reusable solution. If the validation framework isn't carefully designed, you usually end up polluting your application layers and even pollution your class definition, to avoid the deployment problems cited above.

One thing more about specifications

One thing more about specifications. Although we should, I think many of us Java architects and programmers don't usually dive into a specification. At most, we know that it exist and then rely on the capabilites of the framework-of-the-day. Either under pressure, or because of a lack in the design of our application, or because we're struggling to get the job done and Google seems the saviour, or simply because the human being is lazy, not only may we end up reinventing the wheel: we may end up copy-and-pasting the wheel.

That's the fundamental flaw.

Specifications are there because groups of experts recognized a problem (usually before we do), study it and provide a general solution to it. Either in form of APIs, programming models and sometimes with even more complex technological solutions (such as EJB containers). It's up to you, Java architects, analysts and programmers, recognize if your problems belongs to such a class, evaluate the viability of using a standard and evantually choosing an implementation. Also, don't be blind in the name of a specification. Solutions require a problem to exist and it might also be the case that your problem doesn't perfectly fit in and that a simpler solution will satisfy your requirements. It's up to you deciding if ignoring a standard solution is an advantage for the design and the overall cost of your application.

These are just examples and speculations but that's the kind of choice an architect must do. Nevertheless, as far as it concerns this specification, I'm pretty confident that its flexibility will make the JSR 303 a common guest in our Java enterprise applications.