Use Java Reflection to Get Field w/ Accessor


Java is about objects. Reflection is about knowing things about those objects generally without have specific fields and methods in hand. I must get to one of those field values via its accessor, allowing me to keep the fields private and abstracted away... of course, until I start unit testing. Here's one method...

In our application, we use a jsf converter that converts the string representation of the a jpa-managed object into the object proper.

The required format of this string is thus:

fully.qualified.class.name:primarykey

I don't want to override the toString() method because we use it for other things. And, I don't want to have to create some method to return this formatted string to me in every class that I might want to call this on. So, I created a util method to do this for me.

public static String getEntityConverterString(Object o) {
   String retval = null;
   if (o != null) {
      String id = null;
      for (Field f : o.getClass().getDeclaredFields()) {
      if (f.isAnnotationPresent(Id.class)) {
         String getterName = "get" + StringUtils.capitalize(f.getName());
         for (Method m : o.getClass().getDeclaredMethods()) {
         if (m.getName().equals(getterName)) {
            try {
            Object idObj = m.invoke(o, null);
            if (idObj != null) {
               id = idObj.toString();
               break;
            }
            } catch (IllegalAccessException e) {
            throw new RuntimeException("Cannot find appropriate accessor for @Id field ");
            } catch (InvocationTargetException e) {
            throw new RuntimeException("Exception thrown w/in accessor");
            }
         }
         }
         break;
      }
      }
      retval = o.toString().split("@")[0] + ":" + id;
   }
   return retval;
}

The only stipulation to this working is that the class follows the JavaBean naming convention standard of "get" + capitalized field name following. Oh, and one more: this is only designed for @Entity's with one @Id field (no composite key).

This method goes through all fields, finds the one with the javax.persistence.Id interface annotation, then tries to find a matching accessor method. If it is found, it is executed, the value of the id field is given, finally to be used to create the specially formatted string.