@@ -74,31 +74,38 @@ static void set(Field field, Object obj, Object value) throws IllegalAccessExcep
7474 * Gets a property value from an object, trying both field access and getter method.
7575 */
7676 private static Object getPropertyValue (Object obj , String propertyName ) throws IllegalAccessException {
77+ if (propertyName == null || propertyName .isEmpty ()) {
78+ throw new IllegalAccessException ("Property name cannot be null or empty" );
79+ }
80+
7781 // Try to find the field in the object's class
7882 Field realField = findFieldInHierarchy (obj .getClass (), propertyName );
7983 if (realField != null ) {
8084 realField .setAccessible (true );
8185 return realField .get (obj );
8286 }
8387
84- // Fall back to getter method
88+ // Fall back to getter method - try both 'get' and 'is' prefixes
8589 try {
86- String getterName = "get" + Character .toUpperCase (propertyName .charAt (0 ));
87- if (propertyName .length () > 1 ) {
88- getterName += propertyName .substring (1 );
90+ Method getter = findGetterMethod (obj .getClass (), propertyName );
91+ if (getter != null ) {
92+ getter .setAccessible (true );
93+ return getter .invoke (obj );
8994 }
90- Method getter = obj .getClass ().getMethod (getterName );
91- getter .setAccessible (true );
92- return getter .invoke (obj );
95+ throw new IllegalAccessException ("No getter method found for property '" + propertyName + "'" );
9396 } catch (Exception e ) {
94- throw new IllegalAccessException ("Cannot access property '" + propertyName + "' on " + obj .getClass ().getName ());
97+ throw new IllegalAccessException ("Cannot access property '" + propertyName + "' on " + obj .getClass ().getName () + ": " + e . getMessage () );
9598 }
9699 }
97100
98101 /**
99102 * Sets a property value on an object, trying both field access and setter method.
100103 */
101104 private static void setPropertyValue (Object obj , String propertyName , Object value ) throws IllegalAccessException {
105+ if (propertyName == null || propertyName .isEmpty ()) {
106+ throw new IllegalAccessException ("Property name cannot be null or empty" );
107+ }
108+
102109 // Try to find the field in the object's class
103110 Field realField = findFieldInHierarchy (obj .getClass (), propertyName );
104111 if (realField != null ) {
@@ -109,10 +116,7 @@ private static void setPropertyValue(Object obj, String propertyName, Object val
109116
110117 // Fall back to setter method
111118 try {
112- String setterName = "set" + Character .toUpperCase (propertyName .charAt (0 ));
113- if (propertyName .length () > 1 ) {
114- setterName += propertyName .substring (1 );
115- }
119+ String setterName = "set" + capitalizePropertyName (propertyName );
116120 Method setter = findSetterMethod (obj .getClass (), setterName , value );
117121 if (setter != null ) {
118122 setter .setAccessible (true );
@@ -124,6 +128,38 @@ private static void setPropertyValue(Object obj, String propertyName, Object val
124128 throw new IllegalAccessException ("Cannot set property '" + propertyName + "' on " + obj .getClass ().getName () + ": " + e .getMessage ());
125129 }
126130 }
131+
132+ /**
133+ * Finds a getter method for a property (tries both 'get' and 'is' prefixes).
134+ */
135+ private static Method findGetterMethod (Class <?> clazz , String propertyName ) {
136+ String capitalizedName = capitalizePropertyName (propertyName );
137+ String getterName = "get" + capitalizedName ;
138+ String isGetterName = "is" + capitalizedName ;
139+
140+ Method [] methods = clazz .getMethods ();
141+ for (Method method : methods ) {
142+ if ((method .getName ().equals (getterName ) || method .getName ().equals (isGetterName ))
143+ && method .getParameterTypes ().length == 0 ) {
144+ return method ;
145+ }
146+ }
147+ return null ;
148+ }
149+
150+ /**
151+ * Capitalizes a property name following JavaBeans conventions.
152+ */
153+ private static String capitalizePropertyName (String propertyName ) {
154+ if (propertyName == null || propertyName .isEmpty ()) {
155+ return propertyName ;
156+ }
157+ // Follow JavaBeans convention: if first two chars are uppercase, don't change
158+ if (propertyName .length () > 1 && Character .isUpperCase (propertyName .charAt (0 )) && Character .isUpperCase (propertyName .charAt (1 ))) {
159+ return propertyName ;
160+ }
161+ return Character .toUpperCase (propertyName .charAt (0 )) + propertyName .substring (1 );
162+ }
127163
128164 /**
129165 * Finds a field in the class hierarchy.
0 commit comments