Bug 57141 - JSP 2.3 & EL 3.0 Spec conflict w/Static Fields, Methods, etc.
Summary: JSP 2.3 & EL 3.0 Spec conflict w/Static Fields, Methods, etc.
Alias: None
Product: Tomcat 8
Classification: Unclassified
Component: EL (show other bugs)
Version: 8.0.x-trunk
Hardware: PC All
: P2 normal (vote)
Target Milestone: ----
Assignee: Tomcat Developers Mailing List
Depends on:
Blocks: 57142
  Show dependency tree
Reported: 2014-10-24 21:39 UTC by Arthur Fiedler
Modified: 2014-11-04 00:31 UTC (History)
0 users


Note You need to log in before you can comment on or make changes to this bug.
Description Arthur Fiedler 2014-10-24 21:39:18 UTC
EL 3.0 supports resolving static fields, methods etc. However I could not find a mention of this in the JSP 2.3 spec when using the EL Resolvers. Since ScopedAttributeELResolver is suppose to always set context.propertyResolved(true); even if the attribute is not found, the el processor never reaches the code to check for resolving a class. Making ${Boolean.TRUE} impossible to resolve from a JSP page.

From my understanding even though JSP 2.3 does not mention supporting this functionality, I believe it maybe intended. The proof I have of this starts from following this stackoverflow article


And if you note in the answer, it was also reported and fixed in the glassfish implementation. javax.servlet.jsp api implements this functionality inside the ScopedAttributeELResolver class after an attribute is not found. I've verified this to be true in the current 2.3.2-b01 source code. However I think they might have forgot to call resolveStatic also.

I'm going to make another bug post for an ImportHandler issue that if this is implemented may also effect the functionality.
Comment 1 Mark Thomas 2014-11-01 22:27:10 UTC
Thanks for the report. This has been fixed in 8.0.x for 8.0.15 onwards.
Comment 2 Konstantin Kolinko 2014-11-02 01:09:59 UTC
Re: r1636063

I think it is wrong to change ScopedAttributeELResolver to implement this fix. Thus I am REOPENING this.

The ScopedAttributeELResolver is defined by JSP specification (see JSP.2.9 Resolution of Variables and their Properties) and by its javadoc [1]. Those describe exactly what it does.

It should not resolve imported classes - those are EL implementation responsibility, not JSP one.

The EL3.0 specification says in several places that ELResolver is responsible for resolving "model objects". An imported class is not a model object.

In EL3.0 specification there is chapter 1.5 Resolution of Model Objects and their Properties or Methods.

1.5.3 Evaluating objects with properties

The steps for evaluating an expression with [] or . operators (property reference and method call) are described in Section 1.6, “Operators [] and .”. However, the syntax for . operator is also used to reference a static field, or to invoke a static method. Therefore if the expression with a . operator is not resolved by the ELResolvers, and if the identifier for the base object is the name of an imported class, the expression becomes a reference to a static field, or an invocation of a static method, of the imported class.

Note "Therefore if the expression with a . operator is not resolved by the ELResolvers" phrase. It is not ELResolver's responsibility to perform a resolution here.

[1] http://docs.oracle.com/javaee/7/api/javax/servlet/jsp/el/ScopedAttributeELResolver.html
Comment 3 Mark Thomas 2014-11-02 01:25:44 UTC
Yes, the JSP spec as currently written means that EL imports of static fields simply can't work in EL. That was not the intention of the spec writers but an oversight in the updates that were made in the JSP 2.3 maintenance release to handle the changes required for EL 3.0 support.

See https://java.net/jira/browse/GLASSFISH-20778 (linked from the SO question above)

The same solution was implemented in the EL and JSP reference implementation. That approach was recommended by Kin-man Chung, the spec lead for EL 3.0 and (I believe) the maintenance lead for JSP 2.3. Given his domain knowledge and position within the various EG's, I am more than happy to follow his advice on the correct behaviour in this case.
Comment 4 Konstantin Kolinko 2014-11-02 01:35:54 UTC
One part of what I am saying is that it is odd that a fundamental feature of EL language (el-api.jar) depends on internal implementation of a class that belongs to JSP API (jsp-api.jar).
Comment 5 Mark Thomas 2014-11-02 01:40:52 UTC
That is not the case. Standalone EL works.

The problem is that the documented behaviour of one of the JSP EL resolvers breaks an EL feature so that resolver has to include a work-around. Not ideal but not unexpected given the number of the new features (and associated syntax) added in EL 3.0.
Comment 6 Konstantin Kolinko 2014-11-02 18:20:31 UTC
Ah, I think that I see now. The problem is that ScopedAttributeELResolver calls context.setPropertyResolved(base, property) regardless of whether the property actually exists.

I think that one reason for that behaviour is to avoid an error to be thrown by EL for such expressions as ${undefinedFoo}. So a possible theoretical alternative fix could be the following two changes:

1. Change ScopedAttributeELResolver to do not set "propertyResolved" flag if the property does not exist, I mean if pageContext.findAttribute(key) returned null.

2. Change EL to treat unresolved identifier as having the value of null instead of raising an error.

Given that both this theoretical fix and the actual fix in r1636063 are changing the implementation of ScopedAttributeELResolver, I think the actual fix in r1636063 wins as being less intrusive. It does not need change at EL side.

So Ack for the current fiz.
Comment 7 Arthur Fiedler 2014-11-04 00:31:24 UTC
Just to throw my two cents in, I think the future JSP spec should be to modify the ScopedAttributeELResolver so it only sets the "propertyResolved" when it is in fact found, and add two additional standard ELResolvers following ScopedAttributeELResolver.

The first one being ImportELResolver, which resolves classes via the import handler.

The second one being always the last NotFoundELResolver, which returns null and sets the propertyResolved for all that reach it.

This way future resolvers can be defined in the spec before NotFoundELResolver  and the resolvers can be more clean cut for reuse/extending