[
https://issues.apache.org/jira/browse/FREEMARKER-183?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17751032#comment-17751032
]
Dániel Dékány edited comment on FREEMARKER-183 at 8/4/23 8:45 AM:
------------------------------------------------------------------
The temporary workaround is probably somewhat similar to this issue:
[https://stackoverflow.com/questions/32201528/not-able-to-read-object-values-in-freemarker-template]
Of course this will have to be supported from the core. That they have broken
the bean property read method pattern shows (yet again) how much they are out
of touch with reality at this point, but we have to deal with it anyway.
So it's doable, for records. But, the bigger issue is that now that we have
this precedent, the pattern of having {{T foo()}} instead of {{T getFoo()}}
might will spread. That means that eventually, we might have to allow calling
any random public 0 argument non-void returning method like {{{}obj.foo{}}},
instead of like {{{}obj.foo(){}}}. We can do that, technically, but then, in
non-record types it's not obvious if such a method meant to just read some sort
of variable, or it has side-effects, and the return value is just secondary
information. (I know, that a method name starts with "get"/"is" never
guaranteed that it really just a typical read method either, but in practice,
it's huge difference compared to treating any 0-arg non-void methods like that,
when it comes to keeping templates free of this kind of abuses.) Also, when you
know that the {{foo}} method has side effects, and thus you do want to call it
like {{obj.foo()}} in the template, then you can't anymore, if we do this for
non-records, as the return value of {{obj.foo}} in the template language is not
a method anymore, so you can't follow it with `()`. Yes, we support
multi-types, but they are kind of painful because of the ambiguities they can
cause, and also have a small performance impact, so that would be too awkward
for a such common case. So it sounds like we will even have to change the
language more fundamentally, so that we can have separate property and method
namespace inside the objects, and so that `obj.foo` and `obj.foo()` will search
"foo" in different namespaces. Anyway, first we can just add support for
records of course.
Also it raises the question, how do you get that member as a method reference
(like {{obj.myMethod}} does currently)? I guess, the solution will be something
like `?api`. That is, you can ask for an alternative view of the object, let's
say with `?methods`, and that view only contains methods, and never implicitly
calls them.
was (Author: ddekany):
The temporary workaround is probably somewhat similar to this issue:
[https://stackoverflow.com/questions/32201528/not-able-to-read-object-values-in-freemarker-template]
Of course this will have to be supported from the core. That they have broken
the bean property read method pattern shows (yet again) how much they are out
of touch with reality at this point, but we have to deal with it anyway.
So it's doable, for records. But, the bigger issue is that now that we have
this precedent, the pattern of having {{T foo()}} instead of {{T getFoo()}}
might will spread. That means that eventually, we might have to allow calling
any random public 0 argument non-void returning method like {{{}obj.foo{}}},
instead of like {{{}obj.foo(){}}}. We can do that, technically, but then, in
non-record types it's not obvious if such a method meant to just read some sort
of variable, or it has side-effects, and the return value is just secondary
information. (I know, that a method name starts with "get"/"is" didn't
guarantee that it really just a typical read method either, but in practice,
it's huge difference compared to treating any 0-arg non-void methods like that,
when it comes to keeping template free of this kind of abuses.) Actually, it's
worse. What if you know that the {{foo}} method has side effect, and you do
want to call it like {{obj.foo()}} in the template? Well, you can't anymore, if
we do this for non-records, as the return value of {{obj.foo}} in the template
language is not a method anymore, so you can't follow it with `()`. Yes, we
support multi-types, but they are kind of painful because of the ambiguities
they can cause, and also have a small performance impact. So it sounds like we
will even have to change the language more fundamentally, so that we can have
separate property and method namespace inside the objects, etc.
Also it raises the question, how do you get that member as a method reference
(like {{obj.myMethod}} does currently)? I guess, the solution will be something
like `?api`. That is, you can ask for an alternative view of the object, let's
say with `?methods`, and that view only contains methods, and never implicitly
calls them.
> Add support for Java records
> ----------------------------
>
> Key: FREEMARKER-183
> URL: https://issues.apache.org/jira/browse/FREEMARKER-183
> Project: Apache Freemarker
> Issue Type: Task
> Reporter: Dániel Dékány
> Assignee: Dániel Dékány
> Priority: Major
>
> Currently we don't support records (JEP 395), which was finalized in Java 16.
> Users can extend {{DefaultObjectWrapper}} for that of course, but it should
> be supported out of the box.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)