Sitemap

Java Reflection and OpenAPI generated class

Nash
3 min readOct 2, 2024

As developers, we experience different challenges while working on tasks, no matter how old or experienced we are. This is when we knock at stackoverflow’s door (my personal favourite) and others like baeldung, chatGPT, cursor, etc.

On a recent task, while confidently writing a generic method and using Java Reflection, I happened to stumble upon the NoSuchFieldException thrown by Reflection.

Let me demonstrate..!!

public class Student {
private int rollNo;
private String name;
private String phoneNo;
//constructor
//getter and setter
}

For a generic method, where any type of object can be passed as a parameter, Java Reflection allows us to get the specific field name.

public static <T> void testReflection(T param){
try {
Field sField = param.getClass().getDeclaredField("name");
sField.setAccessible(true);
System.out.println(sField.get(param));
}catch (NoSuchFieldException | IllegalAccessException ex){
System.out.println("Error occurred due to: "+ex);
}
}
public static void main(String[] args){
Student student = new Student(1, "JavaTest", "00000000");
testReflection(student);
}

//Output: JavaTest

Since it has the field “name” so the output will be the name of the student object passed.

This is a simple one, the real challenge is when we write a yaml file to define the API using OpenAPI and the class is auto generated upon executing the yaml file.

Let’s take the same Student and try to define in OpenAPI yaml file…

#some other fields and declaration
Student:
type: object
properties:
RollNo:
type: integer
format: int64
Name:
type: string
format: string
PhoneNo:
type: string
format: string

The auto generated class looks something like this..

public class Student{
public static final String SERIALIZED_NAME_ROLLNO = "RollNo";
@SerializedName(SERIALIZED_NAME_ROLLNO)
private Integer rollNo = null;

public static final String SERIALIZED_NAME_NAME = "Name";
@SerializedName(SERIALIZED_NAME_NAME)
private String name = null;

public static final String SERIALIZED_NAME_PHONENO = "PhoneNo";
@SerializedName(SERIALIZED_NAME_PHONENO)
private String phoneNo = null;

//getters and setters
}

Now I use the same process testReflection and this time it throws error NoSuchFieldException!!!!

Java Reflection throws NoSuchFieldException when the field is not defined in the object
Java Reflection Field Not Found Exception

So, I modified the code a bit to know the fields it contained.

Field[] fields = param.getClass().getDeclaredFields();
for(Field field: fields){
System.out.println(field.getName());
}

I was expecting the fields declared in the class Student would be printed but instead the fields like logger, categoryHelper, jacocoData was printed.

I scratched my head (confused!!) and started looking for solutions and I finally came to the following conclusion.

If the class is a proxy or instrumentation-related class, it may not directly be the class that contains your @SerializedName fields. This often happens in frameworks that use proxies (e.g., Spring, Hibernate, or JaCoCo).

Instead of using getClass() directly on student object, I need to get the super class using getTargetClass(object) which belongs to org.springframework.aop.support.AopUtils and then use getSuperclass().getDeclaredFields() to read the fields of the Student class.

Class<?> class = org.springframework.aop.support.AopUtils.getTargetClass(param);
Field sField = class.getSuperclass().getDeclaredField("name");

That’s it!!! It worked…!!!!

Hope the content of this article has successfully fulfilled its intended objectives and effectively addressed the goals it was meant to achieve.

--

--

Nash
Nash

Written by Nash

Software developer with a passion for Kubernetes, ML, and Networking. Committed to merging skills for innovative solutions.

No responses yet