Tuesday, April 20, 2010

How about iCalendar Autodiscovery?

Love it or hate it, iCalendar is the pervasive calendaring format. If we can enable RSS autodiscovery then why not do the same with iCalendar feeds. Adding one line of code would make it easier for people/machines to subscribe to an iCalendar feed.


<link rel="alternate" type="text/calendar"
title="iCalendar feed for example.com"
href=""calendar.ics"" />

Tuesday, March 30, 2010

Jasig UK 2010 meeting 21 and 22 June

Jasig are a consortium of educational institutions and commercial affiliates sponsoring open source software projects for higher education. Jasig project of particular note include uPortal (a powerful framework for producing campus portals) and CAS (a secure enterprise authentication system and single sign-on service).

The Jasig UK 2010 meeting will be held at Bristol University from Monday 21 to Tuesday 22 June.  The meeting will start at 14.00 on the Monday and finish by 14.00 on the Tuesday. Details can be found at:

http://www.ja-sig.org/wiki/display/UK/2010+Meeting+Bristol

If anyone wants to attend please update the "Interested in Attending" and "Suggested Topics" wiki pages with your details and items you are interested in discussing at the meeting. There is no charge for attending the meeting.

Friday, March 19, 2010

LinkedHashMap enhanced

In my day to day Java programming it is rare for me to feel the need to re-engineer or significantly enhance something quite fundamental to the Java language. I am a pretty average programmer, I get the job done, I like to do things elegantly but I do not spend my spare time creating my own languages and compilers (that stuff looks harder than "rocket science"). Most of the time the standard Java Collections Framework with the ArrayList, HashSet, HashMap and LinkedHashMap is more than ample for my meagre needs. Sometimes I have looked elsewhere to solve a particular problem; I had previously encountered the ArrayListMultimap from the Google Collections Library. This deviates from the standard Map implementations in that it allows you to create a "Map" which may associate multiple values with a single key (well technically it does not implement the Map interface but never mind!).

Google Collections' ArrayListMultimap

The ArrayListMultimap is really useful and very powerful. Imagine for example you wanted tag cloud functionality for a blog. You can iterate through your pages, putting them in your "cloudmap" (new ArrayListMultimap<String,URL>) using the tag as the map key. You can very easily get back a list of URLs with that tag key.


List<URL> links = cloudmap.get("java");

You can also very easily produce the tag counts necessary for a tag cloud using something like.


int linkcount = cloudmap.get("java").size();

My contribution: LinkedHashMap augmented

I have been working on a timetable related application recently which provoked me to extend the behaviour of LinkedHashMap. My situation was that I needed to produce a Map where the entry order of the data was important (e.g. insertion-order). Java Collections' LinkedHashMap is designed specifically for those requirements. I had an additional requirement to be able to fetch a portion of my map whose keys range from fromKey to toKey. LinkedHashMap does not itself implement this. TreeMap is a collections class which does permit accessing ranges of data, however, TreeMap does not support insertion-order. Instead TreeMap supports data with a natural ordering (e.g. numbers in numeric order, dates in chronological order). In my map, although the keys and values were important data, the natural ordering does not provide anything useful.

So I set about extending LinkedHashMap and came up with a class which implements the following interface:


public interface ILinkedHashMapAugmented<K, V> extends Map<K, V> {

LinkedHashMapAugmented<K, V> subMap(K fromKey, K toKey);

LinkedHashMapAugmented<K, V> subMap(int fromIndex, int toIndex);

Map.Entry<K, V> getEntry(int idx);
K getKey(int idx);
V getValue(int idx);
}

You can access the implementation of this interface at this link here LinkedHashMapAugmented.java. I make no claims about this being the most efficient code ever, if I wanted that I would take a copy of open source of LinkedHashMap and rather than extend it I would completely re-engineer it. I wanted something simple and what I have produced is useful and just feels right to me. The LinkedHashMap also supports access-ordering, I have not considered how my enhancement impacts on this but it could be useful.

So for a simplified example of my new class, I can define a week schedule like this:


LinkedHashMapAugmented<String, String> schedule = new LinkedHashMapAugmented<String, String>();
schedule.put("SV14", "21-Sep-09");
schedule.put("0", "28-Sep-09");
schedule.put("1", "05-Oct-09");
schedule.put("2", "12-Oct-09");
schedule.put("3", "19-Oct-09");
schedule.put("CV1", "14-Dec-09");
schedule.put("11", "11-Jan-10");
schedule.put("12", "18-Jan-10");
schedule.put("13", "25-Jan-10");
schedule.put("EV1", "22-Mar-10");
schedule.put("21", "19-Apr-10");
schedule.put("22", "26-Apr-10");
schedule.put("23", "03-May-10");
schedule.put("SV1", "21-Jun-10");

