2012/7/1 Emmanuel Bernard <emmanuel(a)hibernate.org>:
>
> Personally, I find the option of adding support for types of specific
> APIs/frameworks to BV not really appealing. Maybe another API than
> JavaFX appears tomorrow?
>
> I could imagine to make BV extensible in that respect, e.g. by
> providing an SPI for hooking in some sort of adapter which is used by
> BV to retrieve values from given models. JavaFX then could provide an
> implementation of this SPI based on its property model. BV would not
> use reflection to operate on fields and methods and so on but rather
> use the SPI to walk over the type hierarchy (the default
> implementation of course would be the behavior as of today).
We did explore something around service locators to automatically wire
ConstraintValidator implementations to a constraint.
Maybe it is time to bring it back up.
Do you have some more details on that?
>
> Another implementation could be used to place and validate constraints
> on JSON/map-like structures (e.g. when working with MongoDB etc.);
> Constraints would have to be declared via an API/XML but not
> annotations in that case.
I have a hard time to picture that. Do you have something specific in mind? To me linking
BV constraints with the outside world
(DB, html etc) should be done like we did for JPA and client side validation, ie by using
the metadata API.
Today BV is focused on actual Java types adhering to the JavaBeans
convention (types with getters/setters), but there are use cases where
one may have another type model but still would like to use the BV
validation approach.
My thinking was to provide an SPI which allows to customize the way BV
interacts with type models. This SPI would establish an abstract type
model used by the BV runtime. This model would know about "types",
"properties" and so on, but these wouldn't necessarily have to be
actual Java types with bean properties.
The default implementation of course would be based on JavaBeans as
today, but one could plug-in implementations based on other models,
too. One example is a dynamic model like DynaBeans [1] (or e.g.
dynamic EMF models [2]). Here "types" are defined at run-time like
this:
DynaProperty[] props = new DynaProperty[]{
new DynaProperty("address", Map.class),
new DynaProperty("lastName", String.class)
};
BasicDynaClass employeeType = new BasicDynaClass("employee", null, props);
DynaBean employee = employeeType.newInstance();
employee.set("address", new HashMap());
employee.set("lastName", "Flintstone");
As of today, you can't apply constraints to the "employee" type,
though, as it is no JavaBean. In such a case constraints could e.g. be
declared using an API (example based on HV's constraint API):
ConstraintMapping mapping = new ConstraintMapping();
mapping.type( new DynaBeansTypeIdentifier ( employeeType ) )
.property( "address" )
.constraint( new NotNullDef() )
.valid()
.property( "lastName" )
.constraint( new NotNullDef() )
.constraint( new SizeDef().min( 2 ).max( 14 ) );
The SPI would provide a way for declaring constraints (see above) and
functionality used by the BV runtime to navigate over validated types
and retrieve the required type meta data for validation.
Coming back to JavaFX, there the Employee type could look like this:
public class Employee {
@NotNull
@Valid
private final ObjectProperty<Map> address = new
SimpleObjectProperty<Map>(this, "address");
@NotNull
@Size(min=2, max=14)
private final StringProperty lastName = new
SimpleStringProperty(this, "lastName");
...
}
As of today, the annotations would be of no effect, as there are not
validators such as SizeValidator<Size, StringProperty>. But using the
SPI, one could hook in an adapter which creates a representation of
the Employee type in the abstract model (with e.g. the "lastName"
property being of type String), which would allow the BV runtime to
operate on it.
That said, I'm aware of that this would probably be a large addition,
and I'm not sure whether it would be doable at all.
For the JavaFX case, also this solution would be imaginable:
public class Employee {
private final StringProperty lastName = new
SimpleStringProperty(this, "lastName");
@NotNull
@Size(min=2, max=14)
public String getLastName() { return lastName.get(); }
public void setLastName(String lastName) { this.lastName.set( lastName ); }
public StringProperty nameProperty() { return name; }
...
}
That's much wordier than annotating the actual properties, though.
--Gunnar
[1]
http://commons.apache.org/beanutils/api/org/apache/commons/beanutils/pack...
[2]
http://www.devx.com/Java/Article/29093/1763/page/2