Skip to content

Fixed: Call to non-existing method in production run PDF reports (OFBIZ-13504) [release24.09] - #1828

Open
toaditi wants to merge 2 commits into
apache:release24.09from
toaditi:ofbiz-13504-todatestring-visibility-r2409
Open

toaditi wants to merge 2 commits into
apache:release24.09from
toaditi:ofbiz-13504-todatestring-visibility-r2409

Conversation

@toaditi

@toaditi toaditi commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Backport of #1827 to release24.09.

Credits

Thanks to Carsten Heinrigs for reporting OFBIZ-13504 and for naming both the
template and the method in the report.

This follows on from OFBIZ-10478 by Jacques Le Roux and Pradhan Yash Sharma,
reviewed by Michael Brohl — a broad and worthwhile cleanup, in which this one method
happened to have all of its callers in templates, where static analysis could not see them.

The problem

UtilDateTime.toDateString(Date, String) is reached from templates through
Static["org.apache.ofbiz.base.util.UtilDateTime"]. FreeMarker resolves those members
reflectively and so sees public methods only, so narrowing the two-argument overload to
private left the templates unable to resolve it:

Java method "static org.apache.ofbiz.base.util.UtilDateTime.toDateString(Date)"
takes 1 argument, but 2 was given.

The render does not throw — that message is written into the output stream. So the
report still returns HTTP 200 and a structurally valid PDF, with a FreeMarker stack trace
printed where the dates belong.

release24.09 carries the same modifier and the same seven call sites as trunk:
ProductionRun.fo.ftl (4), PRunsProductsAndOrder.fo.ftl:324,
PRunsProductsStacks.fo.ftl:92 and ContentTreeLookupList.ftl:85.

Restoring the overload to public keeps the rendered format unchanged. Dropping the format
string in the templates instead would fall back to the single-argument overload and
silently move the reports from dd/MM/yyyy to MM/dd/yyyy.

This was discussed on the Jira issue, and Carsten Heinrigs, who reported it, agreed that
restoring the method is the better route
, adding that he values being able to specify the
date format string. With the two-argument form private, a template that needs a particular
format has no clean way to ask for one.

Two differences from the trunk PR, both deliberate

1. The test is JUnit 4, matching this branch, rather than the Jupiter version on trunk.

2. There is a one-line build.gradle change. The test task here lists the JUnit
classes it runs explicitly, and FreeMarkerWorkerTests was not among them — so the test
already in that class was never executed. Without the added include, the new regression
test would sit in the tree and never run, which would be worse than not adding it. It is
called out separately here so it is easy to drop if you would rather leave the task list
untouched.

Verification

The test asserts 09/03/2026, a date whose dd/MM/yyyy and MM/dd/yyyy forms differ, so
it also fails if the format string is dropped rather than the method restored. It was
watched failing before the change and passing after, on this branch, against the
FreeMarker 2.3.35 this branch now pins.

./gradlew test checkstyleMain codenarcMain codenarcTest javadoc — all pass, 25 tests,
0 failures, 0 errors.

The trunk change in #1827 was additionally verified by creating a production run and
fetching PrintProductionRun over HTTP before and after, which is what confirmed the
"valid PDF containing a stack trace" behaviour described above. That runtime check was not
repeated here, since the code path and the fix are identical.

…IZ-13504)

Jira: https://issues.apache.org/jira/browse/OFBIZ-13504

Backport of the trunk fix to release24.09.

Thanks to Carsten Heinrigs for reporting this, and for naming both the template
and the method in the report. This also follows on from OFBIZ-10478 by Jacques
Le Roux and Pradhan Yash Sharma, reviewed by Michael Brohl. That was a broad and
worthwhile cleanup; this one method simply happened to have all of its callers in
templates, where static analysis could not see them.

### The problem

`UtilDateTime.toDateString(Date, String)` is reached from templates through
`Static["org.apache.ofbiz.base.util.UtilDateTime"]`. FreeMarker resolves those
members reflectively and so sees public methods only, so narrowing the two
argument overload to private left the templates unable to resolve it:

    Java method "static org.apache.ofbiz.base.util.UtilDateTime.toDateString(Date)"
    takes 1 argument, but 2 was given.

The render does not throw. That message is written into the output stream, so an
`.fo.ftl` still returns a structurally valid PDF with a FreeMarker stack trace
printed where the dates belong, and the HTTP response still looks healthy.

release24.09 carries the same modifier and the same seven call sites as trunk:
`ProductionRun.fo.ftl` (four), `PRunsProductsAndOrder.fo.ftl:324`,
`PRunsProductsStacks.fo.ftl:92` and `ContentTreeLookupList.ftl:85`.

Restoring the two argument overload to public keeps the rendered format
unchanged. Dropping the format string in the templates instead would fall back to
the single argument overload and silently move the reports from dd/MM/yyyy to
MM/dd/yyyy.

### Note on the build.gradle line

The `test` task here lists the JUnit classes it runs explicitly, and
`FreeMarkerWorkerTests` was not among them, so the existing test in that class was
never executed. Without the added `include` the new regression test would sit in
the tree without ever running. It is listed separately in this commit so that it
is easy to drop if reviewers would rather keep the task list unchanged.

### Verification

The test is written for JUnit 4 to match this branch, rather than the Jupiter
version used on trunk. It renders the failing expression through
`FreeMarkerWorker` and asserts `09/03/2026`, a date whose dd/MM/yyyy and
MM/dd/yyyy forms differ, so it also fails if the format string is dropped rather
than the method restored.

Watched failing before the change and passing after, on this branch, against the
FreeMarker 2.3.35 it now pins. `./gradlew test checkstyleMain javadoc` passes with
25 tests, 0 failures, 0 errors.

The equivalent trunk change is in apache#1827,
where it was additionally verified by rendering a production run PDF over HTTP
before and after.
@toaditi

toaditi commented Aug 31, 2026

Copy link
Copy Markdown
Contributor Author

Update from the Jira thread, for anyone reviewing this cold.

Carsten Heinrigs, who reported the issue, has confirmed he is happy with restoring the
two-argument method rather than editing the templates
, and added that he values being able
to specify the date format string.

That flexibility is really the crux of the choice here. With the two-argument form private, a
template that needs a particular format has no clean way to ask for one, since the
single-argument overload is fixed to MM/dd/yyyy. So this is less about undoing what
OFBIZ-10478 tidied away, and more about keeping a capability that templates — including
customised ones in existing deployments — depend on.

Jira thread: https://issues.apache.org/jira/browse/OFBIZ-13504

…IZ-13504)

Thanks to Carsten Heinrigs for confirming the approach on the Jira issue, and for
noting that the ability to pass an explicit date format is worth keeping. That is
the part most at risk of being lost again, so this records it in the source.

The method has no callers in Java code; its callers are FreeMarker templates using
Static["org.apache.ofbiz.base.util.UtilDateTime"], which static analysis cannot see.
That is exactly why the scope reduction in OFBIZ-10478 looked safe. Without a note
in the code, the next such pass would reasonably reach the same conclusion and
reintroduce the bug.

The comment also records that the failure mode is quiet, and that the single
argument overload is fixed to MM/dd/yyyy, so dropping the pattern is not a neutral
simplification.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant