<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">Today I created some JavaFX based UI by using&nbsp;hibernate-validator&nbsp;6.0.0.Beta1<div class="">This version was released today and already integrates the support for the JavaFX ListProperty. I created a PR for all the samples (<a href="https://github.com/hibernate/hibernate-demos/pull/24" class="">https://github.com/hibernate/hibernate-demos/pull/24</a>).</div><div class="">While doing the samples I found a problem in JBV 2.0 in combination with Collections. From my point of view at least one general (maybe Provider based) method for validation is missing in the Validator class. I created an issue:&nbsp;<a href="https://hibernate.atlassian.net/browse/BVAL-622" class="">https://hibernate.atlassian.net/browse/BVAL-622</a></div><div class="">Since the issue contains the description simply copy it:</div><div class=""><br class=""></div><div class=""><div style="margin: 0px; padding: 0px; color: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 14px;" class="">I wrote some JavaSE sample to test the new ValueExtractor classes for JavaFX like ListPropertyValueExtractor. In that case I miss an important feature in the base API.</div><p style="margin: 10px 0px 0px; padding: 0px; color: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 14px;" class="">Let's say I have a model that has the following fields:</p><div class="panel code" style="margin: 9px 0px; padding: 0px; border: 1px solid rgb(204, 204, 204); background-color: rgb(245, 245, 245); line-height: 1.33333333333333; font-family: monospace; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; color: rgb(51, 51, 51);"><div class="codeContent panelContent" style="margin: 0px; padding: 9px 12px;"><pre class="code-java" style="margin-top: 0px; margin-bottom: 0px; padding: 0px; max-height: 30em; overflow: auto; white-space: pre-wrap; word-wrap: normal;">    @NotEmpty(message = <span class="code-quote" style="color: rgb(0, 145, 0);">"Name sollte nicht leer sein!"</span>)
    <span class="code-keyword" style="color: rgb(145, 0, 145);">private</span> <span class="code-keyword" style="color: rgb(145, 0, 145);">final</span> StringProperty name = <span class="code-keyword" style="color: rgb(145, 0, 145);">new</span> SimpleStringProperty();

    <span class="code-keyword" style="color: rgb(145, 0, 145);">private</span> <span class="code-keyword" style="color: rgb(145, 0, 145);">final</span> Property&lt;@Min(50) <span class="code-object" style="color: rgb(0, 0, 145);">Integer</span>&gt; count = <span class="code-keyword" style="color: rgb(145, 0, 145);">new</span> SimpleObjectProperty&lt;&gt;();

    @Size(min=1, max=4)
    <span class="code-keyword" style="color: rgb(145, 0, 145);">private</span> <span class="code-keyword" style="color: rgb(145, 0, 145);">final</span> ListProperty&lt;@Size(min=2, max=32) <span class="code-object" style="color: rgb(0, 0, 145);">String</span>&gt; tags = <span class="code-keyword" style="color: rgb(145, 0, 145);">new</span> SimpleListProperty&lt;&gt;(FXCollections.observableArrayList());
</pre></div></div><p style="margin: 10px 0px 0px; padding: 0px; color: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 14px;" class="">Next I bind all the properties of the model to UI nodes. Example:</p><div class="panel code" style="margin: 9px 0px; padding: 0px; border: 1px solid rgb(204, 204, 204); background-color: rgb(245, 245, 245); line-height: 1.33333333333333; font-family: monospace; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; color: rgb(51, 51, 51);"><div class="codeContent panelContent" style="margin: 0px; padding: 9px 12px;"><pre class="code-java" style="margin-top: 0px; margin-bottom: 0px; padding: 0px; max-height: 30em; overflow: auto; white-space: pre-wrap; word-wrap: normal;"> nameField.textProperty().bindBidirectional(model.nameProperty());
</pre></div></div><p style="margin: 10px 0px 0px; padding: 0px; color: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 14px;" class="">In addition I want to do a validation call whenever a value in the model changes. For the name property this can be done by the following code:</p><div class="panel code" style="margin: 9px 0px; padding: 0px; border: 1px solid rgb(204, 204, 204); background-color: rgb(245, 245, 245); line-height: 1.33333333333333; font-family: monospace; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; color: rgb(51, 51, 51);"><div class="codeContent panelContent" style="margin: 0px; padding: 9px 12px;"><pre class="code-java" style="margin-top: 0px; margin-bottom: 0px; padding: 0px; max-height: 30em; overflow: auto; white-space: pre-wrap; word-wrap: normal;">nameErrorNode.visibleProperty().bind(Bindings.createBooleanBinding(() -&gt;
                        !validator.validateProperty(model, <span class="code-quote" style="color: rgb(0, 145, 0);">"name"</span>).isEmpty(),
                model.nameProperty()));
