diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java index 3106b35ebf6..47ef43acf46 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java @@ -611,7 +611,7 @@ public class HttpChannel implements HttpParser.RequestHandler, Runnable { if (isCommitted()) { - _transport.send(content, complete); + _transport.send(null, content, complete); } else { diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelState.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelState.java index 2852fd363c9..ed91b7253cc 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelState.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelState.java @@ -619,7 +619,7 @@ public class HttpChannelState implements AsyncContext protected void scheduleTimeout() { Scheduler scheduler = _channel.getScheduler(); - if (scheduler!=null) + if (scheduler!=null && _timeoutMs>0) _event._timeout=scheduler.schedule(new AsyncTimeout(),_timeoutMs,TimeUnit.MILLISECONDS); } diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnection.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnection.java index 6bf838a0ac0..d002781abf6 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnection.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnection.java @@ -21,9 +21,7 @@ package org.eclipse.jetty.server; import java.io.IOException; import java.io.InterruptedIOException; import java.nio.ByteBuffer; -import java.util.concurrent.ExecutionException; import java.util.concurrent.RejectedExecutionException; -import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import org.eclipse.jetty.http.HttpGenerator; @@ -32,6 +30,7 @@ import org.eclipse.jetty.http.HttpHeaderValue; import org.eclipse.jetty.http.HttpParser; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpVersion; +import org.eclipse.jetty.http.HttpGenerator.ResponseInfo; import org.eclipse.jetty.io.AbstractConnection; import org.eclipse.jetty.io.ByteBufferPool; import org.eclipse.jetty.io.Connection; @@ -39,7 +38,7 @@ import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.io.EofException; import org.eclipse.jetty.util.BlockingCallback; import org.eclipse.jetty.util.BufferUtil; -import org.eclipse.jetty.util.FutureCallback; +import org.eclipse.jetty.util.Callback; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; @@ -322,8 +321,6 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http @Override public void send(HttpGenerator.ResponseInfo info, ByteBuffer content, boolean lastContent) throws IOException { - // TODO This is always blocking! One of the important use-cases is to be able to write large static content without a thread - // If we are still expecting a 100 continues if (_channel.isExpecting100Continue()) // then we can't be persistent @@ -413,11 +410,19 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http } } } - + @Override - public void send(ByteBuffer content, boolean lastContent) throws IOException + public void send(ResponseInfo info, ByteBuffer content, boolean lastContent, C context, Callback callback) { - send(null, content, lastContent); + try + { + send(info,content,lastContent); + callback.completed(context); + } + catch (IOException e) + { + callback.failed(context,e); + } } private void blockingWrite(ByteBuffer... bytes) throws IOException diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpTransport.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpTransport.java index 98b021cac65..21b4c30e654 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpTransport.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpTransport.java @@ -22,12 +22,13 @@ import java.io.IOException; import java.nio.ByteBuffer; import org.eclipse.jetty.http.HttpGenerator; +import org.eclipse.jetty.util.Callback; public interface HttpTransport { void send(HttpGenerator.ResponseInfo info, ByteBuffer content, boolean lastContent) throws IOException; - void send(ByteBuffer content, boolean lastContent) throws IOException; - + void send(HttpGenerator.ResponseInfo info, ByteBuffer content, boolean lastContent, C context, Callback callback); + void completed(); } diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/ResponseTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/ResponseTest.java index 2c791abbcb2..c83f1623483 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/ResponseTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/ResponseTest.java @@ -42,6 +42,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.http.HttpGenerator; +import org.eclipse.jetty.http.HttpGenerator.ResponseInfo; import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpURI; import org.eclipse.jetty.io.AbstractEndPoint; @@ -51,6 +52,7 @@ import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.server.session.HashSessionIdManager; import org.eclipse.jetty.server.session.HashSessionManager; import org.eclipse.jetty.server.session.HashedSession; +import org.eclipse.jetty.util.Callback; import org.eclipse.jetty.util.thread.Scheduler; import org.eclipse.jetty.util.thread.TimerScheduler; import org.hamcrest.Matchers; @@ -84,9 +86,9 @@ public class ResponseTest public void send(HttpGenerator.ResponseInfo info, ByteBuffer content, boolean lastContent) throws IOException { } - + @Override - public void send(ByteBuffer content, boolean lastContent) throws IOException + public void send(ResponseInfo info, ByteBuffer content, boolean lastContent, C context, Callback callback) { } @@ -94,6 +96,7 @@ public class ResponseTest public void completed() { } + }, input); } diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardStream.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardStream.java index bd6eaf5bc20..42b6b07c16b 100644 --- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardStream.java +++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardStream.java @@ -359,12 +359,12 @@ public class StandardStream implements IStream public Future data(DataInfo dataInfo) { FutureCallback fcb = new FutureCallback<>(); - data(dataInfo,0,TimeUnit.MILLISECONDS,fcb); + data(dataInfo,0,TimeUnit.MILLISECONDS,null,fcb); return fcb; } @Override - public void data(DataInfo dataInfo, long timeout, TimeUnit unit, Callback callback) + public void data(DataInfo dataInfo, long timeout, TimeUnit unit, C context, Callback callback) { if (!canSend()) { @@ -379,15 +379,15 @@ public class StandardStream implements IStream // Cannot update the close state here, because the data that we send may // be flow controlled, so we need the stream to update the window size. - session.data(this, dataInfo, timeout, unit, callback, null); + session.data(this, dataInfo, timeout, unit, callback, context); } @Override public Future headers(HeadersInfo headersInfo) { - Promise result = new Promise<>(); - headers(headersInfo,0,TimeUnit.MILLISECONDS,result); - return result; + FutureCallback fcb = new FutureCallback<>(); + headers(headersInfo,0,TimeUnit.MILLISECONDS,fcb); + return fcb; } @Override diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/Stream.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/Stream.java index a18ee2f07d6..4a6ec470ae7 100644 --- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/Stream.java +++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/Stream.java @@ -158,10 +158,11 @@ public interface Stream * @param dataInfo the metadata to send * @param timeout the operation's timeout * @param unit the timeout's unit + * @param context the context passed to the callback * @param callback the completion callback that gets notified of data sent * @see #data(DataInfo) */ - public void data(DataInfo dataInfo, long timeout, TimeUnit unit, Callback callback); + public void data(DataInfo dataInfo, long timeout, TimeUnit unit, C context, Callback callback); /** *

Sends asynchronously a HEADER frame on this stream.

diff --git a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/AsyncTimeoutTest.java b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/AsyncTimeoutTest.java index 68af230723d..89e4950b016 100644 --- a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/AsyncTimeoutTest.java +++ b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/AsyncTimeoutTest.java @@ -125,7 +125,7 @@ public class AsyncTimeoutTest Stream stream = session.syn(new SynInfo(false), null).get(5, TimeUnit.SECONDS); final CountDownLatch failedLatch = new CountDownLatch(1); - stream.data(new StringDataInfo("data", true), timeout, unit, new Callback.Empty() + stream.data(new StringDataInfo("data", true), timeout, unit, null,new Callback.Empty() { @Override public void failed(Void context, Throwable x) diff --git a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/StandardSessionTest.java b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/StandardSessionTest.java index a2715d97c51..16c7af67e64 100644 --- a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/StandardSessionTest.java +++ b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/StandardSessionTest.java @@ -430,9 +430,9 @@ public class StandardSessionTest }; // first data frame should fail on controller.write() - stream.data(new StringDataInfo("data", false), 5, TimeUnit.SECONDS, callback); + stream.data(new StringDataInfo("data", false), 5, TimeUnit.SECONDS, null,callback); // second data frame should fail without controller.writer() as the connection is expected to be broken after first controller.write() call failed. - stream.data(new StringDataInfo("data", false), 5, TimeUnit.SECONDS, callback); + stream.data(new StringDataInfo("data", false), 5, TimeUnit.SECONDS, null,callback); verify(controller, times(1)).write(any(ByteBuffer.class), any(Callback.class), any(FrameBytes.class)); assertThat("Callback.failed has been called twice", failedCalledLatch.await(5, TimeUnit.SECONDS), is(true)); diff --git a/jetty-spdy/spdy-http-server/src/main/java/org/eclipse/jetty/spdy/server/http/HttpTransportOverSPDY.java b/jetty-spdy/spdy-http-server/src/main/java/org/eclipse/jetty/spdy/server/http/HttpTransportOverSPDY.java index dff8ea68127..8ff2f2f2a9d 100644 --- a/jetty-spdy/spdy-http-server/src/main/java/org/eclipse/jetty/spdy/server/http/HttpTransportOverSPDY.java +++ b/jetty-spdy/spdy-http-server/src/main/java/org/eclipse/jetty/spdy/server/http/HttpTransportOverSPDY.java @@ -21,9 +21,8 @@ package org.eclipse.jetty.spdy.server.http; import java.io.IOException; import java.nio.ByteBuffer; import java.util.Set; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpGenerator; @@ -31,7 +30,6 @@ import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.io.EofException; -import org.eclipse.jetty.io.RuntimeIOException; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.HttpChannelConfig; import org.eclipse.jetty.server.HttpTransport; @@ -40,10 +38,10 @@ import org.eclipse.jetty.spdy.api.ReplyInfo; import org.eclipse.jetty.spdy.api.SPDY; import org.eclipse.jetty.spdy.api.Stream; import org.eclipse.jetty.spdy.api.SynInfo; +import org.eclipse.jetty.util.BlockingCallback; import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.Callback; import org.eclipse.jetty.util.Fields; -import org.eclipse.jetty.util.FutureCallback; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; @@ -57,6 +55,7 @@ public class HttpTransportOverSPDY implements HttpTransport private final PushStrategy pushStrategy; private final Stream stream; private final Fields requestHeaders; + private final BlockingCallback streamBlocker = new BlockingCallback(); public HttpTransportOverSPDY(Connector connector, HttpChannelConfig configuration, EndPoint endPoint, PushStrategy pushStrategy, Stream stream, Fields requestHeaders) { @@ -68,73 +67,65 @@ public class HttpTransportOverSPDY implements HttpTransport this.requestHeaders = requestHeaders; } + @Override + public void send(HttpGenerator.ResponseInfo info, ByteBuffer content, boolean lastContent, C context, Callback callback) + { + boolean hasContent = !BufferUtil.isEmpty(content); + + if (info!=null) + { + short version = stream.getSession().getVersion(); + Fields headers = new Fields(); + + HttpVersion httpVersion = HttpVersion.HTTP_1_1; + headers.put(HTTPSPDYHeader.VERSION.name(version), httpVersion.asString()); + + int status = info.getStatus(); + StringBuilder httpStatus = new StringBuilder().append(status); + String reason = info.getReason(); + if (reason == null) + reason = HttpStatus.getMessage(status); + if (reason != null) + httpStatus.append(" ").append(reason); + headers.put(HTTPSPDYHeader.STATUS.name(version), httpStatus.toString()); + LOG.debug("HTTP < {} {}", httpVersion, httpStatus); + + // TODO merge the two Field classes into one + HttpFields fields = info.getHttpFields(); + if (fields != null) + { + for (int i = 0; i < fields.size(); ++i) + { + HttpFields.Field field = fields.getField(i); + String name = field.getName(); + String value = field.getValue(); + headers.put(name, value); + LOG.debug("HTTP < {}: {}", name, value); + } + } + + boolean close = !hasContent && lastContent; + reply(stream, new ReplyInfo(headers, close)); + } + + if ((hasContent || lastContent ) && !stream.isClosed() ) + stream.data(new ByteBufferDataInfo(content, lastContent),endPoint.getIdleTimeout(),TimeUnit.MILLISECONDS,context,callback); + else + callback.completed(context); + + } + @Override public void send(HttpGenerator.ResponseInfo info, ByteBuffer content, boolean lastContent) throws IOException { - short version = stream.getSession().getVersion(); - Fields headers = new Fields(); - - HttpVersion httpVersion = HttpVersion.HTTP_1_1; - headers.put(HTTPSPDYHeader.VERSION.name(version), httpVersion.asString()); - - int status = info.getStatus(); - StringBuilder httpStatus = new StringBuilder().append(status); - String reason = info.getReason(); - if (reason == null) - reason = HttpStatus.getMessage(status); - if (reason != null) - httpStatus.append(" ").append(reason); - headers.put(HTTPSPDYHeader.STATUS.name(version), httpStatus.toString()); - LOG.debug("HTTP < {} {}", httpVersion, httpStatus); - - // TODO merge the two Field classes into one - HttpFields fields = info.getHttpFields(); - if (fields != null) - { - for (int i = 0; i < fields.size(); ++i) - { - HttpFields.Field field = fields.getField(i); - String name = field.getName(); - String value = field.getValue(); - headers.put(name, value); - LOG.debug("HTTP < {}: {}", name, value); - } - } - - boolean hasContent = !BufferUtil.isEmpty(content); - boolean close = !hasContent && lastContent; - reply(stream, new ReplyInfo(headers, close)); - - if (hasContent) - sendToStream(content, lastContent); - } - - @Override - public void send(ByteBuffer content, boolean lastContent) throws IOException - { - // Guard against a last 0 bytes write - // TODO work out if we can avoid double calls for lastContent==true - if (stream.isClosed() && BufferUtil.isEmpty(content) && lastContent) - return; - - sendToStream(content, lastContent); - } - - private void sendToStream(ByteBuffer content, boolean lastContent) throws IOException - { - FutureCallback future = new FutureCallback<>(); - - stream.data(new ByteBufferDataInfo(content, lastContent),endPoint.getIdleTimeout(),TimeUnit.MILLISECONDS,future); - + send(info,content,lastContent,streamBlocker.getPhase(),streamBlocker); try { - future.get(); + streamBlocker.block(); } - catch (ExecutionException e) + catch (IOException e) { - LOG.debug(e); - Throwable cause=e.getCause(); - throw new EofException(cause); + throw e; } catch (Exception e) { @@ -142,6 +133,7 @@ public class HttpTransportOverSPDY implements HttpTransport } } + @Override public void completed() { diff --git a/jetty-spdy/spdy-http-server/src/main/java/org/eclipse/jetty/spdy/server/proxy/ProxyHTTPSPDYConnection.java b/jetty-spdy/spdy-http-server/src/main/java/org/eclipse/jetty/spdy/server/proxy/ProxyHTTPSPDYConnection.java index 817e437e115..77801484d1f 100644 --- a/jetty-spdy/spdy-http-server/src/main/java/org/eclipse/jetty/spdy/server/proxy/ProxyHTTPSPDYConnection.java +++ b/jetty-spdy/spdy-http-server/src/main/java/org/eclipse/jetty/spdy/server/proxy/ProxyHTTPSPDYConnection.java @@ -286,23 +286,23 @@ public class ProxyHTTPSPDYConnection extends HttpConnection implements HttpParse } @Override - public void data(DataInfo dataInfo, long timeout, TimeUnit unit, Callback handler) + public void data(DataInfo dataInfo, long timeout, TimeUnit unit, C context, Callback handler) { try { // Data buffer must be copied, as the ByteBuffer is pooled ByteBuffer byteBuffer = dataInfo.asByteBuffer(false); - send(byteBuffer, dataInfo.isClose()); + send(null, byteBuffer, dataInfo.isClose()); if (dataInfo.isClose()) completed(); - handler.completed(null); + handler.completed(context); } catch (IOException x) { - handler.failed(null, x); + handler.failed(context, x); } } } @@ -322,10 +322,10 @@ public class ProxyHTTPSPDYConnection extends HttpConnection implements HttpParse } @Override - public void data(DataInfo dataInfo, long timeout, TimeUnit unit, Callback handler) + public void data(DataInfo dataInfo, long timeout, TimeUnit unit, C context, Callback handler) { // Ignore pushed data - handler.completed(null); + handler.completed(context); } } } diff --git a/jetty-spdy/spdy-http-server/src/main/java/org/eclipse/jetty/spdy/server/proxy/SPDYProxyEngine.java b/jetty-spdy/spdy-http-server/src/main/java/org/eclipse/jetty/spdy/server/proxy/SPDYProxyEngine.java index d0f5bf37a54..8a51505a167 100644 --- a/jetty-spdy/spdy-http-server/src/main/java/org/eclipse/jetty/spdy/server/proxy/SPDYProxyEngine.java +++ b/jetty-spdy/spdy-http-server/src/main/java/org/eclipse/jetty/spdy/server/proxy/SPDYProxyEngine.java @@ -277,7 +277,7 @@ public class SPDYProxyEngine extends ProxyEngine implements StreamFrameListener private void data(final Stream stream, final DataInfo dataInfo) { - clientStream.data(dataInfo, getTimeout(), TimeUnit.MILLISECONDS, new Callback() + clientStream.data(dataInfo, getTimeout(), TimeUnit.MILLISECONDS, null,new Callback() { @Override public void completed(Void context) @@ -393,7 +393,7 @@ public class SPDYProxyEngine extends ProxyEngine implements StreamFrameListener private void flush(Stream serverStream, DataInfoHandler dataInfoHandler) { logger.debug("P -> S {} on {}", dataInfoHandler.dataInfo, serverStream); - serverStream.data(dataInfoHandler.dataInfo, getTimeout(), TimeUnit.MILLISECONDS, dataInfoHandler); + serverStream.data(dataInfoHandler.dataInfo, getTimeout(), TimeUnit.MILLISECONDS, null,dataInfoHandler); } private class DataInfoHandler implements Callback diff --git a/jetty-spdy/spdy-server/src/test/java/org/eclipse/jetty/spdy/server/ResetStreamTest.java b/jetty-spdy/spdy-server/src/test/java/org/eclipse/jetty/spdy/server/ResetStreamTest.java index a7fb8fef134..302b5549d75 100644 --- a/jetty-spdy/spdy-server/src/test/java/org/eclipse/jetty/spdy/server/ResetStreamTest.java +++ b/jetty-spdy/spdy-server/src/test/java/org/eclipse/jetty/spdy/server/ResetStreamTest.java @@ -134,7 +134,7 @@ public class ResetStreamTest extends AbstractTest }); Stream stream = session.syn(new SynInfo(false),null).get(5,TimeUnit.SECONDS); - stream.data(new StringDataInfo("data",true),5,TimeUnit.SECONDS,new Callback.Empty() + stream.data(new StringDataInfo("data",true),5,TimeUnit.SECONDS,null,new Callback.Empty() { @Override public void completed(Void context) @@ -182,9 +182,9 @@ public class ResetStreamTest extends AbstractTest Stream stream = session.syn(new SynInfo(false),null).get(5,TimeUnit.SECONDS); assertThat("syn is received by server", synLatch.await(5,TimeUnit.SECONDS),is(true)); - stream.data(new StringDataInfo("data",false),5,TimeUnit.SECONDS,null); + stream.data(new StringDataInfo("data",false),5,TimeUnit.SECONDS,null,null); assertThat("stream is reset",rstLatch.await(5,TimeUnit.SECONDS),is(true)); - stream.data(new StringDataInfo("2nd dataframe",false),5L,TimeUnit.SECONDS,new Callback.Empty() + stream.data(new StringDataInfo("2nd dataframe",false),5L,TimeUnit.SECONDS,null,new Callback.Empty() { @Override public void failed(Void context, Throwable x) diff --git a/jetty-spdy/spdy-server/src/test/java/org/eclipse/jetty/spdy/server/SynDataReplyDataLoadTest.java b/jetty-spdy/spdy-server/src/test/java/org/eclipse/jetty/spdy/server/SynDataReplyDataLoadTest.java index a3e436724b7..694714f432f 100644 --- a/jetty-spdy/spdy-server/src/test/java/org/eclipse/jetty/spdy/server/SynDataReplyDataLoadTest.java +++ b/jetty-spdy/spdy-server/src/test/java/org/eclipse/jetty/spdy/server/SynDataReplyDataLoadTest.java @@ -177,7 +177,7 @@ public class SynDataReplyDataLoadTest extends AbstractTest @Override public void completed(Stream stream) { - stream.data(new StringDataInfo("data_" + stream.getId(), true), 0, TimeUnit.SECONDS, null); + stream.data(new StringDataInfo("data_" + stream.getId(), true), 0, TimeUnit.SECONDS, null,null); } }); } diff --git a/jetty-spdy/spdy-server/src/test/java/org/eclipse/jetty/spdy/server/SynReplyTest.java b/jetty-spdy/spdy-server/src/test/java/org/eclipse/jetty/spdy/server/SynReplyTest.java index 51f6c4f255a..5619a21a834 100644 --- a/jetty-spdy/spdy-server/src/test/java/org/eclipse/jetty/spdy/server/SynReplyTest.java +++ b/jetty-spdy/spdy-server/src/test/java/org/eclipse/jetty/spdy/server/SynReplyTest.java @@ -199,7 +199,7 @@ public class SynReplyTest extends AbstractTest Assert.assertTrue(stream.isHalfClosed()); stream.reply(new ReplyInfo(false)); - stream.data(new StringDataInfo(data1, false), 5, TimeUnit.SECONDS, new Callback.Empty() + stream.data(new StringDataInfo(data1, false), 5, TimeUnit.SECONDS, null,new Callback.Empty() { @Override public void completed(Void context)