Repository: incubator-freemarker Updated Branches: refs/heads/2.3 4ffe4b354 -> bc1455f52
Improved exceptions when calling JSP tags: Wrapping of non-TemplateModelException TemplateException-s (typically InvalidReferenceException-s) into TemplateModelException-s is now avoided when the TemplateException occurs in the body of a JSP tag. Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/28561441 Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/28561441 Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/28561441 Branch: refs/heads/2.3 Commit: 285614418263bbf92504692aad6a754ced2c312b Parents: 5f4b7f3 Author: ddekany <ddek...@apache.org> Authored: Sun Feb 4 12:11:45 2018 +0100 Committer: ddekany <ddek...@apache.org> Committed: Sun Feb 4 12:14:58 2018 +0100 ---------------------------------------------------------------------- src/main/java/freemarker/core/Environment.java | 6 +++ .../freemarker/ext/jsp/JspTagModelBase.java | 6 ++- .../template/TemplateModelException.java | 37 ++++++++++++++++-- src/manual/en_US/book.xml | 41 +++++++++++++------- .../basic/WEB-INF/expected/customTags1.txt | 2 +- 5 files changed, 72 insertions(+), 20 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28561441/src/main/java/freemarker/core/Environment.java ---------------------------------------------------------------------- diff --git a/src/main/java/freemarker/core/Environment.java b/src/main/java/freemarker/core/Environment.java index 762f646..310ae9d 100644 --- a/src/main/java/freemarker/core/Environment.java +++ b/src/main/java/freemarker/core/Environment.java @@ -875,6 +875,12 @@ public final class Environment extends Configurable { private void handleTemplateException(TemplateException templateException) throws TemplateException { + if (templateException instanceof TemplateModelException + && ((TemplateModelException) templateException).getReplaceWithCause() + && templateException.getCause() instanceof TemplateException) { + templateException = (TemplateException) templateException.getCause(); + } + // Logic to prevent double-handling of the exception in // nested visit() calls. if (lastThrowable == templateException) { http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28561441/src/main/java/freemarker/ext/jsp/JspTagModelBase.java ---------------------------------------------------------------------- diff --git a/src/main/java/freemarker/ext/jsp/JspTagModelBase.java b/src/main/java/freemarker/ext/jsp/JspTagModelBase.java index 83c0104..032cead 100644 --- a/src/main/java/freemarker/ext/jsp/JspTagModelBase.java +++ b/src/main/java/freemarker/ext/jsp/JspTagModelBase.java @@ -39,6 +39,7 @@ import freemarker.ext.jsp.SimpleTagDirectiveModel.TemplateExceptionWrapperJspExc import freemarker.template.ObjectWrapper; import freemarker.template.ObjectWrapperAndUnwrapper; import freemarker.template.Template; +import freemarker.template.TemplateException; import freemarker.template.TemplateModel; import freemarker.template.TemplateModelException; import freemarker.template.utility.StringUtil; @@ -145,8 +146,9 @@ class JspTagModelBase { if (e instanceof TemplateExceptionWrapperJspException) { return toTemplateModelExceptionOrRethrow(((TemplateExceptionWrapperJspException) e).getCause()); } - return new _TemplateModelException(e, - "Error while invoking the ", new _DelayedJQuote(tagName), " JSP custom tag; see cause exception"); + return new TemplateModelException( + "Error while invoking the " + StringUtil.jQuote(tagName) + " JSP custom tag; see cause exception", + e instanceof TemplateException, e); } /** http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28561441/src/main/java/freemarker/template/TemplateModelException.java ---------------------------------------------------------------------- diff --git a/src/main/java/freemarker/template/TemplateModelException.java b/src/main/java/freemarker/template/TemplateModelException.java index 1ab47b4..2926ba8 100644 --- a/src/main/java/freemarker/template/TemplateModelException.java +++ b/src/main/java/freemarker/template/TemplateModelException.java @@ -27,6 +27,8 @@ import freemarker.core._ErrorDescriptionBuilder; * if the requested data can't be retrieved. */ public class TemplateModelException extends TemplateException { + + private final boolean replaceWithCause; /** * Constructs a <tt>TemplateModelException</tt> with no @@ -64,14 +66,21 @@ public class TemplateModelException extends TemplateException { public TemplateModelException(Throwable cause) { this((String) null, cause); } - /** * The same as {@link #TemplateModelException(String, Throwable)}; it's exists only for binary * backward-compatibility. */ public TemplateModelException(String description, Exception cause) { - super(description, cause, null); + this(description, (Throwable) cause); + } + + /** + * Same as {@link #TemplateModelException(String, boolean, Throwable)} with {@code false} {@code replaceWithCause} + * argument. + */ + public TemplateModelException(String description, Throwable cause) { + this(description, false, cause); } /** @@ -80,13 +89,18 @@ public class TemplateModelException extends TemplateException { * to be raised. * * @param description the description of the error that occurred + * @param replaceWithCause See {@link #getReplaceWithCause()}; usually {@code false}, unless you are forced to wrap + * {@link TemplateException} into a {@link TemplateModelException} merely due to API constraints. * @param cause the underlying {@link Exception} that caused this * exception to be raised + * + * @since 2.3.28 */ - public TemplateModelException(String description, Throwable cause) { + public TemplateModelException(String description, boolean replaceWithCause, Throwable cause) { super(description, cause, null); + this.replaceWithCause = replaceWithCause; } - + /** * Don't use this; this is to be used internally by FreeMarker. * @param preventAmbiguity its value is ignored; it's only to prevent constructor selection ambiguities for @@ -95,6 +109,7 @@ public class TemplateModelException extends TemplateException { protected TemplateModelException(Throwable cause, Environment env, String description, boolean preventAmbiguity) { super(description, cause, env); + this.replaceWithCause = false; } /** @@ -106,6 +121,20 @@ public class TemplateModelException extends TemplateException { Throwable cause, Environment env, _ErrorDescriptionBuilder descriptionBuilder, boolean preventAmbiguity) { super(cause, env, null, descriptionBuilder); + this.replaceWithCause = false; + } + + /** + * Indicates that the cause exception should be thrown instead of this exception; it was only wrapped into this + * exception due to API constraints. Such unwanted wrapping typically occurs when you are only allowed to throw + * {@link TemplateModelException}, but the exception to propagate is a more generic {@link TemplateException}. + * The error handler mechanism of FreeMarker will replace the exception with its {@link #getCause()} when it has + * bubbled up to a place where that constraint doesn't apply anymore. + * + * @since 2.3.28 + */ + public boolean getReplaceWithCause() { + return replaceWithCause; } } http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28561441/src/manual/en_US/book.xml ---------------------------------------------------------------------- diff --git a/src/manual/en_US/book.xml b/src/manual/en_US/book.xml index 7325bd0..91c5893 100644 --- a/src/manual/en_US/book.xml +++ b/src/manual/en_US/book.xml @@ -27110,19 +27110,6 @@ TemplateModel x = env.getVariable("x"); // get variable x</programlisting> <itemizedlist> <listitem> - <para>Bug fixed (<link - xlink:href="https://issues.apache.org/jira/browse/FREEMARKER-88">FREEMARKER-88</link>): - This is related to calling JSP tags from templates. If a - <literal>TemplateException</literal> that's not a - <literal>TemplateModelExceptoin</literal> has occurred in the - body of a JSP <literal>SimpleTag</literal> (typically, an - <literal>InvalidReferenceException</literal>), that has caused a - <literal>ClassCastException</literal> in the exception handling - code, thus the template processing has thrown that instead of - the original exception.</para> - </listitem> - - <listitem> <para>Added new property to <literal>BeansWrapper.MethodAppearanceDecision</literal>: <literal>replaceExistingProperty</literal>. This is useful when @@ -27134,6 +27121,34 @@ TemplateModel x = env.getVariable("x"); // get variable x</programlisting> the real property isn't replaced, but now with <literal>replaceExistingProperty</literal> it can be.</para> </listitem> + + <listitem> + <para>Improved exception handling when calling JSP tags:</para> + + <itemizedlist> + <listitem> + <para>Bug fixed (<link + xlink:href="https://issues.apache.org/jira/browse/FREEMARKER-88">FREEMARKER-88</link>): + If a <literal>TemplateException</literal> that's not a + <literal>TemplateModelExceptoin</literal> has occurred in + the body of a JSP <literal>SimpleTag</literal> (typically, + an <literal>InvalidReferenceException</literal>), that has + caused a <literal>ClassCastException</literal> in the + exception handling code, thus the template processing has + thrown that instead of the original exception.</para> + </listitem> + + <listitem> + <para>Wrapping of + non-<literal>TemplateModelException</literal> + <literal>TemplateException</literal>-s (typically + <literal>InvalidReferenceException</literal>-s) into + <literal>TemplateModelException</literal>-s is now avoided + when the <literal>TemplateException</literal> occurs in the + body of a JSP tag.</para> + </listitem> + </itemizedlist> + </listitem> </itemizedlist> </section> </section> http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28561441/src/test/resources/freemarker/ext/jsp/webapps/basic/WEB-INF/expected/customTags1.txt ---------------------------------------------------------------------- diff --git a/src/test/resources/freemarker/ext/jsp/webapps/basic/WEB-INF/expected/customTags1.txt b/src/test/resources/freemarker/ext/jsp/webapps/basic/WEB-INF/expected/customTags1.txt index 54e6650..6a25e32 100644 --- a/src/test/resources/freemarker/ext/jsp/webapps/basic/WEB-INF/expected/customTags1.txt +++ b/src/test/resources/freemarker/ext/jsp/webapps/basic/WEB-INF/expected/customTags1.txt @@ -35,7 +35,7 @@ doFinally() called here <!-- Test abrupt execution --> doStartTag() called here -doCatch() called here with class freemarker.core._TemplateModelException: Error while invoking the "testtag" JSP custom tag; see cause exception +doCatch() called here with class freemarker.template.TemplateModelException: Error while invoking the "testtag" JSP custom tag; see cause exception doFinally() called here <!-- Test nested execution -->