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