Revision: 8783
Author: [email protected]
Date: Wed Sep 15 03:48:29 2010
Log: Submitting on behalf of Amit after finding a fix for a generics bug in jdk6-google-v3.

Patch (by [email protected]):
Initial implementation of a general purpose Find service based on an EntityProxyId. Added tests that also check with predicates.

Patch by: amitmanjhi
Review by: rjrjr, robertvawter
Review at http://gwt-code-reviews.appspot.com/878801

http://code.google.com/p/google-web-toolkit/source/detail?r=8783

Added:
 /trunk/user/src/com/google/gwt/requestfactory/client/impl/FindRequest.java
/trunk/user/src/com/google/gwt/requestfactory/client/impl/FindRequestObjectImpl.java
 /trunk/user/src/com/google/gwt/requestfactory/server/FindService.java
 /trunk/user/test/com/google/gwt/requestfactory/client/FindServiceTest.java
Modified:
/trunk/user/src/com/google/gwt/requestfactory/client/impl/RequestFactoryJsonImpl.java /trunk/user/src/com/google/gwt/requestfactory/rebind/RequestFactoryGenerator.java /trunk/user/src/com/google/gwt/requestfactory/server/JsonRequestProcessor.java
 /trunk/user/src/com/google/gwt/requestfactory/shared/RequestFactory.java
 /trunk/user/src/com/google/gwt/requestfactory/shared/RequestObject.java
 /trunk/user/test/com/google/gwt/requestfactory/RequestFactorySuite.java

