See the RFE here: https://issues.apache.org/jira/browse/FREEMARKER-84
As you see, the first consensus was introducing `.last_include_found`, but it has two problems: * Sometimes it happens that if, and only if the template exists then you want to do (usually print) something *before* it. Problem is, by the time you know that from `.last_include_found`, it's too late, as the template was already processed. * Like many global state variables in general, this can lead to some confusing edge cases and hard-to-follow code. Like, if `#include` throws an exception, which is then handled by the user with `#attempt`/`#recover`, then `.last_include_found` may or may not be updated, as perhaps we haven't yet reached the point where it can be told if the template exists. (Consider an expression evaluation error in the `#include` parameter, or an I/O error due to which we can't access the template directory). Also there are some public `include` methods in the `Environment` API, but they can't set this variable, as they return a `Template`, and the variable must be set after the `Template` was processed, unless the template was missing. (If you can't figure out why it must be done that way, that proves again how tricky this is... think about includes inside includes.) So, I propose the solution below. Maybe somewhat difficult to grasp first, but it meant to be used rarely, and mostly by "experts"... Let's hope SO and examples in the Manual will help people though. (-; Introduce a new special variable (see https://freemarker.apache.org/docs/ref_specvar.html) called "get_optional_template", which is a TemplateMethodModelEx with these parameters: 1. template name (maybe a relative path, resolved as #include/#import does it) 2. A hash that can have the following keys: "parse", "encoding" (similarly to https://freemarker.apache.org/docs/ref_directive_include.html#ref.directive.include). Example method call (the `.` prefix is the special variable reference syntax): <#assign t = .get_optional_template("foo.ftl", { 'encoding': 'utf-8' })> The method returns a hash (`t` above) that contains the following keys: - "include": directive (or missing); `<@t.include />` has similar effect as `<#include "foo.ftl">` - "import": method (or missing); returns a namespace. `<#assign f = t.import()>` has similar effect as `<#import 'foo.ftl' as f>` - "exists": boolean; returns if the template was found. The method call loads the target template eagerly, i.e., it won't wait until `t.include`, `t.exist` etc. is actually used. Note that the hash is returned even if the template wasn't found (but then it won't contain "include" and "import", and "exists" will be `false`). If some other error occurs, like an I/O error other than a "template not found", or the template has invalid syntax, it will throw exception (just like #include). Use cases: - `#include` with fallback templates or fallback macro (note how we can use the `exp!defaultExp` operator): <@.get_optional_template('foo.ftl') !.get_optional_template('bar.ftl').include !defaultMacro /> - Doing something before `#include` if the template exists: <#assign t = .get_optional_template('foo.ftl')> <#if t.exists> Do before existing template <@t.include /> </#if> Opinions? -- Thanks, Daniel Dekany