Tuesday, October 24, 2006

Do you really need a Persistence Layer?

Well that depends, but in many cases it's far more than what you really need...

Continuing from my earlier post about building an AJAX / SOAP App in 15 minutes, the only way to build an app this fast is KISS. If you're worrying about EJBs, Relational DBMS, or file storage, you've gone too far.

Here's a screenshot of the completed app (you can try a sample of the app yourself here):



For Sticky Notes, the only way to KISS was to stay entirely in the Object domain; that meant keeping a strict eye for only what was necessary, and not a bit more. Thus for the Server side, I chose Terracotta because:

  • I can code plain POJOs without having to worry about another code layer
  • With the Terracotta server in persistence-mode I get to stay in the Object domain, and persist my objects naturally.
I chose XFire, because:
  • It exposes SOAP services from simple POJOs - no work required.
  • It's a cinch to run standalone without a container (it uses Jetty)
For the Client side, I chose OpenLaszlo. A number of key factors influenced my decision:
  • interfaces with SOAP
  • easy to use definition language - no HTML or (sophisticated) Javascript required
  • it looks like they are going to have a number of new output formats real soon now (DHTML and Java ME) - hopefully I will get more bang for my buck using OpenLaszlo than trying to build something out of DHTML and any of the numerous Javascript AJAX toolkits out there...
There are good reasons for needing persistence - I'm not saying you'll never need it. If a customer gives you an order, you know you'll need to eventually put that in a database. On the other hand, while that customer was creating that order, it's probably overkill to keep every change in the database.

If you saw my Notes service version 1.0, it needed a few tweaks to implement the full app. I've updated the Notes project which is now at version 1.1.

In particular, I had to
  • add a "getNotes()" service, which just returns an array of integer ids representing the notes that are stored.
  • add a "deleteNote(int id)" service. This deletes a note given the input id.
  • beefed up the "setNote()" service. I added x, y, width, and height parameters. (Of course I had to add a Note object to store all of these values as well.)
  • beefed up the "getNote()" service. Obviously this now has to return x, y, width and height in addition to the msg.


NOTE THE CODE LINKED TO BELOW IS DEPRECATED! Terracotta is now Open Source, the code below will work fine but has not been updated to the recent versions of Terracotta. There is also a full Terracotta Forge available for projects.

The full source code is available at the Terracotta Project Site. In addition you can view a simple version of the app (which has all of the SOAP removed, so you can see it in action, but no persistence takes place) here.

Thursday, October 19, 2006

Build an AJAX / SOAP App in 15 minutes - Part 1.0...

Ever since I met Dan Diephouse at OSCON back in July, I knew there had to be a way to build something cool with XFire. I kept thinking that somehow some new SOAP specification would eventually need to be clustered, and so I kept pestering him to see if there was a good fit. Well nothing interesting materialized, until this past week when I realized that while the SOAP protocol is stateless (actually, to some extent new standards like WS-Addressing and WS-Conversation are changing that), the application which delivers the service is stateful.

Then I started noticing some noise around JSR-181 and building web services from POJOs using annotations. Now things were starting to get interesting! I wondered to myself - how fast could I implement a compelling, yet simple, stateful SOAP application. For a couple of nights I laid awake, dreaming of what kind of application I could build, and more importantly what AJAX framework I could use to showcase it.

With visions of Web 2.0 apps dancing in my head, I started to narrow down the short list to a few - Instant Messenger, Wiki, Blog, Bookmark, or Sticky Notes. But I still hadn't decided on the most difficult part of this endeavor - picking the AJAX framework. Once again, OSCON and a few old connections of mine helped make the choice - but I'll leave the revealing of that decision for Part 2.0 of this post. I will say that the capabilities of the toolkit you use really shape what is and is not possible, and more importantly, what will and will not work well; so it turns out that I decided to make the Sticky Notes app. You'll see why when I get that GUI finished...

In the meantime, I got in touch with Dan and he pointed me right at the exact piece of information I needed to finally kick off the project - basically a how-to guide to build SOAP services using a POJO in about 5 minutes. So last night I sat down to write the server side of the Sticky Notes app. It probably would have taken me only 5 minutes, except I ran into a problem specifying exactly which dependencies I needed in Maven. Fortunately Dan was around and knew just which ones I needed. After updating the XFire WIKI with that knowledge, I pushed the dependencies into my maven project and, you guessed it, I had the service layer done.

