[hibernate-dev] [Bean Validation] XML Configuration

Emmanuel Bernard emmanuel at hibernate.org
Sat Jan 31 01:50:30 EST 2009


The last big missing piece of the spec was the ability do configure  
Bean Validation via XML. An META-INF/validation.xml file can  
optionally be used for that:
  - choose the default provider
  - choose MessageInterpolator and the other integration point
  - list XML Mapping files
  - list provider specific properties

Here is an attempt to formalize that. Note that I did change the  
Configuration object a bit (see the API below (section 4.4.3) and its  
role in the bootstrap process. It is know responsible for parsing  
valiation.xml and merge metadata from the programmatic calls and from  
XML. You can also force BV to ignore validation.xml (especially useful  
for containers that want to parse such resources themselves).

Th proposal is still rough on the edges. Let me know what is confusing.




4.4.6. XML Configuration: META-INF/validation.xml

Unless explicitly ignored by calling  
Configuration.ignoreXMLConfiguration(), a ValidatorFactory takes into  
account the configuration available in META-INF/validation.xml. This  
configuration file is optional but can be used by application to  
refine some of the Bean Validation behavior.

Unless stated otherwise, XML based configuration settings are  
overridden by values explicitly set via the Configuration API. For  
example, the MessageInterpolator defined  
viaConfiguration.messageInterpolator(MessageInterpolator) has priority  
over the message-interpolator definition.

default-provider: represents the class name of the provider specific  
Configuration sub-interface. If defined, the provider suitable for  
this interface is used (unless a specific provider has been chosen via  
the programmatic approach).

message-interpolator: represents the fully qualified class name of the  
MessageInterpolator implementation. This implementation must have a  
public no-arg constructor. This element is optional.

traversable-resolver: represents the fully qualified class name of the  
TravedrsableResolver implementation. This implementation must have a  
public no-arg constructor. This element is optional.

constraint-validator-factory: represents the fully qualified class  
name of the ConstraintValidatorFactory implementation. This  
implementation must have a public no-arg constructor. This element is  
optional.

constraint-mapping: represents the resource path of an XML mapping  
file. More than one constraint-mapping element can be present.  
Mappings provided viaConfiguration.addMapping(InputString) are added  
to the list of mappings described via constraint-mapping.

property: represents a key/value pair property providing room to  
provider specific configuration. Vendors should use vendor namespaces  
for properties (e.g.,com.acme.validation.logging). Entries that make  
use of the namespace javax.validation and its subnamespaces must not  
be used for vendor-specific information. The namespacejavax.validation  
is reserved for use by this specification. Properties defined via  
Configuration.addProperty(String, String) are added to the properties  
defined via property. If a property with the same name are defined in  
both XML and via the programmatic API, the value provided via  
programmatic API has priority.

Example 4.23. META-INF/validation.xml file

<?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">
     <default-provider>com.acme.ACMEValidatorConfiguration</default- 
provider>
     <message-interpolator>com.acme.ACMEAwareMessageInterpolator</ 
message-interpolator>

     <constraint-mapping>META-INF/validation/order-constraints.xml</ 
constraint-mapping>
     <constraint-mapping>META-INF/validation/catalog-constraints.xml</ 
constraint-mapping>
     <constraint-mapping>META-INF/validation/customer-constraints.xml</ 
constraint-mapping>

     <property name="com.acme.validation.logging">WARN</property>
     <property name="com.acme.validation.safetyChecking">failOnError</ 
property>

</validation-config>
The XML schema is described in Section 7.2, “Configuration schema”.




7.2. Configuration schema

XML Configuration is set in META-INF/validation.xml. The file is  
optional. The XML schema followed by the configuration file is as  
followed.

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema attributeFormDefault="unqualified"
            elementFormDefault="qualified"
            targetNamespace="http://jboss.org/xml/ns/javax/validation/configuration 
"
            xmlns:xs="http://www.w3.org/2001/XMLSchema"
            version="1.0">
     <xs:element name="validation-config" type="validation-configType"/>
     <xs:complexType name="validation-configType">
         <xs:sequence>
             <xs:element type="xs:string" name="default-provider"  
minOccurs="0"/>
             <xs:element type="xs:string" name="message-interpolator"  
minOccurs="0"/>
             <xs:element type="xs:string" name="traversable-resolver"  
minOccurs="0"/>
             <xs:element type="xs:string" name="constraint-validator- 
factory" minOccurs="0"/>
             <xs:element type="xs:string" name="constraint-mapping"  
maxOccurs="unbounded" minOccurs="0"/>
             <xs:element type="propertyType" name="property"  
maxOccurs="unbounded" minOccurs="0"/>
         </xs:sequence>
     </xs:complexType>
     <xs:complexType name="propertyType">
         <xs:attribute name="name" use="required" type="xs:string"/>
     </xs:complexType>
</xs:schema>
See Section 4.4.6, “XML Configuration: META-INF/validation.xml” for  
more information on XML based configuration.




4.4.3. Configuration

Configuration collects configuration informations, determines the  
correct provider implementation and delegates it the ValidatorFactory  
creation. This class lets you define:

the message interpolator strategy instance

the traversable resolver strategy instance

the constraint validator factory instance

XML constraint mappings

provider specific properties

whether or not META-INF/validation.xml is considered.

A Configuration does provide a MessageInterpolator implementation  
following the default Bean Validation MessageInterpolator rules as  
defined in Section 4.3.1, “Default message interpolation” by calling  
getDefaultMessageInterpolator(). Such an implementation is useful to  
let a custom MessageInterpolator delegates to the standard  
MessageInterpolator(see Section 4.3.2, “Custom message interpolation”  
and an example making use of getDefaultMessageInterpolator() in  
Example 4.3, “Contextual container possible MessageInterpolator  
implementation”).

Clients call Configuration.buildValidatorFactory() to retrieve the  
initialized ValidatorFactory instance.

Example 4.12. Configuration interface

/**
  * Receives configuration information, selects the appropriate
  * Bean Validation provider and build the appropriate
  * ValidatorFactory.
  * <p/>
  * Usage:
  * <pre>
  * Configuration<?> configuration = //provided by one of the  
Validation bootstrap methods
  *     ValidatorFactory = configuration
  *         .messageInterpolator( new CustomMessageInterpolator() )
  *         .buildValidatorFactory();
  * </pre>
  * <p/>
  *
  * By default, the configuration information is retrieved from
  * META-INF/validation.xml
  * It is possible to override the configuration retrieved from the  
XML file
  * by using one or more of the Configuration methods.
  *
  * The ValidationProviderResolver is specified at Configuration time
  * (see {@link javax.validation.spi.ValidationProvider}).
  * If none is explicitely requested, the default  
ValidationProviderResolver is used.
  * <p/>
  * The provider is selected in the following way:
  * - if a specific Configuration subclass is requested  
programmatically using
  * Validation.byProvider(Class), find the first provider matching it
  * - if a specific Configuration subclass is defined in META-INF/ 
validation.xml,
  * find the first provider matching it
  * - otherwise, use the first provider returned by the  
ValidationProviderResolver
  * <p/>
  * Implementations are not meant to be thread-safe
  *
  * @author Emmanuel Bernard
  */
public interface Configuration<T extends Configuration<T>> {

     /**
      * Ignore data from the META-INF/validation.xml file if this
      * method is called.
      * This method is typically useful for containers that parse
      * META-INF/validation.xml themselves and pass the information
      * via the Configuration methods.
      */
     T ignoreXmlConfiguration();
     /**
      * Defines the message interpolator used. Has priority over the  
configuration
      * based message interpolator.
      *
      * @param interpolator message interpolator implementation.
      *
      * @return <code>this</code> following the chaining method pattern.
      */
     T messageInterpolator(MessageInterpolator interpolator);

     /**
      * Defines the traversable resolver used. Has priority over the  
configuration
      * based traversable resolver.
      *
      * @param resolver traversable resolver implementation.
      *
      * @return <code>this</code> following the chaining method pattern.
      */
     T traversableResolver(TraversableResolver resolver);

     /**
      * Defines the constraint validator factory. Has priority over  
the configuration
      * based constraint factory.
      *
      * @param constraintValidatorFactory constraint factory  
inmplementation.
      *
      * @return <code>this</code> following the chaining method pattern.
      */
     T constraintValidatorFactory(ConstraintValidatorFactory  
constraintValidatorFactory);

     /**
      * Add a stream describing constaint mapping in the Bean Validation
      * XML format.
      * <p/>
      * The stream should be closed by the client API after the
      * ValidatorFactory has been built. The Bean Validation provider
      * must not close the stream.
      *
      * @param stream XML mapping stream.
      *
      * @return <code>this</code> following the chaining method pattern.
      */
     T addMapping(InputStream stream);

     /**
      * Add a provider specific property. This property is equivalent to
      * XML Configuration properties.
      * If the underlying provider does not know how to handle the  
property,
      * it must silently ignore it.
      *
      * Note: Using this non type-safe method is generally not  
recommended.
      *
      * It is more appropriate to use, if available, the type-safe  
equivalent provided
      * by a specific provider in its Configuration subclass.
      * <code>ValidatorFactory factory =  
Validation.byProvider(ACMEConfiguration.class)
      *        .configure()
      *           .providerSpecificProperty(ACMEState.FAST)
      *           .buildValidatorFactory();
      * </code>
      * This method is typically used by containers parsing META-INF/ 
validation.xml
      * themselves and injecting the state to the Configuration object.
      *
      * If a property with a given name is defined both via this  
method and in the
      * XML configuration, the value set programmatically has priority.
      */
     T addProperty(String name, String value);

     /**
      * Return an implementation of the MessageInterpolator interface  
following the
      * default MessageInterpolator defined in the specification:
      *  - use the ValidationMessages resource bundle to load keys
      *  - use Locale.getDefault()
      *
      * @return default MessageInterpolator implementation compliant  
with the specification
      */
     MessageInterpolator getDefaultMessageInterpolator();

     /**
      * Build a ValidatorFactory implementation.
      *
      * @return ValidatorFactory
      */
     ValidatorFactory buildValidatorFactory();
}
A Bean Validation provider must define a sub interface of  
Configuration uniquely identifying the provider. The isSuitable()  
method of its ValidationProvider implementation must return true when  
this sub interface type is passed as a parameter, false otherwise. The  
Configuration sub interface typically hosts provider specific  
configuration methods.

To facilitate the use of provider specific configuration methods,  
Configuration uses generics: Configuration<T extends  
Configuration<T>> ; the generic return type T is returned by chaining  
methods. The provider specific sub interface must resolve the generic  
T as itself as shown in the following example.

Example 4.13. Example of provider specific Configuration sub interface

/**
  * Unique identifier of the ACME provider
  * also host some provider specific configuration methods
  */
public interface ACMEConfiguration
     extends Configuration<ACMEonfiguration> {

     /**
      * Enables contraints implementation dynamic reloading when using  
ACME
      * default to false
      */
     Configuration enableDynamicReloading(boolean);

}
When Configuration.buildValidatorFactory() is called, the initialized  
ValidatorFactory is returned. More specifically, the requested Bean  
Validation provider is determined and the result of  
validationProvider.buildValidatorFactory(ConfigurationState) is  
returned. ConfigurationState gives access to the configuration  
artifacts defined in META-INF/validation.xml (unless XML configuration  
is ignored) and provided programmatically to Configuration. Generally  
speaking, programmatically defined elements have priority over XML  
defined configuration elements (read the Configuration JavaDoc and see  
Section 4.4.6, “XML Configuration: META-INF/validation.xml” for more  
information). A typical implementation ofConfiguration also implements  
ConfigurationState, hence this can be passed to  
buildValidatorFactory(ConfigurationState).

Streams represented in the XML configuration and opened by the  
Configuration implementation must be closed by the Configuration  
implementation after the ValidatorFactorycreation (or if an exception  
occurs). Streams provided programmatically are the responsibility of  
the application.

Example 4.14. ConfigurationState interface

/**
  * Contract between a <code>Configuration</code> and a
  * </code>ValidatorProvider</code> to create a  
<code>ValidatorFactory</code>.
  * The configuration artifacts defined in the XML configuration and  
provided to the
  * <code>Configuration</code> are merged and passed along via  
ConfigurationState.
  *
  * @author Emmanuel Bernard
  * @author Hardy Ferentschik
  */
public interface ConfigurationState {

     /**
      * returns true if Configuration.ignoreXMLConfiguration() has  
been called
      * In this case, the ValiatorFactory must ignore META-INF/ 
validation.xml
      * @return true if META-INF/validation.xml should be ignored
      */
     boolean isIgnoreXmlConfiguration();

     /**
      * Message interpolator as defined in the following decresing  
priority:
      *  - set via the Configuration programmatic API
      *  - defined in META-INF/validation.xml provided that  
ignoredXmlConfiguration
      * is false. In this case the instance is created via its no-arg  
constructor.
      *  - null if undefined.
      *
      * @return message provider instance or null if not defined
      */
     MessageInterpolator getMessageInterpolator();

     /**
      * Returns a set of stream corresponding to:
      *  - mapping XML streams passed programmatically in Configuration
      *  - mapping XML stream located in the resources defined in
      * META-INF/validation.xml (constraint-mapping element)
      *
      * Streams represented in the XML configuration and opened by the
      * configuration implementation must be closed by the configuration
      * implementation after the ValidatorFactory creation (or if an  
exception
      * occurs).
      *
      * @return set of input stream
      */
     Set<InputStream> getMappingStreams();

     /**
      * ConstraintValidatorFactory implementation as defined in the  
following
      * decreasing priority:
      *  - set via the Configuration programmatic API
      *  - defined in META-INF/validation.xml provided that  
ignoredXmlConfiguration
      * is false. In this case the instance is created via its no-arg  
constructor.
      *  - null if undefined.
      *
      * @return factory instance or null if not defined
      */
     ConstraintValidatorFactory getConstraintValidatorFactory();

     /**
      * TraversableResolver as defined in the following decresing  
priority:
      *  - set via the Configuration programmatic API
      *  - defined in META-INF/validation.xml provided that  
ignoredXmlConfiguration
      * is false. In this case the instance is created via its no-arg  
constructor.
      *  - null if undefined.
      *
      * @return traversable provider instance or null if not defined
      */
     TraversableResolver getTraversableResolver();

     /**
      * return  non type-safe properties defined via:
      *  - Configuration.addProperty(String, String)
      *  - META-INF/validation.xml provided that ignoredXmlConfiguration
      * is false.
      *
      * If a property is defined both programmatically and in XML,
      * the value defined programmatically has priority
      *
      * @return Map whose key is the property key and the value the  
property value
      */
     Map<String, String> getProperties();
}
The requested provider implementation is resolved according to the  
following rules in the following order:

Use the provider implementation requested if Configuration has been  
created from Validation.byProvider(Class).

Use the provider implementation associated with the Configuration  
implementation described in the XML configuration (under  
validation.provider) if defined: the value of this element is the  
fully qualified class name of the Configuration sub interface uniquely  
identifying the provider.

Use the first provider implementation returned by  
validationProviderResolver.getValidationProviders().

The ValidationProviderResolver is specified when Configuration  
instances are created (see ValidationProvider). If no  
ValidationProviderResolver instance has been specified, the default  
ValidationProviderResolver is used.

Configuration instances are provided to the Bean Validation client  
through the Validation methods. Configuration instances are created by  
ValidationProvider.

Here is an example of Configuration use.

Example 4.15. Use Configuration

Configuration configuration = ...
ValidatorFactory factory = configuration
               .messageInterpolator( new WBMessageInterpolator() )
               .traversableResolver( new JPAAwareTraversableResolver() )
               .buildValidatorFactory();

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.jboss.org/pipermail/hibernate-dev/attachments/20090131/2db3f54f/attachment.html 


More information about the hibernate-dev mailing list