1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.example.asyncrest;
20
21 import java.io.IOException;
22 import java.io.PrintWriter;
23 import java.util.Map;
24 import java.util.Queue;
25 import java.util.concurrent.ConcurrentLinkedQueue;
26 import java.util.concurrent.atomic.AtomicInteger;
27
28 import javax.servlet.AsyncContext;
29 import javax.servlet.ServletConfig;
30 import javax.servlet.ServletException;
31 import javax.servlet.http.HttpServletRequest;
32 import javax.servlet.http.HttpServletResponse;
33
34 import org.eclipse.jetty.client.ContentExchange;
35 import org.eclipse.jetty.client.HttpClient;
36 import org.eclipse.jetty.util.ajax.JSON;
37
38
39
40
41
42
43
44
45
46
47
48 public class AsyncRestServlet extends AbstractRestServlet
49 {
50 final static String RESULTS_ATTR = "org.eclipse.jetty.demo.client";
51 final static String DURATION_ATTR = "org.eclipse.jetty.demo.duration";
52 final static String START_ATTR = "org.eclispe.jetty.demo.start";
53
54 HttpClient _client;
55
56 public void init(ServletConfig servletConfig) throws ServletException
57 {
58 super.init(servletConfig);
59
60 _client = new HttpClient();
61 _client.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
62
63 try
64 {
65 _client.start();
66 }
67 catch (Exception e)
68 {
69 throw new ServletException(e);
70 }
71 }
72
73 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
74 {
75 Long start=System.nanoTime();
76
77
78 Queue<Map<String, String>> results = (Queue<Map<String, String>>) request.getAttribute(RESULTS_ATTR);
79
80
81 if (results==null)
82 {
83
84 final Queue<Map<String, String>> resultsQueue = new ConcurrentLinkedQueue<Map<String,String>>();
85 request.setAttribute(RESULTS_ATTR, results=resultsQueue);
86
87
88
89
90 final AsyncContext async = request.startAsync();
91 async.setTimeout(30000);
92
93
94 String[] keywords=request.getParameter(ITEMS_PARAM).split(",");
95 final AtomicInteger outstanding=new AtomicInteger(keywords.length);
96
97
98 for (final String item:keywords)
99 {
100 _client.send(
101 new AsyncRestRequest(item)
102 {
103 void onAuctionFound(Map<String,String> auction)
104 {
105 resultsQueue.add(auction);
106 }
107 void onComplete()
108 {
109 if (outstanding.decrementAndGet()<=0)
110 async.dispatch();
111 }
112 });
113 }
114
115
116 request.setAttribute(START_ATTR, start);
117 request.setAttribute(DURATION_ATTR, new Long(System.nanoTime() - start));
118
119 return;
120 }
121
122
123
124
125 String thumbs = generateThumbs(results);
126
127 response.setContentType("text/html");
128 PrintWriter out = response.getWriter();
129 out.println("<html><head>");
130 out.println(STYLE);
131 out.println("</head><body><small>");
132
133 long initial = (Long) request.getAttribute(DURATION_ATTR);
134 long start0 = (Long) request.getAttribute(START_ATTR);
135
136 long now = System.nanoTime();
137 long total=now-start0;
138 long generate=now-start;
139 long thread=initial+generate;
140
141 out.print("<b>Asynchronous: "+request.getParameter(ITEMS_PARAM)+"</b><br/>");
142 out.print("Total Time: "+ms(total)+"ms<br/>");
143
144 out.print("Thread held (<span class='red'>red</span>): "+ms(thread)+"ms (" + ms(initial) + " initial + " + ms(generate) + " generate )<br/>");
145 out.print("Async wait (<span class='green'>green</span>): "+ms(total-thread)+"ms<br/>");
146
147 out.println("<img border='0px' src='asyncrest/red.png' height='20px' width='"+width(initial)+"px'>"+
148 "<img border='0px' src='asyncrest/green.png' height='20px' width='"+width(total-thread)+"px'>"+
149 "<img border='0px' src='asyncrest/red.png' height='20px' width='"+width(generate)+"px'>");
150
151 out.println("<hr />");
152 out.println(thumbs);
153 out.println("</small>");
154 out.println("</body></html>");
155 out.close();
156 }
157
158 private abstract class AsyncRestRequest extends ContentExchange
159 {
160 AsyncRestRequest(final String item)
161 {
162
163 setMethod("GET");
164 setURL(restURL(item));
165 }
166
167 abstract void onAuctionFound(Map<String,String> details);
168 abstract void onComplete();
169
170 protected void onResponseComplete() throws IOException
171 {
172
173 Map<String,?> query = (Map<String,?>) JSON.parse(this.getResponseContent());
174 Object[] auctions = (Object[]) query.get("Item");
175 if (auctions != null)
176 {
177 for (Object o : auctions)
178 onAuctionFound((Map<String,String>)o);
179 }
180
181 onComplete();
182 }
183
184
185 protected void onConnectionFailed(Throwable ex)
186 {
187 getServletContext().log("onConnectionFailed: ",ex);
188 onComplete();
189 }
190
191
192 protected void onException(Throwable ex)
193 {
194 getServletContext().log("onConnectionFailed: ",ex);
195 onComplete();
196 }
197
198
199 protected void onExpire()
200 {
201 getServletContext().log("onConnectionFailed: expired");
202 onComplete();
203 }
204 }
205
206 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
207 {
208 doGet(request, response);
209 }
210
211 }