Wednesday, September 24, 2008

First Android Device Fails to Impress

T-Mobile in cooperation with Google yesterday announced the G1. I watched the video of the entire press conference. I think Google is not adapting to this new market instead relying on doing business the same way it does on the web. This may have proved successful for their web business but I don't think it will work out very well for the mobile market. Things that just don't work include:
  • No desktop application for syncing. Google is positioning everything to sync from the cloud, gmail, google calendar etc. Yeah, this is just going to be such a joy for organizing your music and other media files on your device.
  • No iTunes support. The largest music retailer in the world will not function with Android.
  • Sim locked to T-Mobile. 2 year contract with a retail price tag of $175. OK, so the device costs a lot more than $175 hence the contract, so why can't we just buy the full version? So much for this open thing.
  • The device is bulky, favoring a full pull out keyboard instead of a touch keyboard similar to the iPhone. I think this is more of a problem with HTC than the Android platform itself. However, now that I think about it, I haven't seen a touch keyboard on this platform period. The emulators don't have it.
  • Limited Bluetooth support and APIs. Google has pledge that future versions of the software will expand on these services.
  • Google Android Market is a good thing but are these devices actually upgradable? Can we upgrade from Android 1.0 to future Android releases?
  • For the relatively small price difference, that 8 GB flash drive found in the iPhone is looking very attractive. Honestly, dump the SD cards already.
  • Tooling support is still sub par. No visual designer is available but the latest Eclipse plugin has visual preview so this may be in the works. However, DroidDraw is available and is pretty good.
Not all is bad however, the strength of the platform is still Java SE. Android is a subset of the full Java SE 5. You can see the number of packages for Android here and for Java SE 5 here. It may be a subset of Java SE 5 but it's still huge compared to any other mobile platform out there. The other thing is that the Android compiler works on Java byte code. So any library written for the Java SE 5 platform, and yes, there are quite a few of them out there, can be potentially used on this platform.

Friday, September 5, 2008

Recipient Address Rejected with PostFix and JavaMail

Really not sure anymore what I wanted to talk about this exactly. I had this problem and the only thing I can recommend if you do have this issue is that the bug is usually in the order of the parameters you pass to JavaMail and not in your PostFix configuration proper.

JavaMail has way too many parameters that are just strings, with methods that take a lot of strings, it becomes way too easy to mix up one string parameter with another.

Folders in a Database

If you're using folders and storing them in a database, the conventional approach is to use recursion for things like folder validation, moves and membership.

Using recursion with a database like this is usually pretty bad performance wise, consider using a token instead. A token could be, for example, a folder id string field that keeps the path of the folder using the identifiers of all its parents.

So, if you had folders "a/b/c", the folder id string for the "c" object could be "/100/101/" representing the path to this folder.

In application code, you should obviously never manipulate this string directly, the string should be completely private to your inner most classes that represent your data model.

Using this technique however, it becomes very simple to answer some very basic questions like:
  • Can I drop this folder into this other folder? Simple, just check if the string starts with the same path or is equal. So "c" can be dropped into "a" or "b", but "a" cannot be dropped in "a" or "b" because the path for "c" contains "a".
  • How many items are contained in this folder? Just check how many items have a matching string.
  • Makes it easy to find siblings, all the items found in the same folder have the same folder id/path.
If you do keep using recursion, make sure your code is secure at least, don't allow for an infinite number of recursions.

Thursday, September 4, 2008

Push vs. Poll

It seems pretty obvious at first but this is no simple matter. For years, I have been in the poll camp. The idea was that if you had long running processes that would poll for updates every 20 to 60 minutes, the cost of setting up, performing requests and tearing down a connection would be less than the cost of maintaining a connection on the server.

Well, there are several problems with this scenario. The first one being that under such conditions, the total number of bytes needed to perform the requests on the server usually ends up being a higher number than the total bytes needed to produce responses to indicate that no new data is available since the last poll. The second is that it is much harder to limit incoming requests to the capacity of your servers. Namely, given n number of client processes out in the field, entropy sets in and will cause your clients to poll at different times. However, as the number of client processes gets bigger and bigger, the number of simultaneous polls that hit the server at the same time grows at the same rate. Using push, we can feed updates to clients at a rate that the server can handle. Since the server is responsible for contacting the clients, it can do so at its own pace completely sidestepping the “Thundering Herd” problem. Third is that not all bytes are of equal cost. In this ever heterogeneous computing landscape, e.g., the cost of a byte on a high speed DSL line isn’t the same than the cost of a byte on a cellular edge network. In the scenario above, sending requests that have empty responses should be a no cost operation on a domestic high speed link but this doesn’t hold true for a user on the cellular network. Fourth, given an update that needs to be pushed, that single piece of information is completely independent of any updates that came before it and will come after it, meaning that it is easy to distribute this work to a farm. For example, we can imagine that for a poll, we would need to query the database for each and every poll. For a push, we would push the result of running a single query to multiple clients. The fourth argument is much more domain specific since your data might not allow for this at all but it’s still perfectly possible on some data sets. Fifth, web applications are not kiosks, they can't be polling only once every hour. However, even for kiosks, push is still superior since it allows for instant monitoring of every client in the field.

The term coined for server side push is comet, or reverse Ajax, and you use this to get to your clients, be it a web application or not, to achieve a server side push. However, the problem is that too often the solutions ends up looking something like this:

but this is not the most optimal solution. First, it does not get rid of the extra request traffic that we are trying to avoid. This is not really server side push but more of a constant poll where the response timeout is extremely high. With comet, the idea is to get to a point where you're shaping your traffic like this:

Not only does this get rid of our unwanted traffic, it truly does provide a scalable way for the server to publish change sets to clients without having to exert itself.

Now the bad news, achieving comet isn't just about behaving in a certain way at the network level. Reaching this level of sophistication means that the server is maintaining work queues of the data that it needs to send to clients. This isn't too bad but remember that not every client will be synchronized to the latest updates when sending out new updates. Your clients will still need to get to the synchronized state using regular requests before they can get updates via comet.

Finally, I would like to mention that there are several tools and kits and what not to add comet support to your application, you don't need to do it yourself. However, I have found that Grizzly, the http web server that ships by default in Glassfish, to be an excellent choice for all my comet needs. Grizzly is really an impressive piece of code, using non-blocking I/O everywhere with a minimal amount of threads to achieve maximum throughput. You'll still need to handle things like dropped connections and other exceptional conditions but the hard part of getting a scalable comet implementation going in the first place will be done at least. Furthermore the plan for Grizzly 2 calls for enhancing the server with the new asynchronous I/O facilities being introduced in Java SE 7, which should make this already impressive beast scale to new heights.