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.
+ *
+ *
+ * public void methodName({@link WebSocketException} error)
+ *
+ */
+@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()
{