You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@freemarker.apache.org by Niels Basjes <ni...@basjes.nl> on 2025/03/24 10:59:15 UTC
Accessing fields in a subclass of a Collection?
Hi,
I'm new to Freemarker and I'm looking for the right solution for
something I ran into but have not been able to figure out.
If I have a Java class like this:
public static class Team {
private final String name;
public Team(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
If I then make a TemplateTest like this
@Test
public void testTeamName() throws Exception {
Team team = new Team("Working");
addToDataModel("team", team);
assertEquals("Working", team.getName());
assertOutput("${team.name}","Working");
}
and it all works.
If I change my Team to be a subclass of a well known collection (I have
tried TreeMap, TreeSet and ArrayList) then my .name attribute is no longer
available in a template.
public static class TeamSet extends TreeSet<User> {
What is the proper way to solve this?
Perhaps a custom Object Wrapper?
Or is this something I should report as a bug?
Thanks.
Niels Basjes
nielsbasjes@apache.org
niels@basjes.nl
Re: Docs search broken on website
Posted by Daniel Dekany <da...@gmail.com>.
If anyone wants to investigate, please go ahead. (Otherwise eventually I
will get at it.)
On Mon, Mar 24, 2025 at 10:42 PM Simon Hartley
<sc...@yahoo.co.uk.invalid> wrote:
> Looking at the announcement here:
> https://lists.apache.org/thread/rkppw05ycmlnytxkcd1o0msm2n4wwbd6
> Perhaps emailing users@infra.apache.org would be more appropriate.
>
> Simon
>
>
>
> On Monday 24 March 2025 at 20:56:51 GMT, Simon Hartley <
> scrhartley@yahoo.co.uk> wrote:
>
>
> Looking at https://privacy.apache.org/policies/website-policy.html they
> already have exceptions for YouTube, Google Maps and social media links.
> If you email privacy@apache.org then you can ask if this could
> potentially be another exception or if there's a recommended solution for
> site search.
>
> Looking at their recommendation for YouTube, with permission, the
> workaround seems to involve modifying:
> https://github.com/apache/freemarker-site/blob/asf-site/.htaccess
>
> Simon
>
>
>
> On Monday 24 March 2025 at 20:44:28 GMT, Daniel Dekany <
> daniel.dekany@gmail.com> wrote:
>
>
> Ouch. If we are not supposed to call external services, then I believe we
> can't solve on site search with Google. Well, I could send the form to
> google.com with site:freemarker.apache.org though... kind of lame. Note
> sure if there's a common solution for this at Apache.
>
> Also there's a font we load from CDN apparently, and now that's also
> blocked. Had to check the licence to decide if we can store it locally
> (because then it has to be part of the source code too).
>
--
Best regards,
Daniel Dekany
Re: Docs search broken on website
Posted by Simon Hartley <sc...@yahoo.co.uk.INVALID>.
Looking at the announcement here: https://lists.apache.org/thread/rkppw05ycmlnytxkcd1o0msm2n4wwbd6
Perhaps emailing users@infra.apache.org would be more appropriate.
Simon
On Monday 24 March 2025 at 20:56:51 GMT, Simon Hartley <sc...@yahoo.co.uk> wrote:
Looking at https://privacy.apache.org/policies/website-policy.html they already have exceptions for YouTube, Google Maps and social media links.
If you email privacy@apache.org then you can ask if this could potentially be another exception or if there's a recommended solution for site search.
Looking at their recommendation for YouTube, with permission, the workaround seems to involve modifying:
https://github.com/apache/freemarker-site/blob/asf-site/.htaccess
Simon
On Monday 24 March 2025 at 20:44:28 GMT, Daniel Dekany <da...@gmail.com> wrote:
Ouch. If we are not supposed to call external services, then I believe we
can't solve on site search with Google. Well, I could send the form to
google.com with site:freemarker.apache.org though... kind of lame. Note
sure if there's a common solution for this at Apache.
Also there's a font we load from CDN apparently, and now that's also
blocked. Had to check the licence to decide if we can store it locally
(because then it has to be part of the source code too).
Re: Docs search broken on website
Posted by Simon Hartley <sc...@yahoo.co.uk.INVALID>.
Looking at https://privacy.apache.org/policies/website-policy.html they already have exceptions for YouTube, Google Maps and social media links.
If you email privacy@apache.org then you can ask if this could potentially be another exception or if there's a recommended solution for site search.
Looking at their recommendation for YouTube, with permission, the workaround seems to involve modifying:
https://github.com/apache/freemarker-site/blob/asf-site/.htaccess
Simon
On Monday 24 March 2025 at 20:44:28 GMT, Daniel Dekany <da...@gmail.com> wrote:
Ouch. If we are not supposed to call external services, then I believe we
can't solve on site search with Google. Well, I could send the form to
google.com with site:freemarker.apache.org though... kind of lame. Note
sure if there's a common solution for this at Apache.
Also there's a font we load from CDN apparently, and now that's also
blocked. Had to check the licence to decide if we can store it locally
(because then it has to be part of the source code too).
On Mon, Mar 24, 2025 at 3:39 PM Simon Hartley
<sc...@yahoo.co.uk.invalid> wrote:
Re: Docs search broken on website
Posted by Daniel Dekany <da...@gmail.com>.
Depends on if we can actually re-enable using these external services. (See
other answer.) If we can't, then yes, we should try this.
On Mon, Mar 24, 2025 at 10:15 PM Christoph Rueger <cr...@apache.org>
wrote:
> An option could be https://pagefind.app/
> It generates a local index at build time (e.g. using Github actions) by
> indexing the generated documentation's html.
> Adding search to the website requires a div with a specific id and a little
> JS snippet which is served from freemarker itself.
> The search looks and works like on the website above.
>
> regarding CSP they require
> script-src 'unsafe-eval'
> https://pagefind.app/docs/hosting/#content-security-policy-csp
>
> I have implemented this in two sites recently via github actions similar to
> this:
>
> https://willschenk.com/labnotes/2023/indexing_a_hugo_site_using_pagefind/#headline-3
>
> If something like this is wanted, I could try to help.
>
> Christoph
>
> Am Mo., 24. März 2025 um 21:45 Uhr schrieb Daniel Dekany <
> daniel.dekany@gmail.com>:
>
> > Ouch. If we are not supposed to call external services, then I believe we
> > can't solve on site search with Google. Well, I could send the form to
> > google.com with site:freemarker.apache.org though... kind of lame. Note
> > sure if there's a common solution for this at Apache.
> >
> > Also there's a font we load from CDN apparently, and now that's also
> > blocked. Had to check the licence to decide if we can store it locally
> > (because then it has to be part of the source code too).
> >
> > On Mon, Mar 24, 2025 at 3:39 PM Simon Hartley
> > <sc...@yahoo.co.uk.invalid> wrote:
> >
> > > This does not work for me:
> > > https://freemarker.apache.org/docs/search-results.html?q=hello
> > > I have tested in Chrome and FireFox.
> > > When looking in the console, I can see CSP errors, even for
> > > https://freemarker.apache.org/
> > >
> > > I assume the search problem is due to this one (Google Programmable
> > Search
> > > Engine / Google Custom Search):
> > > search-results.html?q=hello:52 Refused to load the script '
> > > https://cse.google.com/cse.js?cx=003127866208504630097:arjqbv_znfw'
> > > because it violates the following Content Security Policy directive:
> > > "script-src 'self' 'unsafe-inline' 'unsafe-eval'
> > > https://analytics.apache.org/ https://www.apachecon.com/". Note that
> > > 'script-src-elem' was not explicitly set, so 'script-src' is used as a
> > > fallback.
> > >
> > > Looking at the response headers I see:
> > > Content-Security-Policy:
> > > default-src 'self' data: blob: 'unsafe-inline'
> > https://www.apachecon.com/
> > > https://www.communityovercode.org/ https://analytics.apache.org/;
> > > script-src 'self' 'unsafe-inline' 'unsafe-eval'
> > > https://analytics.apache.org/ https://www.apachecon.com/; style-src
> > > 'self' 'unsafe-inline' data:; frame-ancestors 'self'; frame-src 'self'
> > > data: blob:; img-src 'self' data: https://*.apache.org/
> > > https://www.apachecon.com/; worker-src 'self' data: blob:;
> > >
> > > I assume the following is related: https://infra.apache.org/csp.html
> > (effective March
> > > 1, 2025)
> > > Reading https://privacy.apache.org/policies/website-policy.html:
> > > "Assets (JavaScript files or snippets, images, fonts, CSS, etc.) from
> > > other domains cannot be loaded. All assets need to be hosted on ASF
> > > servers."
> > >
> > > Regards,
> > > Simon
> > >
> >
> >
> > --
> > Best regards,
> > Daniel Dekany
> >
>
--
Best regards,
Daniel Dekany
Re: Docs search broken on website
Posted by Christoph Rueger <cr...@apache.org>.
An option could be https://pagefind.app/
It generates a local index at build time (e.g. using Github actions) by
indexing the generated documentation's html.
Adding search to the website requires a div with a specific id and a little
JS snippet which is served from freemarker itself.
The search looks and works like on the website above.
regarding CSP they require
script-src 'unsafe-eval'
https://pagefind.app/docs/hosting/#content-security-policy-csp
I have implemented this in two sites recently via github actions similar to
this:
https://willschenk.com/labnotes/2023/indexing_a_hugo_site_using_pagefind/#headline-3
If something like this is wanted, I could try to help.
Christoph
Am Mo., 24. März 2025 um 21:45 Uhr schrieb Daniel Dekany <
daniel.dekany@gmail.com>:
> Ouch. If we are not supposed to call external services, then I believe we
> can't solve on site search with Google. Well, I could send the form to
> google.com with site:freemarker.apache.org though... kind of lame. Note
> sure if there's a common solution for this at Apache.
>
> Also there's a font we load from CDN apparently, and now that's also
> blocked. Had to check the licence to decide if we can store it locally
> (because then it has to be part of the source code too).
>
> On Mon, Mar 24, 2025 at 3:39 PM Simon Hartley
> <sc...@yahoo.co.uk.invalid> wrote:
>
> > This does not work for me:
> > https://freemarker.apache.org/docs/search-results.html?q=hello
> > I have tested in Chrome and FireFox.
> > When looking in the console, I can see CSP errors, even for
> > https://freemarker.apache.org/
> >
> > I assume the search problem is due to this one (Google Programmable
> Search
> > Engine / Google Custom Search):
> > search-results.html?q=hello:52 Refused to load the script '
> > https://cse.google.com/cse.js?cx=003127866208504630097:arjqbv_znfw'
> > because it violates the following Content Security Policy directive:
> > "script-src 'self' 'unsafe-inline' 'unsafe-eval'
> > https://analytics.apache.org/ https://www.apachecon.com/". Note that
> > 'script-src-elem' was not explicitly set, so 'script-src' is used as a
> > fallback.
> >
> > Looking at the response headers I see:
> > Content-Security-Policy:
> > default-src 'self' data: blob: 'unsafe-inline'
> https://www.apachecon.com/
> > https://www.communityovercode.org/ https://analytics.apache.org/;
> > script-src 'self' 'unsafe-inline' 'unsafe-eval'
> > https://analytics.apache.org/ https://www.apachecon.com/; style-src
> > 'self' 'unsafe-inline' data:; frame-ancestors 'self'; frame-src 'self'
> > data: blob:; img-src 'self' data: https://*.apache.org/
> > https://www.apachecon.com/; worker-src 'self' data: blob:;
> >
> > I assume the following is related: https://infra.apache.org/csp.html
> (effective March
> > 1, 2025)
> > Reading https://privacy.apache.org/policies/website-policy.html:
> > "Assets (JavaScript files or snippets, images, fonts, CSS, etc.) from
> > other domains cannot be loaded. All assets need to be hosted on ASF
> > servers."
> >
> > Regards,
> > Simon
> >
>
>
> --
> Best regards,
> Daniel Dekany
>
Re: Docs search broken on website
Posted by Daniel Dekany <da...@gmail.com>.
Ouch. If we are not supposed to call external services, then I believe we
can't solve on site search with Google. Well, I could send the form to
google.com with site:freemarker.apache.org though... kind of lame. Note
sure if there's a common solution for this at Apache.
Also there's a font we load from CDN apparently, and now that's also
blocked. Had to check the licence to decide if we can store it locally
(because then it has to be part of the source code too).
On Mon, Mar 24, 2025 at 3:39 PM Simon Hartley
<sc...@yahoo.co.uk.invalid> wrote:
> This does not work for me:
> https://freemarker.apache.org/docs/search-results.html?q=hello
> I have tested in Chrome and FireFox.
> When looking in the console, I can see CSP errors, even for
> https://freemarker.apache.org/
>
> I assume the search problem is due to this one (Google Programmable Search
> Engine / Google Custom Search):
> search-results.html?q=hello:52 Refused to load the script '
> https://cse.google.com/cse.js?cx=003127866208504630097:arjqbv_znfw'
> because it violates the following Content Security Policy directive:
> "script-src 'self' 'unsafe-inline' 'unsafe-eval'
> https://analytics.apache.org/ https://www.apachecon.com/". Note that
> 'script-src-elem' was not explicitly set, so 'script-src' is used as a
> fallback.
>
> Looking at the response headers I see:
> Content-Security-Policy:
> default-src 'self' data: blob: 'unsafe-inline' https://www.apachecon.com/
> https://www.communityovercode.org/ https://analytics.apache.org/;
> script-src 'self' 'unsafe-inline' 'unsafe-eval'
> https://analytics.apache.org/ https://www.apachecon.com/; style-src
> 'self' 'unsafe-inline' data:; frame-ancestors 'self'; frame-src 'self'
> data: blob:; img-src 'self' data: https://*.apache.org/
> https://www.apachecon.com/; worker-src 'self' data: blob:;
>
> I assume the following is related: https://infra.apache.org/csp.html (effective March
> 1, 2025)
> Reading https://privacy.apache.org/policies/website-policy.html:
> "Assets (JavaScript files or snippets, images, fonts, CSS, etc.) from
> other domains cannot be loaded. All assets need to be hosted on ASF
> servers."
>
> Regards,
> Simon
>
--
Best regards,
Daniel Dekany
Docs search broken on website
Posted by Simon Hartley <sc...@yahoo.co.uk.INVALID>.
This does not work for me: https://freemarker.apache.org/docs/search-results.html?q=hello
I have tested in Chrome and FireFox.
When looking in the console, I can see CSP errors, even for https://freemarker.apache.org/
I assume the search problem is due to this one (Google Programmable Search Engine / Google Custom Search):
search-results.html?q=hello:52 Refused to load the script 'https://cse.google.com/cse.js?cx=003127866208504630097:arjqbv_znfw' because it violates the following Content Security Policy directive: "script-src 'self' 'unsafe-inline' 'unsafe-eval' https://analytics.apache.org/ https://www.apachecon.com/". Note that 'script-src-elem' was not explicitly set, so 'script-src' is used as a fallback.
Looking at the response headers I see:
Content-Security-Policy:
default-src 'self' data: blob: 'unsafe-inline' https://www.apachecon.com/ https://www.communityovercode.org/ https://analytics.apache.org/; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://analytics.apache.org/ https://www.apachecon.com/; style-src 'self' 'unsafe-inline' data:; frame-ancestors 'self'; frame-src 'self' data: blob:; img-src 'self' data: https://*.apache.org/ https://www.apachecon.com/; worker-src 'self' data: blob:;
I assume the following is related: https://infra.apache.org/csp.html (effective March 1, 2025)
Reading https://privacy.apache.org/policies/website-policy.html:
"Assets (JavaScript files or snippets, images, fonts, CSS, etc.) from other domains cannot be loaded. All assets need to be hosted on ASF servers."
Regards,
Simon
Re: Accessing fields in a subclass of a Collection?
Posted by Niels Basjes <ni...@basjes.nl>.
Hi,
Thanks for this clear explanation.
I'm going to change my code accordingly.
Niels
On Tue, Mar 25, 2025 at 10:37 PM Daniel Dekany <da...@gmail.com>
wrote:
> The main reason is that unlike in the Java language, in the template
> language there's no separate namespace for methods, and collection
> elements. There's actually a setting in BeansWrapper to expose both, but
> because of the common namespace that leads to some ambiguities and
> surprises. The problem is the most obvious with Map-s, where myObj.name in
> the template can mean both myObject.getName() or myObject.get("name") in
> Java. And then, what should we return when you list myObject with #list?
> Should we return a mix of Map keys, and Java method names? Things like
> that.
>
> The secondary reason is hiding the technical details of the model. If one
> day there's change in the data-model where something that was once an array
> is now List, your templates won't break, because the template never seens
> them as a List or an array, but as a "sequence", which is the native type
> of the template language. By the way, in the rare case where you still want
> to access the Java API, you can use ?api, like this: team?api.name
>
> As a historical perspective, FreeMarker originally didn't support
> accessing properties, or calling methods. You had to put together the
> data-model explicitly from the native types.
>
> On Tue, Mar 25, 2025 at 7:01 PM Niels Basjes <ni...@basjes.nl> wrote:
>
> > Hi,
> >
> > Thanks, this really helps.
> >
> > Just curious; What is the reason for making this distinction?
> > Why does the DefaultObjectWrapper expose the getters of a Pojo, but it
> does
> > not expose them if it implements one of the mentioned collections?
> > Is it possible to combine the two effects and do both (both making it
> #list
> > capable and getting the custom fields)?
> >
> > Niels
> >
> > On Mon, Mar 24, 2025 at 9:28 PM Daniel Dekany <da...@gmail.com>
> > wrote:
> >
> > > It's because if Team implements Set, List, Map, etc., then, by default,
> > it
> > > will only see the Collection/Map elements, and not the Java methods of
> > the
> > > object.
> > >
> > > Probably the cleanest/idiomatic solution is if Team is not a Set, but
> > > instead has a method like Set<User> getUsers(). Regardless of
> FreeMarker,
> > > that's what I would do as a Java programmer.
> > >
> > > But if it must be a Set, you can force FreeMarker to ignore that like
> > this:
> > >
> > > So you can do this:
> > >
> > > public static class CustomObjectWrapper extends
> DefaultObjectWrapper
> > {
> > > public CustomObjectWrapper(Version incompatibleImprovements) {
> > > super(incompatibleImprovements);
> > > }
> > >
> > > @Override
> > > public TemplateModel wrap(Object obj) throws
> > TemplateModelException
> > > {
> > > if (obj instanceof Team) {
> > > return new GenericObjectModel(obj, this);
> > > }
> > > return super.wrap(obj);
> > > }
> > > }
> > >
> > > and then where you create your Configuration singleton:
> > >
> > > configuration.setObjectWrapper(new
> > > CustomObjectWrapper(Configuration.VERSION_2_3_35));
> > >
> > > Although now that being a Set was ignored, team is not #list-able in
> the
> > > template (except with directly calling the Set API-s).
> > >
> > >
> > > On Mon, Mar 24, 2025 at 12:00 PM Niels Basjes <ni...@basjes.nl> wrote:
> > >
> > > > Hi,
> > > >
> > > > I'm new to Freemarker and I'm looking for the right solution for
> > > > something I ran into but have not been able to figure out.
> > > >
> > > > If I have a Java class like this:
> > > >
> > > > public static class Team {
> > > > private final String name;
> > > > public Team(String name) {
> > > > this.name = name;
> > > > }
> > > > public String getName() {
> > > > return name;
> > > > }
> > > > }
> > > >
> > > > If I then make a TemplateTest like this
> > > >
> > > > @Test
> > > > public void testTeamName() throws Exception {
> > > > Team team = new Team("Working");
> > > > addToDataModel("team", team);
> > > > assertEquals("Working", team.getName());
> > > > assertOutput("${team.name}","Working");
> > > > }
> > > >
> > > > and it all works.
> > > > If I change my Team to be a subclass of a well known collection (I
> have
> > > > tried TreeMap, TreeSet and ArrayList) then my .name attribute is no
> > > longer
> > > > available in a template.
> > > >
> > > > public static class TeamSet extends TreeSet<User> {
> > > >
> > > >
> > > > What is the proper way to solve this?
> > > > Perhaps a custom Object Wrapper?
> > > > Or is this something I should report as a bug?
> > > >
> > > > Thanks.
> > > >
> > > > Niels Basjes
> > > > nielsbasjes@apache.org
> > > > niels@basjes.nl
> > > >
> > >
> > >
> > > --
> > > Best regards,
> > > Daniel Dekany
> > >
> >
>
>
> --
> Best regards,
> Daniel Dekany
>
Re: Accessing fields in a subclass of a Collection?
Posted by Daniel Dekany <da...@gmail.com>.
The main reason is that unlike in the Java language, in the template
language there's no separate namespace for methods, and collection
elements. There's actually a setting in BeansWrapper to expose both, but
because of the common namespace that leads to some ambiguities and
surprises. The problem is the most obvious with Map-s, where myObj.name in
the template can mean both myObject.getName() or myObject.get("name") in
Java. And then, what should we return when you list myObject with #list?
Should we return a mix of Map keys, and Java method names? Things like that.
The secondary reason is hiding the technical details of the model. If one
day there's change in the data-model where something that was once an array
is now List, your templates won't break, because the template never seens
them as a List or an array, but as a "sequence", which is the native type
of the template language. By the way, in the rare case where you still want
to access the Java API, you can use ?api, like this: team?api.name
As a historical perspective, FreeMarker originally didn't support
accessing properties, or calling methods. You had to put together the
data-model explicitly from the native types.
On Tue, Mar 25, 2025 at 7:01 PM Niels Basjes <ni...@basjes.nl> wrote:
> Hi,
>
> Thanks, this really helps.
>
> Just curious; What is the reason for making this distinction?
> Why does the DefaultObjectWrapper expose the getters of a Pojo, but it does
> not expose them if it implements one of the mentioned collections?
> Is it possible to combine the two effects and do both (both making it #list
> capable and getting the custom fields)?
>
> Niels
>
> On Mon, Mar 24, 2025 at 9:28 PM Daniel Dekany <da...@gmail.com>
> wrote:
>
> > It's because if Team implements Set, List, Map, etc., then, by default,
> it
> > will only see the Collection/Map elements, and not the Java methods of
> the
> > object.
> >
> > Probably the cleanest/idiomatic solution is if Team is not a Set, but
> > instead has a method like Set<User> getUsers(). Regardless of FreeMarker,
> > that's what I would do as a Java programmer.
> >
> > But if it must be a Set, you can force FreeMarker to ignore that like
> this:
> >
> > So you can do this:
> >
> > public static class CustomObjectWrapper extends DefaultObjectWrapper
> {
> > public CustomObjectWrapper(Version incompatibleImprovements) {
> > super(incompatibleImprovements);
> > }
> >
> > @Override
> > public TemplateModel wrap(Object obj) throws
> TemplateModelException
> > {
> > if (obj instanceof Team) {
> > return new GenericObjectModel(obj, this);
> > }
> > return super.wrap(obj);
> > }
> > }
> >
> > and then where you create your Configuration singleton:
> >
> > configuration.setObjectWrapper(new
> > CustomObjectWrapper(Configuration.VERSION_2_3_35));
> >
> > Although now that being a Set was ignored, team is not #list-able in the
> > template (except with directly calling the Set API-s).
> >
> >
> > On Mon, Mar 24, 2025 at 12:00 PM Niels Basjes <ni...@basjes.nl> wrote:
> >
> > > Hi,
> > >
> > > I'm new to Freemarker and I'm looking for the right solution for
> > > something I ran into but have not been able to figure out.
> > >
> > > If I have a Java class like this:
> > >
> > > public static class Team {
> > > private final String name;
> > > public Team(String name) {
> > > this.name = name;
> > > }
> > > public String getName() {
> > > return name;
> > > }
> > > }
> > >
> > > If I then make a TemplateTest like this
> > >
> > > @Test
> > > public void testTeamName() throws Exception {
> > > Team team = new Team("Working");
> > > addToDataModel("team", team);
> > > assertEquals("Working", team.getName());
> > > assertOutput("${team.name}","Working");
> > > }
> > >
> > > and it all works.
> > > If I change my Team to be a subclass of a well known collection (I have
> > > tried TreeMap, TreeSet and ArrayList) then my .name attribute is no
> > longer
> > > available in a template.
> > >
> > > public static class TeamSet extends TreeSet<User> {
> > >
> > >
> > > What is the proper way to solve this?
> > > Perhaps a custom Object Wrapper?
> > > Or is this something I should report as a bug?
> > >
> > > Thanks.
> > >
> > > Niels Basjes
> > > nielsbasjes@apache.org
> > > niels@basjes.nl
> > >
> >
> >
> > --
> > Best regards,
> > Daniel Dekany
> >
>
--
Best regards,
Daniel Dekany
Re: Accessing fields in a subclass of a Collection?
Posted by Niels Basjes <ni...@basjes.nl>.
Hi,
Thanks, this really helps.
Just curious; What is the reason for making this distinction?
Why does the DefaultObjectWrapper expose the getters of a Pojo, but it does
not expose them if it implements one of the mentioned collections?
Is it possible to combine the two effects and do both (both making it #list
capable and getting the custom fields)?
Niels
On Mon, Mar 24, 2025 at 9:28 PM Daniel Dekany <da...@gmail.com>
wrote:
> It's because if Team implements Set, List, Map, etc., then, by default, it
> will only see the Collection/Map elements, and not the Java methods of the
> object.
>
> Probably the cleanest/idiomatic solution is if Team is not a Set, but
> instead has a method like Set<User> getUsers(). Regardless of FreeMarker,
> that's what I would do as a Java programmer.
>
> But if it must be a Set, you can force FreeMarker to ignore that like this:
>
> So you can do this:
>
> public static class CustomObjectWrapper extends DefaultObjectWrapper {
> public CustomObjectWrapper(Version incompatibleImprovements) {
> super(incompatibleImprovements);
> }
>
> @Override
> public TemplateModel wrap(Object obj) throws TemplateModelException
> {
> if (obj instanceof Team) {
> return new GenericObjectModel(obj, this);
> }
> return super.wrap(obj);
> }
> }
>
> and then where you create your Configuration singleton:
>
> configuration.setObjectWrapper(new
> CustomObjectWrapper(Configuration.VERSION_2_3_35));
>
> Although now that being a Set was ignored, team is not #list-able in the
> template (except with directly calling the Set API-s).
>
>
> On Mon, Mar 24, 2025 at 12:00 PM Niels Basjes <ni...@basjes.nl> wrote:
>
> > Hi,
> >
> > I'm new to Freemarker and I'm looking for the right solution for
> > something I ran into but have not been able to figure out.
> >
> > If I have a Java class like this:
> >
> > public static class Team {
> > private final String name;
> > public Team(String name) {
> > this.name = name;
> > }
> > public String getName() {
> > return name;
> > }
> > }
> >
> > If I then make a TemplateTest like this
> >
> > @Test
> > public void testTeamName() throws Exception {
> > Team team = new Team("Working");
> > addToDataModel("team", team);
> > assertEquals("Working", team.getName());
> > assertOutput("${team.name}","Working");
> > }
> >
> > and it all works.
> > If I change my Team to be a subclass of a well known collection (I have
> > tried TreeMap, TreeSet and ArrayList) then my .name attribute is no
> longer
> > available in a template.
> >
> > public static class TeamSet extends TreeSet<User> {
> >
> >
> > What is the proper way to solve this?
> > Perhaps a custom Object Wrapper?
> > Or is this something I should report as a bug?
> >
> > Thanks.
> >
> > Niels Basjes
> > nielsbasjes@apache.org
> > niels@basjes.nl
> >
>
>
> --
> Best regards,
> Daniel Dekany
>
Re: Accessing fields in a subclass of a Collection?
Posted by Daniel Dekany <da...@gmail.com>.
It's because if Team implements Set, List, Map, etc., then, by default, it
will only see the Collection/Map elements, and not the Java methods of the
object.
Probably the cleanest/idiomatic solution is if Team is not a Set, but
instead has a method like Set<User> getUsers(). Regardless of FreeMarker,
that's what I would do as a Java programmer.
But if it must be a Set, you can force FreeMarker to ignore that like this:
So you can do this:
public static class CustomObjectWrapper extends DefaultObjectWrapper {
public CustomObjectWrapper(Version incompatibleImprovements) {
super(incompatibleImprovements);
}
@Override
public TemplateModel wrap(Object obj) throws TemplateModelException
{
if (obj instanceof Team) {
return new GenericObjectModel(obj, this);
}
return super.wrap(obj);
}
}
and then where you create your Configuration singleton:
configuration.setObjectWrapper(new
CustomObjectWrapper(Configuration.VERSION_2_3_35));
Although now that being a Set was ignored, team is not #list-able in the
template (except with directly calling the Set API-s).
On Mon, Mar 24, 2025 at 12:00 PM Niels Basjes <ni...@basjes.nl> wrote:
> Hi,
>
> I'm new to Freemarker and I'm looking for the right solution for
> something I ran into but have not been able to figure out.
>
> If I have a Java class like this:
>
> public static class Team {
> private final String name;
> public Team(String name) {
> this.name = name;
> }
> public String getName() {
> return name;
> }
> }
>
> If I then make a TemplateTest like this
>
> @Test
> public void testTeamName() throws Exception {
> Team team = new Team("Working");
> addToDataModel("team", team);
> assertEquals("Working", team.getName());
> assertOutput("${team.name}","Working");
> }
>
> and it all works.
> If I change my Team to be a subclass of a well known collection (I have
> tried TreeMap, TreeSet and ArrayList) then my .name attribute is no longer
> available in a template.
>
> public static class TeamSet extends TreeSet<User> {
>
>
> What is the proper way to solve this?
> Perhaps a custom Object Wrapper?
> Or is this something I should report as a bug?
>
> Thanks.
>
> Niels Basjes
> nielsbasjes@apache.org
> niels@basjes.nl
>
--
Best regards,
Daniel Dekany