Now here's the really cool part - just like my last article about building a parallel web spider, I get to release the code freely available for your enjoyment. At this point, however, I bet you're scratching your head wondering how this could really be useful - right?

Right -- for example if we think about this Sticky Notes app, the notes sure aren't going to be very sticky until I write some kind of persistence layer. It's right about here where most Java developers throw up their hands and figure EJB, iBatis , Hibernate , or one of the many other 100+1 Java persistence solutions that exist today are the only way out of that box.

But if you're like me, you hate writing to and worrying about persisting your objects (I mean what better way is there to waste weeks and months worth of time figuring how best to destroy your perfectly good Object Oriented Design by having to figure out how that design has to be contorted into a completely different domain model just so you can store your objects, right?)

Well, what if you could persist your objects in the Java heap, get automatic scale-out of your application, and High Availability to boot, all without writing a line of extra code? I'm sure you've figured it out by now - throw in dash of Terracotta and all you have to do is add 3 lines of XML to the config file, and it's done. Here they are:


<dso>
<persistence>
<mode>permanent-store</mode>
</persistence>
</dso>

I've just posted version 1.0 of the Notes application. I've only included a tiny Test app for now that lists the current notes, and adds a new note. As I mentioned already, I'm working on the GUI right now and will post it up ASAP.

Meanwhile, give the Notes app a try. Try running two instances of the XFire SOAP service, kill one, kill the Terracotta service, or any of the three. Bring them back and your data is right there where you left it. Damn cool if you ask me.

Friday, October 06, 2006

Invert your logic part 2: For loops and while loops

I'm not sure how many people I've convinced or not convinced in my previous post about inverting your logic (I don't really think this is a good term, but so far I don't have a better one). The comments that were left lead me to believe I wasn't 100% successful in my quest.

It may have been that my example was too limited. I don't just apply this style to a single method, but every block of code I write.

Here's a real code sample from my Parallel Web Spider project. In the first version of the code, there was only one pre-condition test that checked to see if the link depth was too great.

Since posting the code early this week, I have made some minor updates to it, including the two extra condition checks you see below that prevent the spider from following binary content and URL protocols that aren't supported.

Here's the code:


...
while (processed != toDo) {
// get result
try {
future = service.take();
processed++;
links = future.get();
} catch (Exception e) {
e.printStackTrace();
continue;
}

// process result
System.out.println("Processing " + links.size() + " link results.");
for (PageLink link : links) {
if (link.getDepth() >= config.getMaxDepth()) {
continue;
}

// don't follow binary content links
if (link.getUrl().endsWith(".pdf") ||
link.getUrl().endsWith(".gz") ||
link.getUrl().endsWith(".tgz") ||
link.getUrl().endsWith(".zip") ||
link.getUrl().endsWith(".doc") ||
link.getUrl().endsWith(".ppt")) {
continue;
}

// we're only going to support http and file for now
if (!link.getUrl().startsWith("http") &&
!link.getUrl().startsWith("file")) {
continue;
}

submit(service, link.getDepth(), link.getUrl());
}
}


The style I am suggesting doesn't just apply to methods, it's for any form of a block.

The benefits to writing code in this stlye are
  • loose coupling - blocks are not dependent. You can add/subtract sections of code without having to worry about the surrounding logic
  • linear flow - mentally, it's easier to grok links in a chain because they require small, focused amounts of brain power. A stack (nested code blocks) requires you to keep state, so the brain power required is additive for each level of nesting you introduce.
Finally, extra credit if you noticed one more application of the same style -- the try/catch block. Notice how much more cleanly I can handle the Exceptions thrown by the take() and get() methods by judiciously using a continue. If I had left the continue out, I would have had to handle the exception way down in the code, nearly 60 lines away.

Wednesday, October 04, 2006

Short, concise and readable code - invert your logic and stop nesting already!

Have you ever heard this maxim:

