Monday, December 28, 2009

Eclipse and friends are memory hungry

I've been using Eclipse Galileo for some time now and have quite a few favourite (and necessary!) plugins installed. These included m2eclipse, subeclipse, findbugs, checkstyle and many more.

I had noticed though that things started to slow down. Even clicking between tabs was slow (started out ok after launching and then got worse over time).

This smelled like a memory performance issue so I re-configured Eclipse to have a maximum memory size of 2GB and all now appears well. 2GB may have been an over-reaction - your mileage might vary, but for me it seems to have done the trick.

Thursday, December 10, 2009

Chrome on Mac - No Google Earth plugin though

I've just installed the Chrome beta on my Mac. Looks good overall.

However the first thing I did ('cause its close to what I'm involved in) was try out the Google Earth Plugin.

No dice:



So perhaps the same constraints holding back the plugin under Safari 4 are holding up it working under Chrome also; perhaps it is the out of process plugin architecture, and/or the new requirement to use Core Animation to render OpenGL...

Actually I've noticed that Chrome doesn't presently support the Core Animation for OpenGL NPAPI plugins (my CA NPAPI plugin isn't able to instantiate - most likely due to the browser stating that CA/Cocoa is unsupported due to the graceful failure).

In searching for some technical insight I noticed that Google provide a great article on the motivation behind Chrome.

First impressions then are that Chrome looks interesting but it isn't quite there for me yet given my specialised NPAPI requirements.

Friday, December 4, 2009

MacPorts - my new best friend

Perhaps it is just that I'm getting older, but I've resisted using package managers on Linux and Mac OS X for some time. I dunno, I guess I preferred to download the source and build it myself. What a sucker I am for punishment!

I think that I had a similar resistance to Apache Maven originally - I just didn't want the learning curve of a new tool.

I'd got to the point with a C++ project that I was fed up managing, building and sorting out the dependencies of various C/C++ based libraries. The catalyst for me was when I started using Cairo, a 2D vector and imaging library (which is great!). Cairo had many dependencies and the project recommended a number of package managers for my OS X build environment.

I ended up with MacPorts and haven't looked back. Managing those dependencies just got a whole lot easier. MacPorts was apparently started by a group of Apple engineers and it grew from there. At the time of writing there are now over 6,000 packages available through MacPorts.

MacPorts likes to put everything in /opt by default. For some bizarre reason I was against using /opt as my root folder for all MacPorts derived packages - talk about resisting change for no good reason! However I got over that and must take a leaf out here and try to resist such time consuming temptations. Who really cares where MacPorts puts stuff so long as at the end of the day your dependencies are being managed and your applications build?

The only thing I found myself changing with the default configuration was the /opt/local/etc/macports/variants.conf file. I wanted +universal as a default. My projects tend to build both 32 bit and 64 bit targets and so I needed MacPorts to do this by default (I kept forgetting to specify the variant on the command line).

All good. MacPorts is great and is another tool that helps me focus on the problem at hand.

Thursday, November 26, 2009

Write less code

I think that old adage of "Sorry I wrote you such a long letter, if I had more time I'd write you a shorter one" certainly applies to software development as well. If you spend a great deal of time learning how to write less code by using more off-the-shelf toolkits and frameworks you will write less code in the end. Sounds obvious, but I still see developers re-inventing the wheel far too often.

The following code requires a steep learning curve around Java, Apache projects, iCal4j (a great calendaring toolkit for iCalendar) Spring, Spring DAO and Maven; and probably many more things. Look how straightforward the expression is though:


from(calendarEventEmailInboundEndpoint).to(
"bean:calendarAttachmentTranslator").to(
"bean:calendarEventTranslator").to(
"bean:calendarEventDAO?method=save");


The above Java code shows a Camel route that reads emails from a pop3 or imap inbox (depending on how calendarEventEmailInboundEndpoint is configured), extracts iCalendar attachments from one or more emails, translates the iCal4j representation into a model form for persistence, and finally persists the calendar event(s) in a database.

Pretty sophisticated stuff for 4 lines of code. :-)

Sunday, October 18, 2009

Maven Release Plugin - My new friend

One tool that slipped my radar until only this week was the Maven Release Plugin. If you are a Maven user and you release what you produce with it (I would hope so!) then you should take a look at this plugin.

