XDocReport:通过在 ODT 文件中使用 Freemarker 填充表格来发布

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

我试图从 XDocReport 文档重建示例,但是当我尝试创建表格或填充它们时。由于以下错误,它总是失败。我不知道是什么问题...

我已经更新了所有依赖项并在 .odt 文件中尝试了不同的语法。

错误:

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;
    }
}

这是我正在使用的 .odt 文件。

Developer class 中你有 getFirstName 而不是 getName。因此 dev.name 将不起作用。