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

Reply via email to