=======================================
--- /dev/null
+++ /trunk/user/src/com/google/gwt/requestfactory/client/impl/FindRequest.java Wed Sep 15 03:48:29 2010
@@ -0,0 +1,31 @@
+/*
+ * 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.requestfactory.client.impl;
+
+import com.google.gwt.requestfactory.server.FindService;
+import com.google.gwt.requestfactory.shared.EntityProxy;
+import com.google.gwt.requestfactory.shared.EntityProxyId;
+import com.google.gwt.requestfactory.shared.ProxyRequest;
+import com.google.gwt.requestfactory.shared.Service;
+
+/**
+ * Request selector interface for implementing a find method.
+ */
+...@service(FindService.class)
+public interface FindRequest {
+  ProxyRequest<EntityProxy> find(EntityProxyId proxyId);
+}
=======================================
--- /dev/null
+++ /trunk/user/src/com/google/gwt/requestfactory/client/impl/FindRequestObjectImpl.java Wed Sep 15 03:48:29 2010
@@ -0,0 +1,42 @@
+/*
+ * 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.requestfactory.client.impl;
+
+import com.google.gwt.requestfactory.shared.EntityProxy;
+import com.google.gwt.requestfactory.shared.EntityProxyId;
+
+/**
+ * Abstract implementation of {...@link AbstractJsonRequestObject} for special find
+ * methods that return single instances of {...@link EntityProxy}.
+ */
+public abstract class FindRequestObjectImpl extends
+    AbstractJsonObjectRequest<EntityProxy, FindRequestObjectImpl> {
+
+ public FindRequestObjectImpl(RequestFactoryJsonImpl factory, EntityProxyId proxyId) {
+    super(((EntityProxyIdImpl) proxyId).schema, factory);
+  }
+
+  // This declaration works around a javac generics bug
+  @Override
+  public FindRequestObjectImpl with(String... propertyRef) {
+    return super.with(propertyRef);
+  }
+
+  @Override
+  protected FindRequestObjectImpl getThis() {
+    return this;
+  }
+}
=======================================
--- /dev/null
+++ /trunk/user/src/com/google/gwt/requestfactory/server/FindService.java Wed Sep 15 03:48:29 2010
@@ -0,0 +1,30 @@
+/*
+ * 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.requestfactory.server;
+
+/**
+ * Server side service to support a generic find method.
+ */
+public class FindService {
+
+  /*
+   * For now, a simple implementation of find will work.
+   */
+  public static <T> T find(T entityInstance) {
+    return entityInstance;
+  }
+}
=======================================
--- /dev/null
+++ /trunk/user/test/com/google/gwt/requestfactory/client/FindServiceTest.java Wed Sep 15 03:48:29 2010
@@ -0,0 +1,126 @@
+/*
+ * 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.requestfactory.client;
+
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.event.shared.SimpleEventBus;
+import com.google.gwt.junit.client.GWTTestCase;
+import com.google.gwt.requestfactory.shared.EntityProxy;
+import com.google.gwt.requestfactory.shared.EntityProxyId;
+import com.google.gwt.requestfactory.shared.Receiver;
+import com.google.gwt.requestfactory.shared.SimpleFooProxy;
+import com.google.gwt.requestfactory.shared.SimpleRequestFactory;
+import com.google.gwt.requestfactory.shared.SyncResult;
+
+import java.util.Set;
+
+/**
+ * Tests for {...@link com.google.gwt.requestfactory.shared.RequestFactory}.
+ */
+public class FindServiceTest extends GWTTestCase {
+
+  private SimpleRequestFactory req;
+
+  @Override
+  public String getModuleName() {
+    return "com.google.gwt.requestfactory.RequestFactorySuite";
+  }
+
+  @Override
+  public void gwtSetUp() {
+    req = GWT.create(SimpleRequestFactory.class);
+    req.init(new SimpleEventBus());
+  }
+
+  @Override
+  public void gwtTearDown() {
+    req.simpleFooRequest().reset().fire(new Receiver<Void>() {
+      @Override
+      public void onSuccess(Void response, Set<SyncResult> syncResults) {
+      }
+    });
+    req.simpleBarRequest().reset().fire(new Receiver<Void>() {
+      @Override
+      public void onSuccess(Void response, Set<SyncResult> syncResults) {
+      }
+    });
+  }
+
+  public void testFetchEntity() {
+    final boolean relationsAbsent = false;
+    delayTestFinish(5000);
+    req.simpleFooRequest().findSimpleFooById(999L).fire(
+        new Receiver<SimpleFooProxy>() {
+          @Override
+          public void onSuccess(SimpleFooProxy response,
+              Set<SyncResult> syncResult) {
+            checkReturnedProxy(response, relationsAbsent);
+
+            final EntityProxyId stableId = response.stableId();
+            req.find(stableId).fire(
+                new Receiver<EntityProxy>() {
+
+                  @Override
+                  public void onSuccess(EntityProxy returnedProxy,
+                      Set<SyncResult> syncResults) {
+                    assertEquals(stableId, returnedProxy.stableId());
+ checkReturnedProxy((SimpleFooProxy) returnedProxy, relationsAbsent);
+                    finishTest();
+                  }
+                });
+          }
+        });
+  }
+
+  public void testFetchEntityWithRelation() {
+    final boolean relationsPresent = true;
+    delayTestFinish(5000);
+    req.simpleFooRequest().findSimpleFooById(999L).with("barField").fire(
+        new Receiver<SimpleFooProxy>() {
+          @Override
+          public void onSuccess(SimpleFooProxy response,
+              Set<SyncResult> syncResult) {
+            checkReturnedProxy(response, relationsPresent);
+
+            final EntityProxyId stableId = response.stableId();
+            req.find(stableId).with("barField").fire(
+                new Receiver<EntityProxy>() {
+
+                  @Override
+                  public void onSuccess(EntityProxy returnedProxy,
+                      Set<SyncResult> syncResults) {
+                    assertEquals(stableId, returnedProxy.stableId());
+ checkReturnedProxy((SimpleFooProxy) returnedProxy, relationsPresent);
+                    finishTest();
+                  }
+                });
+          }
+        });
+  }
+
+ private void checkReturnedProxy(SimpleFooProxy response, boolean checkForRelations) {
+    assertEquals(42, (int) response.getIntId());
+    assertEquals("GWT", response.getUserName());
+    assertEquals(8L, (long) response.getLongField());
+    assertEquals(com.google.gwt.requestfactory.shared.SimpleEnum.FOO,
+        response.getEnumField());
+    if (checkForRelations) {
+      assertNotNull(response.getBarField());
+    } else {
+      assertEquals(null, response.getBarField());
+    }
+  }
+}
=======================================
--- /trunk/user/src/com/google/gwt/requestfactory/client/impl/RequestFactoryJsonImpl.java Mon Sep 13 15:18:55 2010 +++ /trunk/user/src/com/google/gwt/requestfactory/client/impl/RequestFactoryJsonImpl.java Wed Sep 15 03:48:29 2010
@@ -24,6 +24,7 @@
 import com.google.gwt.http.client.Response;
 import com.google.gwt.requestfactory.shared.EntityProxy;
 import com.google.gwt.requestfactory.shared.EntityProxyId;
