javafreemarkeropenoffice-writerodtxdocreport

XDocReport: Issue by filling tables with Freemarker in ODT-file


I tried to rebuild the sample from the XDocReport documentation, but when i try to create tables or fill them. It always fails due to the follwing error. I cannot figure out what the issue is...

I have updated all the dependencies and tried different syntax in the .odt file.

ERROR:

Apr. 12, 2022 10:21:05 VORM. freemarker.log._JULLoggerFactory$JULLogger error
SEVERE: Error executing FreeMarker template
FreeMarker template error:
The following has evaluated to null or missing:
==> devs.name  [in template "fr.opensagres.xdocreport.document.odt.ODTReport@57855c9a!content.xml" at line 5, column 11]

----
Tip: It's the step after the last dot that caused this error, not those before it.
----
Tip: If the failing expression is known to legally refer to something that's sometimes null or missing, either specify a default value like myOptionalVar!myDefault, or use [#if myOptionalVar??]when-present[#else]when-missing[/#if]. (These only cover the last step of the expression; to cover the whole expression, use parenthesis: (myOptionalVar.foo)!myDefault, (myOptionalVar.foo)??
----

----
FTL stack trace ("~" means nesting-related):
    - Failed at: ${devs.name} auto-escaped  [in template "fr.opensagres.xdocreport.document.odt.ODTReport@57855c9a!content.xml" at line 5, column 9]
----

Java stack trace (for programmers):
----
freemarker.core.InvalidReferenceException: [... Exception message was already printed; see it above ...]
    at freemarker.core.InvalidReferenceException.getInstance(InvalidReferenceException.java:134)
    at freemarker.core.EvalUtil.coerceModelToTextualCommon(EvalUtil.java:481)
    at freemarker.core.EvalUtil.coerceModelToStringOrMarkup(EvalUtil.java:401)
    at freemarker.core.EvalUtil.coerceModelToStringOrMarkup(EvalUtil.java:370)
    at freemarker.core.BuiltInForLegacyEscaping._eval(BuiltInForLegacyEscaping.java:34)
    at freemarker.core.Expression.eval(Expression.java:101)
    at freemarker.core.Expression.evalAndCoerceToStringOrUnsupportedMarkup(Expression.java:139)
    at freemarker.core.BuiltInForString.getTargetString(BuiltInForString.java:34)
    at freemarker.core.BuiltInForString._eval(BuiltInForString.java:29)
    at freemarker.core.Expression.eval(Expression.java:101)
    at freemarker.core.MethodCall._eval(MethodCall.java:55)
    at freemarker.core.Expression.eval(Expression.java:101)
    at freemarker.core.Expression.evalAndCoerceToStringOrUnsupportedMarkup(Expression.java:139)
    at freemarker.core.BuiltInForString.getTargetString(BuiltInForString.java:34)
    at freemarker.core.BuiltInForString._eval(BuiltInForString.java:29)
    at freemarker.core.Expression.eval(Expression.java:101)
    at freemarker.core.MethodCall._eval(MethodCall.java:55)
    at freemarker.core.Expression.eval(Expression.java:101)
    at freemarker.core.Expression.evalAndCoerceToStringOrUnsupportedMarkup(Expression.java:139)
    at freemarker.core.BuiltInForString.getTargetString(BuiltInForString.java:34)
    at freemarker.core.BuiltInForString._eval(BuiltInForString.java:29)
    at freemarker.core.Expression.eval(Expression.java:101)
    at freemarker.core.MethodCall._eval(MethodCall.java:55)
    at freemarker.core.Expression.eval(Expression.java:101)
    at freemarker.core.DollarVariable.calculateInterpolatedStringOrMarkup(DollarVariable.java:100)
    at freemarker.core.DollarVariable.accept(DollarVariable.java:63)
    at freemarker.core.Environment.visit(Environment.java:383)
    at freemarker.core.IteratorBlock$IterationContext.executedNestedContentForCollOrSeqListing(IteratorBlock.java:321)
    at freemarker.core.IteratorBlock$IterationContext.executeNestedContent(IteratorBlock.java:271)
    at freemarker.core.IteratorBlock$IterationContext.accept(IteratorBlock.java:244)
    at freemarker.core.Environment.visitIteratorBlock(Environment.java:657)
    at freemarker.core.IteratorBlock.acceptWithResult(IteratorBlock.java:108)
    at freemarker.core.IteratorBlock.accept(IteratorBlock.java:94)
    at freemarker.core.Environment.visit(Environment.java:347)
    at freemarker.core.Environment.visit(Environment.java:353)
    at freemarker.core.Environment.visit(Environment.java:353)
    at freemarker.core.Environment.process(Environment.java:326)
    at fr.opensagres.xdocreport.template.freemarker.FreemarkerTemplateEngine.process(FreemarkerTemplateEngine.java:163)
    at fr.opensagres.xdocreport.template.freemarker.FreemarkerTemplateEngine.processNoCache(FreemarkerTemplateEngine.java:122)
    at fr.opensagres.xdocreport.template.AbstractTemplateEngine.process(AbstractTemplateEngine.java:118)
    at fr.opensagres.xdocreport.template.AbstractTemplateEngine.process(AbstractTemplateEngine.java:83)
    at fr.opensagres.xdocreport.document.AbstractXDocReport.processTemplateEngine(AbstractXDocReport.java:772)
    at fr.opensagres.xdocreport.document.AbstractXDocReport.process(AbstractXDocReport.java:518)
    at fr.opensagres.xdocreport.document.AbstractXDocReport.process(AbstractXDocReport.java:484)
    at report_creation.fillList.main(fillList.java:51)

