Cherry-pick merge of r5023.
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@5024 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/http/client/Request.java b/user/src/com/google/gwt/http/client/Request.java
index fd0ea9d..70c13c4 100644
--- a/user/src/com/google/gwt/http/client/Request.java
+++ b/user/src/com/google/gwt/http/client/Request.java
@@ -148,6 +148,16 @@
* and set this field to null.
*/
private XMLHttpRequest xmlHttpRequest;
+
+ /**
+ * Only used for building a
+ * {@link com.google.gwt.user.client.rpc.impl.FailedRequest}.
+ */
+ protected Request() {
+ timeoutMillis = 0;
+ xmlHttpRequest = null;
+ timer = null;
+ }
/**
* Constructs an instance of the Request object.
diff --git a/user/src/com/google/gwt/user/client/rpc/impl/FailedRequest.java b/user/src/com/google/gwt/user/client/rpc/impl/FailedRequest.java
new file mode 100644
index 0000000..de15658
--- /dev/null
+++ b/user/src/com/google/gwt/user/client/rpc/impl/FailedRequest.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2009 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.impl;
+
+import com.google.gwt.http.client.Request;
+
+/**
+ * A {@link Request} that is already canceled at the moment it is created.
+ */
+public class FailedRequest extends Request {
+ public FailedRequest() {
+ super();
+ }
+}
diff --git a/user/src/com/google/gwt/user/client/rpc/impl/FailingRequestBuilder.java b/user/src/com/google/gwt/user/client/rpc/impl/FailingRequestBuilder.java
new file mode 100644
index 0000000..9227677
--- /dev/null
+++ b/user/src/com/google/gwt/user/client/rpc/impl/FailingRequestBuilder.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2009 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.impl;
+
+import com.google.gwt.http.client.Request;
+import com.google.gwt.http.client.RequestBuilder;
+import com.google.gwt.http.client.RequestCallback;
+import com.google.gwt.http.client.RequestException;
+import com.google.gwt.user.client.rpc.AsyncCallback;
+
+/**
+ * A {@link RequestBuilder} that always immediately fails.
+ */
+public class FailingRequestBuilder extends RequestBuilder {
+ private final Throwable cause;
+ private final AsyncCallback<?> rpcCallback;
+
+ public FailingRequestBuilder(Throwable cause, AsyncCallback<?> rpcCallback) {
+ super(GET, "(bogus)");
+ this.cause = cause;
+ this.rpcCallback = rpcCallback;
+ }
+
+ @Override
+ public Request send() throws RequestException {
+ rpcCallback.onFailure(cause);
+ return new FailedRequest();
+ }
+
+ @Override
+ public Request sendRequest(String requestData, RequestCallback callback)
+ throws RequestException {
+ // This method would not normally be called
+ throw new RequestException(cause);
+ }
+}
diff --git a/user/src/com/google/gwt/user/rebind/rpc/ProxyCreator.java b/user/src/com/google/gwt/user/rebind/rpc/ProxyCreator.java
index 0449c7e..273ef04 100644
--- a/user/src/com/google/gwt/user/rebind/rpc/ProxyCreator.java
+++ b/user/src/com/google/gwt/user/rebind/rpc/ProxyCreator.java
@@ -39,6 +39,8 @@
import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;
import com.google.gwt.user.client.rpc.SerializationException;
import com.google.gwt.user.client.rpc.impl.ClientSerializationStreamWriter;
+import com.google.gwt.user.client.rpc.impl.FailedRequest;
+import com.google.gwt.user.client.rpc.impl.FailingRequestBuilder;
import com.google.gwt.user.client.rpc.impl.RemoteServiceProxy;
import com.google.gwt.user.client.rpc.impl.RequestCallbackAdapter.ResponseReader;
import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
@@ -485,7 +487,25 @@
String exceptionName = nameFactory.createName("ex");
w.println(exceptionName + ") {");
w.indent();
- w.println(callbackName + ".onFailure(" + exceptionName + ");");
+ if (!asyncReturnType.getQualifiedSourceName().equals(
+ RequestBuilder.class.getName())) {
+ /*
+ * If the method returns void or Request, signal the serialization error
+ * immediately. If the method returns RequestBuilder, the error will be
+ * signaled whenever RequestBuilder.send() is invoked.
+ */
+ w.println(callbackName + ".onFailure(" + exceptionName + ");");
+ }
+ if (asyncReturnType.getQualifiedSourceName().equals(
+ RequestBuilder.class.getName())) {
+ w.println("return new " + FailingRequestBuilder.class.getName() + "("
+ + exceptionName + ", " + callbackName + ");");
+ } else if (asyncReturnType.getQualifiedSourceName().equals(
+ Request.class.getName())) {
+ w.println("return new " + FailedRequest.class.getName() + "();");
+ } else {
+ assert asyncReturnType == JPrimitiveType.VOID;
+ }
w.outdent();
w.println("}");
}
diff --git a/user/test/com/google/gwt/user/RPCSuite.gwt.xml b/user/test/com/google/gwt/user/RPCSuite.gwt.xml
index 53c0c51..2360e11 100644
--- a/user/test/com/google/gwt/user/RPCSuite.gwt.xml
+++ b/user/test/com/google/gwt/user/RPCSuite.gwt.xml
@@ -18,7 +18,7 @@
<define-property name='rpc.enforceTypeVersioning' values="true, false" />
<set-property name='rpc.enforceTypeVersioning' value='true' />
- <servlet path='/echo' class='com.google.gwt.user.server.rpc.EchoServiceImpl' />
+ <servlet path='/echo' class='com.google.gwt.user.server.rpc.MixedSerializableEchoServiceImpl' />
<servlet path='/collections'
class='com.google.gwt.user.server.rpc.CollectionsTestServiceImpl' />
<servlet path='/customfieldserializers'
diff --git a/user/test/com/google/gwt/user/RPCSuite.java b/user/test/com/google/gwt/user/RPCSuite.java
index b32b50f..4ded336 100644
--- a/user/test/com/google/gwt/user/RPCSuite.java
+++ b/user/test/com/google/gwt/user/RPCSuite.java
@@ -23,10 +23,13 @@
import com.google.gwt.user.client.rpc.CustomFieldSerializerTestWithTypeObfuscation;
import com.google.gwt.user.client.rpc.EnumsTest;
import com.google.gwt.user.client.rpc.EnumsTestWithTypeObfuscation;
+import com.google.gwt.user.client.rpc.FailedRequestTest;
+import com.google.gwt.user.client.rpc.FailingRequestBuilderTest;
import com.google.gwt.user.client.rpc.InheritanceTest;
import com.google.gwt.user.client.rpc.InheritanceTestWithTypeObfuscation;
import com.google.gwt.user.client.rpc.ObjectGraphTest;
import com.google.gwt.user.client.rpc.ObjectGraphTestWithTypeObfuscation;
+import com.google.gwt.user.client.rpc.RunTimeSerializationErrorsTest;
import com.google.gwt.user.client.rpc.UnicodeEscapingTest;
import com.google.gwt.user.client.rpc.UnicodeEscapingTestWithTypeObfuscation;
import com.google.gwt.user.client.rpc.ValueTypesTest;
@@ -70,6 +73,8 @@
suite.addTestSuite(SerializationPolicyLoaderTest.class);
suite.addTestSuite(RPCServletUtilsTest.class);
suite.addTestSuite(RPCRequestTest.class);
+ suite.addTestSuite(FailedRequestTest.class);
+ suite.addTestSuite(FailingRequestBuilderTest.class);
// GWTTestCases
suite.addTestSuite(ValueTypesTest.class);
@@ -80,6 +85,7 @@
suite.addTestSuite(ObjectGraphTest.class);
suite.addTestSuite(com.google.gwt.user.client.rpc.RemoteServiceServletTest.class);
suite.addTestSuite(UnicodeEscapingTest.class);
+ suite.addTestSuite(RunTimeSerializationErrorsTest.class);
// This test turns on the type-elision feature of RPC
suite.addTestSuite(ValueTypesTestWithTypeObfuscation.class);
diff --git a/user/test/com/google/gwt/user/client/rpc/FailedRequestTest.java b/user/test/com/google/gwt/user/client/rpc/FailedRequestTest.java
new file mode 100644
index 0000000..2691c34
--- /dev/null
+++ b/user/test/com/google/gwt/user/client/rpc/FailedRequestTest.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2009 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;
+
+import com.google.gwt.http.client.Request;
+import com.google.gwt.user.client.rpc.impl.FailedRequest;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests the {@link com.google.gwt.user.client.rpc.impl.FailedRequest} class.
+ */
+public class FailedRequestTest extends TestCase {
+ public void testBasics() {
+ Request failedRequest = new FailedRequest();
+ assertFalse(failedRequest.isPending());
+ failedRequest.cancel();
+ assertFalse(failedRequest.isPending());
+ }
+}
diff --git a/user/test/com/google/gwt/user/client/rpc/FailingRequestBuilderTest.java b/user/test/com/google/gwt/user/client/rpc/FailingRequestBuilderTest.java
new file mode 100644
index 0000000..effa813
--- /dev/null
+++ b/user/test/com/google/gwt/user/client/rpc/FailingRequestBuilderTest.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2009 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;
+
+import com.google.gwt.http.client.RequestBuilder;
+import com.google.gwt.http.client.RequestException;
+import com.google.gwt.user.client.rpc.impl.FailingRequestBuilder;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests the {@link FailingRequestBuilder} class.
+ */
+public class FailingRequestBuilderTest extends TestCase {
+ public void testBasics() throws RequestException {
+ final boolean[] callbackCalled = new boolean[] {false};
+
+ RequestBuilder rb = new FailingRequestBuilder(new SerializationException(),
+ new AsyncCallback<Void>() {
+ public void onFailure(Throwable caught) {
+ assertFalse(callbackCalled[0]);
+ callbackCalled[0] = true;
+ }
+
+ public void onSuccess(Void result) {
+ fail("expected this to fail");
+ }
+ });
+
+ rb.send();
+ }
+}
diff --git a/user/test/com/google/gwt/user/client/rpc/MixedSerializable.java b/user/test/com/google/gwt/user/client/rpc/MixedSerializable.java
new file mode 100644
index 0000000..b7c016f
--- /dev/null
+++ b/user/test/com/google/gwt/user/client/rpc/MixedSerializable.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2009 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;
+
+import java.io.Serializable;
+
+/**
+ * A class with both serializable and non-serializable subclasses.
+ */
+public abstract class MixedSerializable {
+ /**
+ * Subclass that is not serializable.
+ */
+ public static class NonSerializableSub extends MixedSerializable {
+ }
+
+ /**
+ * Subclass that is serializable.
+ */
+ public static class SerializableSub extends MixedSerializable implements
+ Serializable {
+ }
+}
diff --git a/user/test/com/google/gwt/user/client/rpc/MixedSerializableEchoService.java b/user/test/com/google/gwt/user/client/rpc/MixedSerializableEchoService.java
new file mode 100644
index 0000000..0193d9d
--- /dev/null
+++ b/user/test/com/google/gwt/user/client/rpc/MixedSerializableEchoService.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2009 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;
+
+/**
+ * A service whose methods send types across the wire that have both
+ * serializable and unserializable subclasses.
+ */
+public interface MixedSerializableEchoService extends RemoteService {
+ MixedSerializable echoVoid(MixedSerializable mixed);
+
+ MixedSerializable echoRequest(MixedSerializable mixed);
+
+ MixedSerializable echoRequestBuilder(MixedSerializable mixed);
+}
diff --git a/user/test/com/google/gwt/user/client/rpc/MixedSerializableEchoServiceAsync.java b/user/test/com/google/gwt/user/client/rpc/MixedSerializableEchoServiceAsync.java
new file mode 100644
index 0000000..287ce59
--- /dev/null
+++ b/user/test/com/google/gwt/user/client/rpc/MixedSerializableEchoServiceAsync.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2009 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;
+
+import com.google.gwt.http.client.Request;
+import com.google.gwt.http.client.RequestBuilder;
+
+/**
+ * The async interface for {@link MixedSerializableEchoService}.
+ */
+public interface MixedSerializableEchoServiceAsync {
+ void echoVoid(MixedSerializable mixed,
+ AsyncCallback<MixedSerializable> callback);
+
+ Request echoRequest(MixedSerializable mixed,
+ AsyncCallback<MixedSerializable> callback);
+
+ RequestBuilder echoRequestBuilder(MixedSerializable mixed,
+ AsyncCallback<MixedSerializable> callback);
+}
diff --git a/user/test/com/google/gwt/user/client/rpc/RunTimeSerializationErrorsTest.java b/user/test/com/google/gwt/user/client/rpc/RunTimeSerializationErrorsTest.java
new file mode 100644
index 0000000..33e6adb
--- /dev/null
+++ b/user/test/com/google/gwt/user/client/rpc/RunTimeSerializationErrorsTest.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2009 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;
+
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.http.client.Request;
+import com.google.gwt.http.client.RequestBuilder;
+import com.google.gwt.http.client.RequestException;
+import com.google.gwt.junit.client.GWTTestCase;
+
+/**
+ * Tests run-time serialization errors for GWT RPC.
+ */
+public class RunTimeSerializationErrorsTest extends GWTTestCase {
+ private static final int TIMEOUT = 20000;
+
+ public static MixedSerializableEchoServiceAsync getService() {
+ MixedSerializableEchoServiceAsync service = GWT.create(MixedSerializableEchoService.class);
+
+ ((ServiceDefTarget) service).setServiceEntryPoint(GWT.getModuleBaseURL()
+ + "echo");
+
+ return service;
+ }
+
+ @Override
+ public String getModuleName() {
+ return "com.google.gwt.user.RPCSuite";
+ }
+
+ public void testBadSerialization1() {
+ delayTestFinish(TIMEOUT);
+ getService().echoVoid(new MixedSerializable.NonSerializableSub(),
+ new AsyncCallback<MixedSerializable>() {
+ public void onFailure(Throwable caught) {
+ finishTest();
+ }
+
+ public void onSuccess(MixedSerializable result) {
+ fail("RPC request should have failed");
+ }
+ });
+ }
+
+ public void testBadSerialization2() {
+ final boolean[] callbackFired = new boolean[] {false};
+
+ Request req = getService().echoRequest(
+ new MixedSerializable.NonSerializableSub(),
+ new AsyncCallback<MixedSerializable>() {
+ public void onFailure(Throwable caught) {
+ callbackFired[0] = true;
+ }
+
+ public void onSuccess(MixedSerializable result) {
+ fail("RPC request should have failed");
+ }
+ });
+
+ assertTrue(callbackFired[0]); // should have happened synchronously
+ assertFalse(req.isPending());
+ req.cancel();
+ }
+
+ public void testBadSerialization3() throws RequestException {
+ final boolean[] callbackFired = new boolean[] {false};
+
+ RequestBuilder rb = getService().echoRequestBuilder(
+ new MixedSerializable.NonSerializableSub(),
+ new AsyncCallback<MixedSerializable>() {
+ public void onFailure(Throwable caught) {
+ assertFalse("callback fired twice", callbackFired[0]);
+ callbackFired[0] = true;
+ }
+
+ public void onSuccess(MixedSerializable result) {
+ fail("RPC request should have failed");
+ }
+ });
+
+ assertFalse(callbackFired[0]); // should fail when send() is called
+ rb.send();
+ assertTrue(callbackFired[0]); // should have happened now
+ }
+
+ public void testGoodSerialization1() {
+ delayTestFinish(TIMEOUT);
+ getService().echoVoid(new MixedSerializable.SerializableSub(),
+ new AsyncCallback<MixedSerializable>() {
+ public void onFailure(Throwable caught) {
+ fail(caught.toString());
+ }
+
+ public void onSuccess(MixedSerializable result) {
+ finishTest();
+ }
+ });
+ }
+
+ public void testGoodSerialization2() {
+ delayTestFinish(TIMEOUT);
+ getService().echoRequest(new MixedSerializable.SerializableSub(),
+ new AsyncCallback<MixedSerializable>() {
+ public void onFailure(Throwable caught) {
+ fail(caught.toString());
+ }
+
+ public void onSuccess(MixedSerializable result) {
+ finishTest();
+ }
+ });
+ }
+
+ public void testGoodSerialization3() {
+ delayTestFinish(TIMEOUT);
+ getService().echoVoid(new MixedSerializable.SerializableSub(),
+ new AsyncCallback<MixedSerializable>() {
+ public void onFailure(Throwable caught) {
+ fail(caught.toString());
+ }
+
+ public void onSuccess(MixedSerializable result) {
+ finishTest();
+ }
+ });
+ }
+}
\ No newline at end of file
diff --git a/user/test/com/google/gwt/user/server/rpc/MixedSerializableEchoServiceImpl.java b/user/test/com/google/gwt/user/server/rpc/MixedSerializableEchoServiceImpl.java
new file mode 100644
index 0000000..18de78c
--- /dev/null
+++ b/user/test/com/google/gwt/user/server/rpc/MixedSerializableEchoServiceImpl.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2009 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.server.rpc;
+
+import com.google.gwt.user.client.rpc.MixedSerializable;
+import com.google.gwt.user.client.rpc.MixedSerializableEchoService;
+
+/**
+ * Servlet used by the
+ * {@link com.google.gwt.user.client.rpc.RunTimeSerializationErrorsTest}.
+ */
+public class MixedSerializableEchoServiceImpl extends RemoteServiceServlet
+ implements MixedSerializableEchoService {
+ public MixedSerializable echoVoid(MixedSerializable mixed) {
+ return mixed;
+ }
+
+ public MixedSerializable echoRequest(MixedSerializable mixed) {
+ return mixed;
+ }
+
+ public MixedSerializable echoRequestBuilder(MixedSerializable mixed) {
+ return mixed;
+ }
+}