Search code examples
javareflectiongeneric-programming

Is there a better way of obtaining an object's field getters other than java reflection api or i am misusing PropertyDescriptor's getReadMethod?


Context:

I am building an Excel document in a generic way with data i receive from a SOAP service endpoint. I receive the data as a List and i have the model (JavaBeans) for every Object i receive according to the method called. So I set the first row of the sheet as the header from the object's fields (getDeclaredFields). Then i go on filling up the column row by row with values from the list of objects.

The problem:

I haven't found a workable way of getting the object's field values. I have tried using the getters with the java reflection API with something like this answer's https://stackoverflow.com/a/5503534/4807777 findGetterName , findGetter however the PropertyDescriptor's getName sometimes is a different letter case from the field name as obtained from the class's getDeclaredFields.

Let's say i overcome this by capitalizing both names, the getReadMethod stil fails - doesn't seem to find getters for the fields which use the is prefix (i.e boolean fields). I don't know if i am misusing it or it is a bug (debugging the getReadMethod appears to only work with the get prefix, even though it appears to handle the is prefix case for booleans).

Considering the fact the fields aren't accesible outside of the object's package, therefore solely through invoking getters.

Is there a better way of obtaining the object's field getters or i am missing something with the getter methods?


Update: Spring's BeanUtils seems to be better for getting the properties with it's getPropertyDescriptors is better than java Class's getDeclaredFields, when the JavaBean properties are mapped to XML elements.

This fixes the different letter cases situation. However it stil doesn't find it's readMethod when not using the get prefix.


Edited - to show an example of getReadMethod not finding the is prefixed getter, as Laszlo Lugosi requested.

A simple class:

        class Test {
            private String assignmentType;
            private Boolean conserved;
            public String getAssignmentType() {return assignmentType;}
            public void setAssignmentType(String assignmentType) {this.assignmentType = assignmentType;}
            public Boolean isConserved() {return conserved;}
            public void setConserved(Boolean conserved) {this.conserved = conserved;}
        }

Run this with the findGetter and findGetterName written in the answer linked above:

{
    Test obj = new Test();
                obj.setAssignmentType("someType");
                obj.setConserved(true);
                Field[] fields = obj.getClass().getDeclaredFields();
                String fieldName;
                for (int i=0;i<fields.length;i++){
                    fieldName = fields[i].getName();
                    java.lang.reflect.Method method;
                    Object val = null;
                    try {
                        method = obj.getClass().getMethod(findGetterName(obj.getClass(),fieldName));
                        val = method.invoke(obj);
                    }
                    catch (Exception e){
                        e.printStackTrace();
                    }
                }
}


Edited 2 While i could simply write a getReadMethod following the convention Laszlo Lugosi highlighted i do prefer finding an API for handling accessors.


Solution

  • As you know only the object field name, and JavaBean has convention, you can figure out the getters easily. The rules are getUpperfieldname() and isUpperfieldname if field is boolean. And you can find out the return type as well from the object field.