Author Archives: johnnywey

In All Fairness to CloudBees

** EDIT ** Please make sure to check out the comments section for some additional information from a CloudBees engineer. He was kind enough to explain to set up their build environment to support some of the tools I mention below.

Today, due to some frustration I experienced, I tweeted:

In fairness to CloudBees, I should explain further.

Jenkins is, in my opinion, the reference implementation of continuous integration. It’s really great. While it favors Java, it’s not uncommon to see folks use it to run iOS builds, Ruby, Node, you name it. It’s very extendable and has an active developer community. I’ve had significant success using it for the last few years and, earlier this week at my new gig, my team and I setup an environment.

Hosted solutions can be a great idea because they often handle all the stuff about hardware and OS setup I don’t really care about. I am not a system administrator and I didn’t want to provision and manage a VM just for CI if I could help it (I know, being lazy but honest here). CloudBees seemed like a great choice and we had it up and running in literally minutes. It supported Gradle and Grails right out of the box (currently pieces of our software stack), has GitHub integration and other cool features. So far, pretty big win.

However, I’ve grown very used to using Jenkins for things outside of stock Java builds. For example, you can use Jenkins to test JavaScript (see this for an excellent example). We have also been using JRuby and Rake for pieces of our application stack and Jenkins has nice support for that also.

The hosted version, however, didn’t support much outside a stock Java (Ant, Gradle, Maven, Grails) build. I don’t necessarily blame them as trying to keep up with versions of Node, Ruby, PhamtomJS, whatever is probably outside the core competency of CloudBees. They are, first and foremost, a Java hosting platform. However, it sort of sunk us. After trying workarounds for a few hours, my team and I decided to move over to a RackSpace virtual host and setup our own custom solution.

So, to be fair, CloudBees hosted Jenkins (and even their application cloud) is an excellent choice if you are interested in building Java/JVM applications and don’t mind not having support for other, perhaps more fringe, tooling. The system itself ran flawlessly and worked very well for the more common tasks we sent its way. However, it’s just not a long term solution for the things we’re looking to do.

To quote Wheaton’s law:

My tweet was a little uncool and not very fair; I hope this explains it better!

New Gig

About two years ago, I started work at Time Warner Cable on what is easily the best team I’ve ever been on in my career. During that time, I helped build some amazing web applications including services that powered an iPad streaming application that won an engineering Emmy certificate.

Not much could have pulled me away from that team, I think. However, I got offered a position as a founding engineer at a new startup in the Denver area that got me really excited. The idea is something that has the potential to really disrupt the space and no code has been written. Me and my team will be able to decide exactly what the toolchain and technology stack will look like from the bottom up with no legacy considerations. On top of that, we’ll be able to define how engineering works for us without existing bureaucracy or established practice that often tailors to the lowest common denominator in larger organizations.

It’s a risk, of course. But one I’m excited to take.

While there’s not much there yet, watch www.MapVine.com to see the latest developments. I’ll also be discussing more here on some of the decisions we make and why.

I’m really looking forward to this move and I think it has the potential to be pretty amazing!

JSONP: How Does it Work?

Interestingly enough, I’ve seen a few candidates in interviews the last few months flail a bit when asked about getting around the same origin policy using JavaScript in a browser. Most know enough to toss out the term “JSONP” and perhaps another solution (e.g. proxy or CORS) but can’t really explain why one might prefer a certain solution over another. In fact, few could even describe how JSONP works aside from some JQuery library they always “just include”.

What is JSONP?

If you spend some time thinking about how JavaScript operates in a browser, you will probably arrive at the realization that the policy does not seem to effect script tags. Specifically, how many of us get JQuery from the Google CDN or some other source that is not the same origin as our current page? (I hope that answer is “most”, by the way.)

That same logic, combined with some DOM knowledge, would probably lead you to experiment with loading other types of JavaScript, aside from a library, using script tags. Since JavaScript has a global scope, if you were to reference a function that could handle that data you could then link it with your application and do something interesting with it.

JSONP is born.

The idea of JSONP is actually pretty simple: toss a script tag into the DOM with a reference to a resource that returns JSON data. Have the server return said JSON with “padding” (the “P” part of JSONP) that executes a function wrapping the incoming data. In order for this to work properly, the server API must also support JSONP. Typically, the function name is named as the callback parameter. For example, let’s pretend you are accessing a service that returns JSON weather information that looks like:

http://www.weather.com/90210

Which returns JSON like:

{"zipCode": "90210","location": "Beverly Hills","high": "85 degrees","low": "55 degrees"}

Adding JSONP support would result in a URL that looks like:

http://www.weather.com/90210?callback=MyCallback

And returns:

MyCallback({"zipCode": "90210","location": "Beverly Hills","high": "85 degrees","low": "55 degrees"});

This data is now exposed to the rest of the application as long as MyCallback is a valid function name in the global scope.

Most JSONP implementations in libraries like JQuery will automatically generate callback functions as well as cleaning up inserted script tags when the callback executes, but the basic idea is actually pretty simple.

Why To Use JSONP?

JSONP is universally supported on just about every browser and a lot of useful APIs have support for it already in place (Yahoo, Twitter, Google, etc.) Aside from the regular XMLHttpRequest and DOM differences, nothing really special needs to be done to make it work across different browsers. Finally, since it has been around for a bit, there are pretty mature JSONP plugins for just about every major library and framework around (JQuery, YUI, Prototype, etc.)

Why NOT To Use JSONP?

Deciding against using JSONP is directly related to how it works. First of all, the only HTTP method you can use is GET since that is the only method script tags support. This immediately eliminates the use of JSONP as an option to interact with nice RESTful APIs that use other HTTP verbs to do fun stuff like CRUD. And while we’re on the subject of GET, note that using anything other than URL parameters to communicate with the server API (e.g. sending some JSON over) is also not possible. (You could encode JSON as a URL parameter, but shame on you for even thinking that.)

Secondly, since you are relying on a script tag, there is no uniform way to catch errors. Some browsers will allow attaching a callback to the script tag (e.g. onError() {}), but it is not universally supported (any guesses on which browsers don’t support it?) and therefore can’t be relied upon without some unfortunate hacks. If the called API is doing syntactically correct things like returning an HTTP 404 response code when a resource cannot be found, there is no way to easily catch that error condition or parse the response body for further information. Instead, what typically takes place are APIs that return HTTP 200 status codes but contain JSON describing an error condition. There are worse things in the world, but I cringe at that approach these days.

Finally, keep in mind that JSONP is really a security vulnerability. It happens to be an extremely useful one, but the same origin policy does provide value in protecting the application and using JSONP is willfully opening up a hole that could potentially become an attack vector.

What Are Some Alternatives?

The easiest alternative is setting up a proxy to an external API through the same origin as the web application. This can be done pretty easily using tooling built into web servers like Apache and Nginx.

If you are able to remove support for IE7 and don’t care much about Opera, the end game is Cross-Origin Resource Sharing (CORS). This solution allows the full array of HTTP verbs and errors (including POSTing JSON) and has a greater level of security than JSONP. It has decent support on IE8+ (with some provisos) and is relatively easy to implement on the server. The downside is that many popular public JSON APIs today don’t yet support it.

Conclusion

CORS >= Proxy > JSONP (most of the time).

Follow

Get every new post delivered to your Inbox.