Monday, September 29, 2008

'Fluidize' Your Favorite Web Apps

Ever since the advent of tabbed browsing, I've had this naggging problem with having too many open tabs in Firefox. I typically have 15 tabs open at a time. For whatever reason, I seem to have this aversion to closing tabs. In all fairness though, part of this proliferation of tabs has to do with the fact that many of my 'critical' apps are web based. For example, at Bizo, we use the google apps stack: gmail, google docs, google calendar, google sites, fogbugz for project management and bug tracking, and hyperic for monitoring our applications.

There have been numerous times where I've been reading some documentation in one tab and then needed to look at something in gmail. This process requires that I:
  1. find the tab that has gmail on it
  2. do what I need to do in gmail
  3. navigate back to the original tab
Because I have so many tabs open, I found that this process was taking entirely too long and slowing me down.

Not too long ago, I came across Fluid and realized that this might be an answer to my problem. The basic premise of Fluid is that you can elevate the status of any web application into a desktop application by wrapping the web application with a Site Specific Browser (SSB). Brilliant!

Since then, I've 'fluidized' some of my most frequently used web apps and it has eliminated the need to find the browser tab with 'application x' on it. Now, I can just take comfort in the fact that the application is in my dock waiting for me. Sweet.

This is a screenshot of the part of my dock that has been fluidized:
from left to right: gmail, gcal, gdocs, fogbugz, hyperic





I highly recommend Fluid, it's a great little product.

Friday, September 26, 2008

generic method call timeouts using java.lang.reflect.Proxy

In a future post, I hope to share some code and details on a generic wrapper we built for generated Thrift clients. You pass in a generated Thrift class, and it will return an instance that layers connection pooling, fail-over, connection timeouts, and method call timeouts on top of the thrift code, all without changing the original thrift service API, at runtime.

It's pretty cool! Check back later for that.

In this post, I wanted to talk about a small part of that project, a wrapper we built to dynamically add timeouts to the method calls of an instance. I wanted to make this functionality available separately from the thrift wrapper code, so one could easily specify timeouts dynamically, per call.

Timeouts for tasks have been pretty easy to deal with using an ExecutorService since Java 1.5, and this is the timeout mechanism we used.

The interesting part is dynamically adding this behavior to an instance at runtime. I was unaware of it, but since JDK 1.3 there has been a mechanism to do this, the java.lang.reflect.Proxy class.

"Dynamic proxies provide an alternate, dynamic mechanism for implementing many common design patterns, including the Facade, Bridge, Interceptor, Decorator, Proxy (including remote and virtual proxies), and Adapter patterns. While all of these patterns can be easily implemented using ordinary classes instead of dynamic proxies, in many cases the dynamic proxy approach is more convenient and compact and can eliminate a lot of handwritten or generated classes."

From Brian Goetz's excellent article on the use of this class, Decorating with dynamic proxies.

Using this class, we can provide a generic wrapper that implements method call timeouts. Here are some examples:


TimeoutWrapper<Map> wrapper = new TimeoutWrapper(Map.class, new HashMap());
Map m = wrapper.withTimeout(10, TimeUnit.MILLISECONDS);
m.put("key", "value");
m.get("key");


We may want faster gets than puts:

TimeoutWrapper<Map<String>> wrapper = new TimeoutWrapper(Map.class, new HashMap());
wrapper.withTimeout(10, TimeUnit.MILLISECONDS).put("key", "value");
String v = wrapper.withTimeout(5, TimeUnit.MILLISECONDS).get("key");


TimeoutWrapper provides a small (configurable) cache, so that it will reuse the same proxy instances if you pass in the same timeout values when using the above form.

Here's the main code:

TimeoutWrapper.java
TimedInvocationHandler.java

If you want to compile, you'll need some small supporting classes: GenericProxyFactory.java, LRUCache.java.

Monday, September 22, 2008

Capistrano deployment with S3

We recently started using Capistrano for our deployments. It's a great tool and really simplifies doing remote deployments to ec2.

A lot of our projects are java, or java web projects, so we need to deploy the result of a build, not the raw source. I really didn't want to store builds alongside the source code in subversion. Before capistrano, I had written a couple of install shell scripts that would fetch the latest project binary from S3, using bucket names structure like:

${RELEASE_BUCKET}:${PROJECT}/${VERSION}

with 'current' always pointing to the latest version.

There is a capistrano-s3 project that checks out from your scm, creates a .tar.gz, pushes this to s3, and then pushes this to your servers.

This isn't exactly what I wanted, since it's still missing a build step. I thought I could get by with something pretty simple -- just a scm implementation backed by S3. It turns out it was pretty easy.

Here's the S3 scm implementation. You need to have s3sync installed. Drop this in
$GEMPATH/capistrano-2.0.0/lib/capistrano/recipes/deploy/scm
And you can now use the following:

set :scm, :s3
set :repository, "my-bucket:my-path"

by default it will look in my-bucket:my-path/current/, you can also set

set :branch, "1.12"

and it will look in my-bucket:my-path/1.12/

If your AWS keys aren't available in the environment for s3sync, you can also set these in your capfile:

set :access_key, "my key"
set :secret_key, "my secret"

That's basically it. I'm pretty new to both capistrano and ruby, so any comments, feedback, etc. would be appreciated.

Hello Whirled

At Bizo we believe in sharing... This blog is to share the Bizo engineering experience with the world. We hope you find something interesting, helpful, inspiring or otherwise thought provoking.

-Bizo Engineering Team

Wednesday, September 17, 2008

Are we having fun yet?

This is a test of the bizo developer blogging system...

Thanks for setting this up Larry. Now my blogging career can finally take off!