Hi, we’re building a website using a view-agnostic document store and a spring-based webapp that is capable of rendering views for documents that include views of linked documents. The views are typically small freemarker templates (at most some tenths of lines) using a custom include directive that determines the view for the included document and – if it is a freemarker template — tells that template to process itself.
Now, we’re frequently running into stackoverflowerrors which exhibit the level of inclusion and the whole structure of the freemarker templates from the root of up to the custom include. The stacktrace fragment shown below ([1]) is taken from such a stackoverflowerror. I’d suggest to adjust the visitor pattern based implementation so that the accept calls do not invoke Environment#visit again but return the tempate elements to be visited. That way we obtain stacktraces that look as shown further down below ([2]). The patched code resides here: https://github.com/mkleine/incubator-freemarker/tree/avoid-too-much-recursion-when-visiting-template-elements Are we misusing freemarker or is the approach to reduction of stackframes welcome? Kind regards, Moritz [1] at freemarker.ext.beans.BeansWrapper.invokeMethod(BeansWrapper.java:1458) [freemarker-2.3.22.jar:2.3.22] at freemarker.ext.beans.SimpleMethodModel.exec(SimpleMethodModel.java:71) [freemarker-2.3.22.jar:2.3.22] at freemarker.core.MethodCall._eval(MethodCall.java:62) [freemarker-2.3.22.jar:2.3.22] at freemarker.core.Expression.eval(Expression.java:78) [freemarker-2.3.22.jar:2.3.22] at freemarker.core.Expression.evalAndCoerceToString(Expression.java:82) [freemarker-2.3.22.jar:2.3.22] at freemarker.core.BuiltInForString._eval(BuiltInForString.java:26) [freemarker-2.3.22.jar:2.3.22] at freemarker.core.Expression.eval(Expression.java:78) [freemarker-2.3.22.jar:2.3.22] at freemarker.core.Expression.evalAndCoerceToString(Expression.java:82) [freemarker-2.3.22.jar:2.3.22] at freemarker.core.DollarVariable.accept(DollarVariable.java:40) [freemarker-2.3.22.jar:2.3.22] at freemarker.core.Environment.visit(Environment.java:312) [freemarker-2.3.22.jar:2.3.22] at freemarker.core.MixedContent.accept(MixedContent.java:62) [freemarker-2.3.22.jar:2.3.22] at freemarker.core.Environment.visitByHiddingParent(Environment.java:333) [freemarker-2.3.22.jar:2.3.22] at freemarker.core.ConditionalBlock.accept(ConditionalBlock.java:48) [freemarker-2.3.22.jar:2.3.22] at freemarker.core.Environment.visitByHiddingParent(Environment.java:333) [freemarker-2.3.22.jar:2.3.22] at freemarker.core.Environment.visitAndTransform(Environment.java:413) [freemarker-2.3.22.jar:2.3.22] at freemarker.core.CompressedBlock.accept(CompressedBlock.java:37) [freemarker-2.3.22.jar:2.3.22] at freemarker.core.Environment.visit(Environment.java:312) [freemarker-2.3.22.jar:2.3.22] at freemarker.core.Macro$Context.runMacro(Macro.java:178) [freemarker-2.3.22.jar:2.3.22] at freemarker.core.Environment.invoke(Environment.java:700) [freemarker-2.3.22.jar:2.3.22] at freemarker.core.UnifiedCall.accept(UnifiedCall.java:84) [freemarker-2.3.22.jar:2.3.22] at freemarker.core.Environment.visitByHiddingParent(Environment.java:333) [freemarker-2.3.22.jar:2.3.22] at freemarker.core.IteratorBlock$Context.runLoop(IteratorBlock.java:148) [freemarker-2.3.22.jar:2.3.22] at freemarker.core.Environment.visitIteratorBlock(Environment.java:559) [freemarker-2.3.22.jar:2.3.22] at freemarker.core.IteratorBlock.accept(IteratorBlock.java:67) [freemarker-2.3.22.jar:2.3.22] at freemarker.core.Environment.visit(Environment.java:312) [freemarker-2.3.22.jar:2.3.22] at freemarker.core.MixedContent.accept(MixedContent.java:62) [freemarker-2.3.22.jar:2.3.22] at freemarker.core.Environment.visitByHiddingParent(Environment.java:333) [freemarker-2.3.22.jar:2.3.22] at freemarker.core.ConditionalBlock.accept(ConditionalBlock.java:48) [freemarker-2.3.22.jar:2.3.22] at freemarker.core.Environment.visitByHiddingParent(Environment.java:333) [freemarker-2.3.22.jar:2.3.22] at freemarker.core.ConditionalBlock.accept(ConditionalBlock.java:48) [freemarker-2.3.22.jar:2.3.22] at freemarker.core.Environment.visit(Environment.java:312) [freemarker-2.3.22.jar:2.3.22] at freemarker.core.MixedContent.accept(MixedContent.java:62) [freemarker-2.3.22.jar:2.3.22] at freemarker.core.Environment.visit(Environment.java:312) [freemarker-2.3.22.jar:2.3.22] at freemarker.core.EscapeBlock.accept(EscapeBlock.java:48) [freemarker-2.3.22.jar:2.3.22] at freemarker.core.Environment.visit(Environment.java:312) [freemarker-2.3.22.jar:2.3.22] at freemarker.core.Environment.process(Environment.java:290) [freemarker-2.3.22.jar:2.3.22] at freemarker.template.Template.process(Template.java:312) [freemarker-2.3.22.jar:2.3.22] [2] at freemarker.ext.beans.BeansWrapper.invokeMethod(BeansWrapper.java:1458) at freemarker.ext.beans.SimpleMethodModel.exec(SimpleMethodModel.java:71) at freemarker.core.MethodCall._eval(MethodCall.java:62) at freemarker.core.Expression.eval(Expression.java:78) at freemarker.core.ReturnInstruction.accept(ReturnInstruction.java:35) at freemarker.core.Environment.visit(Environment.java:336) at freemarker.core.Macro$Context.runMacro(Macro.java:186) at freemarker.core.Environment.invoke(Environment.java:705) at freemarker.core.MethodCall._eval(MethodCall.java:74) at freemarker.core.Expression.eval(Expression.java:78) at freemarker.core.Expression.evalAndCoerceToString(Expression.java:82) at freemarker.core.DollarVariable.accept(DollarVariable.java:41) at freemarker.core.Environment.visit(Environment.java:336) at freemarker.core.Environment.visit(Environment.java:341) at freemarker.core.Environment.renderElementToString(Environment.java:2200) at freemarker.core.StringLiteral.evalAndCoerceToString(StringLiteral.java:96) at freemarker.core.StringLiteral._eval(StringLiteral.java:73) at freemarker.core.Expression.eval(Expression.java:78) at freemarker.core.Environment.setMacroContextLocalsFromArguments(Environment.java:743) at freemarker.core.Environment.invoke(Environment.java:693) at freemarker.core.UnifiedCall.accept(UnifiedCall.java:85) at freemarker.core.Environment.visit(Environment.java:336) at freemarker.core.Environment.visit(Environment.java:341) at freemarker.core.Environment.visit(Environment.java:341) at freemarker.core.Environment.process(Environment.java:302) at freemarker.template.Template.process(Template.java:325)
