1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 package org.apache.http.impl.client.integration;
28
29 import java.io.IOException;
30
31 import org.apache.http.HttpClientConnection;
32 import org.apache.http.HttpException;
33 import org.apache.http.HttpHost;
34 import org.apache.http.HttpRequest;
35 import org.apache.http.HttpResponse;
36 import org.apache.http.HttpStatus;
37 import org.apache.http.client.HttpClient;
38 import org.apache.http.client.UserTokenHandler;
39 import org.apache.http.client.methods.HttpGet;
40 import org.apache.http.client.protocol.HttpClientContext;
41 import org.apache.http.entity.StringEntity;
42 import org.apache.http.localserver.LocalServerTestBase;
43 import org.apache.http.protocol.BasicHttpContext;
44 import org.apache.http.protocol.HttpContext;
45 import org.apache.http.protocol.HttpRequestHandler;
46 import org.apache.http.util.EntityUtils;
47 import org.junit.Assert;
48 import org.junit.Test;
49
50
51
52
53 public class TestStatefulConnManagement extends LocalServerTestBase {
54
55 private static class SimpleService implements HttpRequestHandler {
56
57 public SimpleService() {
58 super();
59 }
60
61 @Override
62 public void handle(
63 final HttpRequest request,
64 final HttpResponse response,
65 final HttpContext context) throws HttpException, IOException {
66 response.setStatusCode(HttpStatus.SC_OK);
67 final StringEntity entity = new StringEntity("Whatever");
68 response.setEntity(entity);
69 }
70 }
71
72 @Test
73 public void testStatefulConnections() throws Exception {
74
75 final int workerCount = 5;
76 final int requestCount = 5;
77
78 this.serverBootstrap.registerHandler("*", new SimpleService());
79
80 this.connManager.setMaxTotal(workerCount);
81 this.connManager.setDefaultMaxPerRoute(workerCount);
82
83 final UserTokenHandler userTokenHandler = new UserTokenHandler() {
84
85 @Override
86 public Object getUserToken(final HttpContext context) {
87 final String id = (String) context.getAttribute("user");
88 return id;
89 }
90
91 };
92 this.clientBuilder.setUserTokenHandler(userTokenHandler);
93
94 final HttpHost target = start();
95
96 final HttpClientContext[] contexts = new HttpClientContext[workerCount];
97 final HttpWorker[] workers = new HttpWorker[workerCount];
98 for (int i = 0; i < contexts.length; i++) {
99 final HttpClientContext context = HttpClientContext.create();
100 contexts[i] = context;
101 workers[i] = new HttpWorker(
102 "user" + i,
103 context, requestCount, target, this.httpclient);
104 }
105
106 for (final HttpWorker worker : workers) {
107 worker.start();
108 }
109 for (final HttpWorker worker : workers) {
110 worker.join(10000);
111 }
112 for (final HttpWorker worker : workers) {
113 final Exception ex = worker.getException();
114 if (ex != null) {
115 throw ex;
116 }
117 Assert.assertEquals(requestCount, worker.getCount());
118 }
119
120 for (final HttpContext context : contexts) {
121 final String uid = (String) context.getAttribute("user");
122
123 for (int r = 0; r < requestCount; r++) {
124 final String state = (String) context.getAttribute("r" + r);
125 Assert.assertNotNull(state);
126 Assert.assertEquals(uid, state);
127 }
128 }
129
130 }
131
132 static class HttpWorker extends Thread {
133
134 private final String uid;
135 private final HttpClientContext context;
136 private final int requestCount;
137 private final HttpHost target;
138 private final HttpClient httpclient;
139
140 private volatile Exception exception;
141 private volatile int count;
142
143 public HttpWorker(
144 final String uid,
145 final HttpClientContext context,
146 final int requestCount,
147 final HttpHost target,
148 final HttpClient httpclient) {
149 super();
150 this.uid = uid;
151 this.context = context;
152 this.requestCount = requestCount;
153 this.target = target;
154 this.httpclient = httpclient;
155 this.count = 0;
156 }
157
158 public int getCount() {
159 return this.count;
160 }
161
162 public Exception getException() {
163 return this.exception;
164 }
165
166 @Override
167 public void run() {
168 try {
169 this.context.setAttribute("user", this.uid);
170 for (int r = 0; r < this.requestCount; r++) {
171 final HttpGet httpget = new HttpGet("/");
172 final HttpResponse response = this.httpclient.execute(
173 this.target,
174 httpget,
175 this.context);
176 this.count++;
177
178 final HttpClientConnection conn = this.context.getConnection(HttpClientConnection.class);
179 final HttpContext connContext = (HttpContext) conn;
180 String connuid = (String) connContext.getAttribute("user");
181 if (connuid == null) {
182 connContext.setAttribute("user", this.uid);
183 connuid = this.uid;
184 }
185 this.context.setAttribute("r" + r, connuid);
186 EntityUtils.consume(response.getEntity());
187 }
188
189 } catch (final Exception ex) {
190 this.exception = ex;
191 }
192 }
193
194 }
195
196 @Test
197 public void testRouteSpecificPoolRecylcing() throws Exception {
198
199
200
201
202 final int maxConn = 2;
203
204 this.serverBootstrap.registerHandler("*", new SimpleService());
205
206 this.connManager.setMaxTotal(maxConn);
207 this.connManager.setDefaultMaxPerRoute(maxConn);
208
209 final UserTokenHandler userTokenHandler = new UserTokenHandler() {
210
211 @Override
212 public Object getUserToken(final HttpContext context) {
213 return context.getAttribute("user");
214 }
215
216 };
217
218 this.clientBuilder.setUserTokenHandler(userTokenHandler);
219
220 final HttpHost target = start();
221
222
223 final HttpContext context1 = new BasicHttpContext();
224 context1.setAttribute("user", "stuff");
225 final HttpResponse response1 = this.httpclient.execute(
226 target, new HttpGet("/"), context1);
227 EntityUtils.consume(response1.getEntity());
228
229
230
231
232
233 Thread.sleep(100);
234
235
236
237 final HttpContext context2 = new BasicHttpContext();
238 final HttpResponse response2 = this.httpclient.execute(
239 new HttpHost("127.0.0.1", this.server.getLocalPort()), new HttpGet("/"), context2);
240 EntityUtils.consume(response2.getEntity());
241
242
243
244
245 Thread.sleep(100);
246
247
248
249
250
251
252 final HttpContext context3 = new BasicHttpContext();
253 final HttpResponse response3 = this.httpclient.execute(
254 target, new HttpGet("/"), context3);
255
256
257
258
259 EntityUtils.consume(response3.getEntity());
260
261 }
262
263 }