Customizing Validation Error Messages
Sometimes, the default localized messages are not satisfying. Especially when using patterns.
For example, if we get back to our previous email example:
<xs:element name="email"> <xs:simpleType> <xs:restriction base="xs:string"> <xs:pattern value="[^@]+@[^\.]+\..+" /> </xs:restriction> </xs:simpleType> </xs:element>
The default constraint violation message will look like:
This value must match the format "[^@]+@[^\.]+\..+".
Which is true but not very useful. You can customize the message to generate for a specific field.
For the schema named
userdata
and the field namedemail
, add the following entry in your message bundle:label.schema.constraint.violation.PatternConstraint.userdata.email=The value is not a valid email.
If you want to change the message for a field which is a child of a complex property, you have to specify the field full path:
label.schema.constraint.violation.PatternConstraint.schemaUser.user.firstname=The firstname must contain several regular characters.
Here, it's a custom message for the field
firstname
which is a sub-field of theuser
complex type in the schemaschemaUser
.If you want to change the message for a field which is a child of a list property, you have to specify the field full path - including the item's field name:
label.schema.constraint.violation.PatternConstraint.schema.users.user.firstname=The firstname must contain several regular characters.
Here, it's a custom message for the field
firstname
which is a sub-field of theuser
complex type - contained in the listusers
in the schemaschemaUser
.Most of the time, the item has no explicit name (no named type used in the XSD declaration). In that case, use
item
.label.schema.constraint.violation.PatternConstraint.schema.users.item.firstname=The firstname must contain several regular characters.
Creating ObjectResolver Related to Your Business Objects
If you want to make references to your own business objects. you can write your own ObjectResolver
. You will thereby be able to validate, that a value is a reference to an object and you'll be able to easily play with affected properties.
To create a custom ObjectResolver
, you have to create a class implementing org.nuxeo.ecm.core.schema.types.resolver.ObjectResolver
and register that class in a contribution to the component named org.nuxeo.ecm.core.schema.ObjectResolverService
.
Let's suppose you want to make reference to Product
objects provided by a ProductService
.
You have to create an
ObjectResolver
:public class ProductResolver implements ObjectResolver { public void configure(Map<String, String> parameters) { /* no configuration needed */ } public String getName() { return "productResolver"; } public Map<String, Serializable> getParameters() { return Collections.EMPTY_MAP; } public boolean validate(Object value) { return fetch(value) != null; } public Object fetch(Object value) { if (value instanceof String) { return Framework.getService(ProductService.class).findByReference((String) value); } return null; } public <T> T fetch(Class<T> type, Object value) { Object product = fetch(value); if (product != null && type.isInstance(product)) { return (T) product; } return null; } public Serializable getReference(Object object) { if (object != null && object instanceof Product) { return ((Product) object).getReference(); } return null; } public String getConstraintErrorMessage(Object invalidValue, Locale locale) { return ObjectResolver.Helper.getConstraintErrorMessage(this, invalidValue, locale); } }
Add a message to manage validation error:
label.schema.constraint.violation.resolver.productResolver="{0}" is not a valid product reference.
And register it in a Nuxeo contribution:
<?xml version="1.0"?> <component name="org.nuxeo.ecm.core.DocumentModel.resolver"> <documentation> Resolver for document properties containing reference to Product. </documentation> <extension target="org.nuxeo.ecm.core.schema.ObjectResolverService" point="resolvers"> <resolver type="productResolver" class="com.mycompany.nuxeo.ProductResolver" /> </extension> </component>
You can now define your own custom fields:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:ref="http://www.nuxeo.org/ecm/schemas/core/external-references/" xmlns:nxs="http://www.nuxeo.org/ecm/schemas/example" targetNamespace="http://www.nuxeo.org/ecm/schemas/example"> <xs:element name="productReference"> <xs:simpleType> <xs:restriction base="xs:string" ref:resolver="productResolver" /> </xs:simpleType> </xs:element> </xs:schema>
Validation will be activated. It will check if referenced Product exists.
You'll be able to play with the Product class directly on the DocumentModel:
// get a referenced product Product product = document.getObjectResolver("pdt:productReference").fetch(Product.class); // set the product referenced Product product = ....; document.getProperty("pdt:productReference").getObjectResolver().setObject(product);