View
4.127
Download
0
Category
Tags:
Preview:
DESCRIPTION
JavaOne 2010 talk.
Citation preview
Wri$ng Powerful HTTP Apps Using the New Asynchronous HTTP Client
Library
Jeanfrancois Arcand h@p://twi@er.com/jfarcand
h@p://github.com/AsyncH@pClient/async-‐h@p-‐client
Hubert Iwaniuk h@p://twi@er.com/neotyk
Jeanfrancois
Creator of the Grizzly Framework
Creator of GlassFish v3 Grizzly Micro
Kernel Creator and Co-‐
Leader of Atmosphere
9 years @ Sun Microsystem
Creator Async H@p Client
Major contributor to GlassFish
• News and Update • Why
• The Async H@p Client API • Conclusion • Q & A
Since released, we’ve got an impressive amount of
contribu$ons and adop$ons. Library is evolving fast!
Why
JDK’s UrlConnec$on Totally Broken
Why
JDK’s UrlConnec$on Totally Broken
Apache H@pClient high on steroid
Why
JDK’s UrlConnec$on Totally Broken
Apache H@pClient high on steroid
Apache H@p is blocking
Why
JDK’s UrlConnec$on Totally Broken
Apache H@pClient high on steroid
Apache H@p is blocking
Apache H@pClient buffer the bytes in
memory
Why
JDK’s UrlConnec$on Totally Broken
Apache H@pClient high on steroid
Apache H@p is blocking
Apache H@pClient buffer the bytes in
memory
Apache H@pClient is $ed to its own
I/O layer.
Why
AsyncH@pClient supports the “zero-‐copy”
Why
AsyncH@pClient supports the “zero-‐copy”
Large Upload using na$ve memory
Small memory
Why
AsyncH@pClient supports the “zero-‐copy”
AsyncH@pClient is not $ed to it’s
I/O layer
Why
AsyncH@pClient supports the “zero-‐copy”
AsyncH@pClient is not $ed to it’s
I/O layer Ne@y
Grizzly
Apache H@pClient
JDK UrlConnec
$on
Why
AsyncH@pClient supports the “zero-‐copy”
AsyncH@pClient is not $ed to it’s
I/O layer
AsyncH@pClient is blocking or non blocking
Why
AsyncH@pClient supports the “zero-‐copy”
AsyncH@pClient is not $ed to it’s
I/O layer
AsyncH@pClient is blocking or non blocking
Allow efficient streaming
Use the well know
Future<?> API
Why
AsyncH@pClient supports the “zero-‐copy”
AsyncH@pClient is not $ed to it’s
I/O layer
AsyncH@pClient is blocking or non blocking
AsyncH@pClient doesn’t buffer the bytes in memory
Why
AsyncH@pClient supports the “zero-‐copy”
AsyncH@pClient is not $ed to it’s
I/O layer
AsyncH@pClient is blocking or non blocking
AsyncH@pClient doesn’t buffer the bytes in memory
Your applica$on have control
Why
AsyncH@pClient supports the “zero-‐copy”
AsyncH@pClient is not $ed to it’s
I/O layer
AsyncH@pClient is blocking or non blocking
AsyncH@pClient doesn’t buffer the bytes in memory
AsyncH@pClient is easy to use
Fully Asynchronous
request
callback Response chunk
Calling Thread
callback Response chunk
Server Thread Pool (*)
Comple$onHandler
request
Response start
Calling Thread
callback Response end
Server Thread Pool (*)
Future based API AsyncH@pClient asyncH@pClient = new AsyncH@pClient();
Future<Response> f = asyncH@pClient.prepareGet("h@p://www.sonatype.com/").execute();
Response r = f.get();
Handler based API AsyncH@pClient asyncH@pClient = new AsyncH@pClient(); Future<Response> asyncH@pClient. prepareGet("h@p://www.sonatype.com/").execute(
new AsyncComple=onHandler<Response>( { @Override public Response onCompleted(Response r){
return response; }
@Override public void onThrowable(Throwable t){
} });
Typed AsyncH@pClient asyncH@pClient = new AsyncH@pClient(); asyncH@pClient.prepareGet("h@p://www.sonatype.com/").execute( new AsyncComple$onHandler<Integer>( { @Override public Integer onCompleted(Response r){ return response.getStatus(); }
@Override public void onThrowable(Throwable t){
} }).get(); // Return Integer
Request Builder
AsyncH@pClient c= new AsyncH@pClient();
c.preparePost(“h@ps://….”) .setBody(body) .setHeader(header) .setProxy(proxy) .execute();
Streaming Handler AsyncH@pClient c = new AsyncH@pClient(); Future<String> f = c.prepareGet("h@p://www.sonatype.com/").execute(
new AsyncHandler<String>() {
@Override public STATE onStatusReceived(H@pResponseStatus<String> status) throws Excep$on { // return STATE.ABORT to stop }
@Override public STATE onHeadersReceived(H@pResponseHeaders<String> headers) throws Excep$on { …}
@Override public STATE onBodyPartReceived(H@pResponseBodyPart<String> bodyPart) throws Excep$on {…} }.get();
Progress Handler Future<String> f = h@pClient.preparePut(uri) .setRealm(createRealm()) .setProxyServer(createProxyServer()) .setFile(file) .execute(comple$onHandler); ("….").setFile(.execute(
new AsyncComple=onHandler<String>() {
@Override public STATE onHeaderWriteCompleted() { return STATE.CONTINUE; }
@Override public STATE onContentWriteCompleted() { return STATE.CONTINUE; }
@Override public STATE onContentWriteProgess(long amount, long current, long total) { return STATE.CONTINUE; } )
Configurable AsyncH@pClientConfig c = new AsyncH@pClientConfig.Builder(). setResponseTimeoutInMs(30000).build();
AsyncH@pClient asyncH@pClient = new AsyncH@pClient(c);
Realm realm = new Realm.RealmBuilder() .setPrincipal(“me”) .setPassword(“xxxx”).build(); c.setRealm(realm);
AsyncH@pClient asyncH@pClient = new AsyncH@pClient(c);
Zero Copy -‐ Upload
AsyncH@pClient c= new AsyncH@pClient();
c.preparePost(“h@ps://….”) .setBody(body) .setFile(header) .setProxy(proxy).execute();
Zero Copy -‐ Download AsyncH@pClient c = new AsyncH@pClient(); Future<String> f = c.prepareGet("h@p://www.sonatype.com/").execute(
new AsyncHandler<String>() {
@Override public STATE onBodyPartReceived(H@pResponseBodyPart<String> bodyPart) throws Excep$on {
bodyPart.write(OutputStream); } }.get();
TLS Support
// Op$onal AsyncH@pClientConfig c = new AsyncH@pClientConfig.Builder(). setSSLEngine(…).build();
AsyncH@pClient asyncH@pClient = new AsyncH@pClient(c);
Future<String> f = c.prepareGet("hBps://….").get();
Scrip$ng Support -‐ Clojure
• (ns twi@er-‐stream (:require [h@p.async.client :as c] [org.danlarkin.json :as j] [clojure.contrib.logging :as l]))
(doseq [twit-‐str (c/string (c/stream-‐seq :get "h@p://stream.twi@er.com/1/statuses/sample.json" :auth {:user "u" :password "p"} :$meout -‐1))] (try (let [twit (j/decode-‐from-‐str twit-‐str)] (l/info (str (get-‐in twit [:user :screen_name]) "=>" (:text twit)))) (catch Excep$on e (l/warn (str "Failed to parse: " twit-‐str) e))))
Scrip$ng Support -‐ JRuby
client = AsyncH@pClient.new future = client.prepare_get("h@p://…")
.set_header("X-‐Trace", "true").execute
response = future.get
response.headers.each
{ |pair| puts "#{pair.key} =>
#{pair.value.join(", ")}" } client.close
Scrip$ng Support -‐ Jython
client = AsyncH@pClient() future = client.prepareGet("h@p://www.google.com/")
.setHeaders({ "User-‐Agent" : [ "Async HTTP Client/1.0.0" ]})
.execute()
response = future.get() for entry in response.headers: print '%s => %s' % (entry.key, ", ".join(entry.value)) client.close()
What’s Next
• NTLM support • Websocket support
• New Providers: – Grizzly 2.0 – Apache H@pClient
• H@p Pipelining • Annota$on based support.
Fancy @BaseURL("h@p://localhost:12345") public interface FooClient { @GET("/") public Future<Response> getRoot();
@GET("/") public Future<String> getRootAsString();
@GET("/") public Future<String> getRootWithParam(@QueryParam("name") String name); } FancyClientBuilder builder = new FancyClientBuilder(asyncClient); FooClient client = builder.build(FooClient.class);
Recommended