My applications tend to be containers for the many pre-fabricated components of other projects I have. For instance I have 19 projects in my Eclipse workspace where 3 of them are the containers - if you like, the applications themselves.

Having lots of projects means that it can be easy to miss updating the version numbers for them when it comes time to perform a release; particularly missing that a project is being depended on as a snapshot.

In summary two big reasons to use the Maven Release Plugin are:


  • it ensures that there are no snapshot dependencies; and

  • it updates your pom's version number automatically.


In order to use the plugin I found myself having to add an scm element, an element for the plugin itself and a distributionManagement element.

The scm element let's the plugin know where to tag a release. Each time you make a release the plugin will create a tag for it in your source code repository. I was doing this as a manual task prior to the plugin so this feature is great.

I configured the plugin to ignore deploying my source code and javadoc to the repository. I actually had a problem with the maven source plugin given spaces contained in my path. I also didn't need to deploy the source code as I have it within my scm repository and I don't intend releasing the source to other parties.

Lastly you need to let the deploy plugin know how to deploy your project's artifacts in a maven repository i.e. the jar files in my case. The release plugin will invoke the deploy goal by default (actually it does a deploy and then "site deploy"). My projects generally rely upon the default goal with exception to those "application" projects. The application projects simply invoke the assembly plugin as I'm interested in producing a tar.gz file of the entire application. I therefore don't need to specify repository deployment details in my pom for these application projects as there is none.

All in all the maven release plugin saves me time and improves my release build quality.

Thursday, September 17, 2009

Client/server or consumer/provider

Wow, I can't believe that it is now September and I've not posted anything since July. In a nutshell I landed a new airport customer (Subang Skypark - the Kuala Lumpur domestic airport) and so life has been terribly busy. As a result there's a lot of software development to be discussed since my last post. However I'll start with this little one as a result of an interesting conversation today.

