Working version of Servlet 3.1 <-> RS bridge.

This commit is contained in:
Arjen Poutsma
2015-07-07 12:18:52 +02:00
parent 3b45087c87
commit f518d76a77
22 changed files with 997 additions and 316 deletions

View File

@@ -22,6 +22,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
import org.junit.Before;
import org.junit.Test;
import org.reactivestreams.Publisher;
import org.reactivestreams.Subscriber;
import org.reactivestreams.Subscription;
@@ -34,12 +35,12 @@ public class BlockingByteBufQueuePublisherTests {
private BlockingSignalQueue<byte[]> queue;
private BlockingSignalQueuePublisher<byte[]> publisher;
private Publisher<byte[]> publisher;
@Before
public void setUp() throws Exception {
queue = new BlockingSignalQueue<byte[]>();
publisher = new BlockingSignalQueuePublisher<byte[]>(queue);
publisher = queue.publisher();
}
@Test

View File

@@ -0,0 +1,96 @@
/*
* Copyright 2002-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.rx.web.servlet;
import java.net.URI;
import java.util.Random;
import org.junit.Test;
import org.springframework.http.HttpMethod;
import org.springframework.http.RequestEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.util.SocketUtils;
import org.springframework.web.client.RestTemplate;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
public abstract class AbstractHttpHandlerServletIntegrationTestCase {
private static final int REQUEST_SIZE = 4096 * 3;
protected static int port = SocketUtils.findAvailableTcpPort();
private Random rnd = new Random();
@Test
public void bytes() throws Exception {
RestTemplate restTemplate = new RestTemplate();
byte[] body = randomBytes();
RequestEntity<byte[]>
request = new RequestEntity<byte[]>(body, HttpMethod.POST, new URI(url()));
ResponseEntity<byte[]> response = restTemplate.exchange(request, byte[].class);
assertArrayEquals(body, response.getBody());
}
@Test
public void string() throws Exception {
RestTemplate restTemplate = new RestTemplate();
String body = randomString();
RequestEntity<String> request = new RequestEntity<String>(body, HttpMethod.POST, new URI(url()));
ResponseEntity<String> response = restTemplate.exchange(request, String.class);
assertEquals(body, response.getBody());
}
private static String url() {
return "http://localhost:" + port + "/rx";
}
private String randomString() {
StringBuilder builder = new StringBuilder();
int i = 1;
while (builder.length() < REQUEST_SIZE) {
builder.append(randomChar());
if (i % 5 == 0) {
builder.append(' ');
}
if (i % 80 == 0) {
builder.append('\n');
}
i++;
}
return builder.toString();
}
private char randomChar() {
return (char) (rnd.nextInt(26) + 'a');
}
private byte[] randomBytes() {
byte[] buffer = new byte[REQUEST_SIZE];
rnd.nextBytes(buffer);
return buffer;
}
}

View File

@@ -0,0 +1,64 @@
/*
* Copyright 2002-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.rx.web.servlet;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.reactivestreams.Publisher;
import org.reactivestreams.Subscriber;
import org.reactivestreams.Subscription;
/**
* @author Arjen Poutsma
*/
public class CountingHttpHandler implements HttpHandler {
private static final Log logger = LogFactory.getLog(CountingHttpHandler.class);
@Override
public Publisher<byte[]> handle(Publisher<byte[]> request) {
request.subscribe(new Subscriber<byte[]>() {
private Subscription subscription;
private int byteCount = 0;
@Override
public void onSubscribe(Subscription s) {
this.subscription = s;
this.subscription.request(1);
}
@Override
public void onNext(byte[] bytes) {
byteCount += bytes.length;
this.subscription.request(1);
}
@Override
public void onError(Throwable t) {
logger.error("CountingHttpHandler Error", t);
t.printStackTrace();
}
@Override
public void onComplete() {
logger.info("Processed " + byteCount + " bytes");
}
});
return null;
}
}

View File

@@ -0,0 +1,30 @@
/*
* Copyright 2002-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.rx.web.servlet;
import org.reactivestreams.Publisher;
/**
* @author Arjen Poutsma
*/
public class EchoHandler implements HttpHandler {
@Override
public Publisher<byte[]> handle(Publisher<byte[]> request) {
return request;
}
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright 2002-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.rx.web.servlet;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.springframework.util.SocketUtils;
/**
* @author Arjen Poutsma
*/
public class HttpHandlerServletJettyIntegrationTests
extends AbstractHttpHandlerServletIntegrationTestCase {
private static Server jettyServer;
@BeforeClass
public static void startServer() throws Exception {
jettyServer = new Server();
ServerConnector connector = new ServerConnector(jettyServer);
port = SocketUtils.findAvailableTcpPort();
connector.setPort(port);
ServletContextHandler handler = new ServletContextHandler(jettyServer, "", false, false);
HttpHandlerServlet servlet = new HttpHandlerServlet();
servlet.setHandler(new EchoHandler());
ServletHolder servletHolder = new ServletHolder(servlet);
handler.addServlet(servletHolder, "/rx");
jettyServer.addConnector(connector);
jettyServer.start();
}
@AfterClass
public static void stopServer() throws Exception {
jettyServer.stop();
}
}

View File

@@ -0,0 +1,55 @@
/*
* Copyright 2002-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.rx.web.servlet;
import java.io.File;
import org.apache.catalina.Context;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.startup.Tomcat;
import org.junit.AfterClass;
import org.junit.BeforeClass;
/**
* @author Arjen Poutsma
*/
public class HttpHandlerServletTomcatIntegrationTests extends AbstractHttpHandlerServletIntegrationTestCase {
private static Tomcat tomcatServer;
@BeforeClass
public static void startServer() throws LifecycleException, InterruptedException {
tomcatServer = new Tomcat();
tomcatServer.setPort(port);
File base = new File(System.getProperty("java.io.tmpdir"));
Context rootCtx = tomcatServer.addContext("", base.getAbsolutePath());
HttpHandlerServlet servlet = new HttpHandlerServlet();
servlet.setHandler(new EchoHandler());
tomcatServer.addServlet(rootCtx, "handlerServlet", servlet);
rootCtx.addServletMapping("/rx", "handlerServlet");
tomcatServer.start();
}
@AfterClass
public static void stopServer() throws LifecycleException {
tomcatServer.stop();
}
}