Dialect support for SQL comments.
by Daniel Bell
Hi,
I have recently tried turning on SQL comments in hibernate 3.2.6.ga.
However, I found that our database (informix 7.31) did not support SQL
where the comment was at the start of the comment. Instead, the comment
needed to be after the SQL. For example:
/* not accepted by informix 7.31*/ select * from systables;
select * from systables /* accepted by informix 7.31*/
Because of this, I have added a method to the Dialect for adding comments:
/**
* Add a comment to the SQL string.
*
* @param sql StringBuffer holding the SQL.
* @param comment Comment to add to the SQL. May be null.
*/
public void addCommentToSql(StringBuffer sql, String comment) {
if (StringHelper.isNotEmpty(comment))
sql.insert(0, "/* " + comment + " */ ");
}
Thus, the default implementation provides the same functionality as
before. However, derived Dialects may override this method to add the
comment in a different location.
It is also possible to add additional comments in the derived Dialect.
In our case, we also add the Java thread ID.
I have included a complete patch for this change for hibernate 3.2.6.GA.
Please consider its inclusion in Hibernate.
Thanks,
Daniel.
15 years, 6 months
Re: [hibernate-dev] [BVAL-RI] HibrnateValidatorConfiguration
by Emmanuel Bernard
On Jan 31, 2009, at 06:08, Hardy Ferentschik wrote:
> On Sat, 31 Jan 2009 07:49:24 +0100, Emmanuel Bernard <emmanuel(a)hibernate.org
> > wrote:
>
>> I don't think HibernateValidatorConfiguration should go in the
>> engine package. That's a public API. it should stay in the root
>> package.
>
> Ok. The main point was to remove the engine / impl distinction which
> felt kind of arbitrary.
> Also the MessageInterpolator and ConstraintFactory handling has
> changed. I think now it makes more
> sense and we don't have to pass the references around everywhere.
> Let me work a little more in this area. I will keep in mind that in
> the end HibernateValidatorConfiguration
> should move up again.
yes, I agree.
Speaking of ValidatorContextImpl and ValidationContext
I think something should be done in this area, probably
ValidatorContextImpl being passed as a constructore parameter to
ValidatorImpl and encapsulated in ValidationContext.
BTW, either ValidationContext has a bad name or ValidatorContext has a
bad name but one of them has to change:
- ValidationContext => ValidatorExectionContext?
PS in ValidatorContext name has to change, let me know as it impacts
the spec.
15 years, 9 months
[Bean Validation] XML Configuration
by Emmanuel Bernard
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();
15 years, 9 months
[Bean Validation] XML Mapping with rules (in the spec)
by Emmanuel Bernard
Check out chapter 7 of the spec.
It includes all the overriding rules. I adjusted a bit the schema as
well.
The full spec is available on demand.
Chapter 7. XML deployment descriptor
Two kind of XML descriptors are used by Bean Validation. The first one
describes the Bean Validation configuration provided as META-INF/
validation.xml. The second one describes constraints declarations and
closely matches the annotations declaration approach.
7.1. Constraint definition and declaration
Bean Validation lets you declare constraints via XML rather than
annotations. You can either ignore constraints declared via
annotations or consider XML as adding additional constraints on top of
annotation constraints. While it is not possible to define a new
constraint via XML, you can redefine the list of ConstraintValidator
classes associated to a given constraint definition.
There is no distinction between an annotation based constraint
declaration and an XML based constraint declaration: they are
considered equivalent and should be treaded as such by the Bean
Validation provider.. Specifically when exploring metadata, the Bean
Validation provider must ensure that an annotation instance
corresponding to the XML declaration is provided
viaConstraintDescriptor.getAnnnotation(). The annotation elements as
well as ConstraintValidator.getParameters() must reflect the values
described in the XML declaration (seeSection 7.1.3, “Converting the
string representation of a value”). Likewise,
ConstraintDescriptor.getConstraintValidatorClasses() must reflect XML
based constraint definition overriding (see Section 7.1.2, “Overriding
constraint definitions in XML”).
A given class must not be described more than once amongst the XML
mapping descriptors. A given field or getter must not be described
more than once on a given class description. A given constraint
definition must not be overridden more than once amongst the XML
mapping descriptors. If any of these rule is violated in a given
validation deployment, aDuplicateMappingException is raised during the
creation of the ValidatorFactory.
The schema is provided in Section 7.1.4, “XML Schema”.
7.1.1. Constraint declaration in XML
If default-package is set, all unqualified class names (including
annotations) are considered part of the package described by default-
package.
A given JavaBean is described by the bean element. The name of the
class is mandatory. By default, all constraint declarations expressed
via annotation are ignored for classes described in XML. You can force
Bean Validation to consider both annotation and XML constraint
declarations by using ignore-annotation="false" on bean.
If the name of the class does refer to a class not present in in the
classpath, a ConfigurationException is raised.
Example 7.1. Example of bean XML declaration
<constraint-mappings
xmlns="http://jboss.org/xml/ns/javax/validation/mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://jboss.org/xml/ns/javax/validation/mapping
validation-mapping-1.0.xsd">
<default-package>com.acme.app.domain</default-package>
<bean class="Customer" ignore-annotations="false">
[...]
</bean>
<bean class="com.acme.common.model.Address">
[...]
</bean>
</constraint-mappings>
7.1.1.1. Class-level overriding
Class level annotations are described via the class element. If ignore-
annotations is declared, Bean Validation must honor the explicit value
for this element. If not declared, the default value for the bean is
considered.
When ignore annotations is true, class-level Bean Validation
annotations are ignored for this class (including the @GroupSequence).
When ignore annotations is false:
Constraints declared in XML and constraints declared in annotations
are added and form the list of class-level declared constraints.
@GroupSequence is considered unless group-sequence element is
explicitly used.
Example 7.2. Example of class-level declaration
<constraint-mappings
xmlns="http://jboss.org/xml/ns/javax/validation/mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://jboss.org/xml/ns/javax/validation/mapping
validation-mapping-1.0.xsd">
<default-package>com.acme.app.domain</default-package>
<bean class="Customer" ignore-annotations="false">
<class ignore-annotations="true">
[...]
</class>
</bean>
<bean class="com.acme.common.model.Address">
<class>
[...]
</class>
</bean>
</constraint-mappings>
7.1.1.2. Field-level overriding
Field level annotations are described via the field element. The name
attribute correspond to the name of the field considered. If ignore-
annotations is declared, Bean Validation must honor the explicit value
for this element. If not declared, the default value for the bean is
considered.
When ignore annotations is true, field-level Bean Validation
annotations on the targeted field are ignored (including the @Valid).
When ignore annotations is false:
Constraints declared in XML and constraints declared in annotations
are added and form the list of field-level declared constraints.
@Valid is considered unless valid element is explicitly use. Note that
the only way to disable cascading on a field marked as @Valid is to
use ignore-validation=true.
If the name of the field does not correspond to a field in the given
bean a ConfigurationException is raised.
Example 7.3. Field-level declaration
<constraint-mappings
xmlns="http://jboss.org/xml/ns/javax/validation/mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://jboss.org/xml/ns/javax/validation/mapping
validation-mapping-1.0.xsd">
<default-package>com.acme.app.domain</default-package>
<bean class="Customer" ignore-annotations="false">
<field name="firstName">
[...]
</field>
<field name="orders">
<valid/>
[...]
</field>
</bean>
</constraint-mappings>
7.1.1.3. Property-level overriding
Property-level annotations are described via the getter element. The
name attribute correspond to the name of the property considered as
defined in Section 3.1.2, “Field and property validation” (for example
a getter String getAge() would have <getter name="age"/> as a
corresponding descriptor). If ignore-annotations is declared, Bean
Validation must honor the explicit value for this element. If not
declared, the default value for the bean is considered.
When ignore annotations is true, property-level Bean Validation
annotations on the targeted property are ignored (including the
@Valid). When ignore annotations is false:
Constraints declared in XML and constraints declared in annotations
are added and form the list of property-level declared constraints.
@Valid is considered unless valid element is explicitly use. Note that
the only way to disable cascading on a field marked as @Valid is to
use ignore-validation=true.
If the name of the property does not correspond to a property in the
given bean a ConfigurationException is raised.
Example 7.4. Property-level declaration
<constraint-mappings
xmlns="http://jboss.org/xml/ns/javax/validation/mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://jboss.org/xml/ns/javax/validation/mapping
validation-mapping-1.0.xsd">
<default-package>com.acme.app.domain</default-package>
<bean class="Customer" ignore-annotations="false">
<getter name="firstName">
[...]
</getter>
<getter name="orders">
<valid/>
[...]
</getter>
</bean>
</constraint-mappings>
7.1.1.4. Constraint declaration
A new constraint declaration is represented by the constraint element.
The annotation attribute is the class name of the annotation
representing the constraint. Message and groups are defined
respectively by the message and groups elements.
Other custom elements of an annotation are represented by element. The
name attribute is mandatory and represents the name of the element in
the constraint declaration. “message”, “groups” are not permitted
names, use the message or groups elements instead.
If the element represents a primitive type, a class or an enum, the
string representation of its value is placed in the element itself.
See Section 7.1.3, “Converting the string representation of a value”
for a detailed explanation of the conversion rules from string to the
type.
If the element represents a primitive type array, a class array or an
enum array, the string representation of each value is placed in a
value element placed under the element itself.
If the element represents an annotation, the annotation element is
used to represent the annotation and placed under element. An
annotation element contains element elements.
If the element represents an array of annotations, one or more
annotation elements are placed under element.
Elements with default values in the annotation definition do not have
to be represented in XML: the default value will be used in this case.
If an XML constraint declaration is missing mandatory elements, or if
it contains elements not part of the constraint definition, a
ConfigurationException is raised.
Example 7.5. Constraint declaration
<constraint-mappings
xmlns="http://jboss.org/xml/ns/javax/validation/mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://jboss.org/xml/ns/javax/validation/mapping
validation-mapping-1.0.xsd">
<default-package>com.acme.app.domain</default-package>
<bean class="Customer" ignore-annotations="false">
<field name="firstName">
<!-- @LooksLike(patterns={
@Pattern(value="myRegExp",
flag=PatternFlag.INSENSITIVE),
@Pattern(value="my2ndRegExp")}
)
-->
<constraint annotation="com.acme.app.constraint.LooksLike">
<element name="patterns">
<annotation>
<element name="value">myRegExp</element>
<element name="flag">
<value>INSENSITIVE</value>
</element>
</annotation>
<annotation>
<element name="value">my2ndRegExp</element>
</annotation>
</element>
</constraint>
</field>
<field name="orders">
<valid/>
<!-- @DiscreteSize(value={ 0, 20 } )
-->
<constraint
annotation="com.acme.app.constraint.DiscreteSize">
<element name="value">
<value>0</value>
<value>20</value>
</element>
</constraint>
</field>
<getter name="orders">
<valid/>
<!-- @Size(message="Size is limited",
groups={Default.class, LightValidation.class},
max=30
)
-->
<constraint annotation="javax.validation.constraint.Size">
<message>Size is limited</message>
<groups>
<value>com.acme.app.model.LightValidation</value>
<value>javax.persistence.Default</value>
</groups>
<element name="max">30</element>
</constraint>
</getter>
</bean>
</constraint-mappings>
7.1.2. Overriding constraint definitions in XML
A constraint definition (ie. the annotation representing a
constraint), cannot be fully expressed in XML but the list of
ConstraintValidator associated to a given constraint can be altered.
A constraint definition is represented by a constraint-definition
element. The annotation attribute represents the constraint annotation
being altered. The validated-by elements represent the (ordered) list
of ConstraintValidator implementations associated to the constraint.
If include-existing-validator is set to false, ConstraintValidator
defined on the constraint annotation are ignored. If set to true, the
list of ConstraintValidators described in XML are concatenated to the
list of ConstraintValidator described on the annotation to form a new
array of ConstraintValidator evaluated. Annotation based
ConstraintValidator come before XML based ConstraintValidatot in the
array. The new array is returned by
ConstraintDescriptor.getConstraintValidatorClasses().
Example 7.6. Overriding constraint definitions
<constraint-mappings
xmlns="http://jboss.org/xml/ns/javax/validation/mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://jboss.org/xml/ns/javax/validation/mapping
validation-mapping-1.0.xsd">
<default-package>com.acme.app.domain</default-package>
<bean class="com.acme.common.model.Address">
[...]
</bean>
<constraint-definition
annotation="javax.validation.constraint.Size">
<validated-by include-existing-validators="true">
<value>com.acme.app.constraint.SizeValidatorForDictionary</value>
</validated-by>
</constraint-definition>
<constraint-definition annotation="AcmeOrderNumber">
[...]
</constraint-definition>
</constraint-mappings>
7.1.3. Converting the string representation of a value
Primitive types, Class and Enum are represented as strings in the XML
descriptor. Elements of an array are represented by the value element.
byte are represented according to the rules defined in
Byte.parseByte(String).
short are represented according to the rules defined in
Short.parseShort(String).
int are represented according to the rules defined in
Integer.parseInt(String).
long are represented according to the rules defined in
Long.parseLong(String).
float are represented according to the rules defined in
Float.parseFloat(String).
double are represented according to the rules defined in
Double.parseDouble(String).
boolean are represented according to the rules defined in
Boolean.parseBoolean(String).
char are represented according to the following rules:
the string must be of one character long
the character extracted from the string is the returned char
A Class is represented by the fully qualified class name of the class.
Note that if the raw string is unqualified, default package is taken
into account.
An enum is represented by its enum.name() value.
If any of the string representation does not match its type
counterpart, a ConfigurationException is raised.
7.1.4. XML Schema
This section contains the XML schema used for constraint mapping.
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema attributeFormDefault="unqualified"
elementFormDefault="qualified"
targetNamespace="http://jboss.org/xml/ns/javax/validation/mapping
"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
version="1.0">
<xs:element name="constraint-mappings"
type="map:constraint-mappingsType"
xmlns:map="http://jboss.org/xml/ns/javax/validation/mapping
"/>
<xs:complexType name="groupsType">
<xs:sequence>
<xs:element type="xs:string" name="value"
maxOccurs="unbounded" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="groupSequenceType">
<xs:sequence>
<xs:element type="xs:string" name="value"
maxOccurs="unbounded" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="constraint-mappingsType">
<xs:sequence>
<xs:element type="xs:string" name="default-package"
minOccurs="0"/>
<xs:element type="map:beanType"
name="bean"
maxOccurs="unbounded"
minOccurs="0"
xmlns:map="http://jboss.org/xml/ns/javax/validation/mapping
"/>
<xs:element type="map:constraint-definitionType"
name="constraint-definition"
maxOccurs="unbounded"
minOccurs="0"
xmlns:map="http://jboss.org/xml/ns/javax/validation/mapping
"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="validated-byType">
<xs:sequence>
<xs:element type="xs:string" name="value"
maxOccurs="unbounded" minOccurs="0"/>
</xs:sequence>
<xs:attribute type="xs:boolean" name="include-existing-
validators" use="optional"/>
</xs:complexType>
<xs:complexType name="constraintType">
<xs:sequence>
<xs:element type="xs:string" name="message" minOccurs="0"/>
<xs:element type="map:groupsType"
name="groups"
minOccurs="0"
xmlns:map="http://jboss.org/xml/ns/javax/validation/mapping
"/>
<xs:element type="map:elementType"
name="element"
maxOccurs="unbounded"
minOccurs="0"
xmlns:map="http://jboss.org/xml/ns/javax/validation/mapping
"/>
</xs:sequence>
<xs:attribute type="xs:string" name="annotation"
use="required"/>
</xs:complexType>
<xs:complexType name="elementType" mixed="true">
<xs:sequence>
<xs:element type="xs:string" name="value"
maxOccurs="unbounded" minOccurs="0"/>
<xs:element type="map:annotationType"
name="annotation"
maxOccurs="unbounded"
minOccurs="0"
xmlns:map="http://jboss.org/xml/ns/javax/validation/mapping
"/>
</xs:sequence>
<xs:attribute type="xs:string" name="name" use="required"/>
</xs:complexType>
<xs:complexType name="classType">
<xs:sequence>
<xs:element type="groupSequenceType" name="group-
sequence" minOccurs="0"/>
<xs:element type="xs:simpleType" name="stop-constraint-
inheritance" fixed="" minOccurs="0"/>
<xs:element type="map:constraintType"
name="constraint"
maxOccurs="unbounded"
minOccurs="0"
xmlns:map="http://jboss.org/xml/ns/javax/validation/mapping
"/>
</xs:sequence>
<xs:attribute type="xs:boolean" name="ignore-annotations"
use="optional"/>
</xs:complexType>
<xs:complexType name="beanType">
<xs:sequence>
<xs:element type="map:classType"
name="class"
minOccurs="0"
xmlns:map="http://jboss.org/xml/ns/javax/validation/mapping
">
</xs:element>
<xs:element type="map:fieldType"
name="field"
minOccurs="0"
maxOccurs="unbounded"
xmlns:map="http://jboss.org/xml/ns/javax/validation/mapping
"/>
<xs:element type="map:getterType"
name="getter"
minOccurs="0"
maxOccurs="unbounded"
xmlns:map="http://jboss.org/xml/ns/javax/validation/mapping
"/>
</xs:sequence>
<xs:attribute type="xs:string" name="class" use="required"/>
<xs:attribute type="xs:boolean" name="ignore-annotations"
use="optional"/>
</xs:complexType>
<xs:complexType name="annotationType">
<xs:sequence>
<xs:element type="map:elementType"
name="element"
maxOccurs="unbounded"
minOccurs="0"
xmlns:map="http://jboss.org/xml/ns/javax/validation/mapping
"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="getterType">
<xs:sequence>
<xs:element type="xs:string" name="valid" minOccurs="0"
fixed=""/>
<xs:element type="xs:string" name="stop-constraint-
inheritance" minOccurs="0" fixed=""/>
<xs:element type="map:constraintType"
name="constraint"
minOccurs="0"
maxOccurs="unbounded"
xmlns:map="http://jboss.org/xml/ns/javax/validation/mapping
"/>
</xs:sequence>
<xs:attribute type="xs:string" name="name" use="required"/>
<xs:attribute type="xs:boolean" name="ignore-annotations"
use="optional"/>
</xs:complexType>
<xs:complexType name="constraint-definitionType">
<xs:sequence>
<xs:element type="map:validated-byType"
name="validated-by"
xmlns:map="http://jboss.org/xml/ns/javax/validation/mapping
"/>
</xs:sequence>
<xs:attribute type="xs:string" name="annotation"
use="required"/>
</xs:complexType>
<xs:complexType name="fieldType">
<xs:sequence>
<xs:element type="xs:string" name="valid" minOccurs="0"
fixed=""/>
<xs:element type="xs:string" name="stop-constraint-
inheritance" minOccurs="0" fixed=""/>
<xs:element type="map:constraintType"
name="constraint"
minOccurs="0"
maxOccurs="unbounded"
xmlns:map="http://jboss.org/xml/ns/javax/validation/mapping
"/>
</xs:sequence>
<xs:attribute type="xs:string" name="name" use="required"/>
<xs:attribute type="xs:boolean" name="ignore-annotations"
use="optional"/>
</xs:complexType>
</xs:schema>
15 years, 9 months
[Bean Validation] XML Mapping schema
by Emmanuel Bernard
Here is my very first attempt to describe the constraint mapping XML
schema.
I did not look at other product approach to avoid being tainted. If
you have examples of alternative approach, I would appreciate a link.
A couple of comments:
- I would have preferred a Web Beans style XML approach but this kind
of approach is getting some heavy resistance from some members of the
expert committee. So I fell back to a more classic approach.
- constraints themselves cannot be defined: you have to write an
actual annotation. I wonder if we should provide such model. At
minimal we might want to provide a way to override the constraint
validator for a given constraint.
- I used JPA 2 mapping schema as inspiration
- I stayed very close to the Java structure
Better names, enhancements, alternative proposals are welcome.
Emmanuel
<?xml version="1.0" encoding="UTF-8"?>
<validation-mappings>
<package>com.acme.dvdstore.model</package>
<bean class="Customer">
<class>
<constraint annotation="com.acme.validate.SafeCustomer">
<attribute name="category">
<array-
element>com.acme.validate.SecurityLevel.SECURED_COUNTRY</array-element>
<array-
element>com.acme.validate.SecurityLevel.SECURED_ADDRESS</array-element>
<array-
element>com.acme.validate.SecurityLevel.SECURED_FINANCIALS</array-
element>
</attribute>
<attribute name="failPerCategory">false</attribute>
</constraint>
</class>
<fields>
<field name="firstname">
<ignore-annotations/>
<stop-inheritance/>
<constraint annotation="javax.validation.Min">
<message>{error.tooSmall}</message>
<groups>
<group>javax.validation.groups.Default</group>
</groups>
<attribute name="value">45</attribute>
</constraint>
</field>
</fields>
<getters>
<getter name="firstname">
<ignore-annotations/>
<stop-inheritance/>
<constraint annotation="javax.validation.Min">
<message>{error.tooSmall}</message>
<groups>
<group>javax.validation.groups.Default</group>
</groups>
<attribute name="value">45</attribute>
</constraint>
</getter>
</getters>
</bean>
</validation-mappings>
15 years, 9 months
Hibernate Validator next version
by Emmanuel Bernard
The next version of Hibernate Validator will be Bean Validation based
and contain a bridge to support legacy Hibernate Validator.
I am wondering about the version number.
We have three approaches:
- name it 4 but still make it work with Hibernate 3 platform
(waiting for the 4th coming)
- name it 4 but not making it work for Hibernate 3
- name it 3.2 and make it work with Hibernate 3 platform
option 2 is a no go as JPA2 will be Hibernate 3.x based more likely
than 4 based.
option 3 is a bit of a shame because HV is a massive improvement and
API change
so that left option 1 but it means we break the "keep the same
platform number paradigm"
I think we should go for option 1 nevertheless but wanted to ask.
15 years, 9 months
[Bean Validation] Type-safe Validator and resolution algorithm
by Emmanuel Bernard
Today, ConstraintValidator accepts Object and the implementation is
responsible for handling the casting and raise an exception if the
type is not supported.
The idea is to get type-safe validator and a discovery mechanism to
associate a validator to a given runtime type being validated. The
resolution is not 100% complete, you might end up with:
- no valid validator
- no way to decide between two or more validators
and get exceptions at runtime.
I would really like feedback on it as we could arrange some of these
rules to not fail (at least in the latter case):
- do we want this type-safe + auto resolution algorithm strategy or
should we stick with the untyped solution
- do we want to fail in case of ambiguity or rather choose the first
compatible provider?
Personally I find the feature quite elegant and the metadata can be
used by tools to warn a user if a constraint does not match the static
type it is applied on.
API and declaration
A more typesafe proposal would be:
public interface ConstraintValidator<A extends Annotation, T> {
void initialize(A annotation);
boolean isValid(T object, ConstraintValidationContext context);
}
public class StringSizeValidator implements ConstraintValidator<Size,
String> {
...
}
public class CollectionSizeValidator implements
ConstraintValidator<Size, Collection> {
...
}
public class MapSizeValidator implements ConstraintValidator<Size,
Map> {
...
}
public class ArraySizeValidator implements ConstraintValidator<Size,
Object[]> {
...
}
@Constraint(validatedBy={
StringSizeValidator.class, CollectionSizeValidator.class,
MapSizeValidator.class, ArraySizeValidator.class} )
public @interface Size { ... }
We then need to decide at runtime, which validator needs to be executed.
Here is a proposed algorithm heavily based on the Java Language
Specification (boy it's hard to read it).
Resolution algorithm
The type T of a ConstraintValidator must not make direct use of
generics itself.
This is because the algorithm compare the actual type at runtime and
such notion would be lost. So you can do ConstraintValidator<Size,
Collection> but not ConstraintValidator<Size, Collection<String>>.
For a given runtime object t of type T about to be validated for a
given constraint:
if t is null the first validator in the array of available validators
is used.
otherwise
A validator accepting U is said to be compliant with the type T if T
is a subtype of U according to the JLS chapter 4.10.
If no compliant validator is found for T, a
UnexpectedTypeForConstraint exception is raised.
If a validator is taking the responsibility to dispatch types (ie
ConstraintValidator<Size,Object>), it must use the same exception in
the same circumstances.
If one compliant validator is found, it is used.
If more than one compliant validator is found, the one with the most
specific parameter is used. The informal intuition is that one
parameter is more specific than another if any assignment handled by
the first parameter could be passed on to the other one without a
compile-time type error.
Of a given type T, a compliant validator accepting U is considered
maximally specific if no other T compliant validator accepting V is
such as V is a strict subtype of U. String subtype is defined by JSL
chapter 4.10.
If more than one maximally specific validator is found, a
AmbiguousValidatorException is raised.
WDYT?
15 years, 9 months