EL Function Parameters with JBoss EL

By , 26 July 2008

EL Function Parameters with JBoss EL

One of the current missing features of Unified EL as used in JSF is the lack of support for calling methods on an object. You can access a bean's properties that have getters and setters and get elements from a map by name, but cannot call simple functions like ${list.size()}or ${colours.RGBtoHex(0,75,50)}. The clever folks at JBoss built an EL implementation which adds this basic feature, and a recent thread on the JSR 314 mailing list prompted me to add it to our stack.

It's quite easy to do, and you don't have to install Seam. First, you need to download the JBoss EL implementation and add it to your build. Using maven, first add the jar to your repository:

$ mvn install:install-file -Dfile=jboss-el-2.0.1.GA.jar -DgroupId=org.jboss.el \
     -DartifactId=jboss-el -Dversion=2.0.1 -Dpackaging=jar

Then add the dependency it to your pom:

EL Function Parameters with JBoss EL
<dependency>
  <groupId>org.jboss.el</groupId>
  <artifactId>jboss-el</artifactId>
  <version>2.0.1</version>
  <scope>compile</scope>
</dependency>

And configure web.xml to use the new library:

<!-- jboss el expressions allow method params -->
<context-param>
  <param-name>com.sun.faces.expressionFactory</param-name>
  <param-value>org.jboss.el.ExpressionFactoryImpl</param-value>
</context-param>

That's all there is to it! The library is 100% backwards compatible with the stock EL implementation which is pretty handy. Also, it looks like the key features will make their way into JSF 2.0 :)

Some references for you:

About Roger Keays

EL Function Parameters with JBoss EL

Roger Keays is an artist, an engineer, and a student of life. He has no fixed address and has left footprints on 40-something different countries around the world. Roger is addicted to surfing. His other interests are music, psychology, languages, the proper use of semicolons, and finding good food.

Leave a Comment

Please visit https://rogerkeays.com/blog/el-function-parameters-with-jboss-el to add your comments.

Comment posted by: Jean, 15 years ago

I am having the same problam that Ken had...

Comment posted by: Gaurav Arora, 15 years ago

Thanks, works like a charm.

Comment posted by: Rafael Ponte, 16 years ago

Hi Roger, I discovered the problem :) The problem was on the JSF Mojarra version, I was using mojarra 1.2_04 and because this occured the problem, seems that the version 1.2_04 have a bug. I change for version 1.2_05-b06-FCS getting success to works my application with jboss EL.

 

Thanks.

 

Comment posted by: Rafael Ponte, 16 years ago

Hi Roger,

I'm using Tomcat 6.0.18, JSF1.2 (Mojarra) and Facelets 1.1, but seen that the org.jboss.el.ExpressionFactoryImpl doesn't work. When I open a page with any EL as #{bean.list.size()} occurs an error, the expression is not evaluate.

com.sun.facelets.tag.TagAttributeException: /pages/departamentos.xhtml @21,60 value="#{depBean.departamentos.size()}" Error Parsing: #{depBean.departamentos.size()}
at com.sun.facelets.tag.TagAttribute.getValueExpression(TagAttribute.java:259)
at com.sun.facelets.tag.jsf.ValueHolderRule$DynamicValueExpressionMetadata.applyMetadata(ValueHolderRule.java:101)
[...] Caused by: javax.el.ELException: Error Parsing: #{depBean.departamentos.size()}
at org.apache.el.lang.ExpressionBuilder.createNodeInternal(ExpressionBuilder.java:125)
at org.apache.el.lang.ExpressionBuilder.build(ExpressionBuilder.java:146)
[...] Caused by: org.apache.el.parser.ParseException: Encountered "size(" at line 1, column 25.
Was expecting:
<IDENTIFIER> ...

at org.apache.el.parser.ELParser.generateParseException(ELParser.java:2129)

The Tomcat 6.0 already have el-api.jar in the his /lib directory, hence I think that I won't need it in my project, in the project has the el-ri.jar and jboss-el-2.0.1.GA.jar at /WEB-INF/lib/, but the application doesn't work yet!

Do you have any idea about my problem?

Comment posted by: , 16 years ago

Hi Rafael,

I'm using this with Tomcat 6.0. You'll probably still need el-api.jar. I also have commons-el-1.0.jar, but I think that was to satisfy some other library.

