Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Freemarker: Iterate over a LinkedHashMap

Tags:

freemarker

I have following piece of code -

public class Result {
    private Map<String, String> dataPoints = new LinkedHashMap<String, String>();

    public Map<String, String> getData() {
        return Maps.newHashMap(data);
    }

    public Set<Map.Entry<String, String>> getDataEntries() {
        return data.entrySet();
    }

    public void addData(final String key, final String value) {
        this.data.put(key, value);
    }
}

I am using LinkedHashMap as I want to maintain insertion order. I am trying to iterate over the map in my freemarker code as below. However, I get an exception.

<#if (result.dataPoints?keys?size > 0) >
    <#list result.getDataEntries() as entry>
        <tr>
            <td width="35%">
                <div>${entry.key}</div>
            </td>
            <td width="45%">${entry.value}</td>
            <td width="19%">&nbsp;</td>
        </tr>
    </#list>
</#if>

Exception:

Expression result.getDataEntries is undefined on line 50, column 24 in settings/settings-
diagnostics.ftl. The problematic instruction: ---------- ==> list result.getDataEntries() 
as entry [on line 50, column 17 in settings/settings-diagnostics.ftl] in user-directive 
printDiagnosticResult [on line 64, column 25 in settings/settings-diagnostics.ftl] in 
user-directive printDiagnosticResult [on line 76, column 13 in settings/settings-
diagnostics.ftl] in user-directive layout.landingbase [on line 1, column 1 in     
settings/settings-diagnostics.ftl] ---------- Java backtrace for programmers: ---------- 
freemarker.core.InvalidReferenceException: Expression result.getDataEntries is undefined 
on line 50, column 24 in settings/settings-diagnostics.ftl. at 
freemarker.core.TemplateObject.assertNonNull(TemplateObject.java:124) at 
freemarker.core.TemplateObject.invalidTypeException(TemplateObject.java:134) at 
freemarker.core.MethodCall._getAsTemplateModel(MethodCall.java:114) at     
freemarker.core.Expression.getAsTemplateModel(Expression.java:89) at 
freemarker.core.IteratorBlock.accept(IteratorBlock.java:94) at     
freemarker.core.Environment.visit(Environment.java:208) at

If I replace above code with:

<#if (result.dataPoints?keys?size > 0) >
    <#list result.dataPoints?keys as key>
        <tr>
            <td width="35%">
                <div>${key}</div>
            </td>
            <td width="45%">${result.dataPoints[key]}</td>
            <td width="19%">&nbsp;</td>
        </tr>
    </#list>
</#if>

Any idea how do I iterate over the map so that I get the same order?

like image 776
devang Avatar asked Dec 05 '25 05:12

devang


1 Answers

This should do the trick:

<#if result.dataPoints?has_content >
    <#list result.dataPoints.entrySet() as entry>
        <tr>
            <td width="35%">
                <div>${entry.key}</div>
            </td>
            <td width="45%">${entry.value}</td>
            <td width="19%">&nbsp;</td>
        </tr>
    </#list>
</#if>

You may also need set object wrapper for freemarker template configuration. Like this:

BeansWrapper beansWrapper = (BeansWrapper) ObjectWrapper.BEANS_WRAPPER;
beansWrapper.setExposeFields(true);
config.setObjectWrapper(beansWrapper);

Where config is freemarker.template.Configuration. If you using Spring Framework then extends FreeMarkerConfigurer:

public class FreeMarkerBeanWrapperConfigurer extends FreeMarkerConfigurer {
  @Override
  protected void postProcessConfiguration(Configuration config) throws IOException, TemplateException {
    super.postProcessConfiguration(config);

    BeansWrapper beansWrapper = (BeansWrapper) ObjectWrapper.BEANS_WRAPPER;
    beansWrapper.setExposeFields(true);
    config.setObjectWrapper(beansWrapper);
  }
}
like image 101
seralex.vi Avatar answered Dec 08 '25 22:12

seralex.vi



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!