java - Looking for a way to add data to bean validation exception -
i have custom bean validator implements boolean isvalid(object, constraintvalidatorcontext)
performs business logic , returns true/false depending on logic.
what able add data constraintviolation exception thrown. exception handlers catch , process can tease out data include more details error/arg caused it. right can associate message violation lacks these dynamic details.
for example, object passed isvalid contains map contents validated validator. because validator api returns boolean lose granularity of member(s) of map triggered constraint violation. looking way of being able preserve , pass information forward.
edit 8/13/2013 - example solution involving jax-rs
(leaves out jaxb details not relevant question)
fooparam.java
public class fooparam { private map<string, string> subparammap; public map<string, string> getsubparammap() { return this.subparammap; } public void setsubparammap(map<string, string> subparammap) { this.subparammap = subparammap; } public fooparam() { this.subparammap = new hashmap<>(); } }
fooresource.java
public class fooresource { ... public void dosomething(@checkvalidparam(value=fooresoure.class) fooparam fooparam) { ... } }
checkvalidparam.java
@target({elementtype.type, elementtype.method, elementtype.parameter}) @retention(retentionpolicy.runtime) @constraint(validatedby = checkvalidparamvalidator.class) @documented public @interface checkvalidparam{ string message() default "{com.foo.bar.checkvalidparam.message}"; class<?>[] groups() default { }; class<? extends payload>[] payload() default { }; class<?> value(); @target({elementtype.type, elementtype.method, elementtype.parameter}) @retention(retentionpolicy.runtime) @documented @interface list { checkvalidparam[] value(); } }
checkvalidparamvalidator.java
public class checkvalidparamvalidator implements constraintvalidator<checkvalidparam, fooparam> { private class<?> entityclass; @override public void initialize(checkvalidparam checkvalidparam ) { this.entityclass = checkvalidparam.value(); } @override public boolean isvalid(fooparam fooparam, constraintvalidatorcontext constraintvalidatorcontext) { string message = constraintvalidatorcontext.getdefaultconstraintmessagetemplate(); constraintvalidatorcontext.disabledefaultconstraintviolation(); boolean isvalid = true; map<string, string> subparammap = fooparam.getsubparammap(); (map.entry<string, string> entry : subparammap.entryset()) { //contrived validation logic if (entry.getvalue().equalsignorecase("junk")) { constraintvalidatorcontext.buildconstraintviolationwithtemplate(message) .addnode(entry.getkey()).addconstraintviolation(); isvalid = false; } } return isvalid; } }
stripped down version of class intercepts methodconstraintviolationexceptions thrown in jax-rs pipeline illustrate pulling out invalid params , associated error message.
methodconstraintvalidationmapper.java
@provider public class methodconstraintvalidationmapperimplements exceptionmapper<methodconstraintviolationexception> { private static final logger log = logger.getlogger(methodconstraintvalidationmapper.class); @override public response toresponse(methodconstraintviolationexception ex) { response response; set<methodconstraintviolation<?>> violations = ex.getconstraintviolations(); list<validationexceptionerror> errors = new arraylist<>(); (methodconstraintviolation<?> methodconstraintviolation : ex.getconstraintviolations()) { validationexceptionerror error = new validationexceptionerror(); error.setfieldname(((pathimpl) methodconstraintviolation.getpropertypath()).getleafnode().asstring()); error.seterrormessage(methodconstraintviolation.getmessage()); errors.add(error); } return response.status(response.status.precondition_failed).entity(new genericentity<list<validationexceptionerror>>(errors) {}).type(mediatype.application_json).build(); } }
you can retrieve detailed information invalid value constraintviolation object. in particular getpropertypath()
should helpful you, allows navigate path leaf node , provides access concerned key (in case value in map validated) via node#getkey()
.
Comments
Post a Comment