+import com.google.gwt.requestfactory.shared.ProxyRequest;
 import com.google.gwt.requestfactory.shared.RequestEvent;
 import com.google.gwt.requestfactory.shared.RequestEvent.State;
 import com.google.gwt.requestfactory.shared.RequestFactory;
@@ -46,8 +47,31 @@
  */
 public abstract class RequestFactoryJsonImpl implements RequestFactory {

+  final class DataStoreToFutureMap {
+
+ Map<ProxySchema<? extends ProxyImpl>, Map<Object, Object>> internalMap = new HashMap<ProxySchema<? extends ProxyImpl>, Map<Object, Object>>();
+
+ Object get(Object datastoreId, ProxySchema<? extends ProxyImpl> schema) {
+      Map<Object, Object> perSchemaMap = internalMap.get(schema);
+      if (perSchemaMap == null) {
+        return null;
+      }
+      return perSchemaMap.get(datastoreId);
+    }
+
+    /* returns the previous futureId, if any*/
+ Object put(Object datastoreId, ProxySchema<? extends ProxyImpl> schema, Object futureId) {
+      Map<Object, Object> perSchemaMap = internalMap.get(schema);
+      if (perSchemaMap == null) {
+        perSchemaMap = new HashMap<Object, Object>();
+        internalMap.put(schema, perSchemaMap);
+      }
+      return perSchemaMap.put(datastoreId, futureId);
+    }
+  }
   static final boolean IS_FUTURE = true;
   static final boolean NOT_FUTURE = false;
+
private static Logger logger = Logger.getLogger(RequestFactory.class.getName());

   // A separate logger for wire activity, which does not get logged by the
@@ -57,9 +81,8 @@
private static Logger wireLogger = Logger.getLogger("WireActivityLogger");

   private static String SERVER_ERROR = "Server Error";
-
-  private final Integer initialVersion = 1;
-
+
+  private final Integer initialVersion = 1;
   /*
    * Keeping these maps forever is not a desirable solution because of the
* memory overhead but need these if want to provide stable {...@entityproxyid}.
@@ -67,30 +90,8 @@
* futureToDatastoreMap is currently not used, will be useful in find requests.
    */
final Map<Object, Object> futureToDatastoreMap = new HashMap<Object, Object>(); - final DataStoreToFutureMap datastoreToFutureMap = new DataStoreToFutureMap();
-
-  final class DataStoreToFutureMap {
-
- Map<ProxySchema<? extends ProxyImpl>, Map<Object, Object>> internalMap = new HashMap<ProxySchema<? extends ProxyImpl>, Map<Object, Object>>();
-
-    /* returns the previous futureId, if any*/
- Object put(Object datastoreId, ProxySchema<? extends ProxyImpl> schema, Object futureId) {
-      Map<Object, Object> perSchemaMap = internalMap.get(schema);
-      if (perSchemaMap == null) {
-        perSchemaMap = new HashMap<Object, Object>();
-        internalMap.put(schema, perSchemaMap);
-      }
-      return perSchemaMap.put(datastoreId, futureId);
-    }
-
- Object get(Object datastoreId, ProxySchema<? extends ProxyImpl> schema) {
-      Map<Object, Object> perSchemaMap = internalMap.get(schema);
-      if (perSchemaMap == null) {
-        return null;
-      }
-      return perSchemaMap.get(datastoreId);
-    }
-  }
+
+ final DataStoreToFutureMap datastoreToFutureMap = new DataStoreToFutureMap();

   private long currentFutureId = 0;

@@ -108,6 +109,10 @@

     return createFuture(schema);
   }
