Revision: 10239
Author: [email protected]
Date: Fri May 27 05:11:13 2011
Log: Add RequestContext.find() to support chained requests.
Patch by: bobv
Review by: rjrjr
Review at http://gwt-code-reviews.appspot.com/1448806
http://code.google.com/p/google-web-toolkit/source/detail?r=10239
Added:
/trunk/user/src/com/google/web/bindery/requestfactory/shared/testing
/trunk/user/src/com/google/web/bindery/requestfactory/shared/testing/FakeRequestContext.java
Modified:
/trunk/user/src/com/google/web/bindery/requestfactory/shared/RequestContext.java
/trunk/user/src/com/google/web/bindery/requestfactory/shared/RequestFactory.java
/trunk/user/src/com/google/web/bindery/requestfactory/shared/impl/AbstractRequestContext.java
/trunk/user/src/com/google/web/bindery/requestfactory/shared/impl/AbstractRequestFactory.java
/trunk/user/test/com/google/web/bindery/requestfactory/gwt/client/FindServiceTest.java
=======================================
--- /dev/null
+++
/trunk/user/src/com/google/web/bindery/requestfactory/shared/testing/FakeRequestContext.java
Fri May 27 05:11:13 2011
@@ -0,0 +1,84 @@
+/*
+ * 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.web.bindery.requestfactory.shared.testing;
+
+import com.google.web.bindery.requestfactory.shared.BaseProxy;
+import com.google.web.bindery.requestfactory.shared.EntityProxy;
+import com.google.web.bindery.requestfactory.shared.EntityProxyId;
+import com.google.web.bindery.requestfactory.shared.Receiver;
+import com.google.web.bindery.requestfactory.shared.Request;
+import com.google.web.bindery.requestfactory.shared.RequestContext;
+
+/**
+ * A no-op implementation of RequestConext that can be used as a base type
for
+ * writing unit tests.
+ */
+public class FakeRequestContext implements RequestContext {
+
+ /**
+ * Always returns {@code other}.
+ */
+ @Override
+ public <T extends RequestContext> T append(T other) {
+ return other;
+ }
+
+ /**
+ * Returns {@code null}.
+ */
+ @Override
+ public <T extends BaseProxy> T create(Class<T> clazz) {
+ return null;
+ }
+
+ /**
+ * Always returns {@code object}.
+ */
+ @Override
+ public <T extends BaseProxy> T edit(T object) {
+ return object;
+ }
+
+ /**
+ * Returns {@code null}.
+ */
+ @Override
+ public <P extends EntityProxy> Request<P> find(EntityProxyId<P> proxyId)
{
+ return null;
+ }
+
+ /**
+ * No-op.
+ */
+ @Override
+ public void fire() {
+ }
+
+ /**
+ * No-op.
+ */
+ @Override
+ public void fire(Receiver<Void> receiver) {
+ }
+
+ /**
+ * Always returns {@code false}.
+ */
+ @Override
+ public boolean isChanged() {
+ return false;
+ }
+}
=======================================
---
/trunk/user/src/com/google/web/bindery/requestfactory/shared/RequestContext.java
Thu Apr 21 12:15:42 2011
+++
/trunk/user/src/com/google/web/bindery/requestfactory/shared/RequestContext.java
Fri May 27 05:11:13 2011
@@ -16,7 +16,11 @@
package com.google.web.bindery.requestfactory.shared;
/**
- * The base interface for RequestFactory service endpoints.
+ * The base interface for RequestFactory service endpoints.
Implementations of
+ * this interface are provided by the RequestFactory plumbing and this
interface
+ * may be extended in the future.
+ *
+ * @see
com.google.web.bindery.requestfactory.shared.testing.FakeRequestContext
*/
public interface RequestContext {
/**
@@ -59,6 +63,14 @@
*/
<T extends BaseProxy> T edit(T object);
+ /**
+ * Return a request to find a fresh instance of the referenced proxy.
+ *
+ * @param proxyId an {@link EntityProxyId} instance of type P
+ * @return a {@link Request} object
+ */
+ <P extends EntityProxy> Request<P> find(EntityProxyId<P> proxyId);
+
/**
* Send the accumulated changes and method invocations associated with
the
* RequestContext.
=======================================
---
/trunk/user/src/com/google/web/bindery/requestfactory/shared/RequestFactory.java
Mon Apr 18 16:25:25 2011
+++
/trunk/user/src/com/google/web/bindery/requestfactory/shared/RequestFactory.java
Fri May 27 05:11:13 2011
@@ -49,10 +49,14 @@
String JSON_CONTENT_TYPE_UTF8 = "application/json; charset=utf-8";
/**
- * Return a request to find a fresh instance of the referenced proxy.
+ * Return a request to find a fresh instance of the referenced proxy. If
it is
+ * necessary to load several proxy instances, use
+ * {@link RequestContext#find(EntityProxyId)}, which supports chained
+ * requests.
*
* @param proxyId an {@link EntityProxyId} instance of type P
* @return a {@link Request} object
+ * @see RequestContext#find(EntityProxyId)
*/
<P extends EntityProxy> Request<P> find(EntityProxyId<P> proxyId);
=======================================
---
/trunk/user/src/com/google/web/bindery/requestfactory/shared/impl/AbstractRequestContext.java
Fri May 27 04:59:21 2011
+++
/trunk/user/src/com/google/web/bindery/requestfactory/shared/impl/AbstractRequestContext.java
Fri May 27 05:11:13 2011
@@ -33,8 +33,10 @@
import com.google.web.bindery.requestfactory.shared.BaseProxy;
import com.google.web.bindery.requestfactory.shared.EntityProxy;
import com.google.web.bindery.requestfactory.shared.EntityProxyChange;
+import com.google.web.bindery.requestfactory.shared.EntityProxyId;
import com.google.web.bindery.requestfactory.shared.FanoutReceiver;
import com.google.web.bindery.requestfactory.shared.Receiver;
+import com.google.web.bindery.requestfactory.shared.Request;
import com.google.web.bindery.requestfactory.shared.RequestContext;
import
com.google.web.bindery.requestfactory.shared.RequestTransport.TransportReceiver;
import com.google.web.bindery.requestfactory.shared.ServerFailure;
@@ -518,6 +520,23 @@
bean.setTag(Constants.PARENT_OBJECT, parent);
return bean.as();
}
+
+ @Override
+ public <P extends EntityProxy> Request<P> find(final EntityProxyId<P>
proxyId) {
+ return new AbstractRequest<P>(this) {
+ {
+ requestContext.addInvocation(this);
+ }
+
+ @Override
+ protected RequestData makeRequestData() {
+ // This method is normally generated, hence the ugly constructor
+ return new RequestData(
+
"com.google.web.bindery.requestfactory.shared.impl.FindRequest::find",
+ new Object[] {proxyId}, propertyRefs, proxyId.getProxyClass(),
null);
+ }
+ };
+ }
/**
* Make sure there's a default receiver so errors don't get dropped. This
=======================================
---
/trunk/user/src/com/google/web/bindery/requestfactory/shared/impl/AbstractRequestFactory.java
Mon Apr 18 16:25:25 2011
+++
/trunk/user/src/com/google/web/bindery/requestfactory/shared/impl/AbstractRequestFactory.java
Fri May 27 05:11:13 2011
@@ -32,15 +32,13 @@
/**
* Base type for generated RF interfaces.
*/
-public abstract class AbstractRequestFactory extends IdFactory implements
- RequestFactory {
+public abstract class AbstractRequestFactory extends IdFactory implements
RequestFactory {
private static final int MAX_VERSION_ENTRIES = 10000;
private EventBus eventBus;
@SuppressWarnings("serial")
- private final Map<String, String> version = new LinkedHashMap<String,
String>(
- 16, 0.75f, true) {
+ private final Map<String, String> version = new LinkedHashMap<String,
String>(16, 0.75f, true) {
@Override
protected boolean removeEldestEntry(Entry<String, String> eldest) {
return size() > MAX_VERSION_ENTRIES;
@@ -48,30 +46,20 @@
};
private RequestTransport transport;
- public <P extends EntityProxy> Request<P> find(final EntityProxyId<P>
proxyId) {
+ public <P extends EntityProxy> Request<P> find(EntityProxyId<P> proxyId)
{
if (((SimpleEntityProxyId<P>) proxyId).isEphemeral()) {
throw new IllegalArgumentException("Cannot fetch unpersisted
entity");
}
- AbstractRequestContext context = new AbstractRequestContext(
- AbstractRequestFactory.this,
AbstractRequestContext.Dialect.STANDARD) {
- @Override
- protected AutoBeanFactory getAutoBeanFactory() {
- return AbstractRequestFactory.this.getAutoBeanFactory();
- }
- };
- return new AbstractRequest<P>(context) {
- {
- requestContext.addInvocation(this);
- }
-
- @Override
- protected RequestData makeRequestData() {
- return new RequestData(
-
"com.google.web.bindery.requestfactory.shared.impl.FindRequest::find",
- new Object[] {proxyId}, propertyRefs, proxyId.getProxyClass(),
null);
- }
- };
+ AbstractRequestContext context =
+ new AbstractRequestContext(AbstractRequestFactory.this,
+ AbstractRequestContext.Dialect.STANDARD) {
+ @Override
+ protected AutoBeanFactory getAutoBeanFactory() {
+ return AbstractRequestFactory.this.getAutoBeanFactory();
+ }
+ };
+ return context.find(proxyId);
}
public EventBus getEventBus() {
@@ -131,15 +119,13 @@
* Used by {@link AbstractRequestContext} to quiesce update events for
objects
* that haven't truly changed.
*/
- protected boolean hasVersionChanged(SimpleProxyId<?> id,
- String observedVersion) {
+ protected boolean hasVersionChanged(SimpleProxyId<?> id, String
observedVersion) {
assert id != null : "id";
assert observedVersion != null : "observedVersion";
String key = getHistoryToken(id);
String existingVersion = version.get(key);
// Return true if we haven't seen this before or the versions differ
- boolean toReturn = existingVersion == null
- || !existingVersion.equals(observedVersion);
+ boolean toReturn = existingVersion == null |
| !existingVersion.equals(observedVersion);
if (toReturn) {
version.put(key, observedVersion);
}
=======================================
---
/trunk/user/test/com/google/web/bindery/requestfactory/gwt/client/FindServiceTest.java
Mon Apr 18 16:25:25 2011
+++
/trunk/user/test/com/google/web/bindery/requestfactory/gwt/client/FindServiceTest.java
Fri May 27 05:11:13 2011
@@ -26,8 +26,13 @@
import com.google.web.bindery.requestfactory.shared.SimpleFooRequest;
import com.google.web.bindery.requestfactory.shared.SimpleRequestFactory;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
/**
- * Tests for {@link
com.google.web.bindery.requestfactory.shared.RequestFactory}.
+ * Tests for {@link
com.google.web.bindery.requestfactory.shared.RequestFactory}
+ * .
*/
public class FindServiceTest extends RequestFactoryTestBase {
/*
@@ -40,60 +45,99 @@
public String getModuleName() {
return "com.google.web.bindery.requestfactory.gwt.RequestFactorySuite";
}
+
+ /**
+ * Tests {@code RequestContext.find()}, which uses the same plumbing as
+ * {@code RequestFactory.find()}, but can be chained.
+ */
+ public void testChainedFind() {
+ delayTestFinish(TEST_DELAY);
+ List<String> ids = Arrays.asList("1L", "999L");
+ final List<SimpleBarProxy> proxies = new ArrayList<SimpleBarProxy>();
+ SimpleBarRequest ctx = req.simpleBarRequest();
+ for (String id : ids) {
+ ctx.findSimpleBarById(id).to(new Receiver<SimpleBarProxy>() {
+ @Override
+ public void onSuccess(SimpleBarProxy response) {
+ proxies.add(response);
+ }
+ });
+ }
+ ctx.fire(new Receiver<Void>() {
+ @Override
+ public void onSuccess(Void response) {
+ final List<SimpleBarProxy> reloaded = new
ArrayList<SimpleBarProxy>();
+ SimpleBarRequest ctx = req.simpleBarRequest();
+ for (SimpleBarProxy proxy : proxies) {
+ ctx.find(proxy.stableId()).to(new Receiver<SimpleBarProxy>() {
+ @Override
+ public void onSuccess(SimpleBarProxy response) {
+ reloaded.add(response);
+ }
+ });
+ }
+ ctx.fire(new Receiver<Void>() {
+ @Override
+ public void onSuccess(Void response) {
+ assertEquals(proxies, reloaded);
+ finishTest();
+ }
+ });
+ }
+ });
+ }
public void testFetchDeletedEntity() {
delayTestFinish(TEST_DELAY);
SimpleBarRequest context = req.simpleBarRequest();
SimpleBarProxy willDelete = context.create(SimpleBarProxy.class);
- context.persistAndReturnSelf().using(willDelete).fire(
- new Receiver<SimpleBarProxy>() {
- @Override
- public void onSuccess(SimpleBarProxy response) {
- final EntityProxyId<SimpleBarProxy> id = response.stableId();
-
- // Make the entity behave as though it's been deleted
- SimpleBarRequest context = req.simpleBarRequest();
- Request<Void> persist = context.persist().using(response);
- context.edit(response).setFindFails(true);
- persist.fire(new Receiver<Void>() {
-
+ context.persistAndReturnSelf().using(willDelete).fire(new
Receiver<SimpleBarProxy>() {
+ @Override
+ public void onSuccess(SimpleBarProxy response) {
+ final EntityProxyId<SimpleBarProxy> id = response.stableId();
+
+ // Make the entity behave as though it's been deleted
+ SimpleBarRequest context = req.simpleBarRequest();
+ Request<Void> persist = context.persist().using(response);
+ context.edit(response).setFindFails(true);
+ persist.fire(new Receiver<Void>() {
+
+ @Override
+ public void onSuccess(Void response) {
+ // Now try fetching the deleted instance
+ req.find(id).fire(new Receiver<SimpleBarProxy>() {
@Override
- public void onSuccess(Void response) {
- // Now try fetching the deleted instance
- req.find(id).fire(new Receiver<SimpleBarProxy>() {
- @Override
- public void onSuccess(SimpleBarProxy response) {
- assertNull(response);
- finishTestAndReset();
- }
- });
+ public void onSuccess(SimpleBarProxy response) {
+ assertNull(response);
+ finishTestAndReset();
}
});
}
});
+ }
+ });
}
public void testFetchEntityWithLongId() {
final boolean relationsAbsent = false;
delayTestFinish(TEST_DELAY);
- req.simpleFooRequest().findSimpleFooById(999L).fire(
- new Receiver<SimpleFooProxy>() {
- @Override
- public void onSuccess(SimpleFooProxy response) {
- checkReturnedProxy(response, relationsAbsent);
-
- final EntityProxyId<SimpleFooProxy> stableId =
response.stableId();
- req.find(stableId).fire(new Receiver<SimpleFooProxy>() {
-
- @Override
- public void onSuccess(SimpleFooProxy returnedProxy) {
- assertEquals(stableId, returnedProxy.stableId());
- checkReturnedProxy(returnedProxy, relationsAbsent);
- finishTestAndReset();
- }
- });
+ req.simpleFooRequest().findSimpleFooById(999L).fire(new
Receiver<SimpleFooProxy>() {
+ @Override
+ public void onSuccess(SimpleFooProxy response) {
+ checkReturnedProxy(response, relationsAbsent);
+
+ final EntityProxyId<SimpleFooProxy> stableId = response.stableId();
+ req.find(stableId).fire(new Receiver<SimpleFooProxy>() {
+
+ @Override
+ public void onSuccess(SimpleFooProxy returnedProxy) {
+ assertEquals(stableId, returnedProxy.stableId());
+ checkReturnedProxy(returnedProxy, relationsAbsent);
+ finishTestAndReset();
}
});
+ }
+ });
}
public void testFetchEntityWithRelation() {
@@ -106,68 +150,65 @@
checkReturnedProxy(response, relationsPresent);
final EntityProxyId<SimpleFooProxy> stableId =
response.stableId();
- req.find(stableId).with("barField").fire(
- new Receiver<SimpleFooProxy>() {
-
- @Override
- public void onSuccess(SimpleFooProxy returnedProxy) {
- assertEquals(stableId, returnedProxy.stableId());
- checkReturnedProxy(returnedProxy, relationsPresent);
- finishTestAndReset();
- }
- });
+ req.find(stableId).with("barField").fire(new
Receiver<SimpleFooProxy>() {
+
+ @Override
+ public void onSuccess(SimpleFooProxy returnedProxy) {
+ assertEquals(stableId, returnedProxy.stableId());
+ checkReturnedProxy(returnedProxy, relationsPresent);
+ finishTestAndReset();
+ }
+ });
}
});
}
public void testFetchEntityWithStringId() {
delayTestFinish(TEST_DELAY);
- req.simpleBarRequest().findSimpleBarById("999L").fire(
- new Receiver<SimpleBarProxy>() {
- @Override
- public void onSuccess(SimpleBarProxy response) {
- final EntityProxyId<SimpleBarProxy> stableId =
response.stableId();
- req.find(stableId).fire(new Receiver<SimpleBarProxy>() {
-
- @Override
- public void onSuccess(SimpleBarProxy returnedProxy) {
- assertEquals(stableId, returnedProxy.stableId());
- finishTestAndReset();
- }
- });
+ req.simpleBarRequest().findSimpleBarById("999L").fire(new
Receiver<SimpleBarProxy>() {
+ @Override
+ public void onSuccess(SimpleBarProxy response) {
+ final EntityProxyId<SimpleBarProxy> stableId = response.stableId();
+ req.find(stableId).fire(new Receiver<SimpleBarProxy>() {
+
+ @Override
+ public void onSuccess(SimpleBarProxy returnedProxy) {
+ assertEquals(stableId, returnedProxy.stableId());
+ finishTestAndReset();
}
});
+ }
+ });
}
public void testFetchsAfterCreateDontUpdate() {
final int[] count = {0};
- final HandlerRegistration registration =
EntityProxyChange.registerForProxyType(
- req.getEventBus(), SimpleFooProxy.class,
- new EntityProxyChange.Handler<SimpleFooProxy>() {
- public void onProxyChange(EntityProxyChange<SimpleFooProxy>
event) {
- count[0]++;
- }
- });
+ final HandlerRegistration registration =
+ EntityProxyChange.registerForProxyType(req.getEventBus(),
SimpleFooProxy.class,
+ new EntityProxyChange.Handler<SimpleFooProxy>() {
+ public void onProxyChange(EntityProxyChange<SimpleFooProxy>
event) {
+ count[0]++;
+ }
+ });
delayTestFinish(TEST_DELAY);
SimpleFooRequest context = req.simpleFooRequest();
SimpleFooProxy proxy = context.create(SimpleFooProxy.class);
- context.persistAndReturnSelf().using(proxy).fire(
- new Receiver<SimpleFooProxy>() {
+ context.persistAndReturnSelf().using(proxy).fire(new
Receiver<SimpleFooProxy>() {
+ @Override
+ public void onSuccess(SimpleFooProxy response) {
+ // Persist and Update events
+ assertEquals(2, count[0]);
+ req.find(response.stableId()).fire(new Receiver<SimpleFooProxy>() {
@Override
public void onSuccess(SimpleFooProxy response) {
- // Persist and Update events
+ // No new events
assertEquals(2, count[0]);
- req.find(response.stableId()).fire(new
Receiver<SimpleFooProxy>() {
- @Override
- public void onSuccess(SimpleFooProxy response) {
- // No new events
- assertEquals(2, count[0]);
- registration.removeHandler();
- finishTestAndReset();
- }
- });
+ registration.removeHandler();
+ finishTestAndReset();
}
});
+ }
+ });
}
/**
@@ -181,8 +222,8 @@
// Here's the factory from the "previous invocation" of the client
{
SimpleRequestFactory oldFactory = createFactory();
- EntityProxyId<SimpleBarProxy> id =
oldFactory.simpleBarRequest().create(
- SimpleBarProxy.class).stableId();
+ EntityProxyId<SimpleBarProxy> id =
+
oldFactory.simpleBarRequest().create(SimpleBarProxy.class).stableId();
historyToken = oldFactory.getHistoryToken(id);
}
@@ -201,41 +242,39 @@
*/
public void testMultipleFetchesDontUpdate() {
final int[] count = {0};
- final HandlerRegistration registration =
EntityProxyChange.registerForProxyType(
- req.getEventBus(), SimpleFooProxy.class,
- new EntityProxyChange.Handler<SimpleFooProxy>() {
- public void onProxyChange(EntityProxyChange<SimpleFooProxy>
event) {
- count[0]++;
- }
- });
+ final HandlerRegistration registration =
+ EntityProxyChange.registerForProxyType(req.getEventBus(),
SimpleFooProxy.class,
+ new EntityProxyChange.Handler<SimpleFooProxy>() {
+ public void onProxyChange(EntityProxyChange<SimpleFooProxy>
event) {
+ count[0]++;
+ }
+ });
delayTestFinish(TEST_DELAY);
- req.simpleFooRequest().findSimpleFooById(999L).fire(
- new Receiver<SimpleFooProxy>() {
- @Override
- public void onSuccess(SimpleFooProxy response) {
- assertEquals(1, count[0]);
-
- final EntityProxyId<SimpleFooProxy> stableId =
response.stableId();
- req.find(stableId).fire(new Receiver<SimpleFooProxy>() {
-
- @Override
- public void onSuccess(SimpleFooProxy returnedProxy) {
- assertEquals(1, count[0]);
- registration.removeHandler();
- finishTestAndReset();
- }
- });
+ req.simpleFooRequest().findSimpleFooById(999L).fire(new
Receiver<SimpleFooProxy>() {
+ @Override
+ public void onSuccess(SimpleFooProxy response) {
+ assertEquals(1, count[0]);
+
+ final EntityProxyId<SimpleFooProxy> stableId = response.stableId();
+ req.find(stableId).fire(new Receiver<SimpleFooProxy>() {
+
+ @Override
+ public void onSuccess(SimpleFooProxy returnedProxy) {
+ assertEquals(1, count[0]);
+ registration.removeHandler();
+ finishTestAndReset();
}
});
+ }
+ });
}
- private void checkReturnedProxy(SimpleFooProxy response,
- boolean checkForRelations) {
+ private void checkReturnedProxy(SimpleFooProxy response, boolean
checkForRelations) {
assertEquals(42, (int) response.getIntId());
assertEquals("GWT", response.getUserName());
assertEquals(8L, (long) response.getLongField());
-
assertEquals(com.google.web.bindery.requestfactory.shared.SimpleEnum.FOO,
- response.getEnumField());
+
assertEquals(com.google.web.bindery.requestfactory.shared.SimpleEnum.FOO,
response
+ .getEnumField());
if (checkForRelations) {
assertNotNull(response.getBarField());
} else {
--
http://groups.google.com/group/Google-Web-Toolkit-Contributors