"A method should have one and only one exit point"

Well, it couldn't be more wrong. The following are the attributes of a well written method; it should:

  • perform one and only one function,
  • be short and to the point,
  • be easy to read and understand,
  • and it should have a descriptive, accurate and concise name.
Notice that none of these points says anything about how or where a method should exit. To write a clean, easy to read method, follow these guidelines:
  • follow a template. consistent flow is easier to read.
  • check your pre conditions early. If they fail, exit fast
  • nesting is bad. avoid it. invert your logic at every step of the way.
First, the template:
[return value] [method name](parameters)
[throws clause]
{
[check pre conditions]

[core logic]
}
Pretty simple, right? So what's this about invert your logic? Well have a look at the template up there. Do you see any nesting? Right....neither do I. So let me illustrate a common idiom, one that uses in particular the if/else if/else pattern and the single exit strategy:
/**
* Returns the element at index
*/
public Object getElement(int index)
{
Object theItem = null;
boolean listError = false;
boolean indexError = false;

if (list != null) {
if (index > 0 && index < list.size()) {
theItem = list.elementAt(index);
} else {
indexError = true;
}
} else {
listError = true;
}

if (listError) {
throw new Exception("Bad list");
} else if (indexError) {
throw new IndexOutOfBoundsException("Bad index");
} else {
return theItem;
}
}
Wow, what a mouthful. And I didn't even put in a few while loops, case structures and other nonsense I usually see that ends up with code nested 4 and 6 levels deep. Let me rewrite that code up there making it match the pattern I suggested, inverting the logic, and then I will explain what I did.
/**
* Returns the element at index
*/
public Object getElement(int index)
{
if (list == null) {
throw new Exception("Bad list");
}

if (index < 0 || index >= list.size()) {
throw new IndexOutOfBoundsException("Bad index");
}

return list.elementAt(index);
}
Remember when I said check your pre-conditions first, and exit fast. What this allows you to do is evaluate all of the conditions under which your method will fail, and if you detect something amiss, handle it immediately. This strategy is flexible - if the pre-conditions for your class or your method change, you can add and substract the tests for those pre-conditions using this structure without having to modify surrounding code. The worst offender I see is always of the following pattern:

if (condition_to_succeed_is_true) {
do_something();
} else {
do_error();
}
The problem with this is that the reader of your code has to put the conditional test onto their mental stack while they digest what do_something() is doing. If do_something() happens to be long, or complicated, you'll probably blow the mental stack of the reader, forcing them to look at the condition again just to figure out why the do_error() is being done.

On the other hand, when you line up your pre-condition tests linearly, there is no mental stack, the reader simply processes each in turn, and then, when they are all done, they are able to process the real meat - the do_something() - part of your method without all the baggage from your pre-condition tests. So inverting your logic means taking the above test, inverting the condition, and writing it as:
if (!condition_to_succeed_is_true) {
do_error();
return;
}

do_something();

So I hope you remember your CS classes and De Morgan's laws - I find coding like this makes me use them all the time.

There's one other benefit this strategy has, and that's when you are writing synchronized blocks. When you write a synchronized block, you absolutely must strive to perform as little work as is absolutely necessary inside the synchronized block.

Let's look at the problem we have when we use the normal pattern I described above, combined with synchronization -- the code now becomes:
synchronized (lock) {
if (condition_to_succeed_is_true) {
do_something();
} else {
do_error();
}
}
Ugggh! There's no way, in Java, to release the lock before you perform do_something()! (Which we presume takes time and shouldn't be performed under lock). If you invert the logic, however, you can test the condition and release the lock as soon as you've tested it (note that it's often the case that you might need to use some data you acquired during the lock, in that case you should make a copy on the local stack under the lock, and then release it which I have shown below):
synchronized (lock) {
if (!condition_to_succeed_is_true) {
do_error();
return;
}
state = copy_state();
}

do_something(state);
Remember, in these examples I am assuming that do_something(...) is the non trivial part of your method, both in lines of code, complexity, and execution time.

One more thing - I find that using 4 spaces to indent code blocks instead of 2 helps to break me of the habit of nesting my code because it acts like an automatic brake on the indentation level.