+
+  public ProxyRequest<EntityProxy> find(EntityProxyId proxyId) {
+    return findRequest().find(proxyId);
+  }

   public void fire(final RequestObject<?> requestObject) {
     RequestBuilder builder = new RequestBuilder(RequestBuilder.POST,
@@ -158,6 +163,20 @@

   public abstract ProxySchema<?> getSchema(String token);

+  public String getWireFormat(EntityProxyId proxyId) {
+    EntityProxyIdImpl proxyIdImpl = (EntityProxyIdImpl) proxyId;
+    Long id = (Long) proxyIdImpl.id;
+    if (proxyIdImpl.isFuture) {
+      // search for the datastore id for this futureId.
+      Long datastoreId = (Long) futureToDatastoreMap.get(id);
+      if (datastoreId == null) {
+ throw new IllegalArgumentException("Cannot call find on a proxyId before persisting");
+      }
+      id = datastoreId;
+    }
+    return ProxyImpl.getWireFormatId(id, NOT_FUTURE, proxyIdImpl.schema);
+  }
+
   /**
    * @param eventBus
    */
@@ -166,6 +185,8 @@
     this.eventBus = eventBus;
     logger.fine("Successfully initialized RequestFactory");
   }
+
+  protected abstract FindRequest findRequest();

   protected Class<? extends EntityProxy> getClass(String token,
       ProxyToTypeMap recordToTypeMap) {
=======================================
--- /trunk/user/src/com/google/gwt/requestfactory/rebind/RequestFactoryGenerator.java Tue Sep 14 17:54:04 2010 +++ /trunk/user/src/com/google/gwt/requestfactory/rebind/RequestFactoryGenerator.java Wed Sep 15 03:48:29 2010
@@ -45,6 +45,8 @@
 import com.google.gwt.requestfactory.client.impl.AbstractStringRequest;
 import com.google.gwt.requestfactory.client.impl.AbstractVoidRequest;
 import com.google.gwt.requestfactory.client.impl.EnumProperty;
+import com.google.gwt.requestfactory.client.impl.FindRequest;
+import com.google.gwt.requestfactory.client.impl.FindRequestObjectImpl;
 import com.google.gwt.requestfactory.client.impl.Property;
 import com.google.gwt.requestfactory.client.impl.ProxyImpl;
 import com.google.gwt.requestfactory.client.impl.ProxyJsoImpl;
@@ -189,10 +191,14 @@
       JClassType publicProxyType) throws UnableToCompleteException {
     TypeOracle typeOracle = generatorContext.getTypeOracle();

- if (!publicProxyType.isAssignableTo(typeOracle.findType(EntityProxy.class.getName()))) { + JClassType entityProxyClass = typeOracle.findType(EntityProxy.class.getName());
+    if (!publicProxyType.isAssignableTo(entityProxyClass)) {
       return;
     }

+    if (publicProxyType.equals(entityProxyClass)) {
+      return;
+    }
     if (generatedProxyTypes.contains(publicProxyType)) {
       return;
     }
@@ -373,6 +379,16 @@
       }
       requestSelectors.add(method);
     }
+    /*
+     * Hard-code the requestSelectors specified in RequestFactory.
+     */
+    JClassType t = generatorContext.getTypeOracle().findType(
+        RequestFactoryJsonImpl.class.getName());
+    try {
+      requestSelectors.add(t.getMethod("findRequest", new JType[0]));
+    } catch (NotFoundException e) {
+      e.printStackTrace();
+    }

JClassType proxyToTypeInterface = generatorContext.getTypeOracle().findType(
         ProxyToTypeMap.class.getName());
@@ -598,12 +614,17 @@
       String requestClassName = null;

       TypeOracle typeOracle = generatorContext.getTypeOracle();
-      String enumArgument = "";
+      String enumOrFindArgument = "";
       // TODO: refactor this into some kind of extensible map lookup
       if (isProxyListRequest(typeOracle, requestType)) {
         requestClassName = asInnerImplClass("ListRequestImpl", returnType);
       } else if (isProxyRequest(typeOracle, requestType)) {
- requestClassName = asInnerImplClass("ObjectRequestImpl", returnType); + if (selectorInterface.isAssignableTo(typeOracle.findType(FindRequest.class.getName()))) {
+          enumOrFindArgument = ", proxyId";
+          requestClassName = FindRequestObjectImpl.class.getName();
+        } else {
+ requestClassName = asInnerImplClass("ObjectRequestImpl", returnType);
+        }
       } else if (isStringRequest(typeOracle, requestType)) {
         requestClassName = AbstractStringRequest.class.getName();
       } else if (isLongRequest(typeOracle, requestType)) {
@@ -630,7 +651,7 @@
         requestClassName = AbstractBigIntegerRequest.class.getName();
       } else if (isEnumRequest(typeOracle, requestType)) {
         requestClassName = AbstractEnumRequest.class.getName();
- enumArgument = ", " + requestType.isParameterized().getTypeArgs()[0] + enumOrFindArgument = ", " + requestType.isParameterized().getTypeArgs()[0]
             + ".values()";
       } else if (isVoidRequest(typeOracle, requestType)) {
         requestClassName = AbstractVoidRequest.class.getName();
@@ -642,14 +663,14 @@

       sw.println(getMethodDeclaration(method) + " {");
       sw.indent();
- sw.println("return new " + requestClassName + "(factory" + enumArgument + sw.println("return new " + requestClassName + "(factory" + enumOrFindArgument
           + ") {");
       sw.indent();
       String requestDataName = RequestData.class.getSimpleName();
       sw.println("public " + requestDataName + " getRequestData() {");
       sw.indent();
       sw.println("return new " + requestDataName + "(\"" + operationName
-          + "\", " + getParametersAsString(method, typeOracle) + ","
+          + "\", " + getParametersAsString(method, typeOracle) + ", "
           + "getPropertyRefs());");
       sw.outdent();
       sw.println("}");
@@ -705,6 +726,10 @@
       JClassType classType = parameter.getType().isClassOrInterface();

       JType paramType = parameter.getType();
+ if (paramType.getQualifiedSourceName().equals(EntityProxyId.class.getName())) {
+        sb.append("factory.getWireFormat(" + parameter.getName() + ")");
+        continue;
+      }
       JParameterizedType params = paramType.isParameterized();
       if (params != null) {
         classType = params.getTypeArgs()[0];
=======================================
--- /trunk/user/src/com/google/gwt/requestfactory/server/JsonRequestProcessor.java Tue Sep 14 17:54:04 2010 +++ /trunk/user/src/com/google/gwt/requestfactory/server/JsonRequestProcessor.java Wed Sep 15 03:48:29 2010
@@ -16,8 +16,9 @@
 package com.google.gwt.requestfactory.server;

 import com.google.gwt.requestfactory.client.impl.Property;
-import com.google.gwt.requestfactory.shared.ProxyFor;
 import com.google.gwt.requestfactory.shared.EntityProxy;
+import com.google.gwt.requestfactory.shared.EntityProxyId;
+import com.google.gwt.requestfactory.shared.ProxyFor;
 import com.google.gwt.requestfactory.shared.RequestData;
 import com.google.gwt.requestfactory.shared.WriteOperation;

@@ -126,7 +127,7 @@

   private RequestProperty propertyRefs;

- private Map<String, JSONObject> relatedObjects = new HashMap<String, JSONObject>(); + private final Map<String, JSONObject> relatedObjects = new HashMap<String, JSONObject>();

   private OperationRegistry operationRegistry;

@@ -140,10 +141,10 @@
    *
    * <li>Find the changes that need to be sent back.
    */
- private Map<EntityKey, Object> cachedEntityLookup = new HashMap<EntityKey, Object>();
-  private Set<EntityKey> involvedKeys = new HashSet<EntityKey>();
- private Map<EntityKey, DvsData> dvsDataMap = new HashMap<EntityKey, DvsData>(); - private Map<EntityKey, SerializedEntity> beforeDataMap = new HashMap<EntityKey, SerializedEntity>(); + private final Map<EntityKey, Object> cachedEntityLookup = new HashMap<EntityKey, Object>();
+  private final Set<EntityKey> involvedKeys = new HashSet<EntityKey>();
+ private final Map<EntityKey, DvsData> dvsDataMap = new HashMap<EntityKey, DvsData>(); + private final Map<EntityKey, SerializedEntity> beforeDataMap = new HashMap<EntityKey, SerializedEntity>(); private Map<EntityKey, EntityData> afterDvsDataMap = new HashMap<EntityKey, EntityData>();

   @SuppressWarnings({"unchecked", "rawtypes"})
@@ -266,18 +267,32 @@
         EntityKey entityKey = getEntityKey(parameterValue.toString());

         DvsData dvsData = dvsDataMap.get(entityKey);
-        if (dvsData != null) {
-          EntityData entityData = getEntityDataForRecord(entityKey,
-              dvsData.jsonObject, dvsData.writeOperation);
-          return entityData.entityInstance;
-        } else {
-          Method findMeth = sClass.getMethod(
- getMethodNameFromPropertyName(sClass.getSimpleName(), "find"),
-              Long.class);
-          return findMeth.invoke(null, entityKey.id);
-        }
+          if (dvsData != null) {
+            EntityData entityData = getEntityDataForRecord(entityKey,
+                dvsData.jsonObject, dvsData.writeOperation);
+            return entityData.entityInstance;
+          } else {
+            involvedKeys.add(entityKey);
+            Method findMeth = sClass.getMethod(
+ getMethodNameFromPropertyName(sClass.getSimpleName(), "find"),
+                Long.class);
+            return findMeth.invoke(null, entityKey.id);
+          }
       }
     }
+    if (EntityProxyId.class.isAssignableFrom(parameterType)) {
+      EntityKey entityKey = getEntityKey(parameterValue.toString());
+      ProxyFor service = entityKey.record.getAnnotation(ProxyFor.class);
+      if (service == null) {
+ throw new IllegalArgumentException("Unknown service, unable to decode " + parameterValue);
+      }
+      involvedKeys.add(entityKey);
+      Class<?> sClass = service.value();
+      Method findMeth = sClass.getMethod(
+          getMethodNameFromPropertyName(sClass.getSimpleName(), "find"),
+          Long.class);
+      return findMeth.invoke(null, entityKey.id);
+    }
     throw new IllegalArgumentException(
         "Unknown parameter type: " + parameterType);
   }
@@ -655,6 +670,7 @@
     return domainMethod.invoke(domainObject, args);
   }

