Fix infinite recursion in JsonRequestProcessor
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@8633 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/requestfactory/server/JsonRequestProcessor.java b/user/src/com/google/gwt/requestfactory/server/JsonRequestProcessor.java
index a0974cf..1f0d454 100644
--- a/user/src/com/google/gwt/requestfactory/server/JsonRequestProcessor.java
+++ b/user/src/com/google/gwt/requestfactory/server/JsonRequestProcessor.java
@@ -149,6 +149,7 @@
*
* <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>();
@@ -287,6 +288,7 @@
if (service != null) {
Class<?> sClass = service.value();
EntityKey entityKey = getEntityKey(parameterValue.toString());
+
DvsData dvsData = dvsDataMap.get(entityKey);
try {
if (dvsData != null) {
@@ -294,7 +296,9 @@
dvsData.jsonObject, dvsData.writeOperation);
return entityData.entityInstance;
} else {
- Method findMeth = sClass.getMethod(getMethodNameFromPropertyName(sClass.getSimpleName(), "find"), Long.class);
+ Method findMeth = sClass.getMethod(
+ getMethodNameFromPropertyName(sClass.getSimpleName(), "find"),
+ Long.class);
return findMeth.invoke(null, entityKey.id);
}
} catch (NoSuchMethodException e) {
@@ -396,11 +400,14 @@
Object entityInstance = getEntityInstance(writeOperation, entity,
recordObject.get("id"), propertiesInRecord.get("id"));
+ cachedEntityLookup.put(entityKey, entityInstance);
+
Set<ConstraintViolation<Object>> violations = Collections.emptySet();
Iterator<?> keys = recordObject.keys();
while (keys.hasNext()) {
String key = (String) keys.next();
Class<?> propertyType = propertiesInRecord.get(key);
+ Class<?> dtoType = propertiesToDTO.get(key);
if (writeOperation == WriteOperation.CREATE && ("id".equals(key))) {
Long id = generateIdForCreate(key);
if (id != null) {
@@ -408,8 +415,20 @@
propertyType).invoke(entityInstance, id);
}
} else {
- Object propertyValue = getPropertyValueFromRequest(recordObject, key,
- propertiesToDTO.get(key));
+ Object propertyValue = null;
+ if (Record.class.isAssignableFrom(dtoType)) {
+ EntityKey propKey = getEntityKey(recordObject.getString(key));
+ Object cacheValue = cachedEntityLookup.get(propKey);
+ if (cachedEntityLookup.containsKey(propKey)) {
+ propertyValue = cacheValue;
+ } else {
+ propertyValue = getPropertyValueFromRequest(recordObject, key,
+ propertiesToDTO.get(key));
+ }
+ } else {
+ propertyValue = getPropertyValueFromRequest(recordObject, key,
+ propertiesToDTO.get(key));
+ }
entity.getMethod(getMethodNameFromPropertyName(key, "set"),
propertyType).invoke(entityInstance, propertyValue);
}
diff --git a/user/test/com/google/gwt/requestfactory/client/impl/SimpleFooRecordImpl.java b/user/test/com/google/gwt/requestfactory/client/impl/SimpleFooRecordImpl.java
index 301bb8d..63a8e32 100644
--- a/user/test/com/google/gwt/requestfactory/client/impl/SimpleFooRecordImpl.java
+++ b/user/test/com/google/gwt/requestfactory/client/impl/SimpleFooRecordImpl.java
@@ -103,6 +103,10 @@
return get(enumField);
}
+ public SimpleFooRecord getFooField() {
+ return (SimpleFooRecord) getValueStore().getRecordBySchemaAndId(SCHEMA, (Long) (Object) get(fooField));
+ }
+
public java.lang.Integer getIntId() {
return get(intId);
}
@@ -131,6 +135,10 @@
// ignore
}
+ public void setFooField(SimpleFooRecord fooField) {
+ // ignore
+ }
+
public void setIntId(Integer intId) {
// ignore
}
diff --git a/user/test/com/google/gwt/valuestore/client/RequestFactoryTest.java b/user/test/com/google/gwt/valuestore/client/RequestFactoryTest.java
index 3ac6136..02733ec 100644
--- a/user/test/com/google/gwt/valuestore/client/RequestFactoryTest.java
+++ b/user/test/com/google/gwt/valuestore/client/RequestFactoryTest.java
@@ -204,6 +204,26 @@
});
}
+ public void testPersistRecursiveRelation() {
+ final SimpleRequestFactory req = GWT.create(SimpleRequestFactory.class);
+ HandlerManager hm = new HandlerManager(null);
+ req.init(hm);
+ delayTestFinish(5000);
+
+ SimpleFooRecord rayFoo = req.create(SimpleFooRecord.class);
+ final RequestObject<SimpleFooRecord> persistRay = req.simpleFooRequest().persistAndReturnSelf(
+ rayFoo);
+ rayFoo = persistRay.edit(rayFoo);
+ rayFoo.setUserName("Ray");
+ rayFoo.setFooField(rayFoo);
+ persistRay.fire(new Receiver<SimpleFooRecord>() {
+ public void onSuccess(final SimpleFooRecord persistedRay,
+ Set<SyncResult> ignored) {
+ finishTest();
+ }
+ });
+ }
+
public void testPersistRelation() {
final SimpleRequestFactory req = GWT.create(SimpleRequestFactory.class);
HandlerManager hm = new HandlerManager(null);
diff --git a/user/test/com/google/gwt/valuestore/server/SimpleFoo.java b/user/test/com/google/gwt/valuestore/server/SimpleFoo.java
index 27a967f..aa7be4c 100644
--- a/user/test/com/google/gwt/valuestore/server/SimpleFoo.java
+++ b/user/test/com/google/gwt/valuestore/server/SimpleFoo.java
@@ -88,6 +88,8 @@
private SimpleBar barField;
+ private SimpleFoo fooField;
+
public SimpleFoo() {
intId = 42;
version = 1;
@@ -115,6 +117,10 @@
return enumField;
}
+ public SimpleFoo getFooField() {
+ return fooField;
+ }
+
public Long getId() {
return id;
}
@@ -164,6 +170,10 @@
this.enumField = enumField;
}
+ public void setFooField(SimpleFoo fooField) {
+ this.fooField = fooField;
+ }
+
public void setId(Long id) {
this.id = id;
}
diff --git a/user/test/com/google/gwt/valuestore/shared/SimpleFooRecord.java b/user/test/com/google/gwt/valuestore/shared/SimpleFooRecord.java
index b0cf7a2..a161c2b 100644
--- a/user/test/com/google/gwt/valuestore/shared/SimpleFooRecord.java
+++ b/user/test/com/google/gwt/valuestore/shared/SimpleFooRecord.java
@@ -42,6 +42,9 @@
Property<SimpleBarRecord> barField = new Property<SimpleBarRecord>("barField",
SimpleBarRecord.class);
+ Property<SimpleFooRecord> fooField = new Property<SimpleFooRecord>("fooField",
+ SimpleFooRecord.class);
+
SimpleBarRecord getBarField();
Boolean getBoolField();
@@ -50,6 +53,8 @@
SimpleEnum getEnumField();
+ SimpleFooRecord getFooField();
+
Integer getIntId();
Long getLongField();
@@ -64,6 +69,8 @@
void setCreated(Date created);
+ void setFooField(SimpleFooRecord fooField);
+
void setIntId(Integer intId);
void setLongField(Long longField);