Login | Register   
RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


Access In-memory Objects Easily with JoSQL : Page 2

This innovative, new open source engine simplifies your code by allowing you to access your objects using SQL strings instead of coding your own filters. Even better, it has a very small learning curve.

Accessing Objects using SQL
JoSQL allows you to access your objects using a SQL-like syntax. A simple example is shown here:

SELECT * FROM java.io.File WHERE name $LIKE "%.html" AND lastModified BETWEEN toDate('01-12-2004') AND toDate('31-12-2004')

This SQL is passed to a Query object, which acts on a java.util.List object, or one of its derivatives, such as a Vector or ArrayList. (Click here to see the java.util.List documentation.) ). This action will return a QueryResults object from which you can derive your classes.

As with SQL, you're not limited to the SELECT * FROM X WHERE Y=Z type syntax. JoSQL runs the full gamut of SQL commands, so you have the typical 'GROUP BY,' 'HAVING,' 'ORDER BY,' and 'LIMIT' clauses that you would expect.

You can also parameterize your SQL, passing objects into the code as parameters using JoSQL bind variables. These are parameters that are prefixed with a ":" in the SQL string, and then set using the setVariable method on the query object. For example, take a look at the following query:

SELECT name, length FROM java.io.File WHERE name LIKE '*.java' AND lastModified BETWEEN :fromDate AND :toDate

In this case, the fromDate, the toDate, and the path parameters are all bind variables. To set these in code you would need to write:

Query q = new Query(); q.parse(strSQL); q.setVariable ("fromDate", sdf.parse ("10-10-2000")); q.setVariable ("toDate", sdf.parse ("10-10-2001")); QueryResults res = q.execute (myFiles);

Putting It in Action
The download that comes with this article includes a very simple console application that demonstrates how JoSQL can be used. It emulates a chat server application, which is a classic example where you have many objects in memory. These chat examples includes some cool advanced features that you can restrict, if desired, to cut back on the coding needed for implementation.

A typical chat server has a number of clients that connect to it, and these clients will have different properties and attributes. Typically, a client-type object will represent the client, exposing properties for that client such as their names and permissions. This object will also have methods for actions that should be performed on the client, such as sending a message to the client, so that any incoming messages from other clients in the same 'room' as that client can be dispatched to it from the server. Or to provide a disconnect message, where the server can boot the client after a period of inactivity or for behavior that breaks server policies.

Under this structure, if a server has hundreds of clients connected, the code needed to iterate through the clients can bloat enormously, as there can be little reuse. For example, if you want to write a function to say 'Hello' to everyone called 'Bob' or something similar, you would generally write a function that takes the pattern to match (in this case 'Bob') and the message to send. This function would then iterate through the entire list of in-memory clients, finding ones that match 'Bob,' and then invoke their sendMessage functions. Easy enough.

But what if you want to do the same for, say, the room that they are in? In other words, you want to send a message to everybody in room 1, or everybody in rooms 1,3, and 5, or everybody in rooms >17. You would have to write another (similar) function to handle iterating through the rooms, as well as parsing routines to handle the different cases. The result is more code for you to churn out, debug, and support.

Here's where JoSQL is worth its weight in gold. Consider the above use cases (and take a look at them in the download). To send a message to everyone whose name is like 'Bob' with JoSQL you simply write:

Query q = new Query(); q.parse("Select * from devx.article.josql.SimClient WHERE p_ClientName LIKE 'Bob'"); QueryResults clClients = q.execute(myList); List test = clClients.getWhereResults(); ListIterator iter = test.listIterator(); while(iter.hasNext()) { SimClient c = (SimClient) iter.next(); c.SendMessage("Hi Bob"); }

In this case, the chat server uses a class called SimClient to model a client. It keeps an ArrayList of connected clients called myList. It constructs a new Query Object and then sets its SQL to select all clients where the p_ClientName property is LIKE 'Bob'. Note that the SQL LIKE functionality is enough to filter out names beginning with Bob, containing Bob, or ending with Bob. No custom coding is required. It then executes this SQL on the myList ArrayList, to return a list of matching objects. You can then iterate through this list and send a message to everyone in it. Very simple.

Here's some additional power: consider this function, which allows you to match any property on any of your objects to any value, drastically simplifying your code:

private static void DoAction(String strWHEREVAL, String strLIKEVAL, String strWhatToSay) { Query q = new Query(); try { String strSQL = "Select * from devx.article.josql.SimClient"; if (strWHEREVAL!="") { strSQL+=" WHERE " + strWHEREVAL; } if(strLIKEVAL!="") { strSQL+=" LIKE " + strLIKEVAL; } q.parse(strSQL); QueryResults clClients = q.execute(myList); List test = clClients.getWhereResults(); ListIterator iter = test.listIterator(); while(iter.hasNext()) { SimClient c = (SimClient) iter.next(); c.SendMessage(strWhatToSay); } } catch(Exception e) { System.out.println(e.toString()); } }

So now if you want to write routines that perform actions on you objects, you don't have to write accessor functions for each, you can just call this DoAction function and pass it snippets of SQL to meet the required criteria. So, from your chat server, to send messages to everyone whose name is like 'Bob', you can simply use:

DoAction("p_ClientName","'Bob'", "Hi Bob!, This is Bob");

Where p_ClientName is the public property on the client object that you are checking for.

Similarly, you could send a message to everybody in room 1 using:

DoAction("p_CurrentRoom=1","", "Greetings to Room1");

And because this is SQL, it's very simple to put some pretty complex filters in there such as:

DoAction( "(p_CurrentRoom>1 AND p_CurrentRoom<=8)", "" "Greetings to everyone between 1 and 8");

As you can see, using the in-built SQL interpreter to filter your objects can save you a lot of code, and, in many cases allow you to add new features to your application that you wouldn't have wanted to tackle before (because of the volume of code involved).

This is such an innovative and powerful addition to your Java toolbox, that, if you write applications that maintain large numbers of objects, such as the chat example I've discussed, you'll wonder how you ever got on without it. JoSQL is relatively new, having started as an open source project in December 2004. I wouldn't be surprised if Sun were to add this type of functionality to the core Java APIs soon—it's just that good!

JoSQL is a powerful addition to any developer's toolbox. It's not for every application, but should be useful in most cases. Its performance seems ok, though there are no benchmarks available; in some simple tests I did, it performed admirably. It's greatest usefulness is in simplifying your code, allowing you to access your objects using SQL strings instead of coding your own filters. As such, it's amazingly innovative, and has little or no learning curve.

The JoSQL Web site includes thorough documentation on the SQL API, as well as some good JavaDocs on the class libraries themselves. Perhaps the only let-down is in the lack of example applications that will help you to get up and running quickly. The information is all there, however, so a little digging and you'll be JoSQLing away to your heart's content!

Laurence Moroney is a freelance enterprise architect who specializes in designing and implementing service-oriented applications and environments using .NET, J2EE, or (preferably) both. He has authored books on .NET and Web services security, and more than 30 professional articles. A former Wall Street architect, and security analyst, he also dabbles in journalism, reporting for professional sports. You can find his blog at http://www.philotic.com/blog.
Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.