I designed an interface today that describes a set of remote services. As the interface is a consumer of those services I came up with the name XXXConsumer (I didn't really use XXX though). A friend of mine asked why not call it XXXClient? I had to really think about that.

Two seconds later I blurted out that client and server had become an overloaded term and that the hip terms are now consumer and provider respectively. In other words I didn't really know why I preferred to use the word consumer and provider and put it down to the time I've spent with JMS and Apache Camel. These technologies often use the terms consumer and provider.

Wikipedia offer a nice definition of client and server that effectively implies that these names are used for fairly course-grained objects such as applications and systems. My assertion having thought about this a little more is that consumers and providers are used in a finer-grained context. By finer-grained I refer to the software components found within my application.

In addition client and server are certainly overloaded terms and typically imply that an application or system has just this one role. By contrast I often see that components are both consumers and providers of services. Perhaps this is another difference.

Thank you for allowing me to client^H^H^H^H^Hconsume your time!

Friday, July 17, 2009

Replacing jsvc for Java daemons

For some time I have been using the Apache Commons Daemon project to run and maintain my Java based services. jsvc did/does a reasonable job but I start to worry when a project has not been touched for a while.

In addition I am in the midst of deploying a Java based service on Mac OS X and so I am in the world of launchd. I wanted a better way of controlling Java based services; particularly one that did not fork multiple processes given launchd's garbage collection.

The principal issue with a Java service running in the background is that you need to have it respond asynchronously to various singals; particularly SIGTERM which of course is issued when the OS is being shutdown. My service needs to shut down gracefully.

Enter in a feature of Java 1.4.2 that I did not realise existed: Shutdown Hooks. In essence Shutdown Hooks provides your Java application an opportunity to respond to the application quitting.

Followers of this blog know that I am an Apache Camel addict. You will not therefore be surprised to find that what follows is an example of how to start up and shutdown a Camel context using Java's Shutdown Hooks.


public class EntryPoint {
static Logger logger =
Logger.getLogger(EntryPoint.class.getName());

static EntryPoint entryPoint;

Main main;

public static void main(String[] args) {
entryPoint = new EntryPoint();

Runtime.getRuntime()
.addShutdownHook(new Thread() {
public void run() {
try {
entryPoint.stop();
} catch (Exception e) {
logger.fatal(e.toString());
}
}
});

try {
entryPoint.start();
} catch (Exception e) {
logger.fatal(e.toString());
}

}

public void start() throws Exception {
logger.info("Starting up");

// Start up the context
main = new Main();
main.start();

logger.info("Started");
}

public void stop() throws Exception {
logger.info("Stopping");

// Shutdown the context
main.stop();

logger.info("Stopped");
}
}

Friday, July 10, 2009

A Camel based XML Payload HTTP polling provider

Wow, what a mouthful of a title that is.

The EAI Polling Consumer pattern is well documented. Polling consumers are particularly useful for HTTP clients such as AJAX applications. Their presence provides a means of implementing publish and subscribe.

What I needed was some code to service my AJAX consumer; a Polling Provider so to speak.

Given my immersion in Apache Camel I came up with a Polling Provider for XML objects provided by XMLBeans. The provider assumes that an HTTP endpoint is to be interacted with and thus sets the HTTP time headers appropriately.

The Polling Provider holds the notion that the xml object is updated by one thread and then consumed by another. Furthermore the time the xml object was last updated is retained. This allows HTTP consumers to specify the HTTP ifModifiedSince header and block if the condition is not met.

To update the provider (fidsDocumentPollingProvider is an instance of it and newFidsDocument is an XML document object):


fidsDocumentPollingProvider.update(
newFidsDocument, new Date());


To retrieve the resource in a RESTful manner:


// Provide a RESTful service to retrieve FIDS data
from("jetty:http://0.0.0.0:9000/FIDSService/FIDS")
.inOut("direct:getFIDS");

// Provide a component to process FIDS requests
from("direct:getFIDS")
.process(fidsDocumentPollingProvider);


Here is the code I came up with for the provider. I would be very interested to hear of better ways to do this given Apache Camel.


package com.classactionpl.camel.xmlbeans;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import org.apache.camel.Exchange;
import org.apache.camel.Processor;
import org.apache.camel.component.http.HttpProducer;
import org.apache.xmlbeans.XmlObject;

public class XMLHttpPayloadPollingProvider implements Processor {
XmlObject xmlObject;
Date lastModified;
Lock lock = new ReentrantLock();
Condition update = lock.newCondition();

public void update(XmlObject xmlObject, Date lastModified) {
lock.lock();
try {
this.xmlObject = xmlObject;
// We don't need the milliseconds and they can upset
// our comparisons given that they are not passed from the
// outside world.
this.lastModified = new Date((lastModified.getTime() / 1000) * 1000);
update.signal();
} finally {
lock.unlock();
}
}

public void process(Exchange exchange) throws Exception {
lock.lock();
try {
boolean waitForUpdate = true;
Date ifModifiedSince = null;
if (lastModified != null) {
String ifModifiedSinceStr = exchange.getIn().getHeader(
"If-Modified-Since", String.class);
if (ifModifiedSinceStr != null) {
try {
SimpleDateFormat rfc822DateFormat = new SimpleDateFormat(
"EEE', 'dd' 'MMM' 'yyyy' 'HH:mm:ss' 'Z",
Locale.US);
ifModifiedSince = rfc822DateFormat
.parse(ifModifiedSinceStr);
waitForUpdate = (lastModified
.compareTo(ifModifiedSince) <= 0);
} catch (ParseException e) {
}
}
}

boolean provideDateHeader;

if (waitForUpdate) {
update.await(90, TimeUnit.SECONDS);
}

if (xmlObject != null) {
if (ifModifiedSince == null) {
ifModifiedSince = lastModified;
}
if (lastModified.compareTo(ifModifiedSince) > 0) {
exchange.getOut().setBody(xmlObject.newInputStream());
exchange.getOut().setHeader("Content-Type", "text/xml");
provideDateHeader = true;
} else {
exchange.getOut().setHeader(
HttpProducer.HTTP_RESPONSE_CODE, 304);
provideDateHeader = true;
}
} else {
exchange.getOut().setHeader(HttpProducer.HTTP_RESPONSE_CODE,
404);
provideDateHeader = false;
}

if (provideDateHeader && lastModified != null) {
SimpleDateFormat rfc822DateFormat = new SimpleDateFormat(
"EEE', 'dd' 'MMM' 'yyyy' 'HH:mm:ss' GMT'", Locale.US);
rfc822DateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
exchange.getOut().setHeader("Last-Modified",
rfc822DateFormat.format(lastModified));

}

} finally {
lock.unlock();
}
}
}

Thursday, May 14, 2009

Titan Class goes into production



She's finished, well as finished as they always are - which of course means that they are never finished.

I am referring to my work over the past few months which is really just a concerted effort building on years of work. I'm now in a position to track vehicles, containers, you name it.

From a software development perspective there are many things that I'm happy about. I've previously discussed jQuery which really has eased the AJAX programming. From a backend perspective I am using the amazingly functional, scalable and distributable Apache Camel (also discussed in other posts).

One thing with the client-side that has really impressed me is the Google Earth plugin. I hope that you agree that it works very, very well (a link to the site is provided at the end of this post). Some of our potential customers will require their own maps along with their own projections and Google Earth will not handle that (Antarctica for example). However for many scenarios, Google Earth will be great.

Incidentally where we will be required to use specialised maps with funky projections, I have written a Java applet using JavaFX. The applet supports many types of map projections and is based on the work of Proj.4 and friends.

Here is a quick list of the OSS projects I utilised (and even contributed back to in some cases!):

Apache ActiveMQ,
Apache Camel
Apache Directory Server
Apache MINA
Apache Tomcat
Apache Web Server
GEOS
Eclipse
Hibernate
Hibernate Spatial
jQuery
JSON
JTS
JUnit
Linux
Log4J
Maven
PostgresQL
PostGIS
Proj.4
Spring
Subversion
xmlbeans


Go OSS!

Feel free to visit the tracking site and play around with the demo data.

Monday, May 11, 2009

Guice

I found this video introduction on Guice very good. Guice is another Inversion of Control (IoC) container, much like Spring IoC, but with the advantage of coming later. What's particularly interesting about Guice is that it largely forms the basis of JSR-299's IoC.

I'm a big user of Spring IoC and frankly don't have a problem with it. However I can see that Guice could save me some wiring code and, therefore, potentially bugs (not that there are bugs in my code!). I might well consider using Guice for future projects. The outcome of JSR-299 will weigh in heavily on this decision though as I like my code to be as standards-compliant as possible.

One thing that I am comfortable about with Spring though (vs Guice) is that my beans have no knowledge of being injectable; they simply are by being bean conforming. With Guice you must declare what is potentially injectable. I do like the loose coupling between my bean code and the IoC that Spring provides, yet I can see that Guice, by declaring what is injectable, can save some of the wiring code.

I'll guess I'll just have to give Guice a whirl to find out.

Wednesday, May 6, 2009

jQuery

I have just completed an Ajax application that uses the jQuery framework. jQuery's promise is to "write less, do more", which I suppose is the objective of most frameworks. Does jQuery deliver though? In a nutshell, yes.


Writing an Ajax application is hard; not because of network paradigms or Javascript, but because each browser brings with it some quirk. Catering for all of these browsers is simply time consuming so, by hard, I really mean time consuming. It is therefore hard to knock out an Ajax application quickly given the shear amount of cross-browser testing that has to be performed.


jQuery does not eliminate cross-browser issues but it certainly minimises them. With my application, the only real short-fall I found with jQuery was its lack of support for dealing with XML documents (not XHTML). This was primarily due to the lack of XML namespace support and I think that this is an area that jQuery should focus on. However it is important to note that the real culprit for the lack of namespace support is Internet Explorer. In essence there is no support for namespaces with IE. I find this extremely difficult to understand... ok, IE 6 with no namespaces is understandable to a degree, but version 7, and worse even version 8 do not support XML namespaces. Microsoft virtually invented SOAP given their backing of it, yet their browsers can't parse SOAP documents accurately (you can ignore the namespaces, but then you ignore the value of namespaces of course).


Here are some other things I found myself having to cater for explicitely...


iframe shims
iframes shims are provided by a jQuery plugin named bgiframe and you can set up jQuery's dialog so that it uses an iframe. Unfortunately IE6 is not the only browser that requires iframes for the purposes of overlaying html objects on OS rendered content (buttons, applets, objects etc.). I therefore found myself having to roll my own. Here's a snippet of what needs to be done in the case of displaying a login dialog when some label is clicked:



var loginDialog = $("#loginDialog").dialog({
autoOpen: false,
close: function() {
loginDialogIframeShim.css("visibility", "hidden");
},
...
});
var loginDialogIframeShim = $(document.createElement("iframe"));
loginDialogIframeShim.attr("frameborder", "0");
loginDialogIframeShim.attr("scrolling", "no");
loginDialogIframeShim.attr("allowtransparency", "false");
loginDialogIframeShim.css("position", "absolute");
loginDialogIframeShim.css("visibility", "hidden");
$("body").append(loginDialogIframeShim);

var login = $("#login").click(function() {
loginDialog.dialog('open');
var loginDialogParent = loginDialog.parent();
var offset = loginDialogParent.offset();
loginDialogIframeShim.css("left", offset.left + "px");
loginDialogIframeShim.css("top", offset.top + "px");
loginDialogIframeShim.css("width", loginDialogParent.outerWidth() + "px");
loginDialogIframeShim.css("height", loginDialogParent.outerHeight() + "px");
loginDialogIframeShim.css("visibility", "visible");
...
The above works well for Windows FF and IE 7 and Mac OS FF and Safari. I haven't tested other browsers.

Datepicker ranges
It would be great to see the Datepicker (which is really great as is) enhanced to support a date range selection.

XmlHttpRequest
While jQuery does a lot to abstract away the peculiarities of browsers with XmlHttpRequest, I did find myself having to encode credentials for Safari. This is because Safari likes to send credentials as part of the URL initially (if that fails then it tries the conventional way using an authorisation header - I do not understand why).


if($.browser.safari) {
requestUsername = encodeURIComponent(requestUsername);
requestPassword = encodeURIComponent(requestPassword);
}

$.ajax({
url: "...",
dataType: "xml",
username: requestUsername,
password: requestPassword,
...


Date/time utilities
In general terms I found these lacking. Quite often with XML one has to convert from ISO8601 to a Javascript date and back. I needed to provide these functions:



function formatISO8601Time(time) {
var timeStr;

var year = time.getUTCFullYear();
timeStr = "" + year;
timeStr += "-";

var month = time.getUTCMonth() + 1;
if (month < 10) {
month = "0" + month;
} else {
month = "" + month;
}
timeStr += month;
timeStr += "-";

var day = time.getUTCDate();
if (day < 10) {
day = "0" + day;
} else {
day = "" + day;
}
timeStr += day;
timeStr += "T";

var hour = time.getUTCHours();
if (hour < 10) {
hour = "0" + hour;
} else {
hour = "" + hour;
}
timeStr += hour;
timeStr += ":";

var minute = time.getUTCMinutes();
if (minute < 10) {
minute = "0" + minute;
} else {
minute = "" + minute;
}
timeStr += minute;
timeStr += ":";

var second = time.getUTCSeconds();
if (second < 10) {
second = "0" + second;
} else {
second = "" + second;
}
timeStr += second;
timeStr += "Z";

return timeStr;
}

function parseISO8601Time(time) {
var date = new Date();

var year = time.substr(0, 4);
var month = time.substr(5, 2);
var day = time.substr(8, 2);
var hour = time.substr(11, 2);
var minute = time.substr(14, 2);
var second = time.substr(17, 2);

date.setUTCFullYear(year);
date.setUTCMonth(month - 1);
date.setUTCDate(day);
date.setUTCHours(hour);
date.setUTCMinutes(minute);
date.setUTCSeconds(second);
date.setUTCMilliseconds(999);

return date;
}

function formatLocalHoursAndMinutes(time) {
var timeStr;

var hour = time.getHours();
if (hour < 10) {
hour = "0" + hour;
} else {
hour = "" + hour;
}
timeStr = hour;

var minute = time.getMinutes();
if (minute < 10) {
minute = "0" + minute;
} else {
minute = "" + minute;
}
timeStr += minute;

timeStr += "h";

return timeStr;
}


XML Namespace utilities


As mentioned before there is very little support namespaces so here's what I had to roll:



function getElementsByTagNameNS(node, namespaceURI, localName) {
var nodeList;

if (node.getElementsByTagNameNS != null) {
nodeList = node.getElementsByTagNameNS(namespaceURI, localName);
} else {
nodeList = node.getElementsByTagName(resolveNS(namespaceURI) + localName);
}

return nodeList;
}

function getAttributeNS(node, namespaceURI, localName) {
var attrVal;

if (node.getAttributeNS != null) {
attrVal = node.getAttributeNS(namespaceURI, localName);
} else {
attrVal = node.getAttribute(resolveNS(namespaceURI) + localName);
}

return attrVal;
}

function isNode(node, namespaceURI, localName) {
var nodeMatched;
if (node.localName != null) {
nodeMatched = (node.namespaceURI == namespaceURI && node.localName == localName);
} else {
nodeMatched = (node.nodeName == (resolveNS(namespaceURI) + localName));
}

return nodeMatched;
}

function resolveNS(namespaceURI) {
var namespacePrefix;
if (namespaceURI == "http://www.yoururigoeshere") {
namespacePrefix = "ns1:";
} else if (namespaceURI == "you are getting the idea now hopefully") {
namespacePrefix = "ns:";
}
return namespacePrefix;
}


Summary
All in all though jQuery saved me a lot of code, particularly around manipulating and traversing my XHTML DOM. The long short of this was that my XHTML page is semantically correct containing absolutely no erroneous divs, style or class declarations i.e. no presentation considerations.

My last Ajax application was a couple of years ago and I must say that using a framework like jQuery has certainly improved programming here. I think we are now seeing some maturity in the browsers and the Javascript framework.

I look forward to continued use of jQuery.

Monday, March 30, 2009

Java Persistance with Hibernate - what I had to re-visit after reading the book

I recently had a JPA related issue and decided that it was high time to purchase a good book on the subject; particularly as JPA/Hibernate tend to play a very important role of course.


I ended up discovering "Java Persistance with Hibernate" (Bauer, King). This book is a revision of "Hibernate in Action" and it certainly reads as a complete reference to all things ORM. What attracted me to this book in particular was its coverage of JPA. I prefer to use JPA over Hibernate interfaces so that my ORM implementation choice is left open as much as possible. Having said that Hibernate gives me no reason to move to another ORM.


I must have been using Hibernate/JPA for the past 18 months. When I started I recall wanting to skim over the ORM subject as much possible in order to get things done i.e. I did not think deeply about the implications of some of my decisions; or rather I misinterpreted the way things worked e.g. the 2nd level cache. To this end here is a list of things that I found myself re-visiting:


* property annotations instead of field annotations;

* using the Collection interface instead of the Set interface;

* cache annotations;

* bi-directional one-to-many relationships;

* immutable entities


Using property access can boost performance when performing operations on a collection (also as opposed to a set). For example if you want to add to the collection Hibernate does not have to load the existing collection from the database. If you use a Set then it does in order to guarantee Set semantics.


Understanding the second level cache is very important and if you don't have time to learn it then disable it. It is also a good idea to understand whether you have immutable entities so that you can use the Hibernate @Entity(mutable=false) annotation and flag to the cache that the object is read only. This permits Hibernate a few optimisations including a minimisation on the number of update statements that require preparing at startup.


I always wondered why my bi-directional relationships were generating a join table. It finally sunk in that the mappedBy attribute on an association describes the foreign key. No more join tables for bi-directional relationships.


There's no excuse; just buy the book if you're doing any ORM. Having said that even before I made these changes Hibernate was performing exceptionally well!

Tuesday, March 17, 2009

Mutual SSL authentication and LDAP authorisation for ActiveMQ

I now have quite a lot of software infrastructure supporting the business of tracking things that move; particularly aircraft flights. The back-bone of all of this is ActiveMQ. ActiveMQ is an incredible messaging work-horse and easily handles 300 messages per second being received from a number of radar sensors.

I have also re-developed my Titan Class Vision client application using JavaFX (the subject of another blog entry). The goal of this re-write was to be able to deploy Vision on a wider variety of platforms than I could do so previously. Before the JavaFX version Vision was a turn-key hardware/software combination written in Objective-C/C++ and ran on Mac OS X only.

With the advent of the new version I am able to deploy Vision across the internet. Given this there are suddenly many more potential candidates in terms of users and I had a security question to consider: how can I demonstrate to whoever is concerned that I have made every effort to ensure that this sensitive real-time flight data is not being mis-used by anyone.

Authentication
My requirement therefore became one centered around SSL. ActiveMQ permits connections to be established using SSL. Server only authentication is fairly straightforward and covered here. What I was after though was client certificate verification; otherwise known as mutual SSL authentication. In a nutshell, the server verifies the client's certificate as one it trusts, and the client verifies the server's certificate as one it trusts.

When it comes to the client application, in my case the JavaFX application, you need to make sure that the client's keystore is accessible. Don't do as I did and try using the JRE's default keystore for this purpose. I just couldn't get that to work. Instead do as the ActiveMQ SSL page suggests and provide the client with its own keystore.

Another tip for the client, is to set the javax.net.ssl.* properties within the application itself; before you try establishing the JMS connection of course. I express the location of the client's keystore in relation to the user.home system property.

From a broker (server) perspective, one has to use a JAAS LoginModule that permits certificate based authentication. Fortunately I found an ActiveMQ-JAAS class named CertificateLoginModule (of all things). One very subtle thing to note: when specifying the use of this login module in activemq.xml you must use the jaasCertificateAuthenticationPlugin element instead of the jaasAuthenticationElement. I think that this is because the certificate login module requires a different login callback to obtain the client's certificate.

CertificateLoginModule is only half the picture in the same way that authentication is only half the picture. Authorisation is required and the CertificateLoginModule has to be extended to support this; the login module does not know how to authorise a certificate. I can help there as I have provided this code. More on that later though (I insist on you reading the rest of this entry!).

Finally on authentication, you need to tell ActiveMQ that you want to perform client certificate authentication; it will not do it unless told to do so. You do this by specifying "needClientAuth=true" parameter on the ssl transport in activemq.xml.

You might want to disable the other connectors and open up your firewall just for 61617 SSL connectivity. I think that once you make authentication a priority with the broker then you need to give up the non-secure connectors.

Authorisation
With authentication done (I know who you are, you know who I am), I needed to deal with authorisation (now I know who you are, what am I going to allow you to do). For this I wanted to centralise my user and group/role information. ActiveMQ allows you to specify user/group associations in its configuration file, but I wanted to do what all grown-ups do: specify my users and groups in a centralised LDAP directory.

The CertificateLoginModule requires extension to specify how authorisation is done. I have created a CertificateLoginDirectoryRolesModule that will take the subject DN from each client certificate presented (there can be many but typically just one), and then call upon my LDAP store to determine which groups the DN is a member of.

I have set up my LDAP server (ApacheDS - fabulous) to allow anonymous access but also enabled access controls. This means that, by default, the LDAP server permits very little authorisation with just admin access. I then created a group named "activemq" off the "groups" node and used an ACI to allow anonymous searching of that group. I ended up with a group hierarchy as follows:


ou=system
ou=groups
ou=activemq (anonymous users can see this and below)
cn=jms-services
cn=activemq-users
cn=com.classactionpl.javaFlightTopic.Subscribers


Correspondingly here is my authorisation mapping within activemq.xml:


<authorizationPlugin>
<map>
<authorizationMap>
<authorizationEntries>
<authorizationEntry queue=">"
read="jms-services"
write="jms-services"
admin="jms-services" />

<authorizationEntry topic=">"
read="jms-services"
write="jms-services"
admin="jms-services" />

<authorizationEntry topic="com.classactionpl.javaFlightTopic"
read="com.classactionpl.javaFlightTopic.Subscribers" />

<authorizationEntry topic="ActiveMQ.Advisory.>"
read="activemq-users"
write="activemq-users"
admin="activemq-users" />
</authorizationEntries>
</authorizationMap>
</map>
</authorizationPlugin>


What the above states is that jms service providers, such as my Camel based applications, can effectively publish and subscribe to anything. However my client belongs to the javaFlightTopic.Subscribers group and the activemq-users group and so can only consume from a specific topic and perform all required advisory services; the latter being an ActiveMQ requirement.

It is possible to express the authorisation mappings in an LDAP store as well. We'll see if the need surfaces.

Source Code
I have created an open-source project named jaasloginmodules that hosts this JAAS login module and have tested and used the classes. The CertificateLoginDirectoryRolesModule is ready for download and use.

Tuesday, March 3, 2009

When is a POJO no longer a POJO

When is a Plain Old Java Object no longer a Plain Old Java Object?

My take on POJOs is that they are no longer POJOs when there is an import statement for something not conforming to the expression "java*.*".

I see quite a lot of frameworks and toolkits claiming benefits around POJO oriented development. However either through annotations, extension, implementation etc. they require dependencies on non JRE artifacts.

This situation is quite OK of course; I just think that it is useful to distinguish a POJO from its dependent form. For example if you're looking for Object Relational Mapping then you might want to consider the Java Persistence API instead of being directly dependent on an implementation; such as Hibernate. Maintaining this distinction allows you to consider migration strategies to other implementations if required.

Sometimes you need to be dependent on a toolkit or framework and that is of course perfectly acceptable. Being aware is the significant point.

Saturday, February 21, 2009

Who is Palm trying to attract for WebOS development?

I must say that my first impressions of what Palm is offering in terms of the WebOS leaves me curious.

I wrote for the Palm OS over a long period of time. I started my Palm OS development when Palm were US Robotics and programmed the original PalmPilot. The PalmPilot was an amazing achievement for the time.

There were a few things that attracted me to the original Palm OS platform, but a major one was that I could use my C++ skills to create robust and high-performance deliverables. The Metrowerks Codewarrior environment was a joy and I could use the same IDE for Mac OS (then Mac OS 8!) and Palm OS development.

I think that it is reasonable to state that the original Palm OS attracted seasoned software developers; a lot of them were also Mac developers that understood things like usability.

I am little surprised to learn that the WebOS is a Javascript world for the developer. To me Javascript is a language that evolved i.e. it does not appear to have been well thought out from the start. I am not attempting to criticise Javascript here - in fact I think that it is amazing what has been enabled via Javascript in the context of a web browser. I also understand why it has evolved the way it has. The thing is I am just surprised that Palm have chosen Javascript as their primary programming environment for WebOS. Who exactly is it that Palm are trying to attract to their platform?

I suppose what I am saying here is that while Javascript can be written in a disciplined manner, I do not often see this to be the case. I am therefore curious about the quality of applications that will be delivered to the WebOS.

I think that Apple have things almost right with the iPhone SDK and that Google have it completely right with Andriod. Where Apple need to improve is simply to provide a notification mechanism for an application. The notification handler should be able to operate in the background. The original Palm OS provided such a mechanism for handling alarm and other events. The benefit was that you could get an application to do things as a result of various device stimuli. This capability is very important and the iPhone falls short in this regard; so much so that I cannot consider porting my Palm OS based Titan Class Vision software.

In the case of Google I think that the choice of Java is correct. Java is a great way to deliver robust software and rich in its tooling. However Google have to solve the battery life implications of their environment which presently make their phone unusable in many quarters.

I digress slightly. The question remains though, who is Palm trying to attract for WebOS development?

Wednesday, February 4, 2009

Using Camel ProducerTemplate in a POJO

I am enjoying Apache Camel immensely. My productivity in terms of delivering enterprise grade services has increased dramatically. No doubt that the quality of my deliverables has also increased. All of this with no compromise to performance...

In the case of having deployed about 3 Camel based applications (containers for services) and a couple of non-Camel ESB applications, I think that one of the major ESB benefits is the de-coupling the service implementation from the transport. This of course allows the service code to be written as a POJO and with dependency injection, DAOs and a few other patterns, the resulting service has a clean focus on the business logic.

I recently had to implement a service that initialised a biometric device. Initialisation comprised of communicating several messages over a TCP connection to each biometric device. In the first instance I used Camel's ProducerTemplate to send my messages. This all worked fine and of course meets that goal of separating out the transport delivery from the business logic. However I now had a Camel dependency in my otherwise pure POJO service. This did not satisfy my design goal of ensuring that the service remained a POJO so that I could be free with my ESB choice (not that I see myself moving from Camel for any reason!).

To avoid this Camel dependency I created and used my own ProducerTemplate interface. This is merely a proxy to Camel's and only has the methods I need from my service. It looks like this:

public interface ProducerTemplate {
Object sendBody(String endpoint, Object body);
}


I then pass a ProducerTemplate instance and its endpoint details to the invocation of my service along with any other parameters the service needs:

void process(ProducerTemplate producerTemplate, String deviceEndpoint,
Collection fingerprints)


Note that the ProducerTemplate is passed in on each invocation of the service. This is because the template can potentially change between service invocations.

My Camel container project includes the project housing the above POJO. The container defines and instantiates its ProducerTemplate that forwards calls on to Camel's ProducerTemplate. The result is that I now have a POJO based service that interacts with other services in a non-Camel dependent manner.