I am currently using this code:

fillList.java

public class fillList {
    public static void main(String[] args) {
        try {
            // 1) Load ODT file by filling Velocity template engine and cache
            // it to the registry
            InputStream in = fillList.class.getResourceAsStream("Test.odt");
            IXDocReport report = XDocReportRegistry.getRegistry().loadReport(in, TemplateEngineKind.Freemarker);

            // 2) Create fields metadata to manage lazy loop (#foreach velocity)
            // for table row.
            FieldsMetadata metadata = new FieldsMetadata();
            metadata.addFieldAsList("developers.name");
            metadata.addFieldAsList("developers.lastName");
            metadata.addFieldAsList("developers.mail");
            report.setFieldsMetadata(metadata);

            // 3) Create context Java model
            IContext context = report.createContext();
            Project project = new Project("Create Dynamic Reports", 101);
            context.put("project", project);

            // Register developers list
            List<Developer> developers = new ArrayList<>();
            developers.add(new Developer("ZERR", "Angelo", "angelo.zerr@gmail.com"));
            developers.add(new Developer("Leclercq", "Pascal", "pascal.leclercq@gmail.com"));
            context.put("developers", developers);

            // 4) Generate report by merging Java model with the ODT
            OutputStream out = new FileOutputStream(new File("Test2_out.odt"));
            report.process(context, out);
            System.out.println("Report creation successfully completed!");

        } catch (IOException e) {
            System.err.println("[Debug Assistent]: No report created! >> IOException");
            e.printStackTrace();
        } catch (XDocReportException e) {
            System.err.println("[Debug Assistent]: No report created! >> XDocReportException");
            e.printStackTrace();
        }
    }
}

Project.java

public class Project {

    private final String name;
    private final Integer ID;

    public Project(String name, Integer id) {
        this.name = name;
        this.ID = id;
    }

    public String getName() {
        return name;
    }

    public Integer getID() {
        return ID;
    }
}

Developer.java

public class Developer {

    private final String name;
    private final String lastName;
    private final String mail;

    public Developer(String name, String lastName, String mail) {
        this.name = name;
        this.lastName = lastName;
        this.mail = mail;
    }

    public String getFirstName() {
        return name;
    }

    public String getLastName() {
        return lastName;
    }

    public String getMail() {
        return mail;
    }
}

This is the .odt file i am using. odttable


Solution

  • In the Developer class you have getFirstName instead of getName. Hence dev.name won't work.