Comment posted by: Rafael Ponte, 16 years ago

Great post Roger!

I tried to use JBoss EL with Tomcat 6.0.x, but I didn't get success. Do you know to say if JBoss EL works with Tomcat? Is necessary others jars in the project?

Cheers.

Comment posted by: Ken, 16 years ago

I am using facelets 1.1.14 with JSF 1.2 RI 1.2_09.

The target app server is Glassfish v2 ur2, which is Java EE 5 compatible.

Java EE 5 requires both JSF 1.2 and JSP 2.1.

Facelets works fine in this server.

 

Comment posted by: , 16 years ago

You shouldn't need maven. Are you using JSP or Facelets? I haven't tried this with JSP, although the docs indicate that it should work with JSP 2.0:

Incompatibility with JSP 2.1 — JBoss EL can't currently be used with JSP 2.1 as the compiler rejects expressions with parameters in. So, if you want to use this extension with JSF 1.2, you will need to use Facelets. The extension works correctly with JSP 2.0.

Comment posted by: Ken, 16 years ago

If I just add the Jboss El jar to my web app's lib folder, and when I tried to deploy the war to Glassfish v2 ur2, it says:

Unable to instantiate ExpressionFactory 'org.jboss.el.ExpressionFactoryImpl'

Exception sending context initialized event to listener instance of class com.sun.faces.config.ConfigureListener
com.sun.faces.config.ConfigurationException: It appears the JSP version of the container is older than 2.1 and unable to locate the EL RI expression factory, com.sun.el.ExpressionFactoryImpl.  If not using JSP or the EL RI, make sure the context initialization parameter, com.sun.faces.expressionFactory, is properly set.

I did set the web.xml to use "org.jboss.el.ExpressionFactoryImpl".

Any help is greatly appreciated.

Comment posted by: Ken, 16 years ago

Do I have to use Maven to manage and build the project to utilize the Jboss EL lib?

Is there any other way?

 

Comment posted by: , 16 years ago

Hey Nicholas, thanks for the comment. Sounds like some pretty handy features. I forwarded your message to the JSR314 expert group. /me bookmarks this thought.

Comment posted by: Nicholas Hagen, 16 years ago

I actually did this same exact thing myself for my own projects in order to invoke methods from managed beans.  However, I also added support for (1) variable arguments and (2) polymorphism.

For variable arguments, you can define a method such as public double avg(int... values) within a managed bean and then invoke it from an EL expression such as #{bean.avg(1, 2, 3, 4, 5)} and have it return 3.0.  I also added this to the standard EL functions so you could have an EL function mapped to a variable argument java method and invoke #{f:avg(1, 2, 3)}.  This works for any JDK.  For JDK 5 you just map your methods with Type... params and with JDK 4 and older, you just map with Type[] params.  I think this is a feature that would be nice to add to the JBoss EL impl.

In terms of polymorphism and some of this is already supported by standard EL and maybe even the JBoss EL, but I allow you to invoke a method/function and it tries to find the best match within that bean class or its super classes.  Thus, you can have methods like:  String getName(String prefix) and String getName(int prefix) and depending on the evaluated types of the EL params, it will pick the most appropriate method.  This even works with the variable argument support, so you could also have a method named getName(double... values).

Anyways, it would be interesting to get these features maybe added/merged into the JBoss EL.  If anyone is interested, let me know.

Nicholas Hagen

nicholas dot hagen at znetdevelopment dot com

Comment posted by: , 16 years ago

I couldn't find anything in the MyFaces docs about changing the EL Factory. You might have to ask on their mailing list about that.

Comment posted by: Pete Muir, 16 years ago

Good post Roger, nice to see some interest in this under promoted project :-)

Jose: It works with Facelets, you don't need to replace other libs, it will work with MyFaces i they have a way of replacing the expression factory (the context parameter shown is RI specific), it works with RichFaces (of course!) and I know for sure it works with JBoss Portal via the Portlet bridge.

Comment posted by: Jose Noheda, 16 years ago

Great to know. I was using CGLIB to mimic this behavior till now so I'll try it. But the article is a little bit lacking IMHO. Does this work with Facelets? Do we need to replace other libs? Does it work with MyFaces? And RichFaces? Portlets? I'm guessing some responses here but you could have done a better job.