[
https://issues.apache.org/jira/browse/FREEMARKER-213?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17636353#comment-17636353
]
Christoph Rueger commented on FREEMARKER-213:
---------------------------------------------
??Rather, #list, ?first, ?join, etc. needs to close the iterator. Unless I'm
missing something here.??
You are right. Wasn't a good idea to include _?filter_ in my example in the
description. I think it is _?first_ et al which are the problems.
?? that's another thing that's really missing.??
Ok, that makes sense and good to know that this is something missing.
Proposed solution sounds good.
> Handling AutoCloseable Iterators in ?filter / ?first when the iterator is not
> fully consumed
> ---------------------------------------------------------------------------------------------
>
> Key: FREEMARKER-213
> URL: https://issues.apache.org/jira/browse/FREEMARKER-213
> Project: Apache Freemarker
> Issue Type: Improvement
> Components: engine
> Affects Versions: 2.3.31
> Reporter: Christoph Rueger
> Priority: Minor
>
> HI,
> We have expressions like:
> {code:java}
> ${myCatalog.getCSVFileRowsIterator()?filter(row -> row.get("categoryId") ==
> "123")?first}
> {code}
> Under the hood this becomes an IteratorModel().
> The problem is that:
> - the underlying iterator is working on a resource (file, stream)
> - which needs to be *closed when finished*.
> - but ?filter and ?first can abandon and leave the iterator somewhere in the
> middle once it has identified a match
> - this caused Resource Leaks in some cases.
> I debugged down to the following code in _freemarker.core.new
> TemplateModelIterator() {...}.ensurePrefetchDone())_
> {code:java}
> private void ensurePrefetchDone() throws TemplateModelException {
> if (prefetchDone) {
> return;
> }
> boolean conclusionReached = false;
> do {
> if (lhoIterator.hasNext()) {
> TemplateModel element =
> lhoIterator.next();
> boolean elementMatched;
> try {
> elementMatched =
> elementMatches(element, elementTransformer, env);
> } catch (TemplateException e) {
> throw new
> _TemplateModelException(e, env, "Failed to transform element");
> }
> if (elementMatched) {
> prefetchedElement = element;
> conclusionReached = true;
> }
> } else {
> prefetchedEndOfIterator = true;
> prefetchedElement = null;
> conclusionReached = true;
> }
> } while (!conclusionReached);
> prefetchDone = true;
> }
> {code}
> It looks like at this place we have the "iterator" and also know when we stop
> iterating, when finding a match.
> *Question*
> Would it be possible to check if the underlying Iterator implements
> _java.lang.AutoCloseable_ and if yes, call _.close()_ on it, when a match is
> found?
> I am not sure if that is the right thing to do here.
> We have built workarounds so that AutoCloseable objects in the datamodel are
> closed after rendering is finished.
> But it would be better to close it as soon as possible, when the iterator is
> stopped to be consumed. This would help in scenarios where the template does
> that multiple times, e.g.:
> {code:java}
> ${myCustomObject.getCSVRowsIterator()?filter(row -> row.get("categoryId") ==
> "123")?first}
> ${myCustomObject.getCSVRowsIterator()?filter(row -> row.get("categoryId") ==
> "234")?first}
> {code}
> Ideas would be welcome, where this kind of "closing" should happen.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)