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 <daniel.dek...@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 > > nielsbas...@apache.org > > ni...@basjes.nl > > > > > -- > Best regards, > Daniel Dekany >