If a class has a public method something() and a private method hasSomething(), Pebble would first try to call the latter one and that would cause an exception to be thrown if the class is part of JDK. I just ran into this behavior once again. Template:
{{ to.iterator().next() }}
Exception:
java.lang.reflect.InaccessibleObjectException: Unable to make public boolean java.util.ImmutableCollections$Set12$1.hasNext() accessible: module java.base does not "opens java.util" to unnamed module @4e04a765
at java.base/java.lang.reflect.AccessibleObject.throwInaccessibleObjectException(AccessibleObject.java:391)
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:367)
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:315)
at java.base/java.lang.reflect.Method.checkCanSetAccessible(Method.java:203)
at java.base/java.lang.reflect.Method.setAccessible(Method.java:197)
at io.pebbletemplates.pebble.attributes.MemberCacheUtils.reflect(MemberCacheUtils.java:103)
at io.pebbletemplates.pebble.attributes.MemberCacheUtils.cacheMember(MemberCacheUtils.java:32)
at io.pebbletemplates.pebble.attributes.DefaultAttributeResolver.resolve(DefaultAttributeResolver.java:64)
at io.pebbletemplates.pebble.node.expression.GetAttributeExpression.evaluate(GetAttributeExpression.java:83)
at io.pebbletemplates.pebble.node.expression.FilterExpression.evaluate(FilterExpression.java:66)
at io.pebbletemplates.pebble.node.PrintNode.render(PrintNode.java:37)
at io.pebbletemplates.pebble.node.BodyNode.render(BodyNode.java:44)
at io.pebbletemplates.pebble.node.RootNode.render(RootNode.java:31)
at io.pebbletemplates.pebble.template.PebbleTemplateImpl.evaluate(PebbleTemplateImpl.java:157)
at io.pebbletemplates.pebble.template.PebbleTemplateImpl.evaluate(PebbleTemplateImpl.java:105)
at smithereen.templates.RenderedTemplateResponse.renderToWriter(RenderedTemplateResponse.java:103)
at smithereen.SmithereenApplication.lambda$main$45(SmithereenApplication.java:614)
...
I never intended to call hasNext(), I wanted to call literally what I wrote but Pebble won't let me.
If a class has a public method
something()
and a private methodhasSomething()
, Pebble would first try to call the latter one and that would cause an exception to be thrown if the class is part of JDK. I just ran into this behavior once again. Template:Exception:
I never intended to call
hasNext()
, I wanted to call literally what I wrote but Pebble won't let me.The problem is here: https://github.com/PebbleTemplates/pebble/blob/master/pebble/src/main/java/io/pebbletemplates/pebble/attributes/MemberCacheUtils.java#L68-L100 It first checks all the made-up methods, and only then, if none of them exist (regardless of the access), looks for the one I intended. That could lead to all kinds of hard-to-debug bugs. IMO "check if attribute is a public method" should come first.