From: Emmanuel Bernard <emmanuel.bernard(a)JBOSS.COM>
Date: June 15, 2009 17:57:48 EDT
To: JSR-303-EG(a)JCP.ORG
Subject: Re: constraint level payload
Reply-To: Java Community Process JSR #303 Expert List <JSR-303-EG(a)JCP.ORG
>
Done
http://people.redhat.com/~ebernard/validation/#constraintsdefinitionimple...
Pleaase have a look and let me know what you think. I'm not a big
fan of forcing this noew attribute on everybody's constraint but I
don't see muc more possibilities.
2.1.1.3. payload
Every constraint annotation must define a payload element that
specifies which payload the constraint declaration is associated with.
Class<? extends ConstraintPayload>[] payload() default {};
The default value must be an empty array.
Each attachable payload extends ConstraintPayload.
/**
* Payload type that can be attached to a given
* constraint declaration.
* Payloads are typically used to carry on metadata information
* consumed by a validation client.
*
* Use of payloads is not considered portable.
*
* @author Emmanuel Bernard
* @author Gerhard Petracek
*/
public interface ConstraintPayload {
}
Payloads are typically used by validation clients to associate some
metadata information to a given constraint declaration. Payloads are
typically non portable. Describing payloads as interface extensions
as opposed to a string based approach allows an easier and more type-
safe approach.
One use case for payload shown in Example 2.1, “Use of payload to
associate severity to a constraint” is to associate a severity to a
constraint. This severity can be exploited by a presentation
framework to adjust how a constraint failure is displayed.
Example 2.1. Use of payload to associate severity to a constraint
package com.acme.severity;
public class Severity {
public static class Info extends ConstraintPayload {};
public static class Error extends ConstraintPayload {};
}
public class Address {
@NotNull(message="would be nice if we had one",
payload=Severity.Info.class)
public String getZipCode() {...}
@NotNull(message="the city is mandatory",
payload=Severity.Error.class)
String getCity() {...}
}
The payload information can be retrieved from error reports via
ConstraintViolation objects (see Section 4.2, “ConstraintViolation”)
or using the metadata API viaConstraintDescriptor objects (see
Section 5.5, “ConstraintDescriptor”).
On May 29, 2009, at 04:49, Emmanuel Bernard wrote:
> We have had a few discussions around having a payload on
> constraints that could be consumed by client frameworks.
>
> There are 4 competing solutions:
>
> #1 Nothing
> The argument would be that it's not needed and hence we don't need
> any payload.
> On that subject what are the use cases for such a payload. Please
> be as specific as possible.
>
> - We have identified Error / Warn modes which I argued can be
> solved by groups. I also argued that groups and modes are *not*
> orthogonal to groups and hence would not lead to a group explosion.
> Can someone bring a real use case showing groups and modes as
> orthogonal? (something more substantial than Group1
>
> - Sebastian, what were the other use cases you had in mind when
> you wanted the @param approach
>
> #2 keep it open for later
> we could reserve the "payload" or "parameter" attribute name and
> use it for a next rev of this spec.
>
> #3 the string based approach
> Sebastian's proposal
>
> @NotNull
> (params
>
={@Param(key="prio";value="1"),@Param(key="severity";value="3")})
> String myfield;
>
> I personally don't like this approach as it is very verbose and
> totally unsafe. But it has the advantage of allowing parameters
> very easily.
>
> #4 the interface based approach
>
> (Part of) Gerhard's proposal
>
> interface javax.validation.ValidationParameter {}
>
> //framework classes
> interface com.acme.ViolationSeverity extends ValidationParameter {
> FacesMessage.Severity();
> MessageType postfix();
> }
>
> class com.acme.WarnSeverity implements ViolationSeverity {
> FacesMessage.Severity() { return acesMessage.SEVERITY_WARN; }
> MessageType postfix() { return MessageType.WARN;}
> }
>
> //user code
> @NotNull(params=WarnSeverity.class)
>
> Pros:
> much cleaner on the client code
> type safe ont he client code
>
> Cons:
> much more verbose to define a new kind of parameter
> untype safe when the value is read by the framework (so is #3)
> ValidationParameter[] params =
> constraintViolation.getAnnotation().params(); if (params[0]
> instanceof ViolationSeverity) {};
> it creates a compile time dependency on the targeted framework
> no runtime dependency but if the framework is not here, the
> constraint annotation will not be visible