<div dir="ltr">Hey Matt,<div><br></div><div>It&#39;s great to see you here, has been a while :)</div><div><br></div><div>Regarding that annotation, could you provide a small example tailored to the issue at hand to show what you have in mind with it? It&#39;s not fully clear to me yet.</div><div><br></div><div>Thanks,</div><div><br></div><div>--Gunnar</div><div><br></div><div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">2016-11-22 21:22 GMT+01:00 Matt Benson <span dir="ltr">&lt;<a href="mailto:mbenson@apache.org" target="_blank">mbenson@apache.org</a>&gt;</span>:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">In Therian there is a custom annotation to specify a method that<br>
provides a Type value at runtime. Specifically It allows one to<br>
designate a method that returns an instance of the Typed interface<br>
from Apache Commons Lang 3.x.<br>
<br>
Annotation: <a href="https://github.com/mbenson/therian/blob/master/core/src/main/java/therian/BindTypeVariable.java" rel="noreferrer" target="_blank">https://github.com/mbenson/<wbr>therian/blob/master/core/src/<wbr>main/java/therian/<wbr>BindTypeVariable.java</a><br>
Example: <a href="https://github.com/mbenson/therian/blob/master/core/src/main/java/therian/operation/Transform.java" rel="noreferrer" target="_blank">https://github.com/mbenson/<wbr>therian/blob/master/core/src/<wbr>main/java/therian/operation/<wbr>Transform.java</a><br>
Utilities: <a href="https://github.com/mbenson/therian/blob/master/core/src/main/java/therian/util/Types.java#L88" rel="noreferrer" target="_blank">https://github.com/mbenson/<wbr>therian/blob/master/core/src/<wbr>main/java/therian/util/Types.<wbr>java#L88</a><br>
<br>
An approach like this would of course put some onus onto users with<br>
the payoff of being very explicit. In any case, it might provide food<br>
for thought on the subject.<br>
<br>
Matt<br>
<br>
<br>
On Tue, Nov 22, 2016 at 1:15 PM, Emmanuel Bernard<br>
<div><div class="h5">&lt;<a href="mailto:emmanuel@hibernate.org">emmanuel@hibernate.org</a>&gt; wrote:<br>
&gt;<br>
&gt; On 21 Nov 2016, at 14:07, Emmanuel Bernard &lt;<a href="mailto:emmanuel@hibernate.org">emmanuel@hibernate.org</a>&gt; wrote:<br>
&gt;<br>
&gt;<br>
&gt; On 7 Nov 2016, at 23:42, Hendrik Ebbers &lt;<a href="mailto:hendrik.ebbers@me.com">hendrik.ebbers@me.com</a>&gt; wrote:<br>
&gt;<br>
&gt; Let’s say we have the following 2 interfaces:<br>
&gt;<br>
&gt; public interface CachedValue&lt;V&gt; {<br>
&gt;     V getCachedValue();<br>
&gt; }<br>
&gt;<br>
&gt; public interface RealValue&lt;V&gt; {<br>
&gt;     V getRealValue();<br>
&gt; }<br>
&gt;<br>
&gt; Based on this interfaces we can easily create a new class that implements<br>
&gt; both interfaces:<br>
&gt;<br>
&gt; public class CachableValue&lt;V&gt; implements CachedValue&lt;V&gt;, RealValue&lt;V&gt; {<br>
&gt;<br>
&gt;     private V cachedValue;<br>
&gt;<br>
&gt;     @Override<br>
&gt;     public V getCachedValue() {<br>
&gt;         return cachedValue;<br>
&gt;     }<br>
&gt;<br>
&gt;     @Override<br>
&gt;     public V getRealValue() {<br>
&gt;         V realValue = receiveValueFromServer();<br>
&gt;         cachedValue = realValue;<br>
&gt;         return realValue;<br>
&gt;     }<br>
&gt;<br>
&gt;     private V receiveValueFromServer() {<br>
&gt;         return ServerConnector.<wbr>getCurrentValue(); //Some fake code<br>
&gt;     }<br>
&gt; }<br>
&gt;<br>
&gt; Let’s try to add a constraint annotation to validate the content of such a<br>
&gt; CachableValue:<br>
&gt;<br>
&gt; private CachableValue&lt;@NotEmpty String&gt; myValue;<br>
&gt;<br>
&gt; Based on this definition you have absolutely no idea if the @NotEmpty<br>
&gt; annotation is defined for the real value, the cached value or both values.<br>
&gt; From my point of view this is a big problem. Until now its was always easy<br>
&gt; to see how the validation of a model should work based on the validation<br>
&gt; information (annotations) in the model. With this new approach you have no<br>
&gt; idea what will happen.<br>
&gt;<br>
&gt; The most simple solution would be to add the support only to some special<br>
&gt; container / wrapper classes like collections, JavaFX properties, etc. I<br>
&gt; think this is a bad idea since new default might come to future versions of<br>
&gt; JavaSE and JavaEE (or maybe Spring) and that won’t be supported. Based on<br>
&gt; this I think that it will be a must to support all wrapper types.<br>
&gt;<br>
&gt;<br>
&gt; Interesting.<br>
&gt;<br>
&gt; I did think about extractors of subtypes but not extractors of parallel<br>
&gt; types.<br>
&gt; I have been thinking about it and explored a few paths:<br>
&gt; - validating all parallel extractors<br>
&gt; - use one<br>
&gt; - validate none<br>
&gt; - fail<br>
&gt;<br>
&gt; In the end, I think the cleanest solution is to follow what Ceylon and Java<br>
&gt; do for default methods, they don’t allow ambiguous use and force a<br>
&gt; redefinition.<br>
&gt; <a href="http://stackoverflow.com/questions/16764791/how-does-java-8-new-default-interface-model-works-incl-diamond-multiple-inhe#16788295" rel="noreferrer" target="_blank">http://stackoverflow.com/<wbr>questions/16764791/how-does-<wbr>java-8-new-default-interface-<wbr>model-works-incl-diamond-<wbr>multiple-inhe#16788295</a><br>
&gt;<br>
&gt; In practice for us, if there are extractors for CachedValue and for<br>
&gt; RealValue, then CachableValue should fail and require the definition of an<br>
&gt; explicit CachableValue extractor.<br>
&gt; What is interesting in this case is that CachableValue extractor can be see<br>
&gt; as either:<br>
&gt; - a ManyContainerValuesExtractor that will return getCachedValue and<br>
&gt; getRealValue just like a Collection would return get(0) and get(1). This<br>
&gt; approach does not reflect the path difference though<br>
&gt; - or two SingleContainerValueExtractor from the same container type and the<br>
&gt; same value type (*)<br>
&gt;<br>
&gt; (*) this is something we do not allow for the moment, we have a unique<br>
&gt; extractor per container + value type. We need to think about how to make<br>
&gt; that work and still allow people to override extractors.<br>
&gt;<br>
&gt; So back to your original concern of uncertainty, I think forcing a more<br>
&gt; specific extractor solves the uncertainty that you mentioned. Granted, the<br>
&gt; user would have to know the extractor(s) behavior but in many ways, people<br>
&gt; do need to know about that regardless.<br>
&gt;<br>
&gt; Thoughts?<br>
&gt;<br>
&gt;<br>
&gt; Gunnar and I discussed this problem further and the proposal at large, in<br>
&gt; particular in the light of his alternative proposal (section 3).<br>
&gt;<br>
&gt; The main question we have is how common are constraints on user defined type<br>
&gt; like:<br>
&gt;<br>
&gt; - CachableValue&lt;V&gt; // CacheableValue&lt;@Email String&gt; value;<br>
&gt; - Tuple&lt;V1,V2&gt; // Tuple&lt;@Email String, @Valid Address&gt; userIdAndAddress;<br>
&gt; - …<br>
&gt;<br>
&gt; Here I am excluding:<br>
&gt; - Optional<br>
&gt; - Collection and Map (and all Iterable really)<br>
&gt; - even Collections of non Java languages (Scala, Ceylon, Kotlin if they have<br>
&gt; their own collection type, etc)<br>
&gt;<br>
&gt; If constraints on the user defined types described above are common, then we<br>
&gt; need a more systematic solution than imposing to write an extractor for each<br>
&gt; of these cases.<br>
&gt; If they are uncommon and the only containers are Optional, Collection, Map,<br>
&gt; JavaFX containers and other language collections, or more generally<br>
&gt; framework provided containers, then a requiring an extractor implementation<br>
&gt; is not too problematic.<br>
&gt;<br>
&gt;<br>
&gt; To put some context, the overall BVAL-508 proposal addresses several things:<br>
&gt; - how to extract value from a container<br>
&gt; - where to express constraints on the values of a container<br>
&gt; - how and when the cascading logic should work<br>
&gt;<br>
&gt; In my proposal. extractors are explicit implementations (with built-in as<br>
&gt; well as custom implementations). The extractors:<br>
&gt; - extract the value(s)<br>
&gt; - express the link between the extractor and the type parameter (and thus<br>
&gt; the parameterized type)<br>
&gt; - must be implemented explicitly for each tuple extractor / type parameter<br>
&gt;<br>
&gt; Gunnar has an alternative proposal or rather a proposal that builds on top<br>
&gt; of the existing one but provide a default generic extractor logic.<br>
&gt;<br>
&gt; If no explicit extractor exists, the following will happen<br>
&gt;<br>
&gt; Assuming<br>
&gt;<br>
&gt; Tuple&lt;@Email String, @Valid Address&gt; userIdAndAddress;<br>
&gt;<br>
&gt; class Tuple&lt;V1, V2&gt; {<br>
&gt;     V1 v1;<br>
&gt;     V2 v2;<br>
&gt;<br>
&gt;     V1 getV1() { return v1; };<br>
&gt;     V2 getV2() { return v2; };<br>
&gt; }<br>
&gt;<br>
&gt; The default extractor would look for all getters that return the<br>
&gt; parameterized type(s) and use the getter as extractor. It then would apply<br>
&gt; the constraint.<br>
&gt; In our case, the code would validate getV1() against @Email and getV2() will<br>
&gt; be cascaded.<br>
&gt;<br>
&gt; This is elegant and extremely regular. But it has a very ugly angle: should<br>
&gt; we validate the getters or the fields or the getters then the fields?<br>
&gt;<br>
&gt; The rule proposed by Gunnar is to validate the getters first because he<br>
&gt; likes them better and then look for fields with no corresponding getter and<br>
&gt; validate them.<br>
&gt;<br>
&gt; Assuming<br>
&gt;<br>
&gt; Tuple&lt;@Email String, @Valid Address&gt; userIdAndAddress;<br>
&gt;<br>
&gt; class Tuple&lt;V1, V2&gt; {<br>
&gt;     V1 v1;<br>
&gt;     V1 v1b;<br>
&gt;     V2 v2;<br>
&gt;<br>
&gt;     V1 getV1() { return v1; };<br>
&gt;     V2 getV2() { return v2; };<br>
&gt; }<br>
&gt;<br>
&gt; In this example, the code would validate getV1() against @Email, getV2()<br>
&gt; will be cascaded and v1b will be validated against @Email.<br>
&gt;<br>
&gt; This alternative proposal has two advantages:<br>
&gt; - it reduces the number of necessary extractor implementations (assuming the<br>
&gt; relevant elements have getters)<br>
&gt; - it makes the problem described by Hendrik with CacheableValue fully<br>
&gt; deterministic<br>
&gt; - it makes the logic of cascading very regular (for non collection at least)<br>
&gt; - it still requires the ability to write custom extractors for collection<br>
&gt; type containers<br>
&gt;<br>
&gt; I have to admit I hate the arbitrary logic of choosing getters and then<br>
&gt; fields.<br>
&gt;<br>
&gt; So my questions to you are:<br>
&gt; - how common do you see the Tuple, CacheableValue and other user defined<br>
&gt; type needing validation?<br>
&gt; - would you be satisfied by the getter approach as an extractor?<br>
&gt; - what do you think of the getter priority logic?<br>
&gt;<br>
&gt; What do you think?<br>
&gt;<br>
&gt; Emmanuel<br>
&gt;<br>
</div></div>&gt; ______________________________<wbr>_________________<br>
&gt; beanvalidation-dev mailing list<br>
&gt; <a href="mailto:beanvalidation-dev@lists.jboss.org">beanvalidation-dev@lists.<wbr>jboss.org</a><br>
&gt; <a href="https://lists.jboss.org/mailman/listinfo/beanvalidation-dev" rel="noreferrer" target="_blank">https://lists.jboss.org/<wbr>mailman/listinfo/<wbr>beanvalidation-dev</a><br>
<br>
______________________________<wbr>_________________<br>
beanvalidation-dev mailing list<br>
<a href="mailto:beanvalidation-dev@lists.jboss.org">beanvalidation-dev@lists.<wbr>jboss.org</a><br>
<a href="https://lists.jboss.org/mailman/listinfo/beanvalidation-dev" rel="noreferrer" target="_blank">https://lists.jboss.org/<wbr>mailman/listinfo/<wbr>beanvalidation-dev</a></blockquote></div><br></div>