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

Reply via email to