Introduces a common SerializableThrowable as public API.
Change-Id: I98ae52858d87b6ac4a0c844464b25540be454942
Review-Link: https://gwt-review.googlesource.com/#/c/2160/
Review by: skybrian@google.com
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@11552 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/core/client/impl/SerializableThrowable.java b/user/src/com/google/gwt/core/client/impl/SerializableThrowable.java
index f5b993d..509679a 100644
--- a/user/src/com/google/gwt/core/client/impl/SerializableThrowable.java
+++ b/user/src/com/google/gwt/core/client/impl/SerializableThrowable.java
@@ -1,30 +1,26 @@
/*
* Copyright 2010 Google Inc.
- *
+ *
* 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 com.google.gwt.core.client.impl;
import java.io.Serializable;
/**
- * The emulated Throwable class does not serialize Throwables recursively and
- * does not serialize the stack trace. This class is an alternative, and
- * can be used by writing a custom serializer for the class which contains a
- * Throwable. See {@link LogRecord_CustomFieldSerializer} as an example.
- *
+ * @deprecated use {@link com.google.gwt.core.shared.SerializableThrowable} instead.
*/
+@Deprecated
public class SerializableThrowable implements Serializable {
private SerializableThrowable cause = null;
private String message = null;
@@ -32,8 +28,9 @@
private String typeName = null;
/**
- * A subclass of Throwable that contains the serialized exception class type.
+ * @deprecated use com.google.gwt.core.client.SerializableThrowable instead.
*/
+ @Deprecated
public static class ThrowableWithClassName extends Throwable {
private String typeName;
diff --git a/user/src/com/google/gwt/core/shared/SerializableThrowable.java b/user/src/com/google/gwt/core/shared/SerializableThrowable.java
new file mode 100644
index 0000000..a44fb04
--- /dev/null
+++ b/user/src/com/google/gwt/core/shared/SerializableThrowable.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * 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 com.google.gwt.core.shared;
+
+import com.google.gwt.core.client.JavaScriptException;
+
+/**
+ * A serializable copy of a {@link Throwable}, including its causes and stack trace. It overrides
+ * {@code #toString} to mimic original {@link Throwable#toString()} so that {@link #printStackTrace}
+ * will work as if it is coming from the original exception.
+ * <p>
+ * This class is especially useful for logging and testing as the emulated Throwable class does not
+ * serialize recursively and does not serialize the stack trace. This class, as an alternative, can
+ * be used to transfer the Throwable without losing any of these data, even if the underlying
+ * Throwable is not serializable.
+ * <p>
+ * Please note that, to get more useful stack traces from client side, this class needs to be used
+ * in conjunction with {@link com.google.gwt.core.server.StackTraceDeobfuscator}.
+ */
+public final class SerializableThrowable extends Throwable {
+
+ /**
+ * Create a new {@link SerializableThrowable} from a provided throwable and its causes
+ * recursively.
+ *
+ * @return a new SerializableThrowable or the passed object itself if it is {@code null} or
+ * already a SerializableThrowable.
+ */
+ public static SerializableThrowable fromThrowable(Throwable throwable) {
+ if (throwable instanceof SerializableThrowable) {
+ return (SerializableThrowable) throwable;
+ } else if (throwable != null) {
+ return createSerializable(throwable);
+ } else {
+ return null;
+ }
+ }
+
+ private String typeName;
+ private boolean exactTypeKnown;
+ private StackTraceElement[] dummyFieldToIncludeTheTypeInSerialization;
+
+ /**
+ * Constructs a new SerializableThrowable with the specified detail message.
+ */
+ public SerializableThrowable(String designatedType, String message) {
+ super(message);
+ this.typeName = designatedType;
+ }
+
+ @Override
+ public Throwable fillInStackTrace() {
+ // This is a no-op for optimization as we don't need stack traces to be auto-filled.
+ return this;
+ }
+
+ /**
+ * Sets the designated Throwable's type name.
+ *
+ * @param typeName the class name of the underlying designated throwable.
+ * @param isExactType {@code false} if provided type name is not the exact type.
+ *
+ * @see #isExactDesignatedTypeKnown()
+ */
+ public void setDesignatedType(String typeName, boolean isExactType) {
+ this.typeName = typeName;
+ this.exactTypeKnown = isExactType;
+ }
+
+ /**
+ * Returns the designated throwable's type name.
+ *
+ * @see #isExactDesignatedTypeKnown()
+ */
+ public String getDesignatedType() {
+ return typeName;
+ }
+
+ /**
+ * Return {@code true} if provided type name is the exact type of the throwable that is designed
+ * by this instance. This can return {@code false} if the class metadata is not available in the
+ * runtime. In that case {@link #getDesignatedType()} will return the type resolved by best-effort
+ * and may not be the exact type; instead it can be one of the ancestors of the real type that
+ * this instance designates.
+ */
+ public boolean isExactDesignatedTypeKnown() {
+ return exactTypeKnown;
+ }
+
+ /**
+ * Initializes the cause of this throwable.
+ * <p>
+ * This method will convert the cause to {@link SerializableThrowable} if it is not already.
+ */
+ @Override
+ public Throwable initCause(Throwable cause) {
+ return super.initCause(fromThrowable(cause));
+ }
+
+ @Override
+ public String toString() {
+ String type = exactTypeKnown ? typeName : (typeName + "(EXACT TYPE UNKNOWN)");
+ String msg = getMessage();
+ return msg == null ? type : (type + ": " + msg);
+ }
+
+ private static SerializableThrowable createSerializable(Throwable t) {
+ SerializableThrowable throwable = new SerializableThrowable(null, t.getMessage());
+ throwable.setStackTrace(t.getStackTrace());
+ throwable.initCause(t.getCause());
+ if (isClassMetadataAvailable()) {
+ throwable.setDesignatedType(t.getClass().getName(), true);
+ } else {
+ resolveDesignatedType(throwable, t);
+ }
+ return throwable;
+ }
+
+ // TODO(goktug): Replace when availability of class metadata can be checked in compile-time so
+ // that #resolveDesignatedType will be compiled out.
+ private static boolean isClassMetadataAvailable() {
+ return !GWT.isScript()
+ || SerializableThrowable.class.getName().endsWith(".SerializableThrowable");
+ }
+
+ /**
+ * Resolves best effort class name by checking against some common exception types.
+ */
+ private static void resolveDesignatedType(SerializableThrowable t, Throwable designatedType) {
+ String resolvedName;
+ Class<?> resolvedType;
+ try {
+ throw designatedType;
+ } catch (NullPointerException e) {
+ resolvedName = "java.lang.NullPointerException";
+ resolvedType = NullPointerException.class;
+ } catch (JavaScriptException e) {
+ resolvedName = "com.google.gwt.core.client.JavaScriptException";
+ resolvedType = JavaScriptException.class;
+ } catch (RuntimeException e) {
+ resolvedName = "java.lang.RuntimeException";
+ resolvedType = RuntimeException.class;
+ } catch (Exception e) {
+ resolvedName = "java.lang.Exception";
+ resolvedType = Exception.class;
+ } catch (Error e) {
+ resolvedName = "java.lang.Error";
+ resolvedType = Error.class;
+ } catch (Throwable e) {
+ resolvedName = "java.lang.Throwable";
+ resolvedType = Throwable.class;
+ }
+ t.setDesignatedType(resolvedName, resolvedType == designatedType.getClass());
+ }
+}
diff --git a/user/src/com/google/gwt/user/client/rpc/core/com/google/gwt/core/shared/SerializableThrowable_CustomFieldSerializer.java b/user/src/com/google/gwt/user/client/rpc/core/com/google/gwt/core/shared/SerializableThrowable_CustomFieldSerializer.java
new file mode 100644
index 0000000..e37d21d
--- /dev/null
+++ b/user/src/com/google/gwt/user/client/rpc/core/com/google/gwt/core/shared/SerializableThrowable_CustomFieldSerializer.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * 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 com.google.gwt.user.client.rpc.core.com.google.gwt.core.shared;
+
+import com.google.gwt.core.shared.SerializableThrowable;
+import com.google.gwt.user.client.rpc.CustomFieldSerializer;
+import com.google.gwt.user.client.rpc.SerializationException;
+import com.google.gwt.user.client.rpc.SerializationStreamReader;
+import com.google.gwt.user.client.rpc.SerializationStreamWriter;
+
+/**
+ * Custom field serializer for SerializableThrowable.
+ */
+public final class SerializableThrowable_CustomFieldSerializer
+ extends CustomFieldSerializer<SerializableThrowable> {
+
+ public static SerializableThrowable instantiate(SerializationStreamReader streamReader)
+ throws SerializationException {
+ return new SerializableThrowable(null, streamReader.readString());
+ }
+
+ public static void deserialize(
+ SerializationStreamReader streamReader, SerializableThrowable instance)
+ throws SerializationException {
+ String type = streamReader.readString();
+ boolean typeIsExact = streamReader.readBoolean();
+ instance.setDesignatedType(type, typeIsExact);
+ instance.setStackTrace((StackTraceElement[]) streamReader.readObject());
+ instance.initCause((Throwable) streamReader.readObject());
+ }
+
+ public static void serialize(
+ SerializationStreamWriter streamWriter, SerializableThrowable instance)
+ throws SerializationException {
+ streamWriter.writeString(instance.getMessage());
+ streamWriter.writeString(instance.getDesignatedType());
+ streamWriter.writeBoolean(instance.isExactDesignatedTypeKnown());
+ streamWriter.writeObject(instance.getStackTrace());
+ streamWriter.writeObject(instance.getCause());
+ }
+
+ @Override
+ public boolean hasCustomInstantiateInstance() {
+ return true;
+ }
+
+ @Override
+ public SerializableThrowable instantiateInstance(SerializationStreamReader streamReader)
+ throws SerializationException {
+ return instantiate(streamReader);
+ }
+
+ @Override
+ public void deserializeInstance(
+ SerializationStreamReader streamReader, SerializableThrowable instance)
+ throws SerializationException {
+ deserialize(streamReader, instance);
+ }
+
+ @Override
+ public void serializeInstance(
+ SerializationStreamWriter streamWriter, SerializableThrowable instance)
+ throws SerializationException {
+ serialize(streamWriter, instance);
+ }
+}
diff --git a/user/test/com/google/gwt/core/CoreSuite.java b/user/test/com/google/gwt/core/CoreSuite.java
index 39cb829..d1f6f2b 100644
--- a/user/test/com/google/gwt/core/CoreSuite.java
+++ b/user/test/com/google/gwt/core/CoreSuite.java
@@ -1,12 +1,12 @@
/*
* Copyright 2008 Google Inc.
- *
+ *
* 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
@@ -28,6 +28,7 @@
import com.google.gwt.core.client.impl.SchedulerImplTest;
import com.google.gwt.core.client.impl.StackTraceCreatorTest;
import com.google.gwt.core.client.prefetch.RunAsyncCodeTest;
+import com.google.gwt.core.shared.SerializableThrowableTest;
import com.google.gwt.dev.StrictModeTest;
import com.google.gwt.junit.tools.GWTTestSuite;
@@ -52,6 +53,7 @@
suite.addTestSuite(SchedulerImplTest.class);
suite.addTestSuite(SchedulerTest.class);
suite.addTestSuite(ScriptInjectorTest.class);
+ suite.addTestSuite(SerializableThrowableTest.class);
suite.addTestSuite(StackTraceCreatorTest.class);
suite.addTestSuite(StrictModeTest.class);
suite.addTestSuite(RunAsyncCodeTest.class);
diff --git a/user/test/com/google/gwt/core/shared/SerializableThrowableTest.java b/user/test/com/google/gwt/core/shared/SerializableThrowableTest.java
new file mode 100644
index 0000000..476b50d
--- /dev/null
+++ b/user/test/com/google/gwt/core/shared/SerializableThrowableTest.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * 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 com.google.gwt.core.shared;
+
+import com.google.gwt.junit.client.GWTTestCase;
+
+/**
+ * Tests for the {@link SerializableThrowable} class.
+ *
+ * @see com.google.gwt.user.client.rpc.ExceptionsTest for serialization tests.
+ */
+public class SerializableThrowableTest extends GWTTestCase {
+
+ private static final String TEST_CLASS_NAME =
+ "com.google.gwt.core.shared.SerializableThrowableTest";
+
+ @Override
+ public String getModuleName() {
+ return "com.google.gwt.core.Core";
+ }
+
+ public void testToString() throws Exception {
+ SerializableThrowable t = SerializableThrowable.fromThrowable(new RuntimeException("msg"));
+ t.setDesignatedType("a.A", true);
+ assertEquals("a.A: msg", t.toString());
+ t.setDesignatedType("a.A", false);
+ assertEquals("a.A(EXACT TYPE UNKNOWN): msg", t.toString());
+ }
+
+ public void testFromThrowable() throws Exception {
+ RuntimeException exception = new RuntimeException("msg");
+ exception.initCause(new RuntimeException("cause"));
+
+ SerializableThrowable serializableThrowable = SerializableThrowable.fromThrowable(exception);
+ assertEquals("msg", serializableThrowable.getMessage());
+ assertEquals(exception.getStackTrace().length, serializableThrowable.getStackTrace().length);
+ assertEquals("java.lang.RuntimeException: msg", serializableThrowable.toString());
+
+ SerializableThrowable cause = (SerializableThrowable) serializableThrowable.getCause();
+ assertEquals("cause", cause.getMessage());
+ assertEquals("java.lang.RuntimeException: cause", cause.toString());
+ }
+
+ public void testFromThrowable_alreadySerializable() {
+ SerializableThrowable expected = new SerializableThrowable(null, "msg");
+ assertSame(expected, SerializableThrowable.fromThrowable(expected));
+ }
+
+ public void testFromThrowable_null() {
+ assertNull(SerializableThrowable.fromThrowable(null));
+ }
+
+ private static class MyException extends Exception { }
+ private static class MyRuntimeException extends RuntimeException { }
+ private static class MyNullPointerException extends NullPointerException { }
+
+ public void testDesignatedType() throws Exception {
+ SerializableThrowable t = SerializableThrowable.fromThrowable(new RuntimeException());
+ assertEquals("java.lang.RuntimeException", t.getDesignatedType());
+ assertTrue(t.isExactDesignatedTypeKnown());
+ }
+
+ public void testDesignatedType_withClassMetadata() throws Exception {
+ if (!isClassMetadataAvailable()) {
+ return;
+ }
+ SerializableThrowable t;
+
+ t = SerializableThrowable.fromThrowable(new MyException());
+ assertEquals(TEST_CLASS_NAME + "$MyException", t.getDesignatedType());
+ assertTrue(t.isExactDesignatedTypeKnown());
+
+ t = SerializableThrowable.fromThrowable(new MyRuntimeException());
+ assertEquals(TEST_CLASS_NAME + "$MyRuntimeException", t.getDesignatedType());
+ assertTrue(t.isExactDesignatedTypeKnown());
+
+ t = SerializableThrowable.fromThrowable(new MyNullPointerException());
+ assertEquals(TEST_CLASS_NAME + "$MyNullPointerException", t.getDesignatedType());
+ assertTrue(t.isExactDesignatedTypeKnown());
+ }
+
+ public void testDesignatedType_withoutClassMetadata() throws Exception {
+ if (isClassMetadataAvailable()) {
+ return;
+ }
+ SerializableThrowable t;
+
+ t = SerializableThrowable.fromThrowable(new MyException());
+ assertEquals("java.lang.Exception", t.getDesignatedType());
+ assertFalse(t.isExactDesignatedTypeKnown());
+
+ t = SerializableThrowable.fromThrowable(new MyRuntimeException());
+ assertEquals("java.lang.RuntimeException", t.getDesignatedType());
+ assertFalse(t.isExactDesignatedTypeKnown());
+
+ t = SerializableThrowable.fromThrowable(new MyNullPointerException());
+ assertEquals("java.lang.NullPointerException", t.getDesignatedType());
+ assertFalse(t.isExactDesignatedTypeKnown());
+ }
+
+ private static boolean isClassMetadataAvailable() {
+ return SerializableThrowableTest.class.getName().endsWith(".SerializableThrowableTest");
+ }
+}
diff --git a/user/test/com/google/gwt/user/client/rpc/ExceptionsTest.java b/user/test/com/google/gwt/user/client/rpc/ExceptionsTest.java
index 600b5c4..69ad74f 100644
--- a/user/test/com/google/gwt/user/client/rpc/ExceptionsTest.java
+++ b/user/test/com/google/gwt/user/client/rpc/ExceptionsTest.java
@@ -16,6 +16,7 @@
package com.google.gwt.user.client.rpc;
import com.google.gwt.core.client.GWT;
+import com.google.gwt.core.shared.SerializableThrowable;
import com.google.gwt.event.shared.UmbrellaException;
/**
@@ -26,21 +27,46 @@
private ExceptionsTestServiceAsync exceptionsTestService;
public void testUmbrellaException() {
- ExceptionsTestServiceAsync service = getServiceAsync();
- delayTestFinishForRpc();
final UmbrellaException expected = TestSetFactory.createUmbrellaException();
- service.echo(expected,
- new AsyncCallback<UmbrellaException>() {
- public void onFailure(Throwable caught) {
- TestSetValidator.rethrowException(caught);
- }
+ checkException(expected, new AsyncCallback<UmbrellaException>() {
+ public void onFailure(Throwable caught) {
+ TestSetValidator.rethrowException(caught);
+ }
- public void onSuccess(UmbrellaException result) {
- assertNotNull(result);
- assertTrue(TestSetValidator.isValid(expected, result));
- finishTest();
- }
- });
+ public void onSuccess(UmbrellaException result) {
+ assertNotNull(result);
+ assertTrue(TestSetValidator.isValid(expected, result));
+ finishTest();
+ }
+ });
+ }
+
+ public void testSerializableThrowable() {
+ SerializableThrowable expected = new SerializableThrowable(null, "msg");
+ expected.setDesignatedType("x", true);
+ expected.setStackTrace(new StackTraceElement[] {new StackTraceElement("c", "m", "f", 42)});
+ expected.initCause(new SerializableThrowable(null, "cause"));
+
+ checkException(expected, new AsyncCallback<SerializableThrowable>() {
+ public void onFailure(Throwable caught) {
+ TestSetValidator.rethrowException(caught);
+ }
+
+ public void onSuccess(SerializableThrowable result) {
+ assertNotNull(result);
+ assertEquals("msg", result.getMessage());
+ assertEquals("x", result.getDesignatedType());
+ assertTrue(result.isExactDesignatedTypeKnown());
+ assertEquals("c.m(f:42)", result.getStackTrace()[0].toString());
+ assertEquals("cause", ((SerializableThrowable) result.getCause()).getMessage());
+ finishTest();
+ }
+ });
+ }
+
+ private <T extends Throwable> void checkException(T expected, AsyncCallback<T> callback) {
+ delayTestFinishForRpc();
+ getServiceAsync().echo(expected, callback);
}
private ExceptionsTestServiceAsync getServiceAsync() {
diff --git a/user/test/com/google/gwt/user/client/rpc/ExceptionsTestService.java b/user/test/com/google/gwt/user/client/rpc/ExceptionsTestService.java
index fc258d7..551f0ac 100644
--- a/user/test/com/google/gwt/user/client/rpc/ExceptionsTestService.java
+++ b/user/test/com/google/gwt/user/client/rpc/ExceptionsTestService.java
@@ -15,26 +15,10 @@
*/
package com.google.gwt.user.client.rpc;
-import com.google.gwt.event.shared.UmbrellaException;
-
/**
* Remote Service for testing the serialization of GWT Exception classes.
*/
@RemoteServiceRelativePath("exceptions")
public interface ExceptionsTestService extends RemoteService {
-
- /**
- * Exception specific to testing of GWT exception serialization.
- */
- final class ExceptionsTestServiceException extends Exception {
- public ExceptionsTestServiceException() {
- }
-
- public ExceptionsTestServiceException(String msg) {
- super(msg);
- }
- }
-
- UmbrellaException echo(UmbrellaException exception)
- throws ExceptionsTestServiceException;
+ <T extends Throwable> T echo(T throwable);
}
diff --git a/user/test/com/google/gwt/user/client/rpc/ExceptionsTestServiceAsync.java b/user/test/com/google/gwt/user/client/rpc/ExceptionsTestServiceAsync.java
index a19197d..e347c31 100644
--- a/user/test/com/google/gwt/user/client/rpc/ExceptionsTestServiceAsync.java
+++ b/user/test/com/google/gwt/user/client/rpc/ExceptionsTestServiceAsync.java
@@ -1,12 +1,12 @@
/*
* Copyright 2011 Google Inc.
- *
+ *
* 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
@@ -15,11 +15,10 @@
*/
package com.google.gwt.user.client.rpc;
-import com.google.gwt.event.shared.UmbrellaException;
/**
* Async remote service class for testing GWT Exception serialization.
*/
public interface ExceptionsTestServiceAsync {
- void echo(UmbrellaException exception, AsyncCallback<UmbrellaException> callback);
+ <T extends Throwable> void echo(T exception, AsyncCallback<T> callback);
}
diff --git a/user/test/com/google/gwt/user/server/rpc/ExceptionsTestServiceImpl.java b/user/test/com/google/gwt/user/server/rpc/ExceptionsTestServiceImpl.java
index ed8bdd4..3006c79 100644
--- a/user/test/com/google/gwt/user/server/rpc/ExceptionsTestServiceImpl.java
+++ b/user/test/com/google/gwt/user/server/rpc/ExceptionsTestServiceImpl.java
@@ -15,10 +15,7 @@
*/
package com.google.gwt.user.server.rpc;
-import com.google.gwt.event.shared.UmbrellaException;
import com.google.gwt.user.client.rpc.ExceptionsTestService;
-import com.google.gwt.user.client.rpc.TestSetFactory;
-import com.google.gwt.user.client.rpc.TestSetValidator;
/**
* Remote Service Implementation for Exception serialization tests.
@@ -26,14 +23,9 @@
public class ExceptionsTestServiceImpl extends HybridServiceServlet implements
ExceptionsTestService {
- public UmbrellaException echo(UmbrellaException exception)
- throws ExceptionsTestServiceException {
- UmbrellaException expected = TestSetFactory.createUmbrellaException();
- if (!TestSetValidator.isValid(expected, exception)) {
- throw new ExceptionsTestServiceException();
- }
-
- return exception;
+ @Override
+ public <T extends Throwable> T echo(T throwable) {
+ return throwable;
}
}