Friday, December 08, 2006

Dirty Tricks with JSF and JSP EL

JSF's great weakness is that you often need to break out of the JSF tag library cocoon when developing the web pages to be rendered. For example, let's say you need to pass a variable value that is set in your backing been to some section of JavaScript. The JSP 2.x Expression Language is the way to do this. It requires Tomcat 5.x, so if you are still using Tomcat 4...well, the first decade of the 21st century is winding down. It's time to upgrade.

Anyway, you probably are already set up to do this. So lets assume you have to set a value in a Google Map object from your backing bean:

<script>
...
map.center(new GPoint (-117.24, 33.03),10);
</script>:

In a JSF application, the lat/lon values (33.03, -117.24) will be in something like a MapBean.java class, which you call mapBean in your faces-xml.config file. So how do you get these values into the JavaScript? You do it with JSP EL (not JSF EL). This will be active in your page unless you explicitly turn it off (and why would you do that?) so just place your javascript fragment inside the f:view tags and then use

map.center(new GPoint(${mapBean.valueY}, ${mapBean.valueX}),10);

There is one dirty (or crafty, if you prefer) trick to this: you need to initialize the mapBean object in the page. JSF normally takes care of this in the process of rendering its own EL expressions, or you could do it explicitly the JSP way (I suppose). But let's say you want to use JSP EL exclusively for your page (and avoid the obscurities of JSF tags), or perhaps you just don't have any JSF tags in this particular page. The problem is that the mapBean object will not be instantiated in the page--mapBean.valueY will return an empty String. To work around this, you could use the following evil shortcut:

<h:outputText value="#{mapBean.valueX}" rendered="false"/>

The actual value you use here doesn't matter (it doesn't need to be valueX, could be any other property in mapBean). This will force the mapBean object to be initialized and yet won't render the associated value.

2 comments:

Marcus Christie said...

Wow, now that I've been using facelets, that post almost didn't make any sense. You don't need these sort of hacks with facelets.

Marlon Pierce said...

The main point is that I was proud to figure out how to get backing bean variable values into javascript in the .jsf page. Maybe this was obvious, and I think you would do a similar thing with facelets.