java - Is this a good pattern for annotation processing? -


i've got standard spring webapp, , have number of custom annotations use denote requirements , constraints applied given web-service method. instance, might apply @requireslogin annotation method requires valid user session, , @requiresparameters(paramnames = {"name", "email"}) on method requires "name" , "email" set, , on.

in support of implemented ad-hoc utility validating method's annotated constraints @ runtime, followed pattern of:

map<class<? extends annotation>, annotation> annotations = mergeconstraintsfromclassandmethod(serviceclass, servicemethod); if (annotations.containskey(annotationtype1.class)) {     annotationtype1 annotation = (annotationtype1)annotations.get(annotationtype1.class);     //do validation appropriate 'annotationtype1' } if (annotations.containskey(annotationtype2.class)) {     annotationtype2 annotation = (annotationtype2)annotations.get(annotationtype2.class);     //do validation appropriate 'annotationtype2' } //... 

this works fine, has become bit unwieldy have added additional annotations. i'd replace bit more maintainable. ideally i'd able do:

list<validatableannotation> annotations = mergeconstraintsfromclassandmethod(serviceclass, servicemethod); (validatableannotation annotation : annotations) {     annotation.validate(request); } 

but i'm pretty sure not possible since annotations cannot contain executable code , since compiler not let me extend java.lang.annotation.annotation (not i'd know how go allowing executable code contained in annotation if compiler let me try).

what annotations can contain, however, nested inner class, , inner class can normal java class can do. i've come based upon , in interest of keeping validation code closely associated annotation being validated possible is:

public interface annotationprocessor {     public boolean processrequest(annotation theannotation, httpservletrequest request); } 

and annotations can implemented like:

@retention(retentionpolicy.runtime) @target({elementtype.method, elementtype.type}) public @interface requireslogin {      public static class processor implements annotationprocessor {          @override         public boolean processrequest(annotation theannotation, httpservletrequest request) {             if (! (theannotation instanceof requireslogin)) {                 //someone made invalid call, return true                 return true;             }             return request.getsession().getattribute(constants.session_user_key) != null;         }     } } 

which keeps validation logic nice , tightly coupled annotation being validated. ad-hoc validation code can replaced with:

list<annotation> annotations = mergeconstraintsfromclassandmethod(serviceclass, servicemethod); (annotation annotation : annotations) {     processannotation(annotation, request); }   private static boolean processannotation(annotation annotation, httpservletrequest request) {     annotationprocessor processor = null;     (class<?> processorclass : annotation.annotationtype().getdeclaredclasses()) {         if (annotationprocessor.class.isassignablefrom(processorclass)) {             try {                 processor = (annotationprocessor)processorclass.newinstance();                 break;             }             catch (exception ignored) {                 //couldn't create it, maybe there inner                  //class implements required interface                  //we can construct, keep going             }         }     }     if (processor != null) {         return processor.processrequest(annotation, request);     }      //couldn't a processor , can't process      //annotation, perhaps annotation not support     //validation, return true     return true; } 

which leaves no more ad-hoc code needs revised every time add new annotation type. implement validator part of annotation, , i'm done.

does seem reasonable pattern use? if not might work better?

you may want investigate aop. can advise methods expose annotations , perform pre/post processing accordingly.


Comments

Popular posts from this blog

linux - Using a Cron Job to check if my mod_wsgi / apache server is running and restart -

actionscript 3 - TweenLite does not work with object -

jQuery Ajax Render Fragments OR Whole Page -