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