418632 - WebSocket / Jsr annotated @OnMessage with InputStream fails to be called
+ Fixed load order issue with binary vs text + Fixed decoder assignment for InputStream + Added unit tests to prevent regression of this feature
This commit is contained in:
parent
d535cb9c92
commit
a0ddb2c5d7
|
@ -64,8 +64,8 @@ public class AnnotatedEndpointScanner<T extends Annotation, C extends EndpointCo
|
||||||
paramsOnError.add(JsrParamIdOnError.INSTANCE);
|
paramsOnError.add(JsrParamIdOnError.INSTANCE);
|
||||||
|
|
||||||
metadata.customizeParamsOnMessage(paramsOnMessage);
|
metadata.customizeParamsOnMessage(paramsOnMessage);
|
||||||
paramsOnMessage.add(JsrParamIdBinary.INSTANCE);
|
|
||||||
paramsOnMessage.add(JsrParamIdText.INSTANCE);
|
paramsOnMessage.add(JsrParamIdText.INSTANCE);
|
||||||
|
paramsOnMessage.add(JsrParamIdBinary.INSTANCE);
|
||||||
paramsOnMessage.add(JsrParamIdPong.INSTANCE);
|
paramsOnMessage.add(JsrParamIdPong.INSTANCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,7 @@ import org.eclipse.jetty.websocket.common.events.annotated.InvalidSignatureExcep
|
||||||
import org.eclipse.jetty.websocket.jsr356.annotations.Param.Role;
|
import org.eclipse.jetty.websocket.jsr356.annotations.Param.Role;
|
||||||
import org.eclipse.jetty.websocket.jsr356.decoders.ByteArrayDecoder;
|
import org.eclipse.jetty.websocket.jsr356.decoders.ByteArrayDecoder;
|
||||||
import org.eclipse.jetty.websocket.jsr356.decoders.ByteBufferDecoder;
|
import org.eclipse.jetty.websocket.jsr356.decoders.ByteBufferDecoder;
|
||||||
|
import org.eclipse.jetty.websocket.jsr356.decoders.InputStreamDecoder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Param handling for static Binary @{@link OnMessage} parameters.
|
* Param handling for static Binary @{@link OnMessage} parameters.
|
||||||
|
@ -63,7 +64,7 @@ public class JsrParamIdBinary extends JsrParamIdOnMessage implements IJsrParamId
|
||||||
{
|
{
|
||||||
assertPartialMessageSupportDisabled(param,callable);
|
assertPartialMessageSupportDisabled(param,callable);
|
||||||
param.bind(Role.MESSAGE_BINARY_STREAM);
|
param.bind(Role.MESSAGE_BINARY_STREAM);
|
||||||
// Streaming have no decoder
|
callable.setDecoderClass(InputStreamDecoder.class);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
|
|
||||||
package org.eclipse.jetty.websocket.jsr356.metadata;
|
package org.eclipse.jetty.websocket.jsr356.metadata;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
|
@ -20,6 +20,7 @@ package org.eclipse.jetty.websocket.jsr356.endpoints;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.*;
|
import static org.hamcrest.Matchers.*;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -43,6 +44,8 @@ import org.eclipse.jetty.websocket.jsr356.endpoints.samples.BasicErrorSessionThr
|
||||||
import org.eclipse.jetty.websocket.jsr356.endpoints.samples.BasicErrorSocket;
|
import org.eclipse.jetty.websocket.jsr356.endpoints.samples.BasicErrorSocket;
|
||||||
import org.eclipse.jetty.websocket.jsr356.endpoints.samples.BasicErrorThrowableSessionSocket;
|
import org.eclipse.jetty.websocket.jsr356.endpoints.samples.BasicErrorThrowableSessionSocket;
|
||||||
import org.eclipse.jetty.websocket.jsr356.endpoints.samples.BasicErrorThrowableSocket;
|
import org.eclipse.jetty.websocket.jsr356.endpoints.samples.BasicErrorThrowableSocket;
|
||||||
|
import org.eclipse.jetty.websocket.jsr356.endpoints.samples.BasicInputStreamSocket;
|
||||||
|
import org.eclipse.jetty.websocket.jsr356.endpoints.samples.BasicInputStreamWithThrowableSocket;
|
||||||
import org.eclipse.jetty.websocket.jsr356.endpoints.samples.BasicOpenSessionSocket;
|
import org.eclipse.jetty.websocket.jsr356.endpoints.samples.BasicOpenSessionSocket;
|
||||||
import org.eclipse.jetty.websocket.jsr356.endpoints.samples.BasicOpenSocket;
|
import org.eclipse.jetty.websocket.jsr356.endpoints.samples.BasicOpenSocket;
|
||||||
import org.eclipse.jetty.websocket.jsr356.endpoints.samples.BasicPongMessageSocket;
|
import org.eclipse.jetty.websocket.jsr356.endpoints.samples.BasicPongMessageSocket;
|
||||||
|
@ -97,6 +100,7 @@ public class ClientAnnotatedEndpointScanner_GoodSignaturesTest
|
||||||
Field fError = findFieldRef(AnnotatedEndpointMetadata.class,"onError");
|
Field fError = findFieldRef(AnnotatedEndpointMetadata.class,"onError");
|
||||||
Field fText = findFieldRef(AnnotatedEndpointMetadata.class,"onText");
|
Field fText = findFieldRef(AnnotatedEndpointMetadata.class,"onText");
|
||||||
Field fBinary = findFieldRef(AnnotatedEndpointMetadata.class,"onBinary");
|
Field fBinary = findFieldRef(AnnotatedEndpointMetadata.class,"onBinary");
|
||||||
|
Field fBinaryStream = findFieldRef(AnnotatedEndpointMetadata.class,"onBinaryStream");
|
||||||
Field fPong = findFieldRef(AnnotatedEndpointMetadata.class,"onPong");
|
Field fPong = findFieldRef(AnnotatedEndpointMetadata.class,"onPong");
|
||||||
|
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
|
@ -120,6 +124,9 @@ public class ClientAnnotatedEndpointScanner_GoodSignaturesTest
|
||||||
Case.add(data, BasicBinaryMessageByteBufferSocket.class, fBinary, ByteBuffer.class);
|
Case.add(data, BasicBinaryMessageByteBufferSocket.class, fBinary, ByteBuffer.class);
|
||||||
// -- Pong Events
|
// -- Pong Events
|
||||||
Case.add(data, BasicPongMessageSocket.class, fPong, PongMessage.class);
|
Case.add(data, BasicPongMessageSocket.class, fPong, PongMessage.class);
|
||||||
|
// -- InputStream Events
|
||||||
|
Case.add(data, BasicInputStreamSocket.class, fBinaryStream, InputStream.class);
|
||||||
|
Case.add(data, BasicInputStreamWithThrowableSocket.class, fBinaryStream, InputStream.class);
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
|
|
||||||
// TODO: validate return types
|
// TODO: validate return types
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
//
|
||||||
|
// ========================================================================
|
||||||
|
// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// All rights reserved. This program and the accompanying materials
|
||||||
|
// are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
// and Apache License v2.0 which accompanies this distribution.
|
||||||
|
//
|
||||||
|
// The Eclipse Public License is available at
|
||||||
|
// http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
//
|
||||||
|
// The Apache License v2.0 is available at
|
||||||
|
// http://www.opensource.org/licenses/apache2.0.php
|
||||||
|
//
|
||||||
|
// You may elect to redistribute this code under either of these licenses.
|
||||||
|
// ========================================================================
|
||||||
|
//
|
||||||
|
|
||||||
|
package org.eclipse.jetty.websocket.jsr356.endpoints.samples;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import javax.websocket.ClientEndpoint;
|
||||||
|
import javax.websocket.OnMessage;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.util.IO;
|
||||||
|
import org.eclipse.jetty.websocket.jsr356.endpoints.TrackingSocket;
|
||||||
|
|
||||||
|
@ClientEndpoint
|
||||||
|
public class BasicInputStreamSocket extends TrackingSocket
|
||||||
|
{
|
||||||
|
@OnMessage
|
||||||
|
public void onBinary(InputStream stream)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
String msg = IO.toString(stream);
|
||||||
|
addEvent("onBinary(%s)",msg);
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
super.errorQueue.add(e);
|
||||||
|
}
|
||||||
|
dataLatch.countDown();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
//
|
||||||
|
// ========================================================================
|
||||||
|
// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// All rights reserved. This program and the accompanying materials
|
||||||
|
// are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
// and Apache License v2.0 which accompanies this distribution.
|
||||||
|
//
|
||||||
|
// The Eclipse Public License is available at
|
||||||
|
// http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
//
|
||||||
|
// The Apache License v2.0 is available at
|
||||||
|
// http://www.opensource.org/licenses/apache2.0.php
|
||||||
|
//
|
||||||
|
// You may elect to redistribute this code under either of these licenses.
|
||||||
|
// ========================================================================
|
||||||
|
//
|
||||||
|
|
||||||
|
package org.eclipse.jetty.websocket.jsr356.endpoints.samples;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import javax.websocket.ClientEndpoint;
|
||||||
|
import javax.websocket.OnMessage;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.util.IO;
|
||||||
|
import org.eclipse.jetty.websocket.jsr356.endpoints.TrackingSocket;
|
||||||
|
|
||||||
|
@ClientEndpoint
|
||||||
|
public class BasicInputStreamWithThrowableSocket extends TrackingSocket
|
||||||
|
{
|
||||||
|
@OnMessage
|
||||||
|
public void onBinary(InputStream stream) throws IOException
|
||||||
|
{
|
||||||
|
String msg = IO.toString(stream);
|
||||||
|
addEvent("onBinary(%s)",msg);
|
||||||
|
}
|
||||||
|
}
|
|
@ -30,6 +30,7 @@ import javax.websocket.OnClose;
|
||||||
import javax.websocket.OnError;
|
import javax.websocket.OnError;
|
||||||
import javax.websocket.OnMessage;
|
import javax.websocket.OnMessage;
|
||||||
import javax.websocket.OnOpen;
|
import javax.websocket.OnOpen;
|
||||||
|
import javax.websocket.RemoteEndpoint.Basic;
|
||||||
import javax.websocket.Session;
|
import javax.websocket.Session;
|
||||||
|
|
||||||
@ClientEndpoint
|
@ClientEndpoint
|
||||||
|
@ -37,6 +38,7 @@ public class EchoClientSocket extends TrackingSocket
|
||||||
{
|
{
|
||||||
public final CountDownLatch eventCountLatch;
|
public final CountDownLatch eventCountLatch;
|
||||||
private Session session;
|
private Session session;
|
||||||
|
private Basic remote;
|
||||||
|
|
||||||
public EchoClientSocket(int expectedEventCount)
|
public EchoClientSocket(int expectedEventCount)
|
||||||
{
|
{
|
||||||
|
@ -76,6 +78,7 @@ public class EchoClientSocket extends TrackingSocket
|
||||||
public void onOpen(Session session)
|
public void onOpen(Session session)
|
||||||
{
|
{
|
||||||
this.session = session;
|
this.session = session;
|
||||||
|
this.remote = session.getBasicRemote();
|
||||||
openLatch.countDown();
|
openLatch.countDown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,16 +96,16 @@ public class EchoClientSocket extends TrackingSocket
|
||||||
|
|
||||||
public void sendObject(Object obj) throws IOException, EncodeException
|
public void sendObject(Object obj) throws IOException, EncodeException
|
||||||
{
|
{
|
||||||
session.getBasicRemote().sendObject(obj);
|
remote.sendObject(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendPartialBinary(ByteBuffer part, boolean fin) throws IOException
|
public void sendPartialBinary(ByteBuffer part, boolean fin) throws IOException
|
||||||
{
|
{
|
||||||
session.getBasicRemote().sendBinary(part,fin);
|
remote.sendBinary(part,fin);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendPartialText(String part, boolean fin) throws IOException
|
public void sendPartialText(String part, boolean fin) throws IOException
|
||||||
{
|
{
|
||||||
session.getBasicRemote().sendText(part,fin);
|
remote.sendText(part,fin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,9 +32,11 @@ import javax.websocket.WebSocketContainer;
|
||||||
|
|
||||||
import org.eclipse.jetty.toolchain.test.EventQueue;
|
import org.eclipse.jetty.toolchain.test.EventQueue;
|
||||||
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
|
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
|
||||||
|
import org.eclipse.jetty.util.BufferUtil;
|
||||||
import org.eclipse.jetty.webapp.WebAppContext;
|
import org.eclipse.jetty.webapp.WebAppContext;
|
||||||
import org.eclipse.jetty.websocket.jsr356.server.EchoCase.PartialBinary;
|
import org.eclipse.jetty.websocket.jsr356.server.EchoCase.PartialBinary;
|
||||||
import org.eclipse.jetty.websocket.jsr356.server.EchoCase.PartialText;
|
import org.eclipse.jetty.websocket.jsr356.server.EchoCase.PartialText;
|
||||||
|
import org.eclipse.jetty.websocket.jsr356.server.samples.binary.ByteBufferSocket;
|
||||||
import org.eclipse.jetty.websocket.jsr356.server.samples.partial.PartialTextSessionSocket;
|
import org.eclipse.jetty.websocket.jsr356.server.samples.partial.PartialTextSessionSocket;
|
||||||
import org.eclipse.jetty.websocket.jsr356.server.samples.partial.PartialTextSocket;
|
import org.eclipse.jetty.websocket.jsr356.server.samples.partial.PartialTextSocket;
|
||||||
import org.eclipse.jetty.websocket.jsr356.server.samples.primitives.BooleanObjectTextSocket;
|
import org.eclipse.jetty.websocket.jsr356.server.samples.primitives.BooleanObjectTextSocket;
|
||||||
|
@ -54,6 +56,7 @@ import org.eclipse.jetty.websocket.jsr356.server.samples.primitives.LongObjectTe
|
||||||
import org.eclipse.jetty.websocket.jsr356.server.samples.primitives.LongTextSocket;
|
import org.eclipse.jetty.websocket.jsr356.server.samples.primitives.LongTextSocket;
|
||||||
import org.eclipse.jetty.websocket.jsr356.server.samples.primitives.ShortObjectTextSocket;
|
import org.eclipse.jetty.websocket.jsr356.server.samples.primitives.ShortObjectTextSocket;
|
||||||
import org.eclipse.jetty.websocket.jsr356.server.samples.primitives.ShortTextSocket;
|
import org.eclipse.jetty.websocket.jsr356.server.samples.primitives.ShortTextSocket;
|
||||||
|
import org.eclipse.jetty.websocket.jsr356.server.samples.streaming.InputStreamSocket;
|
||||||
import org.eclipse.jetty.websocket.jsr356.server.samples.streaming.ReaderParamSocket;
|
import org.eclipse.jetty.websocket.jsr356.server.samples.streaming.ReaderParamSocket;
|
||||||
import org.eclipse.jetty.websocket.jsr356.server.samples.streaming.ReaderSocket;
|
import org.eclipse.jetty.websocket.jsr356.server.samples.streaming.ReaderSocket;
|
||||||
import org.eclipse.jetty.websocket.jsr356.server.samples.streaming.StringReturnReaderParamSocket;
|
import org.eclipse.jetty.websocket.jsr356.server.samples.streaming.StringReturnReaderParamSocket;
|
||||||
|
@ -178,6 +181,12 @@ public class EchoTest
|
||||||
|
|
||||||
// PathParam based
|
// PathParam based
|
||||||
EchoCase.add(TESTCASES,IntParamTextSocket.class).requestPath("/echo/primitives/integer/params/5678").addMessage(1234).expect("1234|5678");
|
EchoCase.add(TESTCASES,IntParamTextSocket.class).requestPath("/echo/primitives/integer/params/5678").addMessage(1234).expect("1234|5678");
|
||||||
|
|
||||||
|
// ByteBuffer based
|
||||||
|
EchoCase.add(TESTCASES,ByteBufferSocket.class).addMessage(BufferUtil.toBuffer("Hello World")).expect("Hello World");
|
||||||
|
|
||||||
|
// InputStream based
|
||||||
|
EchoCase.add(TESTCASES,InputStreamSocket.class).addMessage(BufferUtil.toBuffer("Hello World")).expect("Hello World");
|
||||||
|
|
||||||
// Reader based
|
// Reader based
|
||||||
EchoCase.add(TESTCASES,ReaderSocket.class).addMessage("Hello World").expect("Hello World");
|
EchoCase.add(TESTCASES,ReaderSocket.class).addMessage("Hello World").expect("Hello World");
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
//
|
||||||
|
// ========================================================================
|
||||||
|
// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// All rights reserved. This program and the accompanying materials
|
||||||
|
// are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
// and Apache License v2.0 which accompanies this distribution.
|
||||||
|
//
|
||||||
|
// The Eclipse Public License is available at
|
||||||
|
// http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
//
|
||||||
|
// The Apache License v2.0 is available at
|
||||||
|
// http://www.opensource.org/licenses/apache2.0.php
|
||||||
|
//
|
||||||
|
// You may elect to redistribute this code under either of these licenses.
|
||||||
|
// ========================================================================
|
||||||
|
//
|
||||||
|
|
||||||
|
package org.eclipse.jetty.websocket.jsr356.server.samples.binary;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import javax.websocket.OnError;
|
||||||
|
import javax.websocket.OnMessage;
|
||||||
|
import javax.websocket.Session;
|
||||||
|
import javax.websocket.server.ServerEndpoint;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.util.BufferUtil;
|
||||||
|
import org.eclipse.jetty.util.log.Log;
|
||||||
|
import org.eclipse.jetty.util.log.Logger;
|
||||||
|
import org.eclipse.jetty.websocket.jsr356.server.StackUtil;
|
||||||
|
|
||||||
|
@ServerEndpoint("/echo/binary/bytebuffer")
|
||||||
|
public class ByteBufferSocket
|
||||||
|
{
|
||||||
|
private static final Logger LOG = Log.getLogger(ByteBufferSocket.class);
|
||||||
|
|
||||||
|
@OnMessage
|
||||||
|
public String onByteBuffer(ByteBuffer bbuf)
|
||||||
|
{
|
||||||
|
return BufferUtil.toUTF8String(bbuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnError
|
||||||
|
public void onError(Session session, Throwable cause) throws IOException
|
||||||
|
{
|
||||||
|
LOG.warn("Error",cause);
|
||||||
|
session.getBasicRemote().sendText("Exception: " + StackUtil.toString(cause));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
//
|
||||||
|
// ========================================================================
|
||||||
|
// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// All rights reserved. This program and the accompanying materials
|
||||||
|
// are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
// and Apache License v2.0 which accompanies this distribution.
|
||||||
|
//
|
||||||
|
// The Eclipse Public License is available at
|
||||||
|
// http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
//
|
||||||
|
// The Apache License v2.0 is available at
|
||||||
|
// http://www.opensource.org/licenses/apache2.0.php
|
||||||
|
//
|
||||||
|
// You may elect to redistribute this code under either of these licenses.
|
||||||
|
// ========================================================================
|
||||||
|
//
|
||||||
|
|
||||||
|
package org.eclipse.jetty.websocket.jsr356.server.samples.streaming;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import javax.websocket.OnError;
|
||||||
|
import javax.websocket.OnMessage;
|
||||||
|
import javax.websocket.Session;
|
||||||
|
import javax.websocket.server.ServerEndpoint;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.util.IO;
|
||||||
|
import org.eclipse.jetty.util.StringUtil;
|
||||||
|
import org.eclipse.jetty.util.log.Log;
|
||||||
|
import org.eclipse.jetty.util.log.Logger;
|
||||||
|
import org.eclipse.jetty.websocket.jsr356.server.StackUtil;
|
||||||
|
|
||||||
|
@ServerEndpoint("/echo/streaming/inputstream")
|
||||||
|
public class InputStreamSocket
|
||||||
|
{
|
||||||
|
private static final Logger LOG = Log.getLogger(InputStreamSocket.class);
|
||||||
|
|
||||||
|
@OnMessage
|
||||||
|
public String onInputStream(InputStream stream) throws IOException
|
||||||
|
{
|
||||||
|
return IO.toString(stream, StringUtil.__UTF8);
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnError
|
||||||
|
public void onError(Session session, Throwable cause) throws IOException
|
||||||
|
{
|
||||||
|
LOG.warn("Error",cause);
|
||||||
|
session.getBasicRemote().sendText("Exception: " + StackUtil.toString(cause));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue