[FREEMARKER-234] Expose Boolean isFoo() getters as bean properties#127
[FREEMARKER-234] Expose Boolean isFoo() getters as bean properties#127mapeders wants to merge 1 commit intoapache:2.3-gaefrom
Conversation
When an incompatible_improvements of 2.3.35 or higher is set, isFoo() methods that return java.lang.Boolean (the wrapper class) are now exposed as the foo bean property, matching the long-standing behaviour for primitive boolean and the contract promised in the manual. java.beans.Introspector follows the strict JavaBeans spec and only reports primitive-boolean is-getters, so ClassIntrospector now supplements its result with a targeted scan (mirroring the pattern already used for Java 8 default methods), and _MethodUtil accepts the wrapper return type. Static methods, and isFoo() methods with any other return type, remain excluded.
|
As stated in https://issues.apache.org/jira/browse/FREEMARKER-234 this is based on the Java Beans Specification Section 8.3.2 which is only for As suggested in the ticket, Freemarker should probably improve its documentation that |
|
Thanks @chrisrueger — fair point on 8.3.2, the current behavior is strictly That said, the FreeMarker manual already says model.foo invokes getFoo() or Happy either way though: if the committers prefer a docs-only fix, I'll gladly |
|
While this is not a bug, it's certainly quite annyoing and people keep running into it. But I will have to review the implementation to see if there's any cost involved that everyone has to pay, etc. |
Summary
Fixes FREEMARKER-234:
BeansWrapperdid not exposeisFoo()methods that returnjava.lang.Boolean(wrapper) as thefoobean property, even though the manual states thatmodel.fooshould invoke eitherobj.getFoo()orobj.isFoo(). The restriction to primitivebooleancame fromjava.beans.Introspector, which is strict to the JavaBeans spec.incompatible_improvements≥ 2.3.35 — pre-existing configurations see no change.ClassIntrospector.getPropertyDescriptorsnow supplementsjava.beans.Introspector's output by scanning forpublic Boolean isXxx()methods (mirroring the existing Java 8 default-method supplement path)._MethodUtil.getBeanPropertyNameFromReaderMethodNameacceptsBoolean.classalongsideboolean.class.isFoo()and non-BooleanisFoo()(e.g.String isLabel()) remain excluded from property exposure.Test plan
GetPropertyNameFromReaderMethodNameTest— flipped the assertion that codified the bug (isFoo+Boolean.class→"foo"), addedisF/Boolean.classsymmetry.BeansWrapperMiscTest.booleanWrapperIsGetterAsPropertyTest— verifies:.obsoleteis missing and only the method form is reachable..obsoleteresolves to the wrappedBoolean, primitiveboolean isActive()still works,String isLabel()is not exposed as a property,static Boolean isArchived()is not exposed as a property, andisObsoleteremains reachable as a method../gradlew :test --rerun-tasks).