You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by an...@apache.org on 2010/03/21 15:30:02 UTC
svn commit: r925773 - in
/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src:
main/java/org/apache/cayenne/remote/hessian/
main/java/org/apache/cayenne/remote/hessian/service/
main/java/org/apache/cayenne/util/ test/java/org/apache/cayenne/rem...
Author: andrey
Date: Sun Mar 21 14:30:02 2010
New Revision: 925773
URL: http://svn.apache.org/viewvc?rev=925773&view=rev
Log:
CAY-1404 ClassCastException during ObjectDetachOperation
Added:
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/remote/ROPPrefetchToManyMapTest.java
Modified:
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/remote/hessian/ClientSerializerFactory.java
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/remote/hessian/service/ServerSerializerFactory.java
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/util/DeepMergeOperation.java
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/util/ObjectDetachOperation.java
Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/remote/hessian/ClientSerializerFactory.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/remote/hessian/ClientSerializerFactory.java?rev=925773&r1=925772&r2=925773&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/remote/hessian/ClientSerializerFactory.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/remote/hessian/ClientSerializerFactory.java Sun Mar 21 14:30:02 2010
@@ -19,11 +19,9 @@
package org.apache.cayenne.remote.hessian;
-import java.util.HashMap;
-import java.util.Map;
-
import org.apache.cayenne.DataRow;
import org.apache.cayenne.util.PersistentObjectList;
+import org.apache.cayenne.util.PersistentObjectMap;
import com.caucho.hessian.io.AbstractSerializerFactory;
import com.caucho.hessian.io.Deserializer;
@@ -38,8 +36,9 @@ import com.caucho.hessian.io.Serializer;
*/
class ClientSerializerFactory extends AbstractSerializerFactory {
- private Map<Class, Deserializer> deserializers;
private Deserializer dataRowDeserializer;
+ private Deserializer listDeserializer;
+ private Deserializer mapDeserializer;
@Override
public Serializer getSerializer(Class cl) throws HessianProtocolException {
@@ -48,28 +47,22 @@ class ClientSerializerFactory extends Ab
@Override
public Deserializer getDeserializer(Class cl) throws HessianProtocolException {
- Deserializer deserializer = null;
-
+ //turns out Hessian uses its own (incorrect) serialization mechanism for maps
+ if (PersistentObjectMap.class.isAssignableFrom(cl)) {
+ if (mapDeserializer == null) {
+ mapDeserializer = new JavaDeserializer(cl);
+ }
+ return mapDeserializer;
+ }
+
if (PersistentObjectList.class.isAssignableFrom(cl)) {
-
- synchronized (this) {
-
- if (deserializers != null) {
- deserializer = deserializers.get(cl);
- }
-
- if (deserializer == null) {
- deserializer = new JavaDeserializer(cl);
-
- if (deserializers == null) {
- deserializers = new HashMap<Class, Deserializer>();
- }
-
- deserializers.put(cl, deserializer);
- }
+ if (listDeserializer == null) {
+ listDeserializer = new JavaDeserializer(cl);
}
+ return listDeserializer;
}
- else if(DataRow.class.isAssignableFrom(cl)) {
+
+ if(DataRow.class.isAssignableFrom(cl)) {
if(dataRowDeserializer == null) {
dataRowDeserializer = new DataRowDeserializer();
}
@@ -77,6 +70,6 @@ class ClientSerializerFactory extends Ab
return dataRowDeserializer;
}
- return deserializer;
+ return null;
}
}
Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/remote/hessian/service/ServerSerializerFactory.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/remote/hessian/service/ServerSerializerFactory.java?rev=925773&r1=925772&r2=925773&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/remote/hessian/service/ServerSerializerFactory.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/remote/hessian/service/ServerSerializerFactory.java Sun Mar 21 14:30:02 2010
@@ -21,10 +21,12 @@ package org.apache.cayenne.remote.hessia
import org.apache.cayenne.DataRow;
import org.apache.cayenne.util.PersistentObjectList;
+import org.apache.cayenne.util.PersistentObjectMap;
import com.caucho.hessian.io.AbstractSerializerFactory;
import com.caucho.hessian.io.Deserializer;
import com.caucho.hessian.io.HessianProtocolException;
+import com.caucho.hessian.io.JavaSerializer;
import com.caucho.hessian.io.Serializer;
/**
@@ -35,6 +37,7 @@ import com.caucho.hessian.io.Serializer;
class ServerSerializerFactory extends AbstractSerializerFactory {
private ServerPersistentObjectListSerializer persistentObjectListSerializer;
private ServerDataRowSerializer dataRowSerilaizer;
+ private Serializer javaSerializer;
ServerSerializerFactory() {
this.persistentObjectListSerializer = new ServerPersistentObjectListSerializer();
@@ -50,6 +53,13 @@ class ServerSerializerFactory extends Ab
else if (DataRow.class.isAssignableFrom(cl)) {
return dataRowSerilaizer;
}
+ //turns out Hessian uses its own (incorrect) serialization mechanism for maps
+ else if (PersistentObjectMap.class.isAssignableFrom(cl)) {
+ if (javaSerializer == null) {
+ javaSerializer = new JavaSerializer(cl);
+ }
+ return javaSerializer;
+ }
return null;
}
Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/util/DeepMergeOperation.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/util/DeepMergeOperation.java?rev=925773&r1=925772&r2=925773&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/util/DeepMergeOperation.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/util/DeepMergeOperation.java Sun Mar 21 14:30:02 2010
@@ -22,8 +22,8 @@ package org.apache.cayenne.util;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
-import java.util.Iterator;
import java.util.Map;
+import java.util.Map.Entry;
import org.apache.cayenne.CayenneRuntimeException;
import org.apache.cayenne.ObjectContext;
@@ -32,6 +32,7 @@ import org.apache.cayenne.Persistent;
import org.apache.cayenne.reflect.AttributeProperty;
import org.apache.cayenne.reflect.ClassDescriptor;
import org.apache.cayenne.reflect.PropertyVisitor;
+import org.apache.cayenne.reflect.ToManyMapProperty;
import org.apache.cayenne.reflect.ToManyProperty;
import org.apache.cayenne.reflect.ToOneProperty;
@@ -99,21 +100,38 @@ public class DeepMergeOperation {
public boolean visitToMany(ToManyProperty property) {
if (!property.isFault(source)) {
- Collection collection = (Collection) property.readProperty(source);
-
- Collection targetCollection = new ArrayList(collection.size());
-
- Iterator it = collection.iterator();
- while (it.hasNext()) {
- Object destinationSource = it.next();
- Object destinationTarget = destinationSource != null ? merge(
- destinationSource,
- property.getTargetDescriptor()) : null;
-
- targetCollection.add(destinationTarget);
+ Object value = property.readProperty(source);
+ Object targetValue;
+
+ if (property instanceof ToManyMapProperty) {
+ Map<?, ?> map = (Map) value;
+ Map targetMap = new HashMap();
+
+ for (Entry entry : map.entrySet()) {
+ Object destinationSource = entry.getValue();
+ Object destinationTarget = destinationSource != null
+ ? merge(destinationSource, property.getTargetDescriptor())
+ : null;
+
+ targetMap.put(entry.getKey(), destinationTarget);
+ }
+ targetValue = targetMap;
+ }
+ else {
+ Collection collection = (Collection) value;
+ Collection targetCollection = new ArrayList(collection.size());
+
+ for (Object destinationSource : collection) {
+ Object destinationTarget = destinationSource != null
+ ? merge(destinationSource, property.getTargetDescriptor())
+ : null;
+
+ targetCollection.add(destinationTarget);
+ }
+ targetValue = targetCollection;
}
- property.writePropertyDirectly(target, null, targetCollection);
+ property.writePropertyDirectly(target, null, targetValue);
}
return true;
Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/util/ObjectDetachOperation.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/util/ObjectDetachOperation.java?rev=925773&r1=925772&r2=925773&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/util/ObjectDetachOperation.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/util/ObjectDetachOperation.java Sun Mar 21 14:30:02 2010
@@ -22,8 +22,8 @@ package org.apache.cayenne.util;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
-import java.util.Iterator;
import java.util.Map;
+import java.util.Map.Entry;
import org.apache.cayenne.CayenneRuntimeException;
import org.apache.cayenne.ObjectId;
@@ -34,6 +34,7 @@ import org.apache.cayenne.reflect.Attrib
import org.apache.cayenne.reflect.ClassDescriptor;
import org.apache.cayenne.reflect.Property;
import org.apache.cayenne.reflect.PropertyVisitor;
+import org.apache.cayenne.reflect.ToManyMapProperty;
import org.apache.cayenne.reflect.ToManyProperty;
import org.apache.cayenne.reflect.ToOneProperty;
@@ -128,25 +129,42 @@ public class ObjectDetachOperation {
PrefetchTreeNode child = prefetchTree.getNode(property.getName());
if (child != null) {
- Collection collection = (Collection) property
- .readProperty(source);
-
- Collection targetCollection = new ArrayList(collection.size());
-
- Iterator it = collection.iterator();
- while (it.hasNext()) {
- Object destinationSource = it.next();
- Object destinationTarget = destinationSource != null
+ Object value = property.readProperty(source);
+ Object targetValue;
+
+ if (property instanceof ToManyMapProperty) {
+ Map<?, ?> map = (Map) value;
+ Map targetMap = new HashMap();
+
+ for (Entry entry : map.entrySet()) {
+ Object destinationSource = entry.getValue();
+ Object destinationTarget = destinationSource != null
? detach(destinationSource, property
- .getTargetDescriptor(), child)
- : null;
+ .getTargetDescriptor(), child)
+ : null;
- targetCollection.add(destinationTarget);
+ targetMap.put(entry.getKey(), destinationTarget);
+ }
+ targetValue = targetMap;
+ }
+ else {
+ Collection collection = (Collection) value;
+ Collection targetCollection = new ArrayList(collection.size());
+
+ for (Object destinationSource : collection) {
+ Object destinationTarget = destinationSource != null
+ ? detach(destinationSource, property
+ .getTargetDescriptor(), child)
+ : null;
+
+ targetCollection.add(destinationTarget);
+ }
+ targetValue = targetCollection;
}
ToManyProperty targetProperty = (ToManyProperty) targetDescriptor
.getProperty(property.getName());
- targetProperty.writeProperty(target, null, targetCollection);
+ targetProperty.writeProperty(target, null, targetValue);
}
}
Added: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/remote/ROPPrefetchToManyMapTest.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/remote/ROPPrefetchToManyMapTest.java?rev=925773&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/remote/ROPPrefetchToManyMapTest.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/remote/ROPPrefetchToManyMapTest.java Sun Mar 21 14:30:02 2010
@@ -0,0 +1,53 @@
+/*****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.cayenne.remote;
+
+import org.apache.cayenne.Cayenne;
+import org.apache.cayenne.ObjectContext;
+import org.apache.cayenne.query.RefreshQuery;
+import org.apache.cayenne.query.SelectQuery;
+import org.apache.cayenne.testdo.mt.ClientMtMapToMany;
+import org.apache.cayenne.testdo.mt.ClientMtMapToManyTarget;
+
+public class ROPPrefetchToManyMapTest extends RemoteCayenneCase {
+ public void test() throws Exception {
+ deleteTestData();
+ ObjectContext context = createROPContext();
+
+ ClientMtMapToMany map = context.newObject(ClientMtMapToMany.class);
+ ClientMtMapToManyTarget target = context.newObject(ClientMtMapToManyTarget.class);
+ target.setMapToMany(map);
+ context.commitChanges();
+
+ context.performQuery(new RefreshQuery());
+
+ SelectQuery query = new SelectQuery(ClientMtMapToMany.class);
+ query.addPrefetch("targets");
+
+ map = (ClientMtMapToMany) Cayenne.objectForQuery(context, query);
+
+ try {
+ blockQueries();
+ assertEquals(map.getTargets().size(), 1);
+ }
+ finally {
+ unblockQueries();
+ }
+ }
+}