This method will be called "only" when doStartTag() returns Tag.EVAL_BODY_INCLUDE or BodyTag.EVAL_BODY_BUFFERED.
The keyword "only" make it wrong.
I don't think so: the only valid return values for doStartTag() are SKIP_BODY, EVAL_BODY_INCLUDE and EVAL_BODY_BUFFERED.
If SKIP_BODY is returned, execution always jumps straight to doEndTag().
If EVAL_BODY_INCLUDE is returned, the body is evaluated before execution reaches doAfterBody().
If EVAL_BODY_BUFFERED is returned, some buffer methods are invoked, the body is evaluated, then execution reaches doAfterBody().
So we conclude that
only a return value of EVAL_BODY_INCLUDE or EVAL_BODY_BUFFERED will cause doAfterBody() to be invoked. Do you still disagree? If so, for what reason?