Saturday, May 27, 2006
Thursday, May 25, 2006
Poor Man's Trackback
I wanted to send a trackback today, but Blogger doesn't support them (with good reason, details at the end of this post). Fortunately, a trackback is nothing more than an HTTP post with your blog entry's URL to the other blog's trackback URL. A simple curl command does the trick:
$ curl -d url=[my entry's URL] [trackback URL]
If successful, the command outputs something like this:
<?xml version="1.0" encoding="utf-8"?> <response> <error>0</error> </response>You can also specify the
title
, excerpt
, and blog_name
using additional -d
parameters.
I guess you can imagine trackbacks are pretty prone to spamming. For example, unlike comments, I don't see any way you can insert a captcha.
Blogger on the other hand supports backlinks. Instead of allowing/requiring users to manually post reverse links, Blogger asks Google Blog Search for links back to an entry. This way you don't have to build trackback functionality into every blog tool, and you can use Blog Search as a giant spam filter.
Until everyone else catches on, we have curl.
Saturday, May 20, 2006
Scooter the Tooter
w
, height h = w / ratio + 27
.
Duplicate Feed Items
Friday, May 19, 2006
JavaOne: InfoQ
JavaOne: Google Web Toolkit vs. JSF
XMLHttpRequest
s.
The GWT enables you to call back to the server via a simple RPC mechanism. Dust off your DTO and Session Facade patterns, folks. You can even step through your Java code with a debugger while running in the browser!
For the majority of intents and purposes, GWT invalidates JSF. Both frameworks seek to isolate web developers from HTTP, but due to the fact that Google built GWT from the ground up with AJAX in mind, GWT offers a cleaner abstraction, better type safety, and a lower learning curve. When it comes to AJAX and JSF, you're at the mercy of which functionality your JSF components offer. You must write anything beyond that (including your business logic) in Javascript. With GWT, you can stick to 100% Java.
Now, on one end of the spectrum we have request/response, action-based frameworks such as Struts Action 2 and Rails which work great for traditional web applications, and on the other we have GWT which enables you to build rich, component-based AJAX applications. By comparison, JSF seems to awkwardly fall somewhere in the middle. You might argue that JSF is meant for any view technology, not just AJAX, but does anyone really use it for anything else? I don't see myself writing JSF code once and then sharing it between my web site, mobile phone XHTML web site and Swing application. I'm perfectly content to push common functionality down into the service layer.
Disclaimer: If you're a regular reader, you probably already know I work for Google (but, much to my chagrin, not on GWT). I do work on Struts Action 2.
JavaOne: Annotations
JavaOne: Session Concurrency
HttpSession
implementations: developers tend to forget that multiple threads can concurrently access objects on the session. From my experience, web developers think even less about session concurrency than security (yes, it's possible).
It's terribly easy to focus on the happy path during development and ignore the edge cases (especially considering how difficult it is to test them). In the past, we web developers only had to worry about users who double clicked links and buttons, but now technologies like AJAX and asynchronous session replication have exacerbated the problem by increasing the likelihood of two threads stepping on each other and resulting in race conditions or deadlocks.
Case in point: I once had a server grind to a halt due to a strange deadlock. The stack dump showed that one thread was waiting for a lock held by another thread which seemed to be mysteriously stuck in Object.hashCode()
:
daemon runnable at java.lang.Object.hashCode(Native Method) at java.util.HashMap$Entry.hashCode(Unknown Source) at java.util.AbstractMap.hashCode(Unknown Source) ...
How on Earth could a thread block in Object.hashCode()
? The call to a non-synchronized HashMap
in the stack trace unlocked the mystery. Someone nested a HashMap
instance deeply within the session. While one request iterated over the map, another request came in and mutated the map which created a cycle in the HashMap
's underlying data structure, and the first thread went into an infinite loop. Object.hashCode()
didn't really block, but the loop was so tight, it sure looked that way.
How do you avoid this pitfall? There is no silver bullet. You could synchronize. Synchronizing at the appropriate level is tricky. Too fine grained, you don't really solve the problem. Too coarse, and a long running request can block subsequent requests. Last I checked, Struts Action 1 performed no synchronization on session scoped beans, and it wasn't a problem you could solve at the application level (i.e. how would you get Struts to acquire your lock before mapping request parameters to your session-scoped bean?). I'm not sure how JSF implementations and Spring WebFlow address this problem, but I'd love to hear. My current project manages concurrency quite successfully using an in-house wizard framework.
You could also serialize the session at the beginning and end of each request (each request would have its own copy of the session). I think Rails takes this approach by virute of the fact that each request executes in its own process. I'm not sure how you would handle concurrent requests though; would the second request overwrite the session changes from the first? Does Rails write the problem off as too rare to worry about? I suppose you could mitigate this problem to some degree by storing the session in a hidden field on the client.
Nowadays I think I favor keeping all your state in the database and using one of the aforementioned clustered caching frameworks to scale. Thoughts?