+  @SuppressWarnings("unchecked")
   public JSONObject processJsonRequest(String jsonRequestString)
       throws JSONException, NoSuchMethodException, IllegalAccessException,
InvocationTargetException, ClassNotFoundException, SecurityException, InstantiationException {
@@ -726,7 +742,16 @@
         || result instanceof Character || result instanceof Boolean) {
       envelop.put(RequestData.RESULT_TOKEN, result);
     } else {
-      JSONObject jsonObject = toJsonObject(operation, result);
+      Class<? extends EntityProxy> returnType = null;
+ if (operation.getDomainClassName().equals(FindService.class.getName())) {
+        // HACK.
+        if (involvedKeys.size() == 1) {
+          returnType = involvedKeys.iterator().next().record;
+        }
+      } else {
+ returnType = (Class<? extends EntityProxy>) operation.getReturnType();
+      }
+      JSONObject jsonObject = toJsonObject(returnType, result);
       envelop.put(RequestData.RESULT_TOKEN, jsonObject);
     }
     envelop.put(RequestData.SIDE_EFFECTS_TOKEN, sideEffects);
@@ -898,7 +923,7 @@
       EntityData entityData) throws IllegalArgumentException,
       SecurityException, IllegalAccessException, InvocationTargetException,
       NoSuchMethodException, JSONException {
-    if (entityData.entityInstance == null) {
+    if (entityData == null || entityData.entityInstance == null) {
       return null;
     }

@@ -993,7 +1018,9 @@
     JSONArray updateArray = new JSONArray();
     for (EntityKey entityKey : involvedKeys) {
       EntityData entityData = afterDvsDataMap.get(entityKey);
-      assert entityData != null;
+      if (entityData == null) {
+        continue;
+      }
       if (entityKey.isFuture) {
JSONObject createRecord = getCreateReturnRecord(entityKey, entityData);
         if (createRecord != null) {
@@ -1111,12 +1138,10 @@
     return jsonArray;
   }

-  @SuppressWarnings("unchecked")
- private JSONObject toJsonObject(RequestDefinition operation, Object result) + private JSONObject toJsonObject(Class<? extends EntityProxy> returnType, Object result)
       throws JSONException, NoSuchMethodException, IllegalAccessException,
       InvocationTargetException {
-    JSONObject jsonObject = getJsonObject(result,
- (Class<? extends EntityProxy>) operation.getReturnType(), propertyRefs); + JSONObject jsonObject = getJsonObject(result, returnType, propertyRefs);
     return jsonObject;
   }

=======================================
--- /trunk/user/src/com/google/gwt/requestfactory/shared/RequestFactory.java Mon Sep 13 15:18:55 2010 +++ /trunk/user/src/com/google/gwt/requestfactory/shared/RequestFactory.java Wed Sep 15 03:48:29 2010
@@ -33,6 +33,11 @@

   <R extends EntityProxy> R create(Class<R> token);

+  /**
+   * Provide a general purpose find request.
+   */
+  ProxyRequest<EntityProxy> find(EntityProxyId proxyId);
+
   /**
* Return the class object which may be used to create new instances of the * type of the given proxy, via {...@link #create}. Due to limitations of GWT's
@@ -84,6 +89,4 @@
    * Start this request factory.
    */
   void init(EventBus eventBus);
-
-
-}
+}
=======================================
--- /trunk/user/src/com/google/gwt/requestfactory/shared/RequestObject.java Thu Sep 2 20:54:55 2010 +++ /trunk/user/src/com/google/gwt/requestfactory/shared/RequestObject.java Wed Sep 15 03:48:29 2010
@@ -48,5 +48,5 @@

   // reset the DeltaValueStore.
   void reset();
-
-}
+
+}
=======================================
--- /trunk/user/test/com/google/gwt/requestfactory/RequestFactorySuite.java Fri Sep 10 13:31:52 2010 +++ /trunk/user/test/com/google/gwt/requestfactory/RequestFactorySuite.java Wed Sep 15 03:48:29 2010
@@ -17,6 +17,7 @@

 import com.google.gwt.junit.tools.GWTTestSuite;
 import com.google.gwt.requestfactory.client.EditorTest;
+import com.google.gwt.requestfactory.client.FindServiceTest;
 import com.google.gwt.requestfactory.client.RequestFactoryTest;
import com.google.gwt.requestfactory.client.impl.DeltaValueStoreJsonImplTest;
 import com.google.gwt.requestfactory.client.impl.ProxyJsoImplTest;
@@ -36,6 +37,7 @@
     suite.addTestSuite(ValueStoreJsonImplTest.class);
     suite.addTestSuite(DeltaValueStoreJsonImplTest.class);
     suite.addTestSuite(RequestFactoryTest.class);
+    suite.addTestSuite(FindServiceTest.class);
     return suite;
   }
 }

--
http://groups.google.com/group/Google-Web-Toolkit-Contributors

Reply via email to