Fables of the Reconstruction Part 2: Have you tried rebooting it?
When I realized the time had come (in part 1) to move on from Dispatch’s original underlying transport, I knew which ship I would jump to. In Unfiltered we use Netty for serving HTTP with great success. But instead of working with the raw Netty interfaces, Dispatch would be able to benefit from the well regarded async-http-client’s trailblazing in Java. The client even supports other client backends including plain old URLConnection. This would allow Dispatch to focus on providing awesome Scala interfaces to a single interface.
~~~
With Dispatch’s reboot, I’m taking the opportunity to avoid some grief. To fend off another five years of strangers demanding that I rewrite the library more conservatively (or suggesting they might to do so themselves before mysteriously disappearing) I’m structuring Dispatch reboot such that the underlying client’s Java interfaces remain readily available to application code.
So instead of this pile of unfathomable symbols…
val req = host("example.com") / "api" / resourceType / resourceId
You can delight in the grace and clarity of pure alphabetic methods:
val req = new RequestBuilder().setUrl(
"http://example.com/api/%s/%s".format(resourceType, resourceId)
)
Or, moral relativists of method naming can use + for string concatenation:
val req = new RequestBuilder().setUrl(
"http://example.com/api/" + resourceType + "/" + resourceId
)
In prior versions of Dispatch the dispatch.Request class contains
HttpComponents objects, but in the Dispatch reboot we’ll bubble the
com.ning.http.client.RequestBuilder interface up to the
surface. Methods like / are implicitly defined on RequestBuilder
and yield instances of the same type, so that you are never very
far from our underlying library. If you want to use its addHeader
method, go right ahead:
val req = (host("example.com") / path).addHeader(key, value)
This way, indulging in a bit of Dispatch spice does not commit you to the full chicken tikka masala.

While request definitions can look as much or as little like prior versions of Dispatch as you prefer, response handlers are completely different. When it comes to handling requests, believe it or not, I’ve found the limit to my own appreciation of symbolic naming.
For one thing, the first character in handler verbs had to be from the smaller set of symbols that are of equal or lower precedence than those used to build requests. Factoring in that limitation, we quickly ran out of ways to represent different kinds of response handlers that are visually distinct and not completely insane.
It was the contribution of the very cool jsoup and tagsoup handlers that drove this point home for me: there’s an infinite variety of potential useful response handlers. It doesn’t make sense to do symbols for a few basic handlers when you will inevitably run out later.
The same is theoretically true for request builders, it’s but less vexing in practice. And in any case the symbolic request builders are just too useful. When people talk about how quickly they can bang out an API client with Dispatch, it’s because our API is good for parameterizing requests. As I’ve tried to show in the quite typical example above, request verbs can be very nice to have when your request path is not constant. Yet, most HTTP clients don’t provide any special support for this common case.
If I had never gone full bore with symbolic methods in Dispatch, I never would have learned from users just how useful they are for the problem domain of building requests. For handlers they have worked out poorly, and so the sensible thing is not to use them. Without further ado, this is a how to make a request in the forthcoming Dispatch;
val foo = Http(host("example.com") / path > As.string)
Please, try to avoid a symbolic panic attack. We already went over
/. The right arrow > is nothing more than a convenience
function. It’s comporable to -> in the Scala standard library. In
fact, it also produces a Tuple2. The difference, and the reason we
don’t just use ->, is we want to restrict the type of the
handler. In the above case the types are fixed, but we also want
to support function literals as handlers without requiring type
signatures. For example, you could write As.string inline:
val foo = Http(host("example.com") / path > { response =>
response.getResponseBody
})
The implicit method > on RequestBuilder allows Dispatch to
build the request and handler for you. But you don’t have to use it:
val foo = Http(
(host("example.com") / path).build,
new OkayFunctionHandler(As.string)
)
And if you are not even cool with request verbs, there’s always this beauty:
val foo = Http(
new RequestBuilder().setUrl(
"http://example.com/%s".format(path)
).build,
new OkayFunctionHandler(As.string)
)
But if you decided not to use Dispatch’s request and handler builders, why not just use async-http-client directly?
There is a good reason to use Dispatch even in bland-mode, but you’ll have to wait for the next and last part of this series to find out what it is.
Stay tuned for Part 3: The future is not already here

