Cléssio Mendes
Cléssio Mendes

Reputation: 1016

Accessing field annotations on Grails domain classes

I'm trying to annotate fields over my domain classes but I'm not able to get them at runtime by reflection as usual Java fields.

My annotated domain class looks like:

class MyDomainClass {
    @MyAnnotation
    String myField
}

The Java way to access myField by reflection doesn't work:

MyDomainClass.class.getField("myField") //throws java.lang.NoSuchFieldException

The Grails way to inspect domain classes doesn't expose field annotations:

new DefaultGrailsDomainClass(MyDomainClass).getPersistentProperty("myField").??? //there is nothing similar to getAnnotations()

How can I retrieve the annotations associated with a domain field?

Upvotes: 1

Views: 1200

Answers (1)

Burt Beckwith
Burt Beckwith

Reputation: 75681

That's not a field, it's a property. When you declare a class-scope variable like that with no scope modifier (public, protected, etc.) in a Groovy class, the Groovy compiler converts it to a private field with the same type and name, and a getter and setter method, essentially

class MyDomainClass {
   @MyAnnotation
   private String myField

   public String getMyField() {
      return myField
   }
   public void setMyField(String s) {
      myField = s
   }
}

It won't overwrite an existing getter or setter though.

When you access the property you end up calling the getter or setter, which you can see if you add those methods and include println statements. This way Java classes can access the property via those methods, and Groovy pretends that you're directly reading or writing a field but under the hood you end up calling the same methods that you would from Java.

One benefit of this is that if you decide later that you want to add some logic when setting or getting the value, you can define the corresponding method(s) and add what you want without needing to change the code that accesses the property since in Groovy you can still treat it like a field and your custom methods will be called, and Java classes will have been calling the setter and getter all along.

getFields() returns only public fields, but getDeclaredFields() returns all of them, so since the actual field is private that's why getDeclaredFields() (or the property access form declaredFields) is necessary.

Grails doesn't use annotations because Graeme (and others) feel that they're ugly and bulky, not because they're not accessible.

Upvotes: 1

Related Questions