Monday, October 03, 2011

Tomcat 7 JSTL Failed to parse the expression

In Tomcat 7 (v7.0.22) method like isNew() cannot be referred as ${myObject.new} as before:
org.apache.jasper.JasperException: /WEB-INF/jsp/client/form.jsp (line: 5, column: 4) "${client.new}" contains invalid expression(s): javax.el.ELException: Failed to parse the expr
ession [${client.new}

This problem was documented a year ago and someone might be tempted to change the code for something like ${myObject.isNew()} after realizing that does work. However latest version of jasper-el breaks for this case which makes me think I will need to change my code again in future versions of Tomcat.

Solution

Change the code from ${client.new} to ${client['new']}

Alternative(s)

In mailing lists I understood Apache 7 is less permissive and since 'new' is not a valid Java identifier it cannot be part of the EL expression like in ${client.new}. There is flag to make Tomcat 7 more permissive albeit rewriting the code should be preferred:
-Dorg.apache.el.parser.SKIP_IDENTIFIER_CHECK=true

I came up with an alternative and temporary (and again not recommended) solution to avoid changing the code which is downloading latest jasper-el http://repo1.maven.org/maven2/org/apache/tomcat/jasper-el/6.0.33/jasper-el-6.0.33.jar or even copying the jar from a previous tomcat installation. Just remember to remove the old jar file:
$ cd ~
$ curl http://repo1.maven.org/maven2/org/apache/tomcat/jasper-el/6.0.33/jasper-el-6.0.33.jar > jasper-el-6.0.33.jar
$ mv /opt/apache-tomcat-7.0.22/lib/jasper-el.jar .
$ cp jasper-el-6.0.33.jar /opt/apache-tomcat-7.0.22/lib/
However that did not work for some other specific and more complex EL expressions (Not even 6.0.36 work with such more complex expressions. Here is just an example of one:
Internal Server Error org.apache.jasper.JasperException: /WEB-INF/jsp/workflow/processTaskInstance/list.jsp (line: 55, column: 20) "${serviceAgreementTypeNames.contains(processTaskInstanceDto.processDefinitionName)}" contains invalid expression(s): javax.el.ELException: Failed to parse the expression [${serviceAgreementTypeNames.contains(processTaskInstanceDto.processDefinitionName)}] at org.apache.jasper.compiler.DefaultErrorHandler.jspError(DefaultErrorHandler.java:42) at org.apache.jasper.compiler.ErrorDispatcher.dispatch(ErrorDispatcher.java:408) at org.apache.jasper.compiler.ErrorDispatcher.jspError(ErrorDispatcher.java:199) at org.apache.jasper.compiler.Validator$ValidateVisitor.checkXmlAttributes(Validator.java:1218) ...

4 comments:

Eric J. Schwarzenbach said...

I think you want to set SKIP_IDENTIFIER_CHECK to true, not false, for the workaround. And wouldn't that be much preferable to replacing the library with the older version?

Nestor Urquiza said...

Thanks Eric, I have amended that and in fact that is preferable for sure. In fact I just updated that for other more complex expressions changing the library will not work either. In any case the correct way to go is to fix the incorrect expressions rather than skipping the identifier check.

Ray said...

Thanks for the above fix.
We got the problem for use of the name 'default'; i.e. ${calendarType.default} as the object has a method isDefault().
Changed to ${calendarType['default']} to fix it.

Nestor Urquiza said...

@Ray glad to help

Followers