If you download any of the 0.8.8 versions of Pentaho Reporting Classic, you will notice one thing: The last page-footer does contain any values. It contains labels, but it never displays function results or other data-items.
After this bug survived undetected for three month (or maybe simply no one cared for filing a bug-report), I finally received notice of this bug’s existence. Five minutes of debugging later, I got that very ugly feeling. No, this was not a simple bug – it came directly from the 7th circle of hell: A logic bug.
When we introduced sub-reporting into the engine, we also had to change the datasource management of the reporting engine. In the old days, there was not much of a datasource management. Everything was static – when the report started we knew exactly what columns would be available, and that number would never change. Oh, life was beautiful and simple.
But then came the subreporting and everything changed. Subreports introduce their own datasources and an own set of functions. Suddenly the simplicity was gone forever – and would never come back again.
As the Flow-Engine already handles such dynamic datasources already (and I really, really hate to maintain two independent implementation for the same problem), we simply grabbed the datasource-code from that branch and ported it to the classic engine. On the positive side, it gave us the whole datasources and query-management features of the flow engine along with the very flexible parameter-passing mechanism. But we had to pay a price: We now have to maintain a data-context so that we know when to add and to remove columns from the datasource.
As the classic engine is very simple, so is the context management. There is only one context at all, and that’s the report or subreport.
It could have worked out so nice.
The page-footer is not printed, until the system detects that the page is filled. As outlined before, although we layout the page-footer all the time, we do not copy it to the final page until the end of the page has been reached. This actual copying is done outside of the normal report processing. For the last page, however, the report processing has already been finished. The current context is closed and everyone is waiting for the garbage-collector. And at this point, printing the page-footer fails.
How to fix it: Ok, we could start tweaking and start adding workarounds until the system behaves as expected. We did it before, it surely produces a solution – somehow. An unmaintainable solution that eats souls like others eat cornflakes, a nightmare for those who have to maintain the beast and have to fix bugs there.
As chances are good that I’m the one who will be called for that, this patching is no solution. I’m crazy, but not stupid.
And here’s my favorite approach: (1) Look at the flow-engine and how they deal with page-footer definitions. (2) Copy the solution. (3) Be happy.
In the Flow engine, page-header and footer are defined together before the content is genereated. These footers are then pushed down to the layouter, where they get replicated on each new page. Whenever the header or footer changes, the engine simply replaces the stored template with a new one. (And if you look closer on it, then this approach is not that far away from the repeated layouting of the page-footer to compute the available space, as we did it in the classic engine.) The Classic-Engine even already has an storage layer between the report-engine’s element definitions and the output targets content implemented. The ‘MetaBands’ and the ‘MetaPage’ classes currently serve as some kind of a spooling mechanism. It should not be too complicated to transform this into a real layouting layer.
And yet another step on the long road to get both engines aligned.