SeamFramework.orgCommunity Documentation
The Seam Validation module provides enhanced support for dependency injection services related to bean validation. This support falls into two areas:
Retrieval of
javax.validation.ValidatorFactory
and
javax.validation.Validator
via dependency
injection in non-Java EE environments
Dependency injection for constraint validators
As the Bean Validation API is part of Java EE 6 there is an out-of-the-box support for retrieving validator factories and validators instances via dependency injection in any Java EE 6 container.
The Seam Validation module provides the same service for non-Java EE
environments such as for instance stand-alone web containers. Just
annotate any field of type
javax.validation.ValidatorFactory
with
@Inject
to have the default validator factory
injected:
Example 75.1. Injection of default validator factory
package com.mycompany;
import javax.inject.Inject;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
public class MyBean {
@Inject
private ValidatorFactory validatorFactory;
public void doSomething() {
Validator validator = validatorFactory.getValidator();
//...
}
}
The injected factory is the default validator factory returned by
the Bean Validation bootstrapping mechanism. This factory can customized
with help of the configuration file
META-INF/validation.xml
. The Hibernate Validator
Reference Guide describes
in detail the available configuration options.
It is also possible to directly inject a validator created by the default validator factory:
Example 75.2. Injection of a validator from the default validator factory
package com.mycompany;
import java.util.Set;
import javax.inject.Inject;
import javax.validation.ConstraintViolation;
import javax.validation.Validator;
public class MyBean {
@Inject
private Validator validator;
public void doSomething(Foo bar) {
Set<ConstraintViolation<Foo>> constraintViolations = validator.validate(bar);
//...
}
}
The Seam Validation module provides support for dependency injection
within javax.validation.ConstraintValidator
implementations. This is very useful if you need to access other CDI beans
within you constraint validator such as business services etc. In order to
make use of dependency injection within a constraint validator
implementation it must be a valid bean type as described by the CDI
specification, in particular it must be defined within a bean deployment
archive.
Relying on dependency injection reduces portability of a validator implementation, i.e. it won't function properly without the Seam Validation module or a similar solution.
To make use of dependency injection in constraint validators you
have to configure
org.jboss.seam.validation.InjectingConstraintValidatorFactory
as the constraint validator factory to be used by the bean validation
provider. To do so create the file
META-INF/validation.xml
with the following
contents:
Example 75.3. Configuration of InjectingConstraintValidatorFactory in META-INF/validation.xml
<?xml version="1.0" encoding="UTF-8"?>
<validation-config
xmlns="http://jboss.org/xml/ns/javax/validation/configuration" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://jboss.org/xml/ns/javax/validation/configuration validation-configuration-1.0.xsd">
<constraint-validator-factory>
org.jboss.seam.validation.InjectingConstraintValidatorFactory
</constraint-validator-factory>
</validation-config>
Having configured the constraint validator factory you can inject
arbitrary CDI beans into you validator implementations. Listing Example 75.4, “Dependency injection within ConstraintValidator
implementation” shows a
ConstraintValidator
implementation for the
@Past
constraint which uses an injected time
service instead of relying on the JVM's current time to determine whether
a given date is in the past or not.
Example 75.4. Dependency injection within ConstraintValidator implementation
package com.mycompany;
import java.util.Date;
import javax.inject.Inject;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import javax.validation.constraints.Past;
import com.mycompany.services.TimeService;
public class CustomPastValidator implements ConstraintValidator<Past, Date>
{
@Inject
private TimeService timeService;
@Override
public void initialize(Past constraintAnnotation)
{
}
@Override
public boolean isValid(Date value, ConstraintValidatorContext context)
{
if (value == null)
{
return true;
}
return value.before(timeService.getCurrentTime());
}
}
If you want to redefine the constraint validators for built-in
constraints such as @Past
these validator
implementations have to be registered with a custom constraint mapping.
More information can be found in the Hibernate
Validator Reference Guide.