BeanHelper.javaorg.apache.commons.lang3.ArrayUtils — Array concatenation for field/method collection across class hierarchyorg.apache.commons.lang3.StringUtils — String manipulation (capitalize, uncapitalize, split)java.lang.annotation.Annotation — Annotation discovery on fieldsjava.lang.reflect.* — Core Java reflection API: Field, Method, Constructor, Modifier, Array, InvocationTargetExceptionjava.util.* — Collections, iterators, hash maps for cachingorg.slf4j.Logger — Error logging for reflection failuresBeanHelper uses five static synchronized caches to avoid repeated reflection calls, which are expensive in Java. This is critical for Wicket list pages where BeanHelper is called for every cell in a sortable data table.
| Cache | Key | Value | Benefit |
|---|---|---|---|
declaredFieldsCache | Class | Field[] | Avoids re-scanning class hierarchy for fields |
declaredMethodsCache | Class | Method[] | Avoids re-scanning class hierarchy for methods |
declaredFieldAnnotationsCache | "class:fieldname" | Annotation[] | Avoids re-resolving annotated fields (critical for Wicket column sorting) |
getterMethodsCache | "class:fieldname" | Method | Avoids re-searching for getter methods |
declaredGetterMethodsCache | String | Method[] | Declared but appears unused in provided code — may be populated elsewhere |
determinePropertyName(Method) — Strips get/set/is/has prefix and lowercases first characterdetermineGetter(Class, fieldname, onlyPublicGetter) — Finds getter method (getX(), isX() for booleans, hasX() for booleans), handles bridge methods (not returning bridged synthetic methods)determineSetter(Class, fieldname) — Finds setter with single parameterdeterminePropertyType(Class, fieldname) — Gets the return type of the getter (property type)getDeclaredAnnotations(Class, fieldname) supports nested property paths (dot-separated, e.g., "address.city.name") by walking the field chain through reflection to find the terminal field's annotations. This is essential for Wicket data tables that display nested object properties with sortable columns.
getProperty(Object, String) — Invokes getter on a beansetProperty(Object, String, Object) — Invokes settergetIndexedProperty(Object, "prop[3]") — Supports collection/array indexed accessgetNestedProperty(Object, "a.b.c") — Walks dot-separated property path, handling nulls gracefully (returns null if any intermediate is null)Copies specified properties from source to destination object, returning true if any property actually changed. Supports:
Arrays.equals()Objects.equals() (null-safe)getAllDeclaredFields(Class) — Returns all fields including inherited ones, walking the superclass chaingetAllDeclaredMethods(Class) — Returns all methods including inherited onesgetDeclaredPropertyFields(Class) — Returns only non-transient, non-static, non-final fields (actual persistent properties)getFieldValue(Object, Class/String, fieldname) — Reads field value via reflection (setAccessible for private fields)newInstance(Class, ...) — Multiple overloads for reflective object construction with various constructor signaturesinvoke(Object, Method, args) — Generic method invocation with error handlingThe TEST_MODE flag (controlled by enterTestMode()/exitTestMode()) suppresses error logging during test execution. This allows tests to attempt reflection operations that are expected to fail without polluting test logs with stacktraces. The logInstantiationException() methods honor this flag.
determineGetter() skips bridge methods (synthetic methods created by the compiler for generic type erasure) to return the actual implemented methodgetNestedProperty() returns null at any point in the chain where an intermediate value is null, rather than throwing NPEnewInstance() calls constructor.setAccessible(true) to instantiate classes with private constructorscommons-beanutils in the Gradle build, BeanHelper implements its own property resolution rather than using Apache BeanUtils directly — likely for performance control and cachingisEqualList() helper (package-private) performs element-by-element comparison using iterators, not equals(). This means collection equality is based on element identity/equality of corresponding positions, not set equality — two lists with the same elements in different order are not equal.868d6abb7 2025 -> 2026 63081666f Source file headers: 2024-> 2025. a73905c14 Fix typos in projectforge*/ directories Found via codespell 694987647 Migration stuff in progress... (all tests of all packages: OK). ae50b2522 BeanHelper.getProperty supports now nested properties by simply using new PropertyUtils. b6092df09 Copyright 2023 -> 2024 ab45d51fa Copyright 2001-2022 -> 2001-2023. 0203e3261 AbstractListPage: long-running queries: change of sort order shows result list without search button. BeanHelper: lots of caches for faster sort in Wicket result lists.