<$BlogRSDURL$>

Sunday, February 13, 2005

XPath Engines for XOM

XOM is one of the many XML Object Models out there today. It's Open Source (LGPL) and is developed with "correctness, simplicity, and performance" in mind.

XOM is the XML Object Model used for Memoranda.

XPath is "XPath is a syntax for defining parts of an XML document". More specifically, it can be used to query for parts of an XML document. With hierarchal tasks, the querying and searching needs in Memoranda became a lot more complex and a solution such as XPath has to be used.

Previously, the Memoranda Tasklist stored all tasks as a child object "task" under the "tasklist" element. Obtaining the task element needed was really just a case of iterating through all the "task" elements and finding the task that's needed.

However, with hierarchal tasks, iterating now became far more difficult as "task" elements can now be nested inside other "task" elements (i.e. nesting a child task within a parent task)

Hence, the need for XPath. As far as I know, there are current two XPath engines that support XOM (i.e. when you do an XPath query, it returns XOM Nodes). They are Jaxen and Nux. Jaxen's XOM support is still in Beta and none of the code is currently available in a release (at the time of writing at least). In order to check it out, I had to connect to the CVS. On the other hand, XOM support for NUX was available as a release. However, what tipped the balance in the favor of Nux was that it supports XPath 2.0 (which is still in draft but supports more complex queries).

An example of how Nux is used in Memoranda is when we need to retrieve a task from the tasklist based on the task's ID, regardless of where it is in the task tree (i.e. top level or embedded within a parent task or many levels or parent tasks).

private Element getTaskElement(String id) {
Element el = (Element) XQueryUtil.xquery(_doc, "//task[@id='" + id + "']").get(0);
return el;
}

The path "//task[@id='" + id + "']" requests for Nux to return all "task" elements with a particular ID, no matter where it is in the document. It returns a XOM Node which can be cast into a XOM Element.

With XPath support, more complex queries can be done and this could open the door to many more cool features in Memoranda in the future,
Memoranda Development Update

As the team has decided to make a 1.0 release soon, hierarchal tasks will not be in this version. Instead, it will be in the 1.1 version. Of course, those of you who want the latest features can always checkout the latest code from the CVS, or wait for the next development snapshot.

Sorry, I can't really give any dates to any of the above because I don't work on the releases. I just write the code :P

Sunday, February 06, 2005

In J2EE, sometimes portability is just not worth the cost

One of the key bragging points about J2EE is how applications can be portable across the various J2EE application servers. And there's been a lot of emphasis on writing "portable code" and avoiding application server specific features. But there're times where you really need some features really badly and the J2EE spec is simply inadequate and slow in delivering some features, while your app server tempts you with a proprietary implementation that works! So what do you do?

Well I never really had to face this question until recently, when I found myself trudging waist deep in mud with CMP Entity Beans. It came to a point where we had to implement querying of Aggregates such as "COUNT / SUM /AVG" in the Entity Beans, and this meant using EJB Select Queries rather than Finder Queries. Under Finders, Selects take double the amount of code and XDoclet annotations to get working because Select methods are private the bean class and cannot be exposed to the remote caller. Instead, it has to be wrapped around another method with exposes it. It just got to a point where it got so painful I decided that the solution was to switch a JBoss solution -- Dynamic QL.

Dynamic QL allows you to create just one set of methods to service ALL Finder and Select queries. In the past, every single Finder query needs to be defined in the Entity Bean via XDoclet annotations and XDoclet has to be run everytime after a Finder was added, and when a Select method is needed, well, it's quite a lot of work.

Using Dynamic QL means that XDoclet needs only to be run once, as only ONE Dynamic Select method needs to be implemented. The Query can be for an Object or just a single field (note that multiple column selects are not available though). The actual query to be run is instead passed into the Entity Bean at runtime and executed. By doing so, development time is cut significantly.

Furthermore, since portability has already been violated, why not just go ahead and use JBoss QL for the query anyway? It has more features than EJB QL, and allows more queries to be made truly database independant.

By using Dynamic QL and JBoss QL, I have cut development time and writing database independant code has become so much easier. There is a price to pay for app server portability and sometimes it's not worth it, especially when you're not expecting to switch app servers at any point in time anyway.


This page is powered by Blogger. Isn't yours?Weblog Commenting and Trackback by HaloScan.com