I’m trying to convert this ControllerAnnotationHelper into a service, and I’m getting weird issues.
No signature of method AnnotationScannerService.findAnnotatedClosures() is applicable for argument types:
(java.lang.Class, java.lang.Class) values: [class MyController, interface MyAnnotationRequired]
Here’s the original method:
private static Map<String, List<Class>> findAnnotatedClosures(
Class clazz, Class... annotationClasses) {
def map = [:]
for (field in clazz.declaredFields) {
def fieldAnnotations = []
for (annotationClass in annotationClasses) {
if (field.isAnnotationPresent(annotationClass)) {
fieldAnnotations << annotationClass
}
}
if (fieldAnnotations) {
map[field.name] = fieldAnnotations
}
}
return map
}
and mine:
protected Map<String, List<Class>> findAnnotatedClosures(Class clazz, Class... annotationClasses) {
def map = [:]
for (field in clazz.declaredFields) {
def fieldAnnotations = []
for (annotationClass in annotationClasses) {
if (field.isAnnotationPresent(annotationClass)) {
fieldAnnotations << annotationClass
}
}
if (fieldAnnotations) {
map[field.name] = fieldAnnotations
}
}
return map
}
With invocation:
public void test_findAnnotatedClosures() {
Map<String, List<Class>> annotatedClosures =
annotationScannerService.findAnnotatedClosures(MyController, MyRequiredAnnotation)
}
How can I declare this method such that I can call it with a controller class and the class of various annotation interfaces?
A non-public method in a service doesn’t make much sense in general. In particular in Grails it’s going to be problematic since by default services are transactional, so the instance you’ll be working with will be a proxy.
Only public methods are proxied. Protected methods are valid, but would typically just be used when subclassing and calling within the class or sub/super class.
So it boils down to a Groovy/Spring thing. We’re used to Groovy not being strict about access rules, but Grails services are almost purely Spring beans – Grails just lets you write them in Groovy, auto-creates the associated Spring bean, and automatically makes them transactional (unless that’s disabled).
Making the method static also works since you’re bypassing the proxy and going directly to the real class, and Groovy lets you call it even though it’s protected.