@@ -45,4 +45,136 @@ public interface AsyncHandler<T> {
45
45
T onCompleted() throws Exception;
46
46
}
47
47
+-----+
48
-
48
+
49
+ * Creating a Request object
50
+
51
+ The AsynHttpClient uses the builder pattern when it is time to create Request object. The simplest way consist of:
52
+
53
+ +-----+
54
+ RequestBuilder builder = new RequestBuilder("PUT");
55
+ Request request = builder..setUrl("http://")
56
+ .addHeader("name", "value")
57
+ .setBody(new File("myUpload.avi"))
58
+ .build();
59
+ AsyncHttpClient client = new AsyncHttpClient();
60
+ client.execute(request, new AsyncHandler<...>() {
61
+ .....
62
+ } );
63
+ +-----+
64
+
65
+ If you need to work with File, the library supports the {{{./zero-bytes-copy.html}zero copy in memory concept}},
66
+ e.g the File can be uploaded or downloaded without loading its associated bytes in memory, preventing out of memory
67
+ errors in case you need to upload or download many large files. Although the library support the following:
68
+
69
+ +-----+
70
+ Request request = builder.setUrl("http://")
71
+ .addHeader("name", "value")
72
+ .setBody(myInputStream))
73
+ .build();
74
+ +-----+
75
+
76
+ it is discouraged to use <<<InputStream>>> as the library will need to buffer bytes in memory in order to determine
77
+ the length of the stream, and instead highly recommended to either use a File or the <<<BodyGenerator>>> API to avoid
78
+ loading unnecessary bytes in memory:
79
+
80
+ +-----+
81
+ public interface BodyGenerator {
82
+ Body createBody() throws IOException;
83
+ }
84
+ +-----+
85
+
86
+ where a Body is defined as:
87
+
88
+ +-----+
89
+ public interface Body {
90
+ long getContentLength();
91
+
92
+ long read(ByteBuffer buffer)
93
+ throws IOException;
94
+
95
+ void close() throws IOException;
96
+ }
97
+ +-----+
98
+
99
+ This way the library will never read unnecessary bytes in memory, which could significantly improve the performance
100
+ your application.
101
+
102
+ The <<<RequestBuilder>>> can also be used to create per <<<Request>>> configuration,
103
+ like setting a Proxy or request timeout:
104
+
105
+ +-----+
106
+ PerRequestConfig requestConfig = new PerRequestConfig();
107
+ requestConfig.setRequestTimeoutInMs(5 * 1000);
108
+ requestConfig.setProxy(new ProxyServer(...));
109
+ Future responseFuture = client.prepareGet("http://").setPerRequestConfig(requestConfig).execute();
110
+ +-----+
111
+
112
+ * Creating a Response object
113
+
114
+ The AsyncHandler is typed, e.g you can return any object from the <<<AsyncHandler.onCompleted()>>>. One useful object
115
+ of the library is the <<<Response>>> object and it's associate builder. You can incrementally create a <<<Response>>>
116
+ object using the <<<ResponseBuilder.accumulate()>>> method:
117
+
118
+ +-----+
119
+ MyAsyncHandler<Response> asyncHandler = new MyAsyncHanfler<Response>() {
120
+ private final Response.ResponseBuilder builder = new Response.ResponseBuilder();
121
+
122
+ public STATE onBodyPartReceived(final HttpResponseBodyPart content) throws Exception {
123
+ builder.accumulate(content);
124
+ return STATE.CONTINUE;
125
+ }
126
+
127
+ public STATE onStatusReceived(final HttpResponseStatus status) throws Exception {
128
+ builder.accumulate(status);
129
+ return STATE.CONTINUE;
130
+ }
131
+
132
+ public STATE onHeadersReceived(final HttpResponseHeaders headers) throws Exception {
133
+ builder.accumulate(headers);
134
+ return STATE.CONTINUE;
135
+ }
136
+
137
+ public Response onCompleted() throws Exception {
138
+ return builder.build();
139
+ }
140
+
141
+ }
142
+
143
+ Response response = client.prepareGet("http://sonatype.com").execute(asyncHandler).get();
144
+ +-----+
145
+
146
+ One thing to consider when creating a <<<Response>>> object is the size of the response body. By default,
147
+ a <<<Response>>> object will accumulate all response's bytes in memory, and that could potentially create an out of
148
+ memory error. If you are planning to use the API for downloading large files, it is not recommended to accumulate
149
+ bytes in memory and instead flush the bytes on disk as soon as they are available. Note that you can still use the
150
+ <<<Response>>> object, except you don't accumulate the response's bytes as demonstrated below:
151
+
152
+ +-----+
153
+ MyAsyncHandler<Response> asyncHandler = new MyAsyncHanfler<Response>() {
154
+ private final Response.ResponseBuilder builder = new Response.ResponseBuilder();
155
+
156
+ public STATE onBodyPartReceived(final HttpResponseBodyPart content) throws Exception {
157
+ content.write(myOutputStream);
158
+ return STATE.CONTINUE;
159
+ }
160
+
161
+ public STATE onStatusReceived(final HttpResponseStatus status) throws Exception {
162
+ builder.accumulate(status); return STATE.CONTINUE;
163
+ }
164
+
165
+ public STATE onHeadersReceived(final HttpResponseHeaders headers) throws Exception {
166
+ builder.accumulate(headers);
167
+ return STATE.CONTINUE;
168
+ }
169
+
170
+ public Response onCompleted() throws Exception {
171
+ return builder.build();
172
+ }
173
+
174
+ }
175
+
176
+ Response response = client.prepareGet("http://sonatype.com").execute(asyncHandler).get();
177
+ +-----+
178
+
179
+ Note that in the above scenario invoking <<<Response.getResponseBodyAsStream()>>> or <<<getResponseBody()>>> will
180
+ return an <<<IllegalStateException>>> because the body wasn't accumulated by the <<<Response>>> object.
0 commit comments