Hi, as you know, we are about to introduce the concept of method level constraints in Hibernate Validator 4.2 (see [1] for more details).
In this context we are also planning to support the definition of method level constraints using the programmatic constraint API [2]. Hardy, Kevin and I have discussed the required changes for a while and came to a point where we would like to get some more feedback. As of today this API is used as follows: ConstraintMapping mapping = new ConstraintMapping(); mapping.type( Car.class ) .property( "licensePlate", FIELD ) .constraint( SizeDef.class ) .min( 2 ) .max( 14 ) .property( "seatCount", FIELD ) .constraint( MinDef.class ) .value ( 2 ); Note, that this is one single invocation chain. In particular, constraint definitions are part of this chain. With the introduction of method level constraints this leads to problems as it doesn't make sense any more to invoke any method of the API at any point of time. For instance the following invocation should be possible: ConstraintMapping mapping = new ConstraintMapping(); mapping.type( Car.class ) .method( "drive" ) .parameter(1) .constraint( NotNullDef.class ) .parameter(2) .constraint( SizeDef.class ) .min( 2 ) .max( 14 ) .genericConstraint (Pattern.class) .param( "regex", "..."); But not the following one (as invoking parameter() doesn't make sense when being on a property): ConstraintMapping mapping = new ConstraintMapping(); mapping.type( Car.class ) .property( "licensePlate", FIELD ) .constraint( NotNull.class ) .parameter(2) //doesn't make sense ... So the general problem is, that depending on the current invocation context only certain methods should be part of the API at that point. This is no problem when looking at specific methods (such as property(), method(), parameter() etc.) which return an appropriate context offering the methods allowed next. But this fails with a generic method such as constraint() which is allowed to be invoked at several places but should return a specific constraint definition at the same time. After several experiments the following seems to be the best solution IMO: ConstraintMapping mapping = new ConstraintMapping(); mapping.type( Car.class ) .method( "drive" ) .parameter(1) .constraint( ConstraintDef.create( NotNull.class ) ) .parameter(2) .constraint( ConstraintDef.create( SizeDef.class ) .min( 2 ) .max( 14 ) ) .constraint( ConstraintDef.createGeneric( Pattern.class) .param( "regex", "...") ); Here constraint definitions are created and configured separately and then are passed to constraint(). That way the invocation context is not propagated through constraint definition types and can be modeled to contain exactly the allowed methods at each point of time. Some variations of this approach are discussed in this Gist [3], e.g. ... constraint( new SizeDef().min( 2 ).max( 14 ) ) ... On the downside the API looses a bit of its "fluency" and at least for beginners it might not be obvious how to obtain constraint definition instances. Personally I think this is ok for the sake of API consistency (plus, actually I start to like this hierarchical approach of first configuring constraints and then placing them). WDYT, is this a step into the right direction? Or do you see any other approaches we've missed so far (one other thing we've tried was to parametrize constraint definitions with the current context type, but this worked out to be pretty cumbersome [4])? Another question is whether we should enforce an order within the constraint definitions for one type (e.g. class-level -> properties -> method 1 parameters -> method 1 return value -> method 2 ...) or allow an arbitrary order here. Personally I don't see the need for such an order (we don't require one implementation-wise, and users could adhere to one by convention if they want to), but Hardy and Kevin feel different about this :) For the interested the current proposal can be found at [5]. Thanks for any feedback, Gunnar [1] http://in.relation.to/18074.lace [2] http://docs.jboss.org/hibernate/validator/4.2/reference/en-US/html/chapter-custom-options.html#programmaticapi [3] https://gist.github.com/940438 [4] https://github.com/gunnarmorling/hibernate-validator/commit/6cfe540144828a91acf3f6e8815eaf4a22706e28#diff-33 [5] https://github.com/gunnarmorling/hibernate-validator/tree/HV-431-new _______________________________________________ hibernate-dev mailing list hibernate-dev@lists.jboss.org https://lists.jboss.org/mailman/listinfo/hibernate-dev