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)

Reply via email to