Uploaded image for project: 'Confluence Data Center'
  1. Confluence Data Center
  2. CONFSERVER-97514

Methods beginning with 'render' or 'getRender' that return a non-String type, will throw an exception when invoked from a Velocity template

XMLWordPrintable

      Issue Summary

      Original report: here

      I found a small bug with com.atlassian.confluence.user.actions.AbstractUserProfileAction#getRenderedAboutMe when called in a Velocity template for an Action class that is extending AbstractUserProfileAction:

      • when called as $renderedAboutMe: all good, value is shown 
      • when called as $action.renderedAboutMe: value is not shown, but literal “$action.renderedAboutMe”, i.e. used value in Velocity is null 
      • when called as $action.getRenderedAboutMe(): Server error is thrown, with root-cause java.lang.IllegalArgumentException: Attempting to box an already boxed value

      After taking a deep-dive into how Velocity handles html-safe methods, I found out the following:

      • According to com.atlassian.velocity.htmlsafe.HtmlSafeMethodNameAnnotator methods starting with “render” or “getRender” (or ending in “Html”) are treated as @HtmlSafe
      • Problematic method AbstractUserProfileAction#getRenderedAboutMe returns a com.atlassian.velocity.htmlsafe.HtmlFragment instead of a normal String.
      • → These 2 facts collide somehow: The method is treated as being doubly html-safe, which com.atlassian.velocity.htmlsafe.introspection.AnnotatedValue doesn’t like → Exception “Attempting to box an already boxed value” is thrown

      I also looked into why it matters how that method is called. (Did that via the stacktrace):

      • when called as $renderedAboutMe: Velocity’s introspection is not used, but Struts/OGNL stuff
        • → Exception does not occur
      • when called as $action.renderedAboutMe: Velocity’s introspection IS used → Exception IS thrown, but swallowed by try block in org.apache.velocity.runtime.parser.node.ASTIdentifier 
        • → null is used instead
      • when called as $action.getRenderedAboutMe(): Velocity’s introspection IS used → Exception IS thrown, and NOT swallowed by org.apache.velocity.runtime.parser.node.ASTMethod
        • → Exception bubbles up and is thrown in user’s face

      Steps to Reproduce

      1. Define a Struts Action extending AbstractUserProfileAction and map it to a Velocity template result.
      2. Call $action.getRenderedAboutMe() from Velocity template.

      Expected Results

      Renders 'About Me' content.

      Actual Results

      The below exception is thrown:

      Caused by: java.lang.IllegalArgumentException: Attempting to box an already boxed value
      at com.google.common.base.Preconditions.checkArgument(Preconditions.java:143)
      at com.atlassian.velocity.htmlsafe.introspection.AnnotatedValue.<init>(AnnotatedValue.java:45)
      at com.atlassian.velocity.htmlsafe.introspection.AnnotationBoxingMethod.invoke(AnnotationBoxingMethod.java:25)
      at com.atlassian.velocity.htmlsafe.introspection.UnboxingMethod.invoke(UnboxingMethod.java:28) 

      Workaround

      Bypass Velocity Uberspect by using OGNL shortcut $renderedAboutMe.

              Unassigned Unassigned
              854eef6f5746 Kusal Kithul-Godage
              Votes:
              1 Vote for this issue
              Watchers:
              2 Start watching this issue

                Created:
                Updated: