Adding nonstandard support for c:set and c:remove#842
Conversation
|
While only targeting |
Great suggestion, thank you. Edge cases are a big concern so please keep them coming! |
markt-asf
left a comment
There was a problem hiding this comment.
Thinking long term, I am wondering whether we need to provide the ability for users to customise these optimisations. If we do then we can add something like a GeneratorFactory and users can provide their own generator that overrides the built-in one along the lines of ELInterpreterFactory. For now, I don't think is necessary.
|
|
||
| public static void nonstandardSetTag(jakarta.servlet.jsp.PageContext pageContext, String var, Object value) { | ||
| if (value == null) { | ||
| pageContext.removeAttribute(var); | ||
| } else { | ||
| pageContext.setAttribute(var, value); | ||
| } | ||
| } | ||
|
|
There was a problem hiding this comment.
This only appears to be used in test code. If true, it should be removed.
There was a problem hiding this comment.
The generated JSP code calls this method, why is why it's not called within Tomcat itself.
There was a problem hiding this comment.
Can you point out where. I only see calls to the 4-arg method, not the 3-arg method.
There was a problem hiding this comment.
Thank you, sorry, I missed the 3-arg vs. 4-arg distinction. You're correct and I'll remove the 3-arg.
There was a problem hiding this comment.
I verified this by comparison to the JSTL tag and realized I missed some logic to clean up the VariableMapper. I added that as well.
| if (scope == null) { | ||
| out.printil("pageContext.removeAttribute(\"" + varValue + "\");"); | ||
| } else { | ||
| String scopeValue = translateScopeToConstant(jspAttributes); | ||
| out.printil("pageContext.removeAttribute(\"" + varValue + "\", " + scopeValue + ");"); | ||
| } |
There was a problem hiding this comment.
This takes a different approach to handling null scope compared to set. It isn't wrong but it is inconsistent. Why? If there is a good reason, it should be documented else folks coming later are going to wonder why. If there isn't a good reason, set and remove should be consistent (and I have no preference for either approach).
There was a problem hiding this comment.
I modeled the code here after the tag implementations (SetTag and RemoveTag), with the goal of maintaining compatibility... so any mismatch is either an error in how I copied the logic, or how the tags themselves are implemented. What specific differences do you see?
There was a problem hiding this comment.
set calls
String scopeValue = translateScopeToConstant(jspAttributes);
whereas remove treats scope == null as a special case
if (scope == null) {
out.printil("pageContext.removeAttribute(\"" + varValue + "\");");
} else {
String scopeValue = translateScopeToConstant(jspAttributes);
out.printil("pageContext.removeAttribute(\"" + varValue + "\", " + scopeValue + ");");
}
I'd probably remove the special case treatment from remove.
There was a problem hiding this comment.
Weird as this is, I think it matches the logic from RemoveTag:
// removes the variable (from a specific scope, if specified)
public int doEndTag() throws JspException {
if (!scopeSpecified)
pageContext.removeAttribute(var);
else
pageContext.removeAttribute(var, scope);
return EVAL_PAGE;
}
And PageContextImpl .remove(var) removes from every scope, whereas .remove(var, scope) only removes from one:.
@Override
public void removeAttribute(final String name) {
if (name == null) {
throw new NullPointerException(Localizer.getMessage("jsp.error.attribute.null_name"));
}
removeAttribute(name, PAGE_SCOPE);
removeAttribute(name, REQUEST_SCOPE);
if (session != null) {
try {
removeAttribute(name, SESSION_SCOPE);
} catch (IllegalStateException ise) {
// Session has been invalidated.
// Ignore and fall throw to application scope.
}
}
removeAttribute(name, APPLICATION_SCOPE);
}
Until this effort, I didn't know that remove w/o scope cleared all scopes.
There was a problem hiding this comment.
Understood. I didn't realise there was a difference until I looked at the PageContext Javadoc. It is probably worth a short comment on both set and remove on how no/null scope is handled since it is different.
There was a problem hiding this comment.
Great suggestion, will do. I'll make a pass on all of this code and add more descriptive comments wherever I got surprised.
Honestly, this is where I started, but I had to make a bazillion fields, methods, and classes public or protected. I figured I'd start here and we can bite that off later. |
markt-asf
left a comment
There was a problem hiding this comment.
I'm fine with GeneratorFactory being something we consider later if necessary. Just want to make sure we don't do anything now to make it harder to do that if we need to.
|
|
||
| public static void nonstandardSetTag(jakarta.servlet.jsp.PageContext pageContext, String var, Object value) { | ||
| if (value == null) { | ||
| pageContext.removeAttribute(var); | ||
| } else { | ||
| pageContext.setAttribute(var, value); | ||
| } | ||
| } | ||
|
|
There was a problem hiding this comment.
Can you point out where. I only see calls to the 4-arg method, not the 3-arg method.
| if (scope == null) { | ||
| out.printil("pageContext.removeAttribute(\"" + varValue + "\");"); | ||
| } else { | ||
| String scopeValue = translateScopeToConstant(jspAttributes); | ||
| out.printil("pageContext.removeAttribute(\"" + varValue + "\", " + scopeValue + ");"); | ||
| } |
There was a problem hiding this comment.
set calls
String scopeValue = translateScopeToConstant(jspAttributes);
whereas remove treats scope == null as a special case
if (scope == null) {
out.printil("pageContext.removeAttribute(\"" + varValue + "\");");
} else {
String scopeValue = translateScopeToConstant(jspAttributes);
out.printil("pageContext.removeAttribute(\"" + varValue + "\", " + scopeValue + ");");
}
I'd probably remove the special case treatment from remove.
5279b3a to
8957f56
Compare
8957f56 to
c288103
Compare
Enables optimized, non-standard behavior for the most common JSP tags, when configured to do so.
Impact: benchmark (included)shows 99% reduction in cpu, 100% reduction in object allocation
Activation: off by default, enabled via an init param to the JSP servlet, such as:
Example:
Old code (standard): one method, two parameters, 10+ lines of code, one object allocated (and it's large!).
New code (nonstandard) - one parameter, one line of code, zero objects allocated.
Caller code is simplified by eliminating the boolean check, from:
to