</pre></div></div><p style="margin: 10px 0px 0px; padding: 0px; color: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 14px;" class="">By doing it like this only the name property will be validated whenever it changes. It would be wrong to validate the complete model in this case.<br class="">I can simply do the same for the list:</p><div class="panel code" style="margin: 9px 0px; padding: 0px; border: 1px solid rgb(204, 204, 204); background-color: rgb(245, 245, 245); line-height: 1.33333333333333; font-family: monospace; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; color: rgb(51, 51, 51);"><div class="codeContent panelContent" style="margin: 0px; padding: 9px 12px;"><pre class="code-java" style="margin-top: 0px; margin-bottom: 0px; padding: 0px; max-height: 30em; overflow: auto; white-space: pre-wrap; word-wrap: normal;">tagErrorNode.visibleProperty().bind(Bindings.createBooleanBinding(() -&gt;
                        !validator.validateProperty(model, <span class="code-quote" style="color: rgb(0, 145, 0);">"tags"</span>).isEmpty(),
                model.tagsProperty()));
</pre></div></div><p style="margin: 10px 0px 0px; padding: 0px; color: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 14px;" class="">In this case the list will be validated whenever the list changes. This happens for example if a new element will be added, updated or removed. Let's imagine a list with 1_000_000 entries or so. In that case I do not want to validate the complete list when I update an element. Based on this I think that an additional method next to&nbsp;</p><div class="panel code" style="margin: 9px 0px; padding: 0px; border: 1px solid rgb(204, 204, 204); background-color: rgb(245, 245, 245); line-height: 1.33333333333333; font-family: monospace; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; color: rgb(51, 51, 51);"><div class="codeContent panelContent" style="margin: 0px; padding: 9px 12px;"><pre class="code-java" style="margin-top: 0px; margin-bottom: 0px; padding: 0px; max-height: 30em; overflow: auto; white-space: pre-wrap; word-wrap: normal;">Validator.validateProperty()
</pre></div></div><p style="margin: 10px 0px 0px; padding: 0px; color: rgb(51, 51, 51); font-family: Arial, sans-serif; font-size: 14px;" class="">is needed in the JBV Spec to validate internal elements.</p></div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><br class=""><div><blockquote type="cite" class=""><div class="">Am 21.04.2017 um 08:31 schrieb Gunnar Morling &lt;<a href="mailto:gunnar@hibernate.org" class="">gunnar@hibernate.org</a>&gt;:</div><br class="Apple-interchange-newline"><div class=""><div class="">Right, it's an issue with parallel class hierarchies in general. The<br class="">same could happen during constraint validator resolution. In both<br class="">cases an extractor (or validator) for the specific sub-type must be<br class="">provided to resolve the ambiguity. This would also address your case<br class="">of cached and real value.<br class=""><br class="">Based on the preference of option 2), I've added this to the pending<br class="">PR in the section on built-in extractors:<br class=""><br class="">===<br class="">Compatible implementations provide value extractors for the following<br class="">types out of the box:<br class=""><br class="">[...]<br class=""><br class="">* javafx.beans.observable.ObservableValue; value() must be invoked<br class="">with the observable value, passing null as node name; the extractor<br class="">must be marked with @UnwrapByDefault<br class=""><br class="">* javafx.beans.property.ReadOnlyListProperty and<br class="">javafx.beans.property.ListProperty; indexedValue() must be invoked for<br class="">each contained element, passing the string literal &lt;iterable element&gt;<br class="">as node name<br class=""><br class="">* javafx.beans.property.ReadOnlyMapProperty and<br class="">javafx.beans.property.MapProperty; both map keys and map values are to<br class="">be supported; keyedValue() must be invoked by the map key extractor<br class="">for each contained key, passing the string literal &lt;map key&gt; as node<br class="">name; keyedValue() must be invoked by the map value extractor for each<br class="">contained value, passing the string literal &lt;map value&gt; as node name<br class="">===<br class=""><br class="">2017-04-19 14:42 GMT+02:00 Hendrik Ebbers &lt;<a href="mailto:hendrik.ebbers@me.com" class="">hendrik.ebbers@me.com</a>&gt;:<br class=""><blockquote type="cite" class="">I think this is not a JavaFX specific problem. This can happen everywhere if<br class="">you have defined extractors for 2 interface types and and have an<br class="">implementation of both.<br class="">In this specific example I would prefer to define ListProperty as a List.<br class=""><br class="">In general I think that this problem might / will happen in other frameworks<br class="">and APIs, too.<br class=""><br class="">I added such an example in a mail about the usage of annotations in the<br class="">generic information:<br class=""><br class="">Until now I only worked with lists and here the approach is quite nice.<br class="">Sadly it won’t work always. By adding an constraints annotation to the<br class="">generic type of the list we know that the annotation mentions the content of<br class="">the list. But this is only working because of one point: The generic type of<br class="">a collection defines the type of the collection content. This works fine for<br class="">collections (and for example JavaFX properties) but in other cases this will<br class="">end in problems.<br class=""><br class="">Let’s say we have the following 2 interfaces:<br class=""><br class="">public interface CachedValue&lt;V&gt; {<br class=""> &nbsp;&nbsp;&nbsp;V getCachedValue();<br class="">}<br class=""><br class="">public interface RealValue&lt;V&gt; {<br class=""> &nbsp;&nbsp;&nbsp;V getRealValue();<br class="">}<br class=""><br class="">Based on this interfaces we can easily create a new class that implements<br class="">both interfaces:<br class=""><br class="">public class CachableValue&lt;V&gt; implements CachedValue&lt;V&gt;, RealValue&lt;V&gt; {<br class=""><br class=""> &nbsp;&nbsp;&nbsp;private V cachedValue;<br class=""><br class=""> &nbsp;&nbsp;&nbsp;@Override<br class=""> &nbsp;&nbsp;&nbsp;public V getCachedValue() {<br class=""> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return cachedValue;<br class=""> &nbsp;&nbsp;&nbsp;}<br class=""><br class=""> &nbsp;&nbsp;&nbsp;@Override<br class=""> &nbsp;&nbsp;&nbsp;public V getRealValue() {<br class=""> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;V realValue = receiveValueFromServer();<br class=""> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cachedValue = realValue;<br class=""> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return realValue;<br class=""> &nbsp;&nbsp;&nbsp;}<br class=""><br class=""> &nbsp;&nbsp;&nbsp;private V receiveValueFromServer() {<br class=""> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return ServerConnector.getCurrentValue(); //Some fake code<br class=""> &nbsp;&nbsp;&nbsp;}<br class="">}<br class=""><br class=""><br class=""><br class=""><br class="">Am 18.04.2017 um 14:57 schrieb Emmanuel Bernard &lt;<a href="mailto:emmanuel@hibernate.org" class="">emmanuel@hibernate.org</a>&gt;:<br class=""><br class="">I'm not using JavaFX but I would be in favor of 2. because it let's<br class="">people put a size constraint on the List.<br class=""><br class="">Have you considered a blog post to get more feedback. Here people don't<br class="">use JavaFX or are shy.<br class=""><br class="">On Wed 17-04-12 16:16, Guillaume Smet wrote:<br class=""><br class="">Hi,<br class=""><br class="">We are refining the value extraction work and one of the remaining tasks is<br class="">to throw a proper exception if we have ValueExtractors defined in parallel<br class="">hierarchies for a given type.<br class=""><br class="">This led to discovering the below issue with the JavaFX collection types.<br class=""><br class="">Let's take the ListProperty example (we have the same issue with Set and<br class="">Map): ListProperty inherits from ObservableValue and from List.<br class=""><br class="">For now, it uses (by chance) the ObservableValue extractor which unwraps<br class="">the value by default. So basically:<br class="">@NotNull<br class="">private ListProperty&lt;String&gt; listProperty = new<br class="">ReadOnlyListWrapper&lt;String&gt;( null );<br class="">will return a violation.<br class=""><br class="">With the new conflict detection, it will throw an exception as it's unable<br class="">to find ONE most specific ValueExtractor as there are 2 valid candidates:<br class="">ObservableValueValueExtractor and ListValueExtractor.<br class=""><br class="">If we want to solve the conflict, we need to introduce a specific<br class="">ValueExtractor for ListProperty and decide of its behavior.<br class=""><br class="">We have 2 possibilities:<br class="">1/ consider ListProperty as an ObservableValue and thus simply unwrap the<br class="">list and validate the constraint against the list. In the above example,<br class="">@NotNull would then apply to the inner list. Same behavior as explained<br class="">above.<br class="">2/ consider ListProperty as a List. Thus the value extractor would iterate<br class="">over the element of the list. In the above case, it won't return a<br class="">violation. In the below example, the @NotNull would refer to listProperty<br class="">itself and the constraints on the elements of the list would be validated:<br class="">@NotNull<br class="">private ListProperty&lt;@Size(min = 3) String&gt; listProperty = new<br class="">ReadOnlyListWrapper&lt;String&gt;( null );<br class=""><br class="">Gunnar and I are in favor of 2/ but it changes the current behavior as the<br class="">@NotNull would refer to the container instead of referring to the wrapped<br class="">value.<br class=""><br class="">We would really like to have some feedback from people using JavaFX.<br class=""><br class="">Thanks!<br class=""><br class="">--<br class="">Guillaume<br class=""><br class=""><br class="">_______________________________________________<br class="">beanvalidation-dev mailing list<br class=""><a href="mailto:beanvalidation-dev@lists.jboss.org" class="">beanvalidation-dev@lists.jboss.org</a><br class="">https://lists.jboss.org/mailman/listinfo/beanvalidation-dev<br class=""><br class=""><br class="">_______________________________________________<br class="">beanvalidation-dev mailing list<br class="">beanvalidation-dev@lists.jboss.org<br class="">https://lists.jboss.org/mailman/listinfo/beanvalidation-dev<br class=""><br class=""><br class=""><br class="">_______________________________________________<br class="">beanvalidation-dev mailing list<br class="">beanvalidation-dev@lists.jboss.org<br class="">https://lists.jboss.org/mailman/listinfo/beanvalidation-dev<br class=""></blockquote><br class="">_______________________________________________<br class="">beanvalidation-dev mailing list<br class=""><a href="mailto:beanvalidation-dev@lists.jboss.org" class="">beanvalidation-dev@lists.jboss.org</a><br class="">https://lists.jboss.org/mailman/listinfo/beanvalidation-dev</div></div></blockquote></div><br class=""></div></body></html>