Revision: 9543
Author: robertvaw...@google.com
Date: Fri Jan 14 04:27:42 2011
Log: Public (by t.broyer):
Don't allow exceptions escaping from RequestFactory Receiver callback
methods to prevent other callbacks from being called.
Issue 5872
http://gwt-code-reviews.appspot.com/1290801/show
Patch by: t.broyer
Review by: bobv
http://code.google.com/p/google-web-toolkit/source/detail?r=9543
Added:
/trunk/user/test/com/google/gwt/requestfactory/client/RequestFactoryExceptionPropagationTest.java
/trunk/user/test/com/google/gwt/requestfactory/server/RequestFactoryExceptionPropagationJreTest.java
Modified:
/trunk/user/src/com/google/gwt/requestfactory/server/testing/InProcessRequestTransport.java
/trunk/user/src/com/google/gwt/requestfactory/shared/impl/AbstractRequestContext.java
/trunk/user/test/com/google/gwt/requestfactory/RequestFactoryJreSuite.java
/trunk/user/test/com/google/gwt/requestfactory/RequestFactorySuite.java
/trunk/user/test/com/google/gwt/requestfactory/server/SimpleFoo.java
/trunk/user/test/com/google/gwt/requestfactory/shared/SimpleFooRequest.java
=======================================
--- /dev/null
+++
/trunk/user/test/com/google/gwt/requestfactory/client/RequestFactoryExceptionPropagationTest.java
Fri Jan 14 04:27:42 2011
@@ -0,0 +1,308 @@
+/*
+ * 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
+ * License for the specific language governing permissions and limitations
under
+ * the License.
+ */
+package com.google.gwt.requestfactory.client;
+
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.event.shared.UmbrellaException;
+import com.google.gwt.requestfactory.shared.Receiver;
+import com.google.gwt.requestfactory.shared.RequestContext;
+import com.google.gwt.requestfactory.shared.ServerFailure;
+import com.google.gwt.requestfactory.shared.SimpleFooProxy;
+import com.google.gwt.requestfactory.shared.SimpleFooRequest;
+import com.google.gwt.requestfactory.shared.Violation;
+
+import java.util.Set;
+
+/**
+ * Tests that an exception thrown by a {@link Receiver} does not prevent
other
+ * {@link Receiver}s from being called.
+ */
+public class RequestFactoryExceptionPropagationTest extends
+ RequestFactoryTestBase {
+ /*
+ * DO NOT USE finishTest(). Instead, call finishTestAndReset();
+ */
+
+ private class CountingReceiver extends Receiver<Object> {
+ int failureCallCount;
+ int successCallCount;
+ int violationCallCount;
+
+ public void assertCounts(int expectedFailureCallCount,
+ int expectedSuccessCallCount, int expectedViolationCallCount) {
+ assertEquals(expectedFailureCallCount, failureCallCount);
+ assertEquals(expectedSuccessCallCount, successCallCount);
+ assertEquals(expectedViolationCallCount, violationCallCount);
+ }
+
+ @Override
+ public void onFailure(ServerFailure error) {
+ failureCallCount++;
+ }
+
+ @Override
+ public void onSuccess(Object response) {
+ successCallCount++;
+ }
+
+ @Override
+ public void onViolation(Set<Violation> errors) {
+ violationCallCount++;
+ }
+ }
+
+ private class ThrowingReceiver<T> extends Receiver<T> {
+ private final RuntimeException e;
+
+ public ThrowingReceiver(RuntimeException e) {
+ this.e = e;
+ }
+
+ @Override
+ public void onFailure(ServerFailure error) {
+ throw e;
+ }
+
+ @Override
+ public void onSuccess(T response) {
+ throw e;
+ }
+
+ @Override
+ public void onViolation(Set<Violation> errors) {
+ throw e;
+ }
+ }
+
+ private static final int DELAY_TEST_FINISH = 10 * 1000;
+
+ GWT.UncaughtExceptionHandler defaultUncaughtExceptionHandler;
+
+ @Override
+ public String getModuleName() {
+ return "com.google.gwt.requestfactory.RequestFactorySuite";
+ }
+
+ @Override
+ public void gwtSetUp() {
+ super.gwtSetUp();
+
+ defaultUncaughtExceptionHandler = GWT.getUncaughtExceptionHandler();
+ }
+
+ /**
+ * Test mixed invocation failure and success. One receiver will throw
from
+ * onSuccess and another from onFailure. Other receivers onSuccess and
+ * onFailure will corectly be called.
+ */
+ public void testMixedSuccessAndFailureThrow() {
+ delayTestFinish(DELAY_TEST_FINISH);
+
+ final RuntimeException exception1 = new RuntimeException("first
exception");
+ final RuntimeException exception2 = new RuntimeException("second
exception");
+ final CountingReceiver count = new CountingReceiver();
+
+ SimpleFooRequest context = req.simpleFooRequest();
+ // 42 is the crash causing magic number for a runtime exception
+ context.pleaseCrash(42).to(count);
+ context.returnNullString().to(new
ThrowingReceiver<String>(exception1));
+ context.returnNullString().to(count);
+
+ fireContextAndCatch(context, new ThrowingReceiver<Void>(exception2),
+ new GWT.UncaughtExceptionHandler() {
+ public void onUncaughtException(Throwable e) {
+ if (e instanceof UmbrellaException) {
+ count.assertCounts(1, 1, 0);
+
+ Set<Throwable> causes = ((UmbrellaException) e).getCauses();
+ assertEquals(2, causes.size());
+ assertTrue(causes.contains(exception1));
+ assertTrue(causes.contains(exception2));
+
+ finishTestAndReset();
+ } else {
+ defaultUncaughtExceptionHandler.onUncaughtException(e);
+ }
+ }
+ });
+ }
+
+ /**
+ * Test invocation failure. Other invocations' onSuccess should
correctly be
+ * called.
+ */
+ public void testOnFailureThrow() {
+ delayTestFinish(DELAY_TEST_FINISH);
+
+ final RuntimeException exception1 = new RuntimeException("first
exception");
+ final RuntimeException exception2 = new RuntimeException("second
exception");
+ final CountingReceiver count = new CountingReceiver();
+
+ SimpleFooRequest context = req.simpleFooRequest();
+ context.returnNullString().to(count);
+ // 42 is the crash causing magic number for a runtime exception
+ context.pleaseCrash(42).to(new ThrowingReceiver<Void>(exception1));
+ context.returnNullString().to(count);
+
+ fireContextAndCatch(context, new ThrowingReceiver<Void>(exception2),
+ new GWT.UncaughtExceptionHandler() {
+ public void onUncaughtException(Throwable e) {
+ if (e instanceof UmbrellaException) {
+ count.assertCounts(0, 2, 0);
+
+ Set<Throwable> causes = ((UmbrellaException) e).getCauses();
+ assertEquals(2, causes.size());
+ assertTrue(causes.contains(exception1));
+ assertTrue(causes.contains(exception2));
+
+ finishTestAndReset();
+ } else {
+ defaultUncaughtExceptionHandler.onUncaughtException(e);
+ }
+ }
+ });
+ }
+
+ /**
+ * Test global failure. All receivers will have their onFailure called,
and
+ * some of them will throw.
+ */
+ public void testOnGlobalFailureThrow() {
+ delayTestFinish(DELAY_TEST_FINISH);
+
+ final RuntimeException exception1 = new RuntimeException("first
exception");
+ final RuntimeException exception2 = new RuntimeException("second
exception");
+ final CountingReceiver count = new CountingReceiver();
+
+ SimpleFooRequest context = req.simpleFooRequest();
+ SimpleFooProxy newFoo = context.create(SimpleFooProxy.class);
+
+ context.returnNullString().to(count);
+ context.persist().using(newFoo).to(new
ThrowingReceiver<Void>(exception1));
+ context.returnNullString().to(count);
+
+ final SimpleFooProxy mutableFoo = context.edit(newFoo);
+ // 42 is the crash causing magic number for a runtime exception
+ mutableFoo.setPleaseCrash(42);
+
+ fireContextAndCatch(context, new ThrowingReceiver<Void>(exception2),
+ new GWT.UncaughtExceptionHandler() {
+ public void onUncaughtException(Throwable e) {
+ if (e instanceof UmbrellaException) {
+ count.assertCounts(2, 0, 0);
+
+ Set<Throwable> causes = ((UmbrellaException) e).getCauses();
+ assertEquals(2, causes.size());
+ assertTrue(causes.contains(exception1));
+ assertTrue(causes.contains(exception2));
+
+ finishTestAndReset();
+ } else {
+ defaultUncaughtExceptionHandler.onUncaughtException(e);
+ }
+ }
+ });
+ }
+
+ /**
+ * All receivers will have their onSuccess called, and some of them will
+ * throw.
+ */
+ public void testOnSuccessThrow() {
+ delayTestFinish(DELAY_TEST_FINISH);
+
+ final RuntimeException exception1 = new RuntimeException("first
exception");
+ final RuntimeException exception2 = new RuntimeException("second
exception");
+ final CountingReceiver count = new CountingReceiver();
+
+ SimpleFooRequest context = req.simpleFooRequest();
+ context.returnNullString().to(count);
+ context.returnNullString().to(new
ThrowingReceiver<String>(exception1));
+ context.returnNullString().to(count);
+
+ fireContextAndCatch(context, new ThrowingReceiver<Void>(exception2),
+ new GWT.UncaughtExceptionHandler() {
+ public void onUncaughtException(Throwable e) {
+ if (e instanceof UmbrellaException) {
+ count.assertCounts(0, 2, 0);
+
+ Set<Throwable> causes = ((UmbrellaException) e).getCauses();
+ assertEquals(2, causes.size());
+ assertTrue(causes.contains(exception1));
+ assertTrue(causes.contains(exception2));
+
+ finishTestAndReset();
+ } else {
+ defaultUncaughtExceptionHandler.onUncaughtException(e);
+ }
+ }
+ });
+ }
+
+ /**
+ * Test violations. All receivers will have their onViolation called,
and some
+ * of them will throw.
+ */
+ public void testOnViolationThrow() {
+ delayTestFinish(DELAY_TEST_FINISH);
+
+ final RuntimeException exception1 = new RuntimeException("first
exception");
+ final RuntimeException exception2 = new RuntimeException("second
exception");
+ final CountingReceiver count = new CountingReceiver();
+
+ SimpleFooRequest context = req.simpleFooRequest();
+ SimpleFooProxy newFoo = context.create(SimpleFooProxy.class);
+ newFoo.setUserName("a"); // too short
+
+ context.returnNullString().to(count);
+ context.persist().using(newFoo).to(new
ThrowingReceiver<Void>(exception1));
+ context.returnNullString().to(count);
+
+ fireContextAndCatch(context, new ThrowingReceiver<Void>(exception2),
+ new GWT.UncaughtExceptionHandler() {
+ public void onUncaughtException(Throwable e) {
+ if (e instanceof UmbrellaException) {
+ count.assertCounts(0, 0, 2);
+
+ Set<Throwable> causes = ((UmbrellaException) e).getCauses();
+ assertEquals(2, causes.size());
+ assertTrue(causes.contains(exception1));
+ assertTrue(causes.contains(exception2));
+
+ finishTestAndReset();
+ } else {
+ defaultUncaughtExceptionHandler.onUncaughtException(e);
+ }
+ }
+ });
+ }
+
+ protected void fireContextAndCatch(RequestContext context,
+ Receiver<Void> receiver, GWT.UncaughtExceptionHandler
exceptionHandler) {
+ GWT.setUncaughtExceptionHandler(exceptionHandler);
+
+ if (receiver == null) {
+ context.fire();
+ } else {
+ context.fire(receiver);
+ }
+ }
+
+ @Override
+ protected void gwtTearDown() throws Exception {
+ GWT.setUncaughtExceptionHandler(defaultUncaughtExceptionHandler);
+ }
+}
=======================================
--- /dev/null
+++
/trunk/user/test/com/google/gwt/requestfactory/server/RequestFactoryExceptionPropagationJreTest.java
Fri Jan 14 04:27:42 2011
@@ -0,0 +1,52 @@
+/*
+ * 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
+ * License for the specific language governing permissions and limitations
under
+ * the License.
+ */
+package com.google.gwt.requestfactory.server;
+
+import com.google.gwt.core.client.GWT;
+import
com.google.gwt.requestfactory.client.RequestFactoryExceptionPropagationTest;
+import com.google.gwt.requestfactory.shared.Receiver;
+import com.google.gwt.requestfactory.shared.RequestContext;
+import com.google.gwt.requestfactory.shared.SimpleRequestFactory;
+
+/**
+ * JRE version of {@link RequestFactoryExceptionPropagationTest}.
+ */
+public class RequestFactoryExceptionPropagationJreTest extends
+ RequestFactoryExceptionPropagationTest {
+ @Override
+ public String getModuleName() {
+ return null;
+ }
+
+ @Override
+ protected SimpleRequestFactory createFactory() {
+ return
RequestFactoryJreTest.createInProcess(SimpleRequestFactory.class);
+ }
+
+ @Override
+ protected void fireContextAndCatch(RequestContext context,
+ Receiver<Void> receiver, GWT.UncaughtExceptionHandler
exceptionHandler) {
+ try {
+ if (receiver == null) {
+ context.fire();
+ } else {
+ context.fire(receiver);
+ }
+ } catch (Throwable e) {
+ exceptionHandler.onUncaughtException(e);
+ }
+ }
+}
=======================================
---
/trunk/user/src/com/google/gwt/requestfactory/server/testing/InProcessRequestTransport.java
Tue Dec 7 22:33:06 2010
+++
/trunk/user/src/com/google/gwt/requestfactory/server/testing/InProcessRequestTransport.java
Fri Jan 14 04:27:42 2011
@@ -47,18 +47,20 @@
}
public void send(String payload, TransportReceiver receiver) {
+ String result;
try {
if (DUMP_PAYLOAD) {
System.out.println(">>> " + payload);
}
- String result = processor.process(payload);
+ result = processor.process(payload);
if (DUMP_PAYLOAD) {
System.out.println("<<< " + result);
}
- receiver.onTransportSuccess(result);
} catch (RuntimeException e) {
e.printStackTrace();
receiver.onTransportFailure(new ServerFailure(e.getMessage()));
- }
+ return;
+ }
+ receiver.onTransportSuccess(result);
}
}
=======================================
---
/trunk/user/src/com/google/gwt/requestfactory/shared/impl/AbstractRequestContext.java
Wed Dec 8 08:24:06 2010
+++
/trunk/user/src/com/google/gwt/requestfactory/shared/impl/AbstractRequestContext.java
Fri Jan 14 04:27:42 2011
@@ -24,6 +24,7 @@
import com.google.gwt.autobean.shared.AutoBeanVisitor;
import com.google.gwt.autobean.shared.Splittable;
import com.google.gwt.autobean.shared.ValueCodex;
+import com.google.gwt.event.shared.UmbrellaException;
import com.google.gwt.requestfactory.shared.BaseProxy;
import com.google.gwt.requestfactory.shared.EntityProxy;
import com.google.gwt.requestfactory.shared.EntityProxyChange;
@@ -628,14 +629,7 @@
errors.add(new MyViolation(message));
}
- reuse();
- for (AbstractRequest<?> request : new
ArrayList<AbstractRequest<?>>(
- invocations)) {
- request.onViolation(errors);
- }
- if (receiver != null) {
- receiver.onViolation(errors);
- }
+ violation(receiver, errors);
return;
}
@@ -643,37 +637,115 @@
processReturnOperations(response);
// Send return values
+ Set<Throwable> causes = null;
for (int i = 0, j = invocations.size(); i < j; i++) {
- if (response.getStatusCodes().get(i)) {
-
invocations.get(i).onSuccess(response.getInvocationResults().get(i));
- } else {
- ServerFailureMessage failure = AutoBeanCodex.decode(
- MessageFactoryHolder.FACTORY, ServerFailureMessage.class,
- response.getInvocationResults().get(i)).as();
- invocations.get(i).onFail(
- new ServerFailure(failure.getMessage(),
- failure.getExceptionType(), failure.getStackTrace(),
- failure.isFatal()));
+ try {
+ if (response.getStatusCodes().get(i)) {
+ invocations.get(i).onSuccess(
+ response.getInvocationResults().get(i));
+ } else {
+ ServerFailureMessage failure = AutoBeanCodex.decode(
+ MessageFactoryHolder.FACTORY, ServerFailureMessage.class,
+ response.getInvocationResults().get(i)).as();
+ invocations.get(i).onFail(
+ new ServerFailure(failure.getMessage(),
+ failure.getExceptionType(), failure.getStackTrace(),
+ failure.isFatal()));
+ }
+ } catch (Throwable t) {
+ if (causes == null) {
+ causes = new HashSet<Throwable>();
+ }
+ causes.add(t);
}
}
if (receiver != null) {
- receiver.onSuccess(null);
+ try {
+ receiver.onSuccess(null);
+ } catch (Throwable t) {
+ if (causes == null) {
+ causes = new HashSet<Throwable>();
+ }
+ causes.add(t);
+ }
}
// After success, shut down the context
editedProxies.clear();
invocations.clear();
returnedProxies.clear();
+
+ if (causes != null) {
+ throw new UmbrellaException(causes);
+ }
}
+ /**
+ * Invoke the appropriate {@code onFailure} callbacks, possibly
throwing
+ * an {@link UmbrellaException} if one or more callbacks fails.
+ */
private void fail(Receiver<Void> receiver, ServerFailure failure) {
reuse();
+ Set<Throwable> causes = null;
for (AbstractRequest<?> request : new
ArrayList<AbstractRequest<?>>(
invocations)) {
- request.onFail(failure);
+ try {
+ request.onFail(failure);
+ } catch (Throwable t) {
+ if (causes == null) {
+ causes = new HashSet<Throwable>();
+ }
+ causes.add(t);
+ }
}
if (receiver != null) {
- receiver.onFailure(failure);
+ try {
+ receiver.onFailure(failure);
+ } catch (Throwable t) {
+ if (causes == null) {
+ causes = new HashSet<Throwable>();
+ }
+ causes.add(t);
+ }
+ }
+
+ if (causes != null) {
+ throw new UmbrellaException(causes);
+ }
+ }
+
+ /**
+ * Invoke the appropriate {@code onViolation} callbacks, possibly
throwing
+ * an {@link UmbrellaException} if one or more callbacks fails.
+ */
+ private void violation(final Receiver<Void> receiver,
+ Set<Violation> errors) {
+ reuse();
+ Set<Throwable> causes = null;
+ for (AbstractRequest<?> request : new
ArrayList<AbstractRequest<?>>(
+ invocations)) {
+ try {
+ request.onViolation(errors);
+ } catch (Throwable t) {
+ if (causes == null) {
+ causes = new HashSet<Throwable>();
+ }
+ causes.add(t);
+ }
+ }
+ if (receiver != null) {
+ try {
+ receiver.onViolation(errors);
+ } catch (Throwable t) {
+ if (causes == null) {
+ causes = new HashSet<Throwable>();
+ }
+ causes.add(t);
+ }
+ }
+
+ if (causes != null) {
+ throw new UmbrellaException(causes);
}
}
});
=======================================
---
/trunk/user/test/com/google/gwt/requestfactory/RequestFactoryJreSuite.java
Tue Dec 14 07:17:57 2010
+++
/trunk/user/test/com/google/gwt/requestfactory/RequestFactoryJreSuite.java
Fri Jan 14 04:27:42 2011
@@ -20,6 +20,7 @@
import com.google.gwt.requestfactory.server.ComplexKeysJreTest;
import com.google.gwt.requestfactory.server.FindServiceJreTest;
import com.google.gwt.requestfactory.server.LocatorJreTest;
+import
com.google.gwt.requestfactory.server.RequestFactoryExceptionPropagationJreTest;
import
com.google.gwt.requestfactory.server.RequestFactoryInterfaceValidatorTest;
import com.google.gwt.requestfactory.server.RequestFactoryJreTest;
import
com.google.gwt.requestfactory.server.RequestFactoryUnicodeEscapingJreTest;
@@ -39,11 +40,12 @@
suite.addTestSuite(ComplexKeysJreTest.class);
suite.addTestSuite(FindServiceJreTest.class);
suite.addTestSuite(LocatorJreTest.class);
- suite.addTestSuite(RequestFactoryJreTest.class);
- suite.addTestSuite(SimpleEntityProxyIdTest.class);
+ suite.addTestSuite(RequestFactoryExceptionPropagationJreTest.class);
suite.addTestSuite(RequestFactoryInterfaceValidatorTest.class);
+ suite.addTestSuite(RequestFactoryJreTest.class);
suite.addTestSuite(RequestFactoryModelTest.class);
suite.addTestSuite(RequestFactoryUnicodeEscapingJreTest.class);
+ suite.addTestSuite(SimpleEntityProxyIdTest.class);
return suite;
}
}
=======================================
--- /trunk/user/test/com/google/gwt/requestfactory/RequestFactorySuite.java
Tue Dec 14 07:17:57 2010
+++ /trunk/user/test/com/google/gwt/requestfactory/RequestFactorySuite.java
Fri Jan 14 04:27:42 2011
@@ -18,6 +18,7 @@
import com.google.gwt.junit.tools.GWTTestSuite;
import com.google.gwt.requestfactory.client.FindServiceTest;
import
com.google.gwt.requestfactory.client.RequestFactoryExceptionHandlerTest;
+import
com.google.gwt.requestfactory.client.RequestFactoryExceptionPropagationTest;
import com.google.gwt.requestfactory.client.RequestFactoryPolymorphicTest;
import com.google.gwt.requestfactory.client.RequestFactoryTest;
import
com.google.gwt.requestfactory.client.RequestFactoryUnicodeEscapingTest;
@@ -42,6 +43,7 @@
suite.addTestSuite(LocatorTest.class);
suite.addTestSuite(RequestFactoryTest.class);
suite.addTestSuite(RequestFactoryExceptionHandlerTest.class);
+ suite.addTestSuite(RequestFactoryExceptionPropagationTest.class);
suite.addTestSuite(RequestFactoryPolymorphicTest.class);
suite.addTestSuite(RequestFactoryUnicodeEscapingTest.class);
return suite;
=======================================
--- /trunk/user/test/com/google/gwt/requestfactory/server/SimpleFoo.java
Tue Dec 14 07:17:57 2010
+++ /trunk/user/test/com/google/gwt/requestfactory/server/SimpleFoo.java
Fri Jan 14 04:27:42 2011
@@ -169,6 +169,16 @@
foo.setUnpersisted(true);
return foo;
}
+
+ public static void pleaseCrash(Integer crashIf42or43) throws Exception {
+ if (crashIf42or43 == 42) {
+ throw new UnsupportedOperationException(
+ "THIS EXCEPTION IS EXPECTED BY A TEST");
+ }
+ if (crashIf42or43 == 43) {
+ throw new Exception("THIS EXCEPTION IS EXPECTED BY A TEST");
+ }
+ }
/**
* Check client-side upcasting to BigDecimal and return a list of
BigDecimals
@@ -754,13 +764,7 @@
}
public void setPleaseCrash(Integer crashIf42or43) throws Exception {
- if (crashIf42or43 == 42) {
- throw new UnsupportedOperationException(
- "THIS EXCEPTION IS EXPECTED BY A TEST");
- }
- if (crashIf42or43 == 43) {
- throw new Exception("THIS EXCEPTION IS EXPECTED BY A TEST");
- }
+ pleaseCrash(crashIf42or43);
pleaseCrash = crashIf42or43;
}
=======================================
---
/trunk/user/test/com/google/gwt/requestfactory/shared/SimpleFooRequest.java
Wed Dec 8 12:37:05 2010
+++
/trunk/user/test/com/google/gwt/requestfactory/shared/SimpleFooRequest.java
Fri Jan 14 04:27:42 2011
@@ -50,7 +50,7 @@
Request<Set<Integer>> getNumberSet();
Request<SimpleFooProxy> getSimpleFooWithNullVersion();
-
+
Request<SimpleFooProxy> getSimpleFooWithSubPropertyCollection();
Request<SimpleFooProxy> getTripletReference();
@@ -65,10 +65,12 @@
InstanceRequest<SimpleFooProxy, SimpleFooProxy>
persistCascadingAndReturnSelf();
- Request<List<BigInteger>> processBigIntegerList(List<BigInteger> values);
+ Request<Void> pleaseCrash(Integer crashIf42or43);
Request<List<BigDecimal>> processBigDecimalList(List<BigDecimal> values);
+ Request<List<BigInteger>> processBigIntegerList(List<BigInteger> values);
+
Request<Boolean> processBooleanList(List<Boolean> values);
Request<List<Date>> processDateList(List<Date> values);
--
http://groups.google.com/group/Google-Web-Toolkit-Contributors