Codebase list resteasy / 156491d
Merge pull request #433 from patriot1burke/master netty4 fixes Bill Burke 10 years ago
11 changed file(s) with 765 addition(s) and 220 deletion(s). Raw diff Collapse all Expand all
1616 <groupId>org.jboss.resteasy</groupId>
1717 <artifactId>resteasy-jaxrs</artifactId>
1818 <version>${project.version}</version>
19 </dependency>
20 <dependency>
21 <groupId>org.jboss.resteasy</groupId>
22 <artifactId>resteasy-client</artifactId>
23 <version>${project.version}</version>
24 <scope>test</scope>
25 </dependency>
26 <dependency>
27 <groupId>org.jboss.resteasy</groupId>
28 <artifactId>resteasy-jaxb-provider</artifactId>
29 <version>${project.version}</version>
30 <scope>test</scope>
1931 </dependency>
2032 <dependency>
2133 <groupId>io.netty</groupId>
5353 private final boolean is100ContinueExpected;
5454 private NettyExecutionContext executionContext;
5555 private final ChannelHandlerContext ctx;
56 private volatile boolean flushed;
5657
5758 public NettyHttpRequest(ChannelHandlerContext ctx, ResteasyHttpHeaders httpHeaders, ResteasyUriInfo uri, String httpMethod, SynchronousDispatcher dispatcher, NettyHttpResponse response, boolean is100ContinueExpected)
5859 {
103104 public ResteasyAsynchronousContext getAsyncContext()
104105 {
105106 return executionContext;
107 }
108
109 public boolean isFlushed()
110 {
111 return flushed;
106112 }
107113
108114 @Override
331337 finally
332338 {
333339 done = true;
334 ctx.writeAndFlush(nettyResponse.getDefaultFullHttpResponse());
335 ctx.close();
340 nettyFlush();
336341 }
337342 }
338343 }
349354 }
350355 done = true;
351356 cancelled = true;
352 return internalResume(Response.status(Response.Status.SERVICE_UNAVAILABLE).build());
357 try
358 {
359 return internalResume(Response.status(Response.Status.SERVICE_UNAVAILABLE).build());
360 }
361 finally
362 {
363 nettyFlush();
364 }
353365 }
354366 }
355367
361373 if (done) return false;
362374 done = true;
363375 cancelled = true;
364 return internalResume(Response.status(Response.Status.SERVICE_UNAVAILABLE).header(HttpHeaders.RETRY_AFTER, retryAfter).build());
365 }
366 }
367
368 @Override
376 try
377 {
378 return internalResume(Response.status(Response.Status.SERVICE_UNAVAILABLE).header(HttpHeaders.RETRY_AFTER, retryAfter).build());
379 }
380 finally
381 {
382 nettyFlush();
383 }
384 }
385 }
386
387 protected synchronized void nettyFlush()
388 {
389 flushed = true;
390 ctx.writeAndFlush(nettyResponse.getDefaultFullHttpResponse());
391 ctx.close();
392 }
393
394 @Override
369395 public boolean cancel(Date retryAfter) {
370396 synchronized (responseLock)
371397 {
373399 if (done) return false;
374400 done = true;
375401 cancelled = true;
376 return internalResume(Response.status(Response.Status.SERVICE_UNAVAILABLE).header(HttpHeaders.RETRY_AFTER, retryAfter).build());
402 try
403 {
404 return internalResume(Response.status(Response.Status.SERVICE_UNAVAILABLE).header(HttpHeaders.RETRY_AFTER, retryAfter).build());
405 }
406 finally
407 {
408 nettyFlush();
409 }
377410 }
378411 }
379412
99 import io.netty.handler.codec.http.HttpVersion;
1010 import org.jboss.resteasy.specimpl.MultivaluedMapImpl;
1111 import org.jboss.resteasy.spi.HttpResponse;
12 import org.jboss.resteasy.spi.ResteasyProviderFactory;
1213
1314 import javax.ws.rs.core.HttpHeaders;
1415 import javax.ws.rs.core.MultivaluedMap;
3132 private final ChannelHandlerContext ctx;
3233 private boolean committed;
3334 private boolean keepAlive;
35 private ResteasyProviderFactory providerFactory;
3436
35 public NettyHttpResponse(ChannelHandlerContext ctx, boolean keepAlive)
37 public NettyHttpResponse(ChannelHandlerContext ctx, boolean keepAlive, ResteasyProviderFactory providerFactory)
3638 {
3739 outputHeaders = new MultivaluedMapImpl<String, Object>();
3840 byteBuf = ctx.alloc().buffer();
3941 os = new ByteBufOutputStream(byteBuf);
4042 this.ctx = ctx;
4143 this.keepAlive = keepAlive;
44 this.providerFactory = providerFactory;
4245 }
4346
4447 @Override
144147 byteBuf.retain(1);
145148 }
146149
147 public DefaultFullHttpResponse getDefaultFullHttpResponse() {
150 public DefaultFullHttpResponse getDefaultFullHttpResponse()
151 {
148152 HttpResponseStatus status = HttpResponseStatus.valueOf(getStatus());
149 return new DefaultFullHttpResponse(HTTP_1_1, status, getBuffer());
153 DefaultFullHttpResponse res = new DefaultFullHttpResponse(HTTP_1_1, status, getBuffer());
154 RestEasyHttpResponseEncoder.transformHeaders(this, res, providerFactory);
155 return res;
150156 }
151157 }
0 package org.jboss.resteasy.plugins.server.netty;
1
2 import io.netty.bootstrap.ServerBootstrap;
3 import io.netty.channel.ChannelInitializer;
4 import io.netty.channel.ChannelOption;
5 import io.netty.channel.EventLoopGroup;
6 import io.netty.channel.nio.NioEventLoopGroup;
7 import io.netty.channel.socket.SocketChannel;
8 import io.netty.channel.socket.nio.NioServerSocketChannel;
9 import io.netty.handler.codec.http.HttpObjectAggregator;
10 import io.netty.handler.codec.http.HttpRequestDecoder;
11 import io.netty.handler.codec.http.HttpResponseEncoder;
12 import io.netty.handler.ssl.SslHandler;
13 import io.netty.util.concurrent.EventExecutor;
14 import org.jboss.resteasy.core.SynchronousDispatcher;
15 import org.jboss.resteasy.plugins.server.embedded.EmbeddedJaxrsServer;
16 import org.jboss.resteasy.plugins.server.embedded.SecurityDomain;
17 import org.jboss.resteasy.spi.ResteasyDeployment;
18
19 import javax.net.ssl.SSLContext;
20 import javax.net.ssl.SSLEngine;
21
22 /**
23 * An HTTP server that sends back the content of the received HTTP request
24 * in a pretty plaintext form.
25 *
26 * @author <a href="http://www.jboss.org/netty/">The Netty Project</a>
27 * @author Andy Taylor (andy.taylor@jboss.org)
28 * @author <a href="http://gleamynode.net/">Trustin Lee</a>
29 * @author Norman Maurer
30 * @version $Rev: 2080 $, $Date: 2010-01-26 18:04:19 +0900 (Tue, 26 Jan 2010) $
31 */
32 public class NettyJaxrsServer implements EmbeddedJaxrsServer
33 {
34 protected ServerBootstrap bootstrap = new ServerBootstrap();
35 protected int port = 8080;
36 protected ResteasyDeployment deployment = new ResteasyDeployment();
37 protected String root = "";
38 protected SecurityDomain domain;
39 private EventLoopGroup eventLoopGroup;
40 private EventLoopGroup eventExecutor;
41 private int ioWorkerCount = Runtime.getRuntime().availableProcessors() * 2;
42 private int executorThreadCount = 16;
43 private SSLContext sslContext;
44 private int maxRequestSize = 1024 * 1024 * 10;
45 private int backlog = 128;
46
47 public void setSSLContext(SSLContext sslContext)
48 {
49 this.sslContext = sslContext;
50 }
51
52 /**
53 * Specify the worker count to use. For more information about this please see the javadocs of {@link EventLoopGroup}
54 *
55 * @param ioWorkerCount
56 */
57 public void setIoWorkerCount(int ioWorkerCount)
58 {
59 this.ioWorkerCount = ioWorkerCount;
60 }
61
62 /**
63 * Set the number of threads to use for the EventExecutor. For more information please see the javadocs of {@link EventExecutor}.
64 * If you want to disable the use of the {@link EventExecutor} specify a value <= 0. This should only be done if you are 100% sure that you don't have any blocking
65 * code in there.
66 *
67 * @param executorThreadCount
68 */
69 public void setExecutorThreadCount(int executorThreadCount)
70 {
71 this.executorThreadCount = executorThreadCount;
72 }
73
74 /**
75 * Set the max. request size in bytes. If this size is exceed we will send a "413 Request Entity Too Large" to the client.
76 *
77 * @param maxRequestSize the max request size. This is 10mb by default.
78 */
79 public void setMaxRequestSize(int maxRequestSize)
80 {
81 this.maxRequestSize = maxRequestSize;
82 }
83
84 public int getPort()
85 {
86 return port;
87 }
88
89 public void setPort(int port)
90 {
91 this.port = port;
92 }
93
94 public void setBacklog(int backlog)
95 {
96 this.backlog = backlog;
97 }
98
99 @Override
100 public void setDeployment(ResteasyDeployment deployment)
101 {
102 this.deployment = deployment;
103 }
104
105 @Override
106 public void setRootResourcePath(String rootResourcePath)
107 {
108 root = rootResourcePath;
109 if (root != null && root.equals("/")) root = "";
110 }
111
112 @Override
113 public ResteasyDeployment getDeployment()
114 {
115 return deployment;
116 }
117
118 @Override
119 public void setSecurityDomain(SecurityDomain sc)
120 {
121 this.domain = sc;
122 }
123
124 @Override
125 public void start()
126 {
127 eventLoopGroup = new NioEventLoopGroup(ioWorkerCount);
128 eventExecutor = new NioEventLoopGroup(executorThreadCount);
129 deployment.start();
130 final RequestDispatcher dispatcher = new RequestDispatcher((SynchronousDispatcher)deployment.getDispatcher(), deployment.getProviderFactory(), domain);
131 // Configure the server.
132 if (sslContext == null) {
133 bootstrap.group(eventLoopGroup)
134 .channel(NioServerSocketChannel.class)
135 .childHandler(new ChannelInitializer<SocketChannel>() {
136 @Override
137 public void initChannel(SocketChannel ch) throws Exception {
138 ch.pipeline().addLast(new HttpRequestDecoder());
139 ch.pipeline().addLast(new HttpObjectAggregator(maxRequestSize));
140 ch.pipeline().addLast(new HttpResponseEncoder());
141 ch.pipeline().addLast(new RestEasyHttpRequestDecoder(dispatcher.getDispatcher(), root, RestEasyHttpRequestDecoder.Protocol.HTTP));
142 ch.pipeline().addLast(new RestEasyHttpResponseEncoder(dispatcher));
143 ch.pipeline().addLast(eventExecutor, new RequestHandler(dispatcher));
144 }
145 })
146 .option(ChannelOption.SO_BACKLOG, backlog)
147 .childOption(ChannelOption.SO_KEEPALIVE, true);
148 } else {
149 final SSLEngine engine = sslContext.createSSLEngine();
150 engine.setUseClientMode(false);
151 bootstrap.group(eventLoopGroup)
152 .channel(NioServerSocketChannel.class)
153 .childHandler(new ChannelInitializer<SocketChannel>() {
154 @Override
155 public void initChannel(SocketChannel ch) throws Exception {
156 ch.pipeline().addFirst(new SslHandler(engine));
157 ch.pipeline().addLast(new HttpRequestDecoder());
158 ch.pipeline().addLast(new HttpObjectAggregator(maxRequestSize));
159 ch.pipeline().addLast(new HttpResponseEncoder());
160 ch.pipeline().addLast(new RestEasyHttpRequestDecoder(dispatcher.getDispatcher(), root, RestEasyHttpRequestDecoder.Protocol.HTTPS));
161 ch.pipeline().addLast(new RestEasyHttpResponseEncoder(dispatcher));
162 ch.pipeline().addLast(eventExecutor, new RequestHandler(dispatcher));
163
164 }
165 })
166 .option(ChannelOption.SO_BACKLOG, backlog)
167 .childOption(ChannelOption.SO_KEEPALIVE, true);
168 }
169
170 bootstrap.bind(port).syncUninterruptibly();
171 }
172
173 @Override
174 public void stop()
175 {
176 eventLoopGroup.shutdownGracefully();
177 eventExecutor.shutdownGracefully();
178 }
0 package org.jboss.resteasy.plugins.server.netty;
1
2 import io.netty.bootstrap.ServerBootstrap;
3 import io.netty.channel.ChannelInitializer;
4 import io.netty.channel.ChannelOption;
5 import io.netty.channel.EventLoopGroup;
6 import io.netty.channel.nio.NioEventLoopGroup;
7 import io.netty.channel.socket.SocketChannel;
8 import io.netty.channel.socket.nio.NioServerSocketChannel;
9 import io.netty.handler.codec.http.HttpObjectAggregator;
10 import io.netty.handler.codec.http.HttpRequestDecoder;
11 import io.netty.handler.codec.http.HttpResponseEncoder;
12 import io.netty.handler.ssl.SslHandler;
13 import io.netty.util.concurrent.EventExecutor;
14 import org.jboss.resteasy.core.SynchronousDispatcher;
15 import org.jboss.resteasy.plugins.server.embedded.EmbeddedJaxrsServer;
16 import org.jboss.resteasy.plugins.server.embedded.SecurityDomain;
17 import org.jboss.resteasy.spi.ResteasyDeployment;
18
19 import javax.net.ssl.SSLContext;
20 import javax.net.ssl.SSLEngine;
21
22 /**
23 * An HTTP server that sends back the content of the received HTTP request
24 * in a pretty plaintext form.
25 *
26 * @author <a href="http://www.jboss.org/netty/">The Netty Project</a>
27 * @author Andy Taylor (andy.taylor@jboss.org)
28 * @author <a href="http://gleamynode.net/">Trustin Lee</a>
29 * @author Norman Maurer
30 * @version $Rev: 2080 $, $Date: 2010-01-26 18:04:19 +0900 (Tue, 26 Jan 2010) $
31 */
32 public class NettyJaxrsServer implements EmbeddedJaxrsServer
33 {
34 protected ServerBootstrap bootstrap = new ServerBootstrap();
35 protected int port = 8080;
36 protected ResteasyDeployment deployment = new ResteasyDeployment();
37 protected String root = "";
38 protected SecurityDomain domain;
39 private EventLoopGroup eventLoopGroup;
40 private EventLoopGroup eventExecutor;
41 private int ioWorkerCount = Runtime.getRuntime().availableProcessors() * 2;
42 private int executorThreadCount = 16;
43 private SSLContext sslContext;
44 private int maxRequestSize = 1024 * 1024 * 10;
45 private int backlog = 128;
46
47 public void setSSLContext(SSLContext sslContext)
48 {
49 this.sslContext = sslContext;
50 }
51
52 /**
53 * Specify the worker count to use. For more information about this please see the javadocs of {@link EventLoopGroup}
54 *
55 * @param ioWorkerCount
56 */
57 public void setIoWorkerCount(int ioWorkerCount)
58 {
59 this.ioWorkerCount = ioWorkerCount;
60 }
61
62 /**
63 * Set the number of threads to use for the EventExecutor. For more information please see the javadocs of {@link EventExecutor}.
64 * If you want to disable the use of the {@link EventExecutor} specify a value <= 0. This should only be done if you are 100% sure that you don't have any blocking
65 * code in there.
66 *
67 * @param executorThreadCount
68 */
69 public void setExecutorThreadCount(int executorThreadCount)
70 {
71 this.executorThreadCount = executorThreadCount;
72 }
73
74 /**
75 * Set the max. request size in bytes. If this size is exceed we will send a "413 Request Entity Too Large" to the client.
76 *
77 * @param maxRequestSize the max request size. This is 10mb by default.
78 */
79 public void setMaxRequestSize(int maxRequestSize)
80 {
81 this.maxRequestSize = maxRequestSize;
82 }
83
84 public int getPort()
85 {
86 return port;
87 }
88
89 public void setPort(int port)
90 {
91 this.port = port;
92 }
93
94 public void setBacklog(int backlog)
95 {
96 this.backlog = backlog;
97 }
98
99 @Override
100 public void setDeployment(ResteasyDeployment deployment)
101 {
102 this.deployment = deployment;
103 }
104
105 @Override
106 public void setRootResourcePath(String rootResourcePath)
107 {
108 root = rootResourcePath;
109 if (root != null && root.equals("/")) root = "";
110 }
111
112 @Override
113 public ResteasyDeployment getDeployment()
114 {
115 return deployment;
116 }
117
118 @Override
119 public void setSecurityDomain(SecurityDomain sc)
120 {
121 this.domain = sc;
122 }
123
124 @Override
125 public void start()
126 {
127 eventLoopGroup = new NioEventLoopGroup(ioWorkerCount);
128 eventExecutor = new NioEventLoopGroup(executorThreadCount);
129 deployment.start();
130 final RequestDispatcher dispatcher = new RequestDispatcher((SynchronousDispatcher)deployment.getDispatcher(), deployment.getProviderFactory(), domain);
131 // Configure the server.
132 if (sslContext == null) {
133 bootstrap.group(eventLoopGroup)
134 .channel(NioServerSocketChannel.class)
135 .childHandler(new ChannelInitializer<SocketChannel>() {
136 @Override
137 public void initChannel(SocketChannel ch) throws Exception {
138 ch.pipeline().addLast(new HttpRequestDecoder());
139 ch.pipeline().addLast(new HttpObjectAggregator(maxRequestSize));
140 ch.pipeline().addLast(new HttpResponseEncoder());
141 ch.pipeline().addLast(new RestEasyHttpRequestDecoder(dispatcher.getDispatcher(), root, RestEasyHttpRequestDecoder.Protocol.HTTP));
142 ch.pipeline().addLast(new RestEasyHttpResponseEncoder(dispatcher));
143 ch.pipeline().addLast(eventExecutor, new RequestHandler(dispatcher));
144 }
145 })
146 .option(ChannelOption.SO_BACKLOG, backlog)
147 .childOption(ChannelOption.SO_KEEPALIVE, true);
148 } else {
149 final SSLEngine engine = sslContext.createSSLEngine();
150 engine.setUseClientMode(false);
151 bootstrap.group(eventLoopGroup)
152 .channel(NioServerSocketChannel.class)
153 .childHandler(new ChannelInitializer<SocketChannel>() {
154 @Override
155 public void initChannel(SocketChannel ch) throws Exception {
156 ch.pipeline().addFirst(new SslHandler(engine));
157 ch.pipeline().addLast(new HttpRequestDecoder());
158 ch.pipeline().addLast(new HttpObjectAggregator(maxRequestSize));
159 ch.pipeline().addLast(new HttpResponseEncoder());
160 ch.pipeline().addLast(new RestEasyHttpRequestDecoder(dispatcher.getDispatcher(), root, RestEasyHttpRequestDecoder.Protocol.HTTPS));
161 ch.pipeline().addLast(new RestEasyHttpResponseEncoder(dispatcher));
162 ch.pipeline().addLast(eventExecutor, new RequestHandler(dispatcher));
163
164 }
165 })
166 .option(ChannelOption.SO_BACKLOG, backlog)
167 .childOption(ChannelOption.SO_KEEPALIVE, true);
168 }
169
170 bootstrap.bind(port).syncUninterruptibly();
171 }
172
173 @Override
174 public void stop()
175 {
176 eventLoopGroup.shutdownGracefully();
177 eventExecutor.shutdownGracefully();
178 }
179179 }
7171 future = ctx.writeAndFlush(response);
7272 } else {
7373 // Write an empty response
74 future = ctx.write(response);
74 //future = ctx.write(response);
7575 // retain buffer since it was automatically
7676 // reference counted by the write operation above
77 response.retain();
77 //response.retain();
7878 }
7979 // Close the non-keep-alive connection after the write operation is done.
8080 if (!request.isKeepAlive())
5656 protected void decode(ChannelHandlerContext ctx, io.netty.handler.codec.http.HttpRequest request, List<Object> out) throws Exception
5757 {
5858 boolean keepAlive = HttpHeaders.isKeepAlive(request);
59 final NettyHttpResponse response = new NettyHttpResponse(ctx, keepAlive);
59 final NettyHttpResponse response = new NettyHttpResponse(ctx, keepAlive, dispatcher.getProviderFactory());
6060 final ResteasyHttpHeaders headers;
6161 final ResteasyUriInfo uriInfo;
6262 try
66 import io.netty.handler.codec.http.HttpHeaders.Names;
77 import io.netty.handler.codec.http.HttpHeaders.Values;
88 import io.netty.handler.codec.http.HttpResponse;
9 import org.jboss.resteasy.spi.ResteasyProviderFactory;
910
1011 import javax.ws.rs.ext.RuntimeDelegate;
1112 import java.util.List;
3839 protected void encode(ChannelHandlerContext ctx, NettyHttpResponse nettyResponse, List<Object> out) throws Exception
3940 {
4041 ByteBuf buffer = nettyResponse.getBuffer();
41 if (buffer.readableBytes() == 0) {
42 // content not written yet by the AsyncResponse
43 return;
44 }
4542 HttpResponse response = nettyResponse.getDefaultFullHttpResponse();
4643
47 for (Map.Entry<String, List<Object>> entry : nettyResponse.getOutputHeaders().entrySet())
48 {
49 String key = entry.getKey();
50 for (Object value : entry.getValue())
51 {
52 RuntimeDelegate.HeaderDelegate delegate = dispatcher.providerFactory.getHeaderDelegate(value.getClass());
53 if (delegate != null)
54 {
55 response.headers().add(key, delegate.toString(value));
56 }
57 else
58 {
59 response.headers().set(key, value.toString());
60 }
61 }
62 }
44 transformHeaders(nettyResponse, response, dispatcher.providerFactory);
6345
64 if (nettyResponse.isKeepAlive())
65 {
66 // Add content length and connection header if needed
67 response.headers().set(Names.CONTENT_LENGTH, buffer.readableBytes());
68 response.headers().set(Names.CONNECTION, Values.KEEP_ALIVE);
69 }
7046 out.add(response);
7147 }
7248
49 public static void transformHeaders(NettyHttpResponse nettyResponse, HttpResponse response, ResteasyProviderFactory factory)
50 {
51 ByteBuf buffer = nettyResponse.getBuffer();
52 if (nettyResponse.isKeepAlive())
53 {
54 // Add content length and connection header if needed
55 response.headers().set(Names.CONTENT_LENGTH, buffer.readableBytes());
56 response.headers().set(Names.CONNECTION, Values.KEEP_ALIVE);
57 }
58 for (Map.Entry<String, List<Object>> entry : nettyResponse.getOutputHeaders().entrySet())
59 {
60 String key = entry.getKey();
61 for (Object value : entry.getValue())
62 {
63 RuntimeDelegate.HeaderDelegate delegate = factory.getHeaderDelegate(value.getClass());
64 if (delegate != null)
65 {
66 response.headers().add(key, delegate.toString(value));
67 }
68 else
69 {
70 response.headers().set(key, value.toString());
71 }
72 }
73 }
74 }
75
7376 }
0 package org.jboss.resteasy.test;
1
2
3 import javax.ws.rs.ForbiddenException;
4 import javax.ws.rs.GET;
5 import javax.ws.rs.PUT;
6 import javax.ws.rs.Path;
7 import javax.ws.rs.PathParam;
8 import javax.ws.rs.Produces;
9 import javax.ws.rs.container.AsyncResponse;
10 import javax.ws.rs.container.Suspended;
11 import javax.ws.rs.core.MediaType;
12 import javax.ws.rs.core.Response;
13 import java.util.concurrent.CountDownLatch;
14 import java.util.concurrent.TimeUnit;
15
16 /**
17 * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
18 * @version $Revision: 1 $
19 */
20 @Path("/jaxrs")
21 public class AsyncJaxrsResource
22 {
23 protected boolean cancelled;
24
25 @GET
26 @Path("resume/object")
27 @Produces("application/xml")
28 public void resumeObject(@Suspended final AsyncResponse response) {
29 response.resume(new XmlData("bill"));
30 }
31
32 @GET
33 @Path("resume/object/thread")
34 @Produces("application/xml")
35 public void resumeObjectThread(@Suspended final AsyncResponse response) throws Exception
36 {
37 Thread t = new Thread()
38 {
39 @Override
40 public void run()
41 {
42 response.resume(new XmlData("bill"));
43 }
44 };
45 t.start();
46 }
47
48
49
50 @GET
51 @Path("injection-failure/{param}")
52 public void injectionFailure(@Suspended final AsyncResponse response, @PathParam("param") int id) {
53 System.out.println("injectionFailure: " + id);
54 throw new ForbiddenException("Should be unreachable");
55 }
56
57 @GET
58 @Path("method-failure")
59 public void injectionFailure(@Suspended final AsyncResponse response) {
60 throw new ForbiddenException("Should be unreachable");
61 }
62
63
64
65 @GET
66 @Path("cancelled")
67 public Response getCancelled()
68 {
69 System.out.println("getCancelled called!");
70 if (cancelled) return Response.noContent().build();
71 else return Response.status(500).build();
72 }
73
74 @PUT
75 @Path("cancelled")
76 public void resetCancelled()
77 {
78 cancelled = false;
79
80 }
81
82 @GET
83 @Produces("text/plain")
84 public void get(@Suspended final AsyncResponse response) throws Exception
85 {
86 response.setTimeout(200000, TimeUnit.MILLISECONDS);
87 Thread t = new Thread()
88 {
89 @Override
90 public void run()
91 {
92 try
93 {
94 System.out.println("STARTED!!!!");
95 Thread.sleep(100);
96 Response jaxrs = Response.ok("hello").type(MediaType.TEXT_PLAIN).build();
97 response.resume(jaxrs);
98 }
99 catch (Exception e)
100 {
101 e.printStackTrace();
102 }
103 }
104 };
105 t.start();
106 }
107
108 @GET
109 @Path("empty")
110 @Produces("text/plain")
111 public void getEmpty(@Suspended final AsyncResponse response) throws Exception
112 {
113 response.setTimeout(200000, TimeUnit.MILLISECONDS);
114 Thread t = new Thread()
115 {
116 @Override
117 public void run()
118 {
119 try
120 {
121 System.out.println("STARTED Empty!!!!");
122 Thread.sleep(100);
123 response.resume(Response.noContent().build());
124 }
125 catch (Exception e)
126 {
127 e.printStackTrace();
128 }
129 }
130 };
131 t.start();
132 }
133
134
135 @GET
136 @Path("timeout")
137 @Produces("text/plain")
138 public void timeout(@Suspended final AsyncResponse response)
139 {
140 response.setTimeout(10, TimeUnit.MILLISECONDS);
141 Thread t = new Thread()
142 {
143 @Override
144 public void run()
145 {
146 try
147 {
148 System.out.println("STARTED!!!!");
149 Thread.sleep(100000);
150 Response jaxrs = Response.ok("goodbye").type(MediaType.TEXT_PLAIN).build();
151 response.resume(jaxrs);
152 }
153 catch (Exception e)
154 {
155 e.printStackTrace();
156 }
157 }
158 };
159 t.start();
160 }
161
162
163 @GET
164 @Path("cancel")
165 @Produces("text/plain")
166 public void cancel(@Suspended final AsyncResponse response) throws Exception
167 {
168 response.setTimeout(10000, TimeUnit.MILLISECONDS);
169 final CountDownLatch sync = new CountDownLatch(1);
170 final CountDownLatch ready = new CountDownLatch(1);
171 Thread t = new Thread()
172 {
173 @Override
174 public void run()
175 {
176 try
177 {
178 sync.countDown();
179 System.out.println("cancel awaiting thread");
180 ready.await();
181 System.out.println("cancel resuming");
182 Response jaxrs = Response.ok("hello").type(MediaType.TEXT_PLAIN).build();
183 cancelled = !response.resume(jaxrs);
184 }
185 catch (Exception e)
186 {
187 e.printStackTrace();
188 }
189 }
190 };
191 t.start();
192
193 sync.await();
194 System.out.println("Cancelling...");
195 response.cancel();
196 ready.countDown();
197 }
198
199 }
0 package org.jboss.resteasy.test;
1
2 import org.junit.AfterClass;
3 import org.junit.Assert;
4 import org.junit.BeforeClass;
5 import org.junit.Test;
6
7 import javax.ws.rs.ForbiddenException;
8 import javax.ws.rs.NotFoundException;
9 import javax.ws.rs.client.Client;
10 import javax.ws.rs.client.ClientBuilder;
11 import javax.ws.rs.core.Response;
12
13 import static org.jboss.resteasy.test.TestPortProvider.generateURL;
14
15 /**
16 * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
17 * @version $Revision: 1 $
18 */
19 public class JaxrsAsyncTest
20 {
21 static String BASE_URI = generateURL("");
22 static Client client;
23
24 @BeforeClass
25 public static void setup() throws Exception
26 {
27 NettyContainer.start().getRegistry().addSingletonResource(new AsyncJaxrsResource());
28 client = ClientBuilder.newClient();
29 }
30
31 @AfterClass
32 public static void end() throws Exception
33 {
34 client.close();
35 NettyContainer.stop();
36 }
37
38 @Test
39 public void testInjectionFailure() throws Exception
40 {
41 System.out.println("***INJECTION FAILURE***");
42 long start = System.currentTimeMillis();
43 Client client = ClientBuilder.newClient();
44 Response response = client.target(BASE_URI).path("jaxrs/injection-failure/abcd").request().get();
45 Assert.assertEquals(Response.Status.NOT_FOUND.getStatusCode(), response.getStatus());
46 long end = System.currentTimeMillis() - start;
47 Assert.assertTrue(end < 1000); // should take less than 1 second
48 response.close();
49 client.close();
50 }
51
52 @Test
53 public void testMethodFailure() throws Exception
54 {
55 System.out.println("***method FAILURE***");
56 long start = System.currentTimeMillis();
57 Client client = ClientBuilder.newClient();
58 Response response = client.target(BASE_URI).path("jaxrs/method-failure").request().get();
59 Assert.assertEquals(Response.Status.FORBIDDEN.getStatusCode(), response.getStatus());
60 long end = System.currentTimeMillis() - start;
61 Assert.assertTrue(end < 1000); // should take less than 1 second
62 response.close();
63 client.close();
64 }
65
66
67
68 @Test
69 public void testAsync() throws Exception
70 {
71 Client client = ClientBuilder.newClient();
72 callAsync(client);
73 callAsync(client);
74 callAsync(client);
75 client.close();
76 }
77
78 private void callAsync(Client client)
79 {
80 long start = System.currentTimeMillis();
81 Response response = client.target(BASE_URI).path("jaxrs").request().get();
82 long end = System.currentTimeMillis() - start;
83 Assert.assertEquals(200, response.getStatus());
84 System.out.println(response.getHeaders().size());
85 System.out.println(response.getHeaders().keySet().iterator().next());
86 Assert.assertEquals("hello", response.readEntity(String.class));
87 Assert.assertTrue(end < 1000); // should take less than 1 second
88 response.close();
89 }
90
91 @Test
92 public void testEmpty() throws Exception
93 {
94 Client client = ClientBuilder.newClient();
95 callEmpty(client);
96 callEmpty(client);
97 callEmpty(client);
98 client.close();
99 }
100
101 private void callEmpty(Client client)
102 {
103 long start = System.currentTimeMillis();
104 Response response = client.target(BASE_URI).path("jaxrs/empty").request().get();
105 long end = System.currentTimeMillis() - start;
106 Assert.assertEquals(204, response.getStatus());
107 Assert.assertTrue(end < 1000); // should take less than 1 second
108 response.close();
109 }
110
111
112 @Test
113 public void testTimeout() throws Exception
114 {
115 Client client = ClientBuilder.newClient();
116 Response response = client.target(BASE_URI).path("jaxrs/timeout").request().get();
117 Assert.assertEquals(503, response.getStatus());
118 response.close();
119 client.close();
120 }
121
122 @Test
123 public void testCancelled() throws Exception
124 {
125 Client client = ClientBuilder.newClient();
126 Response response = null;
127 System.out.println("calling cancelled");
128 response = client.target(BASE_URI).path("jaxrs/cancelled").request().put(null);
129 Assert.assertEquals(204, response.getStatus());
130 response.close();
131 response = client.target(BASE_URI).path("jaxrs/cancelled").request().get();
132 System.out.println("returned from calling cancelled");
133 Assert.assertEquals(500, response.getStatus());
134 System.out.println("done");
135
136 response.close();
137 client.close();
138 }
139
140
141 @Test
142 public void testCancel() throws Exception
143 {
144 Client client = ClientBuilder.newClient();
145 Response response = null;
146 System.out.println("calling cancelled");
147 response = client.target(BASE_URI).path("jaxrs/cancelled").request().put(null);
148 Assert.assertEquals(204, response.getStatus());
149 response.close();
150 response = client.target(BASE_URI).path("jaxrs/cancelled").request().get();
151 System.out.println("returned from calling cancelled");
152 Assert.assertEquals(500, response.getStatus());
153 System.out.println("done");
154 response.close();
155
156 System.out.println("calling cancel");
157 response = client.target(BASE_URI).path("jaxrs/cancel").request().get();
158 System.out.println("got response");
159 Assert.assertEquals(503, response.getStatus());
160 response.close();
161 System.out.println("calling cancelled");
162 response = client.target(BASE_URI).path("jaxrs/cancelled").request().get();
163 System.out.println("returned from calling cancelled");
164 Assert.assertEquals(204, response.getStatus());
165 System.out.println("done");
166
167 response.close();
168 client.close();
169 }
170
171 @Test
172 public void testResumeObject() throws Exception
173 {
174 Client client = ClientBuilder.newClient();
175 long start = System.currentTimeMillis();
176 Response response = client.target(BASE_URI).path("jaxrs/resume/object").request().get();
177 long end = System.currentTimeMillis() - start;
178 Assert.assertEquals(200, response.getStatus());
179 Assert.assertEquals("bill", response.readEntity(XmlData.class).getName());
180 Assert.assertTrue(end < 1000); // should take less than 1 second
181 response.close();
182 client.close();
183 }
184
185 @Test
186 public void testResumeObjectThread() throws Exception
187 {
188 Client client = ClientBuilder.newClient();
189 long start = System.currentTimeMillis();
190 Response response = client.target(BASE_URI).path("jaxrs/resume/object/thread").request().get();
191 long end = System.currentTimeMillis() - start;
192 Assert.assertEquals(200, response.getStatus());
193 Assert.assertEquals("bill", response.readEntity(XmlData.class).getName());
194 Assert.assertTrue(end < 1000); // should take less than 1 second
195 response.close();
196 client.close();
197 }
198
199
200 }
0 package org.jboss.resteasy.test;
1
2 import org.jboss.resteasy.client.jaxrs.ResteasyClient;
3 import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
4 import org.jboss.resteasy.client.jaxrs.ResteasyWebTarget;
5 import org.junit.AfterClass;
6 import org.junit.Assert;
7 import org.junit.BeforeClass;
8 import org.junit.Test;
9
10 import javax.ws.rs.GET;
11 import javax.ws.rs.Path;
12 import javax.ws.rs.Produces;
13
14 import static org.jboss.resteasy.test.TestPortProvider.generateURL;
15
16 /**
17 * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
18 * @version $Revision: 1 $
19 */
20 public class NettyTest
21 {
22 @Path("/test")
23 public static class Resource
24 {
25 @GET
26 @Produces("text/plain")
27 public String hello()
28 {
29 return "hello world";
30 }
31
32
33 }
34
35 @BeforeClass
36 public static void setup() throws Exception
37 {
38 NettyContainer.start().getRegistry().addPerRequestResource(Resource.class);
39 }
40
41 @AfterClass
42 public static void end() throws Exception
43 {
44 NettyContainer.stop();
45 }
46
47 @Test
48 public void testBasic() throws Exception
49 {
50 ResteasyClient client = new ResteasyClientBuilder().build();
51 ResteasyWebTarget target = client.target(generateURL("/test"));
52 String val = target.request().get(String.class);
53 Assert.assertEquals(val, "hello world");
54 }
55 }
0 package org.jboss.resteasy.test;
1
2 import javax.xml.bind.annotation.XmlRootElement;
3
4 /**
5 * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
6 * @version $Revision: 1 $
7 */
8 @XmlRootElement(name = "data")
9 public class XmlData
10 {
11 protected String name;
12
13 public XmlData(String data)
14 {
15 this.name = data;
16 }
17
18 public XmlData()
19 {
20 }
21
22 public String getName()
23 {
24 return name;
25 }
26
27 public void setName(String name)
28 {
29 this.name = name;
30 }
31
32
33 }