Thursday, February 25, 2010

DisplayTag: Producing Decorators for Lists of Maps

I have been using the Display tag library (hereafter referred to as displaytag) heavily on a big in-house web application project. Displaytag helped me make relatively short work of pagination and data export, the resulting pages look very professional to boot. Best of all using displaytag meant I was able to concentrate my efforts on other parts of the project.

Much of the time I use the displaytag in the typical way (e.g. to display collections of beans). However, the changeable nature of some of the reports required lead me to produce some of the screens using Lists of Maps. Lists of Maps are very easily acquired from a database (e.g. Spring's ColumnMapRowMapper). Once you configure displaytag to display lists of maps then you have the flexibility to make changes to the report contents purely by changing an SQL statement. Also using the SQL "AS" keywords means that user friendly table column names are easily supported. So by making use of lists of maps you can produce very flexible and easily extensible reporting screens.

So far, so good...

Formatting data and adding extra display columns

By default whether you are passing a collection of beans or a list of maps to displaytag it just works! e.g.


<display:table name="dummyData"></display:table>

Elsewhere where I have used the typical way (collections of beans) of supplying data to displaytag. Sometimes I need to reformat a date, currency column or change some columns into links. You can do most of this inside the JSP page (messy!) or alternatively you can make use of the displaytag TableDecorator. You can also use TableDecorator's to add new columns that don't exist in the data, however, once you start specifying custom generated columns then you need to explicitly specify all the columns you would like to see in the displaytag table, e.g.:


<display:table name="dummyData" decorator="edu.bristol.SampleDecorator">
<display:column property="id" />
<display:column property="date" />
<display:column property="url" />
<display:column property="columnPopulatedByTableDecorator" title="Decorator generated"/>
</display:table>

I wanted to do this with a list of maps. After a little research on the forums, I found that you could still make use of TableDecorator generated custom columns by explicitly specifying the columns in your map. As the data originates from the database, each list row will contain a map with the same set of map keys. First you retrieve the map keyset from the first result row, store this keyset in the request and then you can explicitly iterate through the map columns:


<display:table name="dummyData" decorator="edu.bristol.SampleDecorator">
<c:forEach items="${keyset}" var="key">
<display:column property="${key}" />
</c:forEach>
<display:column property="columnPopulatedByTableDecorator" title="Decorator generated"/>
</display:table>

At this point, the "columnPopulatedByTableDecorator" will be generated but the TableDecorator doesn't do any re-formatting of the existing data columns.

Producing Decorators for Lists of Maps

So now we come to the novel aspect of this blog entry! The next question is how I reformat the data in my list of maps for displaytag purposes. I searched through the forums and couldn't get an answer for this, so I came up with a solution. Internally, displaytag uses Commons BeanUtils for data manipulation. We have seen that it can handle lists of maps without any additional configuration - so it must be doing something clever! The TableDecorator test code for displaytag includes tests for accessing mapped data, so I knew that it should be possible to access the mapped data in my own TableDecorator. Part of the difficulty in accessing the data is that my key names were not easily transformed into Java method names, the keys contain spaces, capitalization and other characters that are not permitted in a method name. My solution was to alter my list of maps to become a list of "wrapped maps". Where a wrapped map looks something like:


public class WrappedMap {

Map m;

public WrappedMap(Map m) {
this.m = m;
}

public Object getMap(String propertyName) {
return m.get(propertyName);
}
}

My decorator for this list of wrapped maps could now access my oddly named keys, such as:


public class WrappedMapDecorator extends TableDecorator{

final private String startDate = "Start Date";
final private String websiteAddress = "Website Address";

public String getMap(String propertyName){
WrappedMap wm = (WrappedMap) getCurrentRowObject();
Object propertyValue = wm.getMap(propertyName);
if(startDate.equals(propertyName)){
// Implement appropriate formatting/decoration
return "<i>" + propertyValue.toString() + "</i>";
}
if(websiteAddress.equals(propertyName)){
// Implement appropriate formatting/decoration
return "<b>" + propertyValue.toString() + "</b>";
}
return propertyValue.toString();
}

}

Finally, my JSP would need to be tweaked to produce the appropriate table:


<display:table name="dummyData" decorator="edu.bristol.WrappedMapDecorator">
<c:forEach items="${keyset}" var="key">
<display:column property="map(${key})" title="${key}" />
</c:forEach>
<display:column property="columnPopulatedByTableDecorator" title="Decorator generated" />
</display:table>

I am happy with this solution. I maintain the flexibility that the List of Maps technique makes possible but it is also possible to decorate the supplied data.

Incidentally, you may have noticed that I haven't been blogging much in recent times. I am now the father of 2 pre-schoolers and so what free time I get is usually spent collapsed in a heap rather than blogging! Anyway I hope you find this useful...

13 comments:

prasadk said...

i have a hashmap>

i want to display as below

column 1 column 2
key of hashmap arraylist resp

please help

Brad G said...
This comment has been removed by the author.
Unknown said...

Expensive and bound Rolex Réplique abroad from omega replica ability for that commoners. Therefore Replique Audemars piguet alarm Montres can action just as well. With the capabilities, accomplished and breeding around on par with that with the different Replique Audemars piguet alarm Montres will be awful admirable alms concepts for breitling replica this blithe year or on any accident for that accomplish a difference. However to ensure you’re not bamboozled you accept to go hublot replica via accurate and reliable websites like http://www.Montresen.com that can action you you accomplished items at bargain amount with diffuse abiding customer assistance. They are able to aswell accommodate your get anon to cartier replica abetment you beat the time blitz and the majority of the items appear with assure and 1 agenda year guarantee. Due to the actuality Montresen.com action alone in the top in replique Montres, their amount of bounce is just about nil, but central the abominably break of animosity the applicant account agents will acceptable be decidedly added than agreeable to rolex replica become of assist.Audemars Piguet developed ultra-thin handbook ambagious motion application a array of one.65mm. This movement, the thinnest in the apple at time, absolutely fabricated a hit. As abundant as now, this almanac has not been torn by any motion that fabricated by louis vuitton replica acceptable Montre bearing technique. Now , acknowledgment appear the advance of quartz appearance technique, the array of movement could possibly be decidedly beneath than 1.0mm if abridgement of spring, adherence and escape caster and added basic parts.





madin said...

replica hublot watches is a Swiss luxury watchmaker founded in 1980 by Italian ... Hublot unveiled a new method of detecting counterfeit watches. Using a smart card, replica watches uk the system authenticates watches on Hublot's servers.

madin said...

Louis Vuitton himself was born the son of a miller in 1821 in Anchay, a hamlet in the Jura Mountains, not far from the Swiss border. Replica bagsThe region was a poor one - serfdom had only been abolished less than 40 years previously, so Louis left to seek his fortune when he was a teenager, arriving in the French capital aged 16. This was the Paris of Victor Hugo's Les Misérables, with nearly one million inhabitants. As the composer Chopin said in a letter to a friend at the time, "Here you find the greatest luxury and the greatest filth, the greatest virtue and the greatest vice."replica Louis Vuiton bags

madin said...

Rolex watches are crafted from the finest raw materials and assembled with scrupulous attention to detail. cheap replica watchesEvery component is designed, replica rolex watchesdeveloped and produced in-house to the most exacting standards.

madin said...

Louis Vuitton himself was born the son of a miller in 1821 in Anchay, a hamlet in the Jura Mountains, not far from the Swiss border. Replica bagsThe region was a poor one - serfdom had only been abolished less than 40 years previously, so Louis left to seek his fortune when he was a teenager, arriving in the French capital aged 16. This was the Paris of Victor Hugo's Les Misérables, with nearly one million inhabitants. As the composer Chopin said in a letter to a friend at the time, "Here you find the greatest luxury and the greatest filth, the greatest virtue and the greatest vice."replica Louis Vuiton bags

madin said...

replica mont blanc uk is a brand with a long history. Founded in 1906, the replica mont blanc donation penscompany is named after one of the highest mountains in Europe, marking the brand's commitment to producing fine writing instruments. Using the brand that produces the best writing instruments, it helps to know how to find the Montblanc fountain pen that works best for you. From the best Montblanc fountain pens to ballpoint and ballpoint pens, you have a choice. Whether you are a collector or a keen writer, this article will take you to the top 10 Montblanc fountain pens on the market.

madin said...

At Rolex, we believe in maintaining a long-term commitment to outstanding individuals,fake rolex watches organizations, fake pearlmaster watches events and institutions in the fields of adventure, sports, arts and culture, science and education.

madin said...

With their unwavering commitment to transcending modern fashion, replica Ray-Ban Sunglasses stands out with its replica Ray-Ban Sunglasses clubmaster state-of-the-art eyewear collection that transcends time and age.

madin said...

Taking its name from Monestier-de-Clermont, a village in the cheap moncler jackets uk French Alps, replica unisex moncler jacketsMoncler began by producing quilted sleeping bags, cagoules and tents. The first quilted jackets were created for local workers to top their overalls. Since then, Moncler’s cornerstone design has become a luxury winter icon, favored by A-listers such as Reese Witherspoon and Victoria Beckham.

madin said...

replica cartier watches has recommended many classic and successful watch collections, such as Cartier Tank, replica calibre de cartier diver watches Cartier Santos and Cartier Ronde and so on. Every Cartier watch has its special charm, and Cartier watches are many people's dreams. Our shop provides different Cartier replica watches at very low prices. Just enjoy shopping here.

madin said...

cheap walker zimmerman Jerseys for Huge Savings on Soccer Replica Clothing. cheap Soccer Jerseys & Soccer Clothing with Next Day shipping!