17

With JSF 2 you should be able to do this:

<h:commandButton action="#{myBean.myAction(myParameter)}"/>

which would then call the action method, passing in the parameter (assume it's an Integer):

@ManagedBean
@SessionScoped
public class MyBean {
    ...
    public String myAction(Integer myParameter) {
        // do something
        return null;
    }
    ...
}

This works on Glassfish v3 perfectly. However not on Tomcat, you get an ELException notifying of the parse error

Caused by: javax.el.ELException: Error Parsing: ...

Now, there's a documented way of making this work using EL 2.2 and Glassfish's implementation by replacing the el-api jar in the Tomcat lib directory, however I still get the same error occurring with no luck. Tomcat's really starting to frustrate me! JSF2 is meant to be easier!

Maven POM fragments:

<repositories>
  <repository>
    <id>sun</id>
    <url>http://download.java.net/maven/2/</url>
  </repository>
  <repository>
    <id>jboss</id>
    <url>http://repository.jboss.com/maven2/</url>
  </repository>
</repositories>
...
  <dependency>
    <groupId>javax.el</groupId>
    <artifactId>el-api</artifactId>
    <version>2.2</version>
    <scope>provided</scope>
  </dependency>

  <dependency>
    <groupId>org.glassfish.web</groupId>
    <artifactId>el-impl</artifactId>
    <version>2.2</version>
    <scope>provided</scope>
  </dependency>

More info.

Here's part of the stack trace, seems it's still using an Apache EL implementation, and not the one I dumped into lib. I completely removed the existing el-api.jar that came with Tomcat, is there an el-impl.jar I'm meant to remove somewhere too that may be overriding something?

Was expecting one of:
    "}" ...
    "." ...
    "[" ...
    ">" ...
    "gt" ...
    "<" ...
    "lt" ...
    ">=" ...
    "ge" ...
    "<=" ...
    "le" ...
    "==" ...
    "eq" ...
    "!=" ...
    "ne" ...
    "&&" ...
    "and" ...
    "||" ...
    "or" ...
    "*" ...
    "+" ...
    "-" ...
    "/" ...
    "div" ...
    "%" ...
    "mod" ...

    at org.apache.el.parser.ELParser.generateParseException(ELParser.java:2142)
    at org.apache.el.parser.ELParser.jj_consume_token(ELParser.java:2024)
    at org.apache.el.parser.ELParser.DeferredExpression(ELParser.java:113)
    at org.apache.el.parser.ELParser.CompositeExpression(ELParser.java:40)
    at org.apache.el.lang.ExpressionBuilder.createNodeInternal(ExpressionBuilder.java:93)
    ... 64 more
Sampson
  • 265,109
  • 74
  • 539
  • 565
jamiebarrow
  • 2,473
  • 3
  • 30
  • 51

4 Answers4

25

As mentioned in other answers, you need to add the el-api-2.2.jar to your Tomcat server's lib folder, and the el-impl-2.2.jar to your WEB-INF/lib folder.

Other answers mention deleting jasper or creating custom implementations of ExpressionFactoryImpl. That might work, but you shouldn't need to do that.

You just need to override the expression factory implementation using org.apache.myfaces.EXPRESSION_FACTORY on MyFaces or com.sun.faces.expressionFactory on Mojarra.

<context-param>
    <param-name>org.apache.myfaces.EXPRESSION_FACTORY</param-name>
    <param-value>com.sun.el.ExpressionFactoryImpl</param-value>
</context-param>
  <context-param>
    <param-name>com.sun.faces.expressionFactory</param-name>
    <param-value>com.sun.el.ExpressionFactoryImpl</param-value>
  </context-param>
Lawrence McAlpin
  • 2,745
  • 20
  • 24
  • Thanks. I tried for two days with all the solutions flying around on the web and this is the only one that works. – ali Apr 12 '12 at 20:56
  • It does not seem common sense to advise for an -api jar to go on a server-side path. -api typically means that this is a specification, and is required compile-time only (which can be done with a "provided" scope in maven. Also, if you supply your own implementation, I would suggest just putting this in your maven project with the "runtime" scope. I deliberately leave the issue of possible conflicts with server side libraries open ... It is obvious if an implementation is already supplied in your tomcat distribution, we will have conflicts here. – YoYo Nov 07 '14 at 05:24
  • 1
    Tomcat already had an el-api in its path, but it was an extremely old version and he wanted to use a newer version. At this point in 2015, of course, it would make more sense to just upgrade Tomcat, but when this question was originally asked, and in the context that switching to something else (such as Glassfish, which worked for him) wasn't an option, replacing the archaic el-api was the only real option. – Lawrence McAlpin Nov 23 '15 at 04:49
8

As I mentioned in a comment, this can be solved by upgrading the EL implementation (i.e. replacing jasper-el.jar with el-impl-2.2.jar)

jamiebarrow
  • 2,473
  • 3
  • 30
  • 51
2

You can use JBoss EL.

It's an implementation of Expression Language 2.1. But it has extensions to allow method parameters as in your example:

<h:commandButton action="#{myBean.myAction(myParameter)}"/>

The advantage is that you only have to change your webapp and not Tomcat's lib directory.

Instructions

  1. Download the latest version of Seam 2
  2. Extract lib/jboss-el.jar
  3. Copy it to WEB-INF/lib/jboss-el.jar
  4. In your web.xml set:

    <context-param>
        <param-name>com.sun.faces.expressionFactory</param-name>
        <param-value>org.jboss.el.ExpressionFactoryImpl</param-value>
    </context-param>
    

See also Invoke direct methods or methods with parameters in EL.

Mahmoud Saleh
  • 33,303
  • 119
  • 337
  • 498
Arend v. Reinersdorff
  • 4,110
  • 2
  • 36
  • 40
1

Replacing el-api.jar and el-impl.jar with el-api-2.2.jar and el-impl-2.2.jar solve the problem.

Also you need to add in your context.xml the context parameter

<context-param>
    <param-name>org.apache.myfaces.EXPRESSION_FACTORY</param-name>
    <param-value>com.sun.el.ExpressionFactoryImpl</param-value>
</context-param>
  <context-param>
    <param-name>com.sun.faces.expressionFactory</param-name>
    <param-value>com.sun.el.ExpressionFactoryImpl</param-value>
  </context-param>
Neos76
  • 315
  • 1
  • 2
  • 7