diff --git a/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/annotations/OnWebSocketError.java b/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/annotations/OnWebSocketError.java new file mode 100644 index 00000000000..8fbf14f3381 --- /dev/null +++ b/jetty-websocket/websocket-api/src/main/java/org/eclipse/jetty/websocket/api/annotations/OnWebSocketError.java @@ -0,0 +1,46 @@ +// +// ======================================================================== +// 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.api.annotations; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.eclipse.jetty.websocket.api.WebSocketException; + +/** + * Annotation for receiving websocket errors (exceptions) that have occurred internally in the websocket implementation. + *

+ * Acceptable method patterns.
+ * Note: methodName can be any name you want to use. + *

+ *

    + *
  1. public void methodName({@link WebSocketException} error)
  2. + *
+ */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target(value = +{ ElementType.METHOD }) +public @interface OnWebSocketError +{ + /* no config */ +} diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/events/EventDriverFactory.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/events/EventDriverFactory.java index a61828e1cfc..e05f9e7ffe9 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/events/EventDriverFactory.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/events/EventDriverFactory.java @@ -28,10 +28,12 @@ import java.util.concurrent.ConcurrentHashMap; import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.websocket.api.InvalidWebSocketException; import org.eclipse.jetty.websocket.api.WebSocketConnection; +import org.eclipse.jetty.websocket.api.WebSocketException; import org.eclipse.jetty.websocket.api.WebSocketListener; import org.eclipse.jetty.websocket.api.WebSocketPolicy; import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose; import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect; +import org.eclipse.jetty.websocket.api.annotations.OnWebSocketError; import org.eclipse.jetty.websocket.api.annotations.OnWebSocketFrame; import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage; import org.eclipse.jetty.websocket.api.annotations.WebSocket; @@ -57,6 +59,11 @@ public class EventDriverFactory */ private static final ParamList validCloseParams; + /** + * Parameter list for @OnWebSocketError + */ + private static final ParamList validErrorParams; + /** * Parameter list for @OnWebSocketFrame */ @@ -76,6 +83,10 @@ public class EventDriverFactory validCloseParams.addParams(int.class,String.class); validCloseParams.addParams(WebSocketConnection.class,int.class,String.class); + validErrorParams = new ParamList(); + validErrorParams.addParams(WebSocketException.class); + validErrorParams.addParams(WebSocketConnection.class,WebSocketException.class); + validTextParams = new ParamList(); validTextParams.addParams(String.class); validTextParams.addParams(WebSocketConnection.class,String.class); @@ -312,6 +323,14 @@ public class EventDriverFactory continue; } + if (method.getAnnotation(OnWebSocketError.class) != null) + { + assertValidSignature(method,OnWebSocketError.class,validErrorParams); + assertUnset(events.onException,OnWebSocketError.class,method); + events.onException = new EventMethod(pojo,method); + continue; + } + if (method.getAnnotation(OnWebSocketFrame.class) != null) { assertValidSignature(method,OnWebSocketFrame.class,validFrameParams); diff --git a/jetty-websocket/websocket-common/src/test/java/examples/AnnotatedTextSocket.java b/jetty-websocket/websocket-common/src/test/java/examples/AnnotatedTextSocket.java index 2a9527156c9..0eb2fe63203 100644 --- a/jetty-websocket/websocket-common/src/test/java/examples/AnnotatedTextSocket.java +++ b/jetty-websocket/websocket-common/src/test/java/examples/AnnotatedTextSocket.java @@ -19,8 +19,10 @@ package examples; import org.eclipse.jetty.websocket.api.WebSocketConnection; +import org.eclipse.jetty.websocket.api.WebSocketException; import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose; import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect; +import org.eclipse.jetty.websocket.api.annotations.OnWebSocketError; import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage; import org.eclipse.jetty.websocket.api.annotations.WebSocket; import org.eclipse.jetty.websocket.common.events.EventCapture; @@ -42,10 +44,15 @@ public class AnnotatedTextSocket capture.add("onConnect(%s)", conn); } + @OnWebSocketError + public void onError(WebSocketException e) + { + capture.add("onError(%s: %s)",e.getClass().getSimpleName(),e.getMessage()); + } + @OnWebSocketMessage public void onText(String message) { capture.add("onText(%s)",capture.q(message)); } - } diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/events/EventDriverFactoryTest.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/events/EventDriverFactoryTest.java index 063cd7490d0..cf7b137ad47 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/events/EventDriverFactoryTest.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/events/EventDriverFactoryTest.java @@ -34,11 +34,6 @@ import org.eclipse.jetty.websocket.common.annotations.MyEchoSocket; import org.eclipse.jetty.websocket.common.annotations.MyStatelessEchoSocket; import org.eclipse.jetty.websocket.common.annotations.NoopSocket; import org.eclipse.jetty.websocket.common.annotations.NotASocket; -import org.eclipse.jetty.websocket.common.events.EventDriver; -import org.eclipse.jetty.websocket.common.events.EventDriverFactory; -import org.eclipse.jetty.websocket.common.events.EventMethod; -import org.eclipse.jetty.websocket.common.events.EventMethods; -import org.eclipse.jetty.websocket.common.events.ListenerEventDriver; import org.junit.Assert; import org.junit.Test; @@ -330,7 +325,7 @@ public class EventDriverFactoryTest assertNoEventMethod(classId + ".onBinary",methods.onBinary); assertHasEventMethod(classId + ".onClose",methods.onClose); assertHasEventMethod(classId + ".onConnect",methods.onConnect); - assertNoEventMethod(classId + ".onException",methods.onException); + assertHasEventMethod(classId + ".onException",methods.onException); assertHasEventMethod(classId + ".onText",methods.onText); assertNoEventMethod(classId + ".onFrame",methods.onFrame); diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/events/EventDriverTest.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/events/EventDriverTest.java index 459477d0c9e..4550bd2c4ea 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/events/EventDriverTest.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/events/EventDriverTest.java @@ -19,6 +19,7 @@ package org.eclipse.jetty.websocket.common.events; import org.eclipse.jetty.websocket.api.StatusCode; +import org.eclipse.jetty.websocket.api.WebSocketException; import org.eclipse.jetty.websocket.api.WebSocketPolicy; import org.eclipse.jetty.websocket.api.extensions.Frame; import org.eclipse.jetty.websocket.common.CloseInfo; @@ -33,6 +34,7 @@ import examples.AdapterConnectCloseSocket; import examples.AnnotatedBinaryArraySocket; import examples.AnnotatedBinaryStreamSocket; import examples.AnnotatedFramesSocket; +import examples.AnnotatedTextSocket; import examples.ListenerBasicSocket; public class EventDriverTest @@ -77,6 +79,23 @@ public class EventDriverTest socket.capture.assertEventStartsWith(2,"onClose(1000,"); } + @Test + public void testAnnotated_Error() + { + AnnotatedTextSocket socket = new AnnotatedTextSocket(); + EventDriver driver = wrap(socket); + + LocalWebSocketSession conn = new LocalWebSocketSession(testname,driver); + conn.open(); + driver.incomingError(new WebSocketException("oof")); + driver.incomingFrame(new CloseInfo(StatusCode.NORMAL).asFrame()); + + socket.capture.assertEventCount(3); + socket.capture.assertEventStartsWith(0,"onConnect"); + socket.capture.assertEventStartsWith(1,"onError(WebSocketException: oof)"); + socket.capture.assertEventStartsWith(2,"onClose(1000,"); + } + @Test public void testAnnotated_Frames() {