VMWare Screen Repaint issues

Posted in Bob Hedlund on April 12th, 2011 by admin

admin originally posted this on Eldorado Software.

I recently added an iMac with 8Gb Ram, and I use VMWare due to a need to run an oracle database and some of the Oracle utilities. To my horror, the repaint on the XP VM was marginal, and I often found myself doing double takes at the things I had written (more than the usual amount anyway).

I tried mucking with the 3D Acceleration on the VM Settings, but that didn't have any effect.

What did the trick was modifying the settings on the Windows VM - in this case XP.

Under Control Panel / Display Settings / Settings Tab

click the Advanced Button

Goto the Troubleshoot Tab

Adjust the Hardware acceleration down one notch.

Restart your VM.

No more double takes due to missing pixels.

Trinidad Date Picker Issue with Daylight Savings Time

Posted in Bob Hedlund on November 11th, 2010 by admin

admin originally posted this on Eldorado Software.

Trinidad Date Pickers in the site went haywire just after the DayLight Savings change on November 6. Users who selected a date prior to November 7 would find the input field populating with the previous day selected. The issue is in the javascript in trinidad-impl jar. We are using version 1.2.13. The issue occurred for servers running on the Unix platform and windows. The issue occurred for people using clients with Mac and PC.

I tried setting the time zone in trinidad-config.xml with a number of different options: UTC-8, GMT-8, and Pacific Daylight Time, but no luck.

So I opened the jar:

jar -xvf trinidad-impl.jar

In META-INF\adf\jsLibs the file DateField is the culprit. In the function

_getDayLightSavOffset(a0)

the function gets the client date, and compares the time zone offset to the server time zone offset. For dates after the time change, the offset is 0. For dates prior to the time zone change the offset is always 60. For our app, we always want the value the user selects in the popup to appear in the date field, so I just always return 0 here. I tested with the server date set to various times before and after the time change, and the fix works fine.

Make your change, jar.cf .jar *, and substitute your new trinidad jar.


There are posts related to this, and the problem seems to have been thought to have been fixed previously:

TRINIDAD-1349:_uixLocaleTZ stores the timezone offset of the server at
* the time the page was displayed (Current time), and currentDateTZOffset
* is the timezone offset of client at the current time as well. However,
* the timezone offsets for both client and server can differ for the
* date that was picked due to daylight savings rules. For example, the
* current time is 3 Dec 2008 and the server is in PST (UTC -8) and
* client is in Perth (AWDT, UTC + 9) so the difference is 17h. But if
* the user picks Apr 25, the server is actually in PDT then (UTC-7) and
* the client in AWST (UTC +8) so the difference is actually 15h. The original
* code would subtract 17h, which would cause the resulting date to move
* to the previous day. *

Performance Improvements for DAO Testing in an ORM environment

Posted in Bob Hedlund on May 20th, 2010 by admin

admin originally posted this on Eldorado Software.

In any good size project using an ORM tool such as Hibernate, you are bound to have a good number of DAO classes that encapsulate persistent interactions. Running JUnit tests against your DAO's can take some time with ANT, as a new Session Factory is instantiated for each Unit Test. In a current project the time to run the tests in our DAO package was about three minutes. I found a solution that cut the time to run all the tests down to 40 seconds. The solution : Junit TestsSuite.

The TestSuite instantiates the SessionFactory once, and all the tests reuse the instance. The code:

public class DaoTestSuite extends TestCase{

public static Test suite(){
TestSuite suite = new TestSuite();
suite.addTestSuite(DaoTest1.class);
suite.addTestSuite(DaoTest2.class);

// and so on ... or you could do this reflectively

suite.addTestSuite(DaoTestN.class);


TestSetup wrapper = new TestSetup(suite){
protected DbUtil dbUtil = new DbUtil();

@Override
protected void setUp(){
//Before the suite, we configure the factory
dbUtil.beginConversationThread();
}


@Override
protected void tearDown(){
//After the suite, we ensure the factory is closed
dbUtil.rollbackTransaction();
}
};

return wrapper;
}



The DbUtil class is a standard ORM class that configures the SessionFactory, ensures that a session is open, transaction is active, and provides a means to rollback the transaction.

The Test classes that are added to the suite have the following before and after methods:

protected DbUtil _dbUtil = new DbUtil();


public void setUp() {
_dbUtil.beginConversationThread();
}


public void tearDown() {
_dbUtil.rollbackTransaction();
}


Where the beginConversationThread() call grabs an active session from the factory, or starts the factory if it is not yet configured and running. Since the TestSuite is run in one JVM, the SessionFactory is configured but once.

Custom JSF Components with Facelets

Posted in Bob Hedlund on December 15th, 2009 by admin

admin originally posted this on Eldorado Software.

The Overview
Creating custom components can really clean up your faces pages and keep you from repeating yourself over and over. And its fun to do! There are a number of posts out there and tutorials about creating custom components, and often times they leave out the most important pieces of configuration. In this post I will specify how to create composite components with Facelets. This is different from the jsf style custom components in that these are much easier to create, require much less configuration, and often times solve the problem at hand very quickly.

The Affected files
  1. the Web Descriptor
  2. The component definition
  3. The tag library descriptor
  4. The pages that you insert the component into


The Web descriptor, (web.xml) tells your container about your tag lib descriptor file.

The component definition fie specifies how the component is laid out. It may have logic in it and you may pass parameters to it. It produces the markup that appears in your faces page.

The Tag Library descriptor is an xml file that describes to the container what to do when it encounters your custom component tag.

Finally, your pages need to include the tag for it to be seen.

Getting Started
The first thing to do when creating a component is to generate the markup, styling and any scripts that accompany it in a sandbox. Try inserting it in your pages and seeing what it looks like and get it to work correctly. Once this is done, you are ready to generate the reusable tag that will display your component each time you need it. In this case I made a progress bar for my application.

Directory Layout
Under WEB-INF, create a directory called facelets, with a sub directory called tags.
In the tags directory we are going to place our tag library decriptor and our component.

myProject.taglib.xml
The Tag Lib Descriptor file: (myProject.taglib.xml)

<?xml version="1.0"?>
<!DOCTYPE facelet-taglib PUBLIC
"-//Sun Microsystems, Inc.//DTD Facelet Taglib 1.0//EN"
"facelet-taglib_1_0.dtd">
<facelet-taglib>
<namespace>http://www.yourId/jsf</namespace>
<tag>
<tag-name>progress</tag-name>
<source>progress.xhtml</source>
</tag>
</facelet-taglib>



The file specifies the following items:

namespace - Your unique id that wont conflict with other known urls. It does not need to exist on a server, it just needs to be unique. In this example I called it http://yourId/jsf. Any components that you place in this tag lib descriptor will be accessed in you pages using this as the uri to find this definition file. So in your pages that contain the component, the following tag will be added in your opening definitions:
xmlns:xx="http://www.yourId/jsf"
where xx will be the tag handle in the page.

tag-name is the name of this particular component. In this case it is a progress bar. In your page you will access it via xx:progress

source is the name of the file that we will create to define our tag - the markup.


web.xml
Now we need to tell the application about our library. In web.xml, create the following entry:

<context-param>
<param-name>facelets.LIBRARIES</param-name>
<param-value>/WEB-INF/facelets/tags/myProject.taglib.xml</param-value>
</context-param>

If you already have an entry like this, the param values can be a semi-colon delimited list.


progress.xhtml
So now we have our tag lib descriptor, and the container knows about it. Lets generate the component file. The name of the file must match the name in the taglib descriptor for the component. It is the source tag. So when the application encounters the tag name in the page, it looks up in the taglib descriptor (which it gets from the namespace definition) and finds the source file associated with the tag name.

This file also resides in WEB-IN/facelets/tags.

The file:



<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:c="http://java.sun.com/jstl/core"
xmlns:fn="http://java.sun.com/jsp/jstl/functions">

<ui:composition>

<span class="progressContainer" >
<div class="progressBar" >

<c:if>
...more markup
</c:if>

</div>
</span>

</ui:composition>
</html>




I've left out my markup, but you can put yours in. We will look at parameter passing a bit later. For now, lets just get you using a tag in your pages. At this point everything is set to go. You just need to include the definition for your library in your page, and then specify the tag in the page.

So in your page:

In the opening tag, include the definition:

xmlns:xx="http://www.yourId/jsf"

Note that this must match the namespace specified in your tag lib descriptor. Remember that this is an arbitrary name for id purposes only. The xx is an arbitrary handle for accesing the library in your page.

Then, in your page to use the tag you would call:


<xx:progress/>



OK So at this point the tag should appear in your pages where you specify it. In the next edition, we will discuss parameter passing and using jstl in the tags. I also like to include certain tags in my templates that pages use. This requires a different approach for parameter passing, as the template defines where the tag will be, but the pages may want to use the tag differently.

Hope that helps.

Refreshing Data in the UI

Posted in Bob Hedlund on October 13th, 2009 by admin

admin originally posted this on Eldorado Software.

Once your application is up and running smoothly, all the data appears as it should, it may seem that all there is left to do is style it up and move on. But in high volume sites, or low volume sites with areas of high transaction, you need to ensure the user is seeing the latest information available. This needs to be done via XMLHttpRequests so that the page that the user is working on remains intact.

Lets first discuss the data is stored and retrieved.

In any web application, the user will request data and you present it. Often the state of the page is determined by the data that is present. So you want to limit the number of calls to the database for this information by caching it in your backing bean. This requires that you reset this data when appropriate. Once the page is loaded, the data remains flat on the page until the user interacts, or you cause an update. Thus we load the data on demand, or lazily, and then cache it until it needs refreshing.

Refresh from the UI is made by AJAX calls. The calls invoke backing bean actions based on the framework you are using. Apache Trinidad has a nice built in mechanism for making AJAX calls to the JSF.

In my backing beans, I add a PollListener method that resets the data I want to refresh in the UI. The method looks like this:

public void tableDataPoll(PollEvent ev) {
resetData();
}


When the bean gets the call from the AJAX event, it resets the underlying data so that when the page requests the data, it is pulled afresh. In the UI the call is made by adding a trinidad poll ( An AJAX call that runs at a certain interval) to the page:

tr:poll interval="30000" pollListener="{bean.tableDataPoll}" id="ajax1"

This causes an AJAX call to invoke my poll listener in the backing bean every thirty seconds. In order for the table of data to update, you need to add a partial trigger to the component that displays the data. This is done as follows:

tr:table value="{bean.backingData}" partialTriggers="::ajax1"

So the poll initiates an ajax call to the bean, resets the backingData in the bean, and the table refreshes by updating itself with the new value for the backing data.

It is incredibly easy to do.

On another project where I did not use Trinidad, we achieved the same by writing out the ajax calls. Basically, the pages would call your ajax javascript library with the ids of the objects to update, and your backing bean would change these values. I found that an extremely useful tool was a window within the page that showed the ajax calls. In the page, I added a div element such as:

div id = "div_ajax_log"
textarea id = "log_ajax" name = "status" rows = "25" cols = "55"
/div

I would have a javascript library for ajax, and in this library I would have a toggle to turn ajax logging on and off. I would also set the style for the div as none or block based on wheterh I was in debug /dev mode or not. That way if there was an issue in production, I could inspect the messages coming to and from the server to the page.

In my js file for ajax, I would specify whether we are logging, and the element to log to :
// Whether to log
var _logging = false;
// Where to log
var _log_elem;

I would then specify a logging function:

function logger(text, clear) {
if(!_log_elem) {
_log_elem=document.getEleemntById("log_ajax");
if(clear)
_log_elem.value="";
var old = _log_elem.value;
_log_elem.value = text + ((old) ? "\r\n" : "") + old;
}

You will need to add in some null checks and/or try blocks in the above basic version.

Then, in my ajax methods I would check to see if the logger was running and if so spit out information to the text area. For outgoing calls:

logger("AJAX Request: " + ((async) ? "Async" : "Sync") + " " + method + ": URL: " + url + ", Data: " + data);

Where the variables were passed in by the calling page. For outgoing responses, I would do the same - here the variable AJAX is the XMLHttpRequest generated in the original call.

logger(AJAX.status);

logger(AJAX.responseText);

The result is a conditional logger to the page with the information carried to and from the page in AJAX calls.

Hope that helps.

Testing Web Applications

Posted in Bob Hedlund on July 14th, 2009 by admin

admin originally posted this on Eldorado Software.

How many times have you been on a project and seen changes to code cause the application to blow up, and yet the Unit Tests all succeeded? To avoid this situation I use HtmlUnit, an open source project distributed under the Apache License.

HtmlUnit emulates a browser that is visiting your web application. Coupled with JUnit, it allows you to write tests that click through the application just as QA does. It ensures that the functionality you put into your pages exists and works properly.

With HtmlUnit and Junit I am able to test most functionality in the web tier : page flow, form population and submission, javascript, popups, dialogs, and AJAX calls. I even created a suite of convenience methods to work with my Trinidad components.

The one shortcoming has been the ability to test Flex animations. These were always a black box to my test suites. However, Gorilla Logic has now released FlexMonkey, which is also based on HtmlUnit, and allows you to test the flex animations from an easy to use test suite.

I use these tests as both integration and unit tests. I ensure the application can be "clicked through"; that all pages appear at the correct time, and that interactions in the page all function correctly. I also test various scenarios that will occur in the application, and ensure that the application responds correctly based on the processing of the data passed in.

I no longer worry about the application blowing up in meetings or demos:

IT'S BEEN TESTED!!

Hibernate Search by Date

Posted in Bob Hedlund on July 14th, 2009 by admin

admin originally posted this on Eldorado Software.

On the project I am on now, we use Dates as a basis for monetary calculations. The Dates are simply based on the day, month and year, disregarding hours, minutes and seconds. We store our dates after base-lining them - stripping out the H:M:S. This is achieved with Calendar utilities:

static Date baseLineDate(Date myDate) {
GregorianCalendar cal = new GregorianCalendar();
cal.setTime(myDate);
cal.set(Calendar.HOUR, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MILLISECOND, 0);
return cal.getTime();
}

Determining if a Date is before, after, or equal to another is straightforward thereafter- just use the Calendar before() and after() methods.

If you look in the database, the dates are stored as 01-Jan-2009. It would be tempting to simply run a Hibernate query that tests equality. You could simply generate a base-lined date and ask Hibernate to return the objects that have this Date. And it works.

However... Databases are part of the seedier side of the software town. Lurking there is data imported from other systems and/or updated by rogue administrators. The best way to handle all possible situations correctly is to use the Hibernate Criteria's between() method:


getCurrentSession().createCriteria( MyItem.class )
.add(Expression.between("myDateField", base-lined-Date, end-lined-Date))
.list();

Where the base-lined-Date has been base-lined as above, and the end-lined-Date corresponds to a Date that is the last millisecond of the day:

static Date EndLineDate(Date d){
if(d==null)return null;
GregorianCalendar cal = new GregorianCalendar();
cal.setTime(d);
cal.set(Calendar.HOUR, 11);
cal.set(Calendar.MINUTE, 59);
cal.set(Calendar.SECOND, 59);
cal.set(Calendar.HOUR_OF_DAY,23);
cal.set(Calendar.MILLISECOND, 999);
return cal.getTime();
}

This solution pulls in all objects that have a certain Date defined by Day, Month and Year only.

Trinidad Draggable Dialogs

Posted in Bob Hedlund on March 24th, 2009 by admin

admin originally posted this on Eldorado Software.

Users of Apache Trinidad may have run across the issue of not being able to move the Trinidad dialogs around the page. They always sit right in the center of your screen and of course block you from seeing the information behind. In release 1.02 the authors proposed that the dialogs should be made drag-able, however nothing has been done. The following is a simple solution I used to make the dialogs drag-able. If I had time, I would commit something to the project to handle this - although I believe the reason it has not yet been implemented is because of the amount of cross browser code needed to affect this. The following solution took about 5 hours to come up with and refine.

The trick with making the dialogs drag-able is that that the dialogs are generated after the page loads, use different markup depending on browser type and version, and the markup contains no ids on the DOM elements of interest. I implemented this for Firefox2, 3 and ie7. For other browsers, the dialog is rendered with standard behavior.


So lets get started:

Step 1: Add the mouse drag event script to the Trinidad dialog:

In your xhtml/jsp file that will display behind the dialog , add a trh:script call that is rendered conditionally based on browser. The call will need to wait until the page loads to execute, so I add a timer to delay invokation:

trh:script text="window.setTimeout('attachDraggabilityToDialog()', 500);"
rendered="#{UiUtils.supportsDialogDrag}"

partialTriggers="::pprDialogCallButton "


The text attribute calls the attachDraggabilityToDialog script 500 ms after the page loads ( I place the script at the bottom of the page. )

The rendered attribute calls a backing bean function that specifies whether the browser version is supported for dragging.

The Partial Triggers attribute references Trinidad element id that pops up the dialog - in this case the button.

Step 2. Create the script:

// the frame
var dialog_frameDiv= null;
// the title bar on the frame
var dialog_titleBar=null;
// the object to drag around
var dialog_dragObj = new Object();
var GECKO=0;
var IE=1;
var BR_VER=GECKO;
new Browser();




/**
* After the page has loaded, and the popup has been displayed,
* Call this function:
* e.g: window.setTimeout(attachDraggabilityToDialog, 500);
* NOTE _ WORKS IN FF2, 3 AND IE 7
*
*/
function attachDraggabilityToDialog() {
dialog_dragObj = new Object();
dialog_frameDiv= null;
dialog_titleBar=null;

if (BR_VER==GECKO) {
for(var i =0; i <
window.document.body.childNodes.length;i++) {
dialog_frameDiv= window.document.body.childNodes[i];
if(dialog_frameDiv!=null && dialog_frameDiv.nodeName=="DIV" && dialog_frameDiv.style.zIndex==5001) {
dialog_titleBar=dialog_frameDiv.childNodes[0];
break;
}
}
}
else if (BR_VER==IE) {
var _node = document.getElementsByTagName("iframe")[0].parentNode;
if(_node !=null && _node.tagName=="DIV"){
dialog_titleBar= dialog_frameDiv=_node;
}
}

if(dialog_titleBar !=null) {
if (BR_VER==IE) {
dialog_titleBar.attachEvent("onmousedown", callDrag);
dialog_titleBar.attachEvent("onmouseup", endDrag);
}
if (BR_VER==GECKO) {
dialog_titleBar.addEventListener("mousedown", callDrag, true);
dialog_titleBar.addEventListener("mouseup", endDrag, true);
}
}

}



Discussion: Based on browser version, we look through the generated markup in the page once the dialog has appeared and find the element based on attributes or expected location of the node in the tree. While not foolproof, this technique works in the many scenarios in our present application, as Trinidad generates the dialogs in a standard manner per browser and version.

The attachDraggabilityToScript injects event handlers onto the elements to be dragged. The event handlers are below:


function callDrag(event) {

var el;
var x, y;
dialog_dragObj.elNode = dialog_frameDiv;

if (BR_VER==IE) {
x = window.event.clientX + document.documentElement.scrollLeft + document.body.scrollLeft;
y = window.event.clientY + document.documentElement.scrollTop+ document.body.scrollTop;
}
if (BR_VER==GECKO) {
x = event.clientX + window.scrollX;
y = event.clientY + window.scrollY;
}


dialog_dragObj.cursorStartX = x;
dialog_dragObj.cursorStartY = y;
dialog_dragObj.elStartLeft = parseInt(dialog_dragObj.elNode.style.left, 10);
dialog_dragObj.elStartTop = parseInt(dialog_dragObj.elNode.style.top, 10);

if (isNaN(dialog_dragObj.elStartLeft)) dialog_dragObj.elStartLeft = 0;
if (isNaN(dialog_dragObj.elStartTop)) dialog_dragObj.elStartTop = 0;

if (BR_VER==IE) {
document.attachEvent("onmousemove", startDrag);
document.attachEvent("onmouseup", endDrag);
window.event.cancelBubble = true;
window.event.returnValue = false;
}
if (BR_VER==GECKO) {
document.addEventListener("mousemove", startDrag, true);
document.addEventListener("mouseup", endDrag, true);
event.preventDefault();
}

}


function startDrag(event) {

var x, y;


if (BR_VER==IE) {
x = window.event.clientX + document.documentElement.scrollLeft + document.body.scrollLeft;
y = window.event.clientY + document.documentElement.scrollTop+ document.body.scrollTop;
}
if (BR_VER==GECKO) {
x = event.clientX + window.scrollX;
y = event.clientY + window.scrollY;
}


// Move drag element by the same amount the cursor has moved.

dialog_dragObj.elNode.style.left =(dialog_dragObj.elStartLeft + x - dialog_dragObj.cursorStartX) + "px";
dialog_dragObj.elNode.style.top =(dialog_dragObj.elStartTop + y - dialog_dragObj.cursorStartY) + "px";

if (BR_VER==IE) {
window.event.cancelBubble = true;
window.event.returnValue = false;
}
if (BR_VER==GECKO) ;
event.preventDefault();
}


function endDrag(event) {
if (BR_VER==IE) {
document.detachEvent("onmousemove", startDrag);
document.detachEvent("onmouseup", stopDrag);
}
if (BR_VER==GECKO) {
document.removeEventListener("mousemove", startDrag, true);
document.removeEventListener("mouseup", stopDrag, true);
}
}



Discussion : The above event handlers move the DOM element based on mouse movements after the user mousesdown on the element, and releases once the user mouses up based on browser version.


Finally, I have a simple browser detect , knowing that my script will not be called unless the browser is Firefox2, 3 or IE 7.


function Browser() {
var ua, i;
ua = navigator.userAgent;
if ((i=ua.indexOf("MSIE")) >= 0) {
BR_VER=IE;
}
}


In my backing bean, I have the following browser detection code that conditionally renders the call to the script based on its findings:



/**
* Currently only ff2,3 ie 7
* @return tru if the browser is one of the above.
*/
public boolean getSupportsDialogDrag() {
String ua = UiBaseUtils.getRequest().getHeader("User-Agent");

if(ua ==null)
return false;

if(ua.contains("MSIE 7"))
return true;
if(ua.toUpperCase().contains("GECKO")){
if(ua.contains("Firefox/3."))
return true;
if(ua.contains("Firefox/2."))
return true;
}
return false;

}



That's it.

I believe the correct way to do this would be to donate time and code to the Trinidad Project. I hope to do this , but I needed to come up with a quick solution that worked. I was able to commit this in less than 24 hours after getting the requirement, so please take this solution with this caveat in mind. QA has found no issues, and user feedback has been positive.

Hibernate AliasToBean Transformer

Posted in Bob Hedlund on March 24th, 2009 by admin

admin originally posted this on Eldorado Software.

Problem: You need to access values from tables that are not hibernate entities, in an aplication that uses hibernate to access the database.

Problem: You want to access a couple columns from any number of tables in your database without bringing back all the associated objects.

Solution: AliasToBean Transformer allows you to retrieve specific information in non entity beans.

This hibernate API call will allow you to run sql against your database and populate a list of pojos that are not a hibernate entity. This technique is great when you need specific information or perhaps you want information fom multiple tables.


Your pojo:

Class PlainOldObject {
String s1;
String s2;

public String getS1() {return s1;}
public String getS2() {return s2;}

public void setS1(String s1) {this.s1=s1;}
public void setS2(String s2) {this.s2=s2;}

}

Then in a hibernate dao :

publc List lookupPlainOldObects() {

// the sql with a reference to the s1 and s2 fields in our object
String sql="select tableX.col1 as s1, tableY.colx as s2 where blah blah blah";

List list = getCurrentSession().createSQLQuery(sql)
.addScalar("s1")
.addScalar("s2")
.setResultTransformer(Transformers.aliasToBean(PlainOldObject.class ) )
.setCachMode(CacheMode.GET)
.list();

return list;

}

This avoids your needing to cycle over multiple objects to pull in the information you need. It also alleviates the need to cycle over Object[] s to sort through your results.

A couple notes:

1. Use the set scalar method to convert the variables in your sql to the fields in your pojo.
2. Use CacheMode.GET to keep these ojects out of the hibernate session cache.




Passing Parameters via JSF

Posted in Bob Hedlund on March 2nd, 2009 by admin

admin originally posted this on Eldorado Software.

JSF allows us to cause updates to via various listeners: actionListseners, disclosureListeners, valueChangeListeners, and phaseListeners to name a few. Sometimes however, you may want to pass a parameter in to a generic method - perhaps to grab the value of an enumeration or access a users ability to view components based on Role.

One little known feature of JSF is that you may access elements of a java.util.Map. This allows us to pass in a key to a map object in one of our contexts, and the map passes back the value pair via the get(Object) method.

The notation in your jsf page would be:

value="${yourContextHandle.mapObject['mapKey']}"

where

yourContextHandle is an object in one of the contexts you use to access backing code
mapObject is a java.util.map that is available on the above object via getMapObject()
mapKey is the parameter passed in to find the object from the map.



In you backing code, generate an object that extends java.util.Map. You will need to implement quite a few methods, so I typically create a base object stub that handles the overriding of the methods beyond get(Object). In the below example, I call this MyBaseJSFMap. Then I extend this object and simply override get(Object);

But how do you get the answer you need?

Consider the following Map :


public Class MyJSFMap extends MyBaseJSFMap{

public Object get(Object o) {
return doSomething((String)o);
}

public String doSomething(String str) {
// your businessLogic here - perhaps a lookup to a database or a pull from a map.
}
}