If I want to get a Map containing data between the weeks labelled 21 to 23 I need only call:


schedule.subMap("21","23");

As insertion-order is significant I have also implemented the ability to retrieve the Nth position of Map.Entry, key or value.

I think I have produced a simple but useful enhancement to the LinkedHashMap. I could have implemented this functionality by using some combination of existing Collections classes and arrays but this single data structure approach feels better to me. I suppose I could complete the loop by implementing a similarly enhanced version of ArrayListMultimap but I currently do not have the need!

Tuesday, March 09, 2010

AJAX decoration: using jQuery Metadata for portlet AJAX

I recently examined a JSR 168 portlet which tackled the thorny area of AJAX in a Portlet ( incidentally the portlet I was looking at is the Jasig Calendar Portlet ). The technique used makes all AJAX requests into POSTs which are then passed via the portal and a redirect to a servlet to acquire the desired response. I am not new to JSR 168 portlets and have personally produced several portlets over the past few years. I have also solved the AJAX in a Portlet problem but in a completely different way. The solution I developed I am calling AJAX decoration and relies on the jQuery Metadata plugin. I think both techniques have their merits and possibly could be applicable to different scenarios. I will attempt to illustrate my solution with a simple example app (note this example is not an actual portlet and will work in your servlet container of choice).

The structure of each of my "portlet" JSPs in my example is something like this:

header.jsp


<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script type="text/javascript" src=""jquery-1.3.2.min.js"><!--" --></script>
<script type="text/javascript" src=""jquery.metadata.js"><!--" --></script>
</head>
<body>
<div id="content-area">

footer.jsp


</div>
<script type="text/javascript">
var pageContext = "${pageContext.request.contextPath}";
var targetArea = "div#content-area";
</script>
<script type="text/javascript" src=""ajaxDecorated.js"><!--" --></script>
</body>
</html>

somepage.jsp


<%@ include file="header.jsp" %>
<h1>Some Page</h1>

<!-- Content goes here -->

<%@ include file="footer.jsp" %>

Notice that we will be using a consistent target area for our AJAX loaded content; in this case a div with the ID of "content-area". The jQuery Metadata plugin makes it possible to read data stored within CSS classes, doing this is a relatively clean way of storing data within our page. In this approach the content links are decorated with data and in turn this data is used to assign appropriate AJAX behaviour.

For a typical link using a GET we could use:


<a href=""page1.jsp"" class="ajaxRenderURL {link: '/page1.jsp'}">page 1</a>

For form submission we could use:


<form action="page2.jsp" class="ajaxActionURL {link: '/page2.jsp'}">
<input type="submit" />
</form>

The magic happens in the "ajaxDecorated.js" file. When the page initially loads initPage() is invoked which attaches AJAX loading behaviour to links and forms.


$(document).ready(function() {
initPage();
});

function setupLinks(){
var data = $(this).metadata();
var loadlink;
var tsSeparator = "&";
if(data.link.indexOf("?") == -1){
tsSeparator = "?"
}
if(!data.link.match("^" + pageContext)){
loadlink = pageContext + data.link + tsSeparator + new Date().getTime() + " " + targetArea;
} else {
loadlink = data.link + tsSeparator + new Date().getTime() + " " + targetArea;
}
$(targetArea).load(loadlink, null,
function () {
initPage();
});
return false;
}

function setupForms(){
var data = $(this).metadata();
var formdata = $(this).serializeArray();
var loadlink;
if(!data.link.match("^" + pageContext)){
loadlink = pageContext + data.link + " " + targetArea;
} else {
loadlink = data.link + " " + targetArea;
}
$(targetArea).load(loadlink, formdata,
function(){
initPage();
});
return false;
}

function initPage(){
$(targetArea).find('a.ajaxRenderURL').click(setupLinks);
$(targetArea).find('form.ajaxActionURL').submit(setupForms);
}

This technique adds AJAX to a web page in an unobtrusive way. In this simple example the URLs loaded by AJAX and those that would be loaded without are the same (page1.jsp, index.jsp etc). However, in an environment where the AJAX URLs and web page URLs are likely to be different or even change dynamically (such as in a portal) then this technique is equally applicable.

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...