From 28221ded45d5e4603a5a86f83ca77f53022354f0 Mon Sep 17 00:00:00 2001
From: pkupczyk <pkupczyk>
Date: Mon, 18 Jun 2012 12:32:01 +0000
Subject: [PATCH] SP-111 / BIS-49: JSON-RPC - properly handle circular
 dependencies

SVN: 25759
---
 ...sonTypeAndClassAnnotationIntrospector.java |  24 +-
 .../server/json/JsonDeserializationTest.java  | 396 ++++++------------
 .../server/json/JsonSerializationTest.java    | 141 ++++---
 .../api/server/json/JsonTestObjectMapper.java |  61 ++-
 .../ObjectWithNestedMapsInMapFactory.java     |  73 ++++
 .../api/server/json/common/ObjectFactory.java |  58 +++
 .../api/server/json/common/ObjectMap.java     |   4 +-
 .../api/server/json/common/ObjectType.java    |   2 +-
 .../json/object/ObjectNestedChildFactory.java |  64 +++
 .../json/object/ObjectNestedFactory.java      |  59 +++
 .../json/object/ObjectWithContainerTypes.java | 311 +-------------
 .../ObjectWithContainerTypesFactory.java      | 265 ++++++++++++
 ...jectWithContainerTypesFactoryAbstract.java | 329 +++++++++++++++
 .../json/object/ObjectWithDateTypes.java      |  52 +--
 .../object/ObjectWithDateTypesFactory.java    |  73 ++++
 .../json/object/ObjectWithEnumTypes.java      |  52 +--
 .../object/ObjectWithEnumTypesFactory.java    |  76 ++++
 .../object/ObjectWithIgnoredProperties.java   |  71 +---
 .../ObjectWithIgnoredPropertiesFactory.java   | 100 +++++
 ...jectWithKnownButNotUniqueClassFactory.java |  69 +++
 .../object/ObjectWithKnownTypeFactory.java    |  65 +++
 .../ObjectWithKnownUniqueClassFactory.java    |  65 +++
 ...jectWithNestedMapsInCollectionFactory.java |  70 ++++
 .../ObjectWithNestedMapsInListFactory.java    |  69 +++
 .../json/object/ObjectWithNestedTypes.java    | 105 +----
 .../object/ObjectWithNestedTypesFactory.java  |  67 +++
 .../json/object/ObjectWithPrimitiveTypes.java |  81 +---
 .../ObjectWithPrimitiveTypesFactory.java      |  94 +++++
 .../json/object/ObjectWithPrivateAccess.java  |  49 +--
 .../ObjectWithPrivateAccessFactory.java       |  58 +++
 .../object/ObjectWithRenamedProperties.java   |  61 +--
 .../ObjectWithRenamedPropertiesFactory.java   |  80 ++++
 .../object/ObjectWithReusedReferences.java    |  47 +++
 .../ObjectWithReusedReferencesFactory.java    |  68 +++
 .../json/object/ObjectWithSelfReference.java  |  38 +-
 .../ObjectWithSelfReferenceFactory.java       |  57 +++
 .../server/json/object/ObjectWithType.java    |  33 +-
 .../server/json/object/ObjectWithTypeA.java   |  38 +-
 .../server/json/object/ObjectWithTypeAA.java  |  42 +-
 .../json/object/ObjectWithTypeAAFactory.java  |  67 +++
 .../json/object/ObjectWithTypeAFactory.java   |  63 +++
 .../object/ObjectWithTypeALegalDuplicate.java |   2 +-
 .../server/json/object/ObjectWithTypeB.java   |  38 +-
 .../json/object/ObjectWithTypeBFactory.java   |  62 +++
 .../ObjectWithTypeBIllegalDuplicate.java      |   2 +-
 .../object/ObjectWithTypeButNoSubtypes.java   |  41 +-
 .../ObjectWithTypeButNoSubtypesFactory.java   |  64 +++
 .../server/json/object/ObjectWithTypeC.java   |  38 +-
 .../json/object/ObjectWithTypeCFactory.java   |  64 +++
 .../json/object/ObjectWithTypeFactory.java    |  58 +++
 .../json/object/ObjectWithUnknownType.java    |  29 +-
 .../object/ObjectWithUnknownTypeFactory.java  |  74 ++++
 52 files changed, 2746 insertions(+), 1323 deletions(-)
 create mode 100644 openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/ObjectWithNestedMapsInMapFactory.java
 create mode 100644 openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/common/ObjectFactory.java
 create mode 100644 openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectNestedChildFactory.java
 create mode 100644 openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectNestedFactory.java
 create mode 100644 openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithContainerTypesFactory.java
 create mode 100644 openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithContainerTypesFactoryAbstract.java
 create mode 100644 openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithDateTypesFactory.java
 create mode 100644 openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithEnumTypesFactory.java
 create mode 100644 openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithIgnoredPropertiesFactory.java
 create mode 100644 openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithKnownButNotUniqueClassFactory.java
 create mode 100644 openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithKnownTypeFactory.java
 create mode 100644 openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithKnownUniqueClassFactory.java
 create mode 100644 openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithNestedMapsInCollectionFactory.java
 create mode 100644 openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithNestedMapsInListFactory.java
 create mode 100644 openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithNestedTypesFactory.java
 create mode 100644 openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithPrimitiveTypesFactory.java
 create mode 100644 openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithPrivateAccessFactory.java
 create mode 100644 openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithRenamedPropertiesFactory.java
 create mode 100644 openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithReusedReferences.java
 create mode 100644 openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithReusedReferencesFactory.java
 create mode 100644 openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithSelfReferenceFactory.java
 create mode 100644 openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeAAFactory.java
 create mode 100644 openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeAFactory.java
 create mode 100644 openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeBFactory.java
 create mode 100644 openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeButNoSubtypesFactory.java
 create mode 100644 openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeCFactory.java
 create mode 100644 openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeFactory.java
 create mode 100644 openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithUnknownTypeFactory.java

diff --git a/openbis-common/source/java/ch/systemsx/cisd/common/api/server/json/introspector/JsonTypeAndClassAnnotationIntrospector.java b/openbis-common/source/java/ch/systemsx/cisd/common/api/server/json/introspector/JsonTypeAndClassAnnotationIntrospector.java
index 449d9f76e50..fe9cc309203 100644
--- a/openbis-common/source/java/ch/systemsx/cisd/common/api/server/json/introspector/JsonTypeAndClassAnnotationIntrospector.java
+++ b/openbis-common/source/java/ch/systemsx/cisd/common/api/server/json/introspector/JsonTypeAndClassAnnotationIntrospector.java
@@ -70,24 +70,20 @@ public class JsonTypeAndClassAnnotationIntrospector extends JacksonAnnotationInt
             JavaType baseType)
     {
 
-        JsonObject typeAnnotation = ac.getRawType().getAnnotation(JsonObject.class);
-
-        if (typeAnnotation == null)
+        if (useCustomResolver(baseType))
         {
-            // for standard classes use a default implementation
-            return super.findTypeResolver(config, ac, baseType);
+            return new JsonTypeAndClassResolverBuilder(classValueToClassObjectsMapping);
         } else
         {
-            if (ac.getRawType().isEnum())
-            {
-                // for enumerations also use a default implementation
-                return super.findTypeResolver(config, ac, baseType);
-            } else
-            {
-                // for our classes (ones with @JsonObject annotation) use the custom deserializer
-                return new JsonTypeAndClassResolverBuilder(classValueToClassObjectsMapping);
-            }
+            return super.findTypeResolver(config, ac, baseType);
         }
     }
 
+    private boolean useCustomResolver(JavaType type)
+    {
+        return type.getRawClass().equals(Object.class)
+                || (type.getRawClass().isAnnotationPresent(JsonObject.class) && !type.getRawClass()
+                        .isEnum());
+    }
+
 }
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/JsonDeserializationTest.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/JsonDeserializationTest.java
index 9c1c43fc66c..8ccbca07479 100644
--- a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/JsonDeserializationTest.java
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/JsonDeserializationTest.java
@@ -16,8 +16,7 @@
 
 package ch.systemsx.cisd.common.api.server.json;
 
-import java.util.ArrayList;
-import java.util.HashMap;
+import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 
@@ -27,24 +26,47 @@ import org.testng.annotations.Test;
 import com.fasterxml.jackson.databind.JsonMappingException;
 import com.fasterxml.jackson.databind.ObjectMapper;
 
-import ch.systemsx.cisd.common.api.server.json.common.ObjectMap;
+import ch.systemsx.cisd.common.api.server.json.common.JsonConstants;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectCounter;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectFactory;
 import ch.systemsx.cisd.common.api.server.json.common.ObjectType;
+import ch.systemsx.cisd.common.api.server.json.object.ObjectNestedChildFactory;
+import ch.systemsx.cisd.common.api.server.json.object.ObjectNestedFactory;
 import ch.systemsx.cisd.common.api.server.json.object.ObjectWithContainerTypes;
+import ch.systemsx.cisd.common.api.server.json.object.ObjectWithContainerTypesFactory;
 import ch.systemsx.cisd.common.api.server.json.object.ObjectWithDateTypes;
+import ch.systemsx.cisd.common.api.server.json.object.ObjectWithDateTypesFactory;
 import ch.systemsx.cisd.common.api.server.json.object.ObjectWithEnumTypes;
+import ch.systemsx.cisd.common.api.server.json.object.ObjectWithEnumTypesFactory;
 import ch.systemsx.cisd.common.api.server.json.object.ObjectWithIgnoredProperties;
+import ch.systemsx.cisd.common.api.server.json.object.ObjectWithIgnoredPropertiesFactory;
+import ch.systemsx.cisd.common.api.server.json.object.ObjectWithNestedMapsInCollectionFactory;
+import ch.systemsx.cisd.common.api.server.json.object.ObjectWithNestedMapsInListFactory;
 import ch.systemsx.cisd.common.api.server.json.object.ObjectWithNestedTypes;
 import ch.systemsx.cisd.common.api.server.json.object.ObjectWithNestedTypes.ObjectNested;
 import ch.systemsx.cisd.common.api.server.json.object.ObjectWithNestedTypes.ObjectNestedChild;
+import ch.systemsx.cisd.common.api.server.json.object.ObjectWithNestedTypesFactory;
 import ch.systemsx.cisd.common.api.server.json.object.ObjectWithPrimitiveTypes;
+import ch.systemsx.cisd.common.api.server.json.object.ObjectWithPrimitiveTypesFactory;
 import ch.systemsx.cisd.common.api.server.json.object.ObjectWithPrivateAccess;
+import ch.systemsx.cisd.common.api.server.json.object.ObjectWithPrivateAccessFactory;
 import ch.systemsx.cisd.common.api.server.json.object.ObjectWithRenamedProperties;
+import ch.systemsx.cisd.common.api.server.json.object.ObjectWithRenamedPropertiesFactory;
+import ch.systemsx.cisd.common.api.server.json.object.ObjectWithReusedReferences;
+import ch.systemsx.cisd.common.api.server.json.object.ObjectWithReusedReferencesFactory;
+import ch.systemsx.cisd.common.api.server.json.object.ObjectWithSelfReference;
+import ch.systemsx.cisd.common.api.server.json.object.ObjectWithSelfReferenceFactory;
 import ch.systemsx.cisd.common.api.server.json.object.ObjectWithType;
 import ch.systemsx.cisd.common.api.server.json.object.ObjectWithTypeA;
 import ch.systemsx.cisd.common.api.server.json.object.ObjectWithTypeAA;
-import ch.systemsx.cisd.common.api.server.json.object.ObjectWithTypeB;
+import ch.systemsx.cisd.common.api.server.json.object.ObjectWithTypeAAFactory;
+import ch.systemsx.cisd.common.api.server.json.object.ObjectWithTypeAFactory;
+import ch.systemsx.cisd.common.api.server.json.object.ObjectWithTypeBFactory;
 import ch.systemsx.cisd.common.api.server.json.object.ObjectWithTypeButNoSubtypes;
+import ch.systemsx.cisd.common.api.server.json.object.ObjectWithTypeButNoSubtypesFactory;
 import ch.systemsx.cisd.common.api.server.json.object.ObjectWithTypeC;
+import ch.systemsx.cisd.common.api.server.json.object.ObjectWithTypeCFactory;
+import ch.systemsx.cisd.common.api.server.json.object.ObjectWithTypeFactory;
 import ch.systemsx.cisd.common.api.server.json.object.ObjectWithTypeInterface1;
 import ch.systemsx.cisd.common.api.server.json.object.ObjectWithTypeInterface2;
 
@@ -57,473 +79,297 @@ public class JsonDeserializationTest
     @Test
     public void testDeserializeJsonWithRootTypeToRootInterface1() throws Exception
     {
-        testDeserializeObjectWithType(ObjectType.TYPE, ObjectWithTypeInterface1.class);
-        testDeserializeObjectWithType(ObjectType.CLASS, ObjectWithTypeInterface1.class);
+        testDeserialize(new ObjectWithTypeFactory(), ObjectWithTypeInterface1.class);
     }
 
     @Test
     public void testDeserializeJsonWithRootTypeToRootInterface2() throws Exception
     {
-        testDeserializeObjectWithType(ObjectType.TYPE, ObjectWithTypeInterface2.class);
-        testDeserializeObjectWithType(ObjectType.CLASS, ObjectWithTypeInterface2.class);
+        testDeserialize(new ObjectWithTypeFactory(), ObjectWithTypeInterface2.class);
     }
 
     @Test
     public void testDeserializeJsonWithRootTypeToRootType() throws Exception
     {
-        testDeserializeObjectWithType(ObjectType.TYPE, ObjectWithType.class);
-        testDeserializeObjectWithType(ObjectType.CLASS, ObjectWithType.class);
+        testDeserialize(new ObjectWithTypeFactory(), ObjectWithType.class);
     }
 
     @Test
     public void testDeserializeJsonWithFirstLevelSubTypeToRootInterface1() throws Exception
     {
-        testDeserializeObjectWithTypeA(ObjectType.TYPE, ObjectWithTypeInterface1.class);
-        testDeserializeObjectWithTypeA(ObjectType.CLASS, ObjectWithTypeInterface1.class);
+        testDeserialize(new ObjectWithTypeAFactory(), ObjectWithTypeInterface1.class);
     }
 
     @Test
     public void testDeserializeJsonWithFirstLevelSubTypeToRootInterface2() throws Exception
     {
-        testDeserializeObjectWithTypeA(ObjectType.TYPE, ObjectWithTypeInterface2.class);
-        testDeserializeObjectWithTypeA(ObjectType.CLASS, ObjectWithTypeInterface2.class);
+        testDeserialize(new ObjectWithTypeAFactory(), ObjectWithTypeInterface2.class);
     }
 
     @Test
     public void testDeserializeJsonWithFirstLevelSubTypeToRootType() throws Exception
     {
-        testDeserializeObjectWithTypeA(ObjectType.TYPE, ObjectWithType.class);
-        testDeserializeObjectWithTypeA(ObjectType.CLASS, ObjectWithType.class);
+        testDeserialize(new ObjectWithTypeAFactory(), ObjectWithType.class);
     }
 
     @Test
     public void testDeserializeJsonWithFirstLevelSubTypeToFirstLevelSubType() throws Exception
     {
-        testDeserializeObjectWithTypeA(ObjectType.TYPE, ObjectWithTypeA.class);
-        testDeserializeObjectWithTypeA(ObjectType.CLASS, ObjectWithTypeA.class);
+        testDeserialize(new ObjectWithTypeAFactory(), ObjectWithTypeA.class);
     }
 
     @Test(expectedExceptions = JsonMappingException.class)
     public void testDeserializeJsonWithFirstLevelSubTypeToSecondLevelSubType() throws Exception
     {
-        testDeserializeObjectWithTypeA(ObjectType.TYPE, ObjectWithTypeAA.class);
-        testDeserializeObjectWithTypeA(ObjectType.CLASS, ObjectWithTypeAA.class);
+        testDeserialize(new ObjectWithTypeAFactory(), ObjectWithTypeAA.class);
     }
 
     @Test
     public void testDeserializeJsonWithSecondLevelSubTypeToRootInterface1() throws Exception
     {
-        testDeserializeObjectWithTypeAA(ObjectType.TYPE, ObjectWithTypeInterface1.class);
-        testDeserializeObjectWithTypeAA(ObjectType.CLASS, ObjectWithTypeInterface1.class);
+        testDeserialize(new ObjectWithTypeAAFactory(), ObjectWithTypeInterface1.class);
     }
 
     @Test
     public void testDeserializeJsonWithSecondLevelSubTypeToRootInterface2() throws Exception
     {
-        testDeserializeObjectWithTypeAA(ObjectType.TYPE, ObjectWithTypeInterface2.class);
-        testDeserializeObjectWithTypeAA(ObjectType.CLASS, ObjectWithTypeInterface2.class);
+        testDeserialize(new ObjectWithTypeAAFactory(), ObjectWithTypeInterface2.class);
     }
 
     @Test
     public void testDeserializeJsonWithSecondLevelSubTypeToRootType() throws Exception
     {
-        testDeserializeObjectWithTypeAA(ObjectType.TYPE, ObjectWithType.class);
-        testDeserializeObjectWithTypeAA(ObjectType.CLASS, ObjectWithType.class);
+        testDeserialize(new ObjectWithTypeAAFactory(), ObjectWithType.class);
     }
 
     @Test
     public void testDeserializeJsonWithSecondLevelSubTypeToFirstLevelSubType() throws Exception
     {
-        testDeserializeObjectWithTypeAA(ObjectType.TYPE, ObjectWithTypeA.class);
-        testDeserializeObjectWithTypeAA(ObjectType.CLASS, ObjectWithTypeA.class);
+        testDeserialize(new ObjectWithTypeAAFactory(), ObjectWithTypeA.class);
     }
 
     @Test
     public void testDeserializeJsonWithSecondLevelSubTypeToSecondLevelSubType() throws Exception
     {
-        testDeserializeObjectWithTypeAA(ObjectType.TYPE, ObjectWithTypeAA.class);
-        testDeserializeObjectWithTypeAA(ObjectType.CLASS, ObjectWithTypeAA.class);
+        testDeserialize(new ObjectWithTypeAAFactory(), ObjectWithTypeAA.class);
     }
 
     @Test
     public void testDeserializeJsonWithNestedRootTypeToNestedRootType() throws Exception
     {
-        testDeserializeObjectNested(ObjectType.TYPE, ObjectNested.class);
-        testDeserializeObjectNested(ObjectType.CLASS, ObjectNested.class);
+        testDeserialize(new ObjectNestedFactory(), ObjectNested.class);
     }
 
     @Test
     public void testDeserializeJsonWithNestedSubTypeToNestedRootType() throws Exception
     {
-        testDeserializeObjectNestedChild(ObjectType.TYPE, ObjectNested.class);
-        testDeserializeObjectNestedChild(ObjectType.CLASS, ObjectNested.class);
+        testDeserialize(new ObjectNestedChildFactory(), ObjectNested.class);
     }
 
     @Test
     public void testDeserializeJsonWithNestedSubTypeToNestedSubType() throws Exception
     {
-        testDeserializeObjectNestedChild(ObjectType.TYPE, ObjectNestedChild.class);
-        testDeserializeObjectNestedChild(ObjectType.CLASS, ObjectNestedChild.class);
+        testDeserialize(new ObjectNestedChildFactory(), ObjectNestedChild.class);
     }
 
     @Test
     public void testDeserializeJsonWithObjectWithPrimitiveTypes() throws Exception
     {
-        testDeserializeObjectWithPrimitiveTypes(ObjectType.TYPE);
-        testDeserializeObjectWithPrimitiveTypes(ObjectType.CLASS);
+        testDeserialize(new ObjectWithPrimitiveTypesFactory(), ObjectWithPrimitiveTypes.class);
     }
 
     @Test
     public void testDeserializeJsonWithObjectWithNestedTypes() throws Exception
     {
-        testDeserializeObjectWithNestedTypes(ObjectType.TYPE);
-        testDeserializeObjectWithNestedTypes(ObjectType.CLASS);
+        testDeserialize(new ObjectWithNestedTypesFactory(), ObjectWithNestedTypes.class);
     }
 
     @Test
     public void testDeserializeJsonWithObjectWithEnumTypes() throws Exception
     {
-        testDeserializeObjectWithEnumTypes(ObjectType.TYPE);
-        testDeserializeObjectWithEnumTypes(ObjectType.CLASS);
+        testDeserialize(new ObjectWithEnumTypesFactory(), ObjectWithEnumTypes.class);
     }
 
     @Test
     public void testDeserializeJsonWithObjectWithDateTypes() throws Exception
     {
-        testDeserializeObjectWithDateTypes(ObjectType.TYPE);
-        testDeserializeObjectWithDateTypes(ObjectType.CLASS);
+        testDeserialize(new ObjectWithDateTypesFactory(), ObjectWithDateTypes.class);
     }
 
     @Test
     public void testDeserializeJsonWithObjectWithContainerTypes() throws Exception
     {
-        testDeserializeObjectWithContainerTypes(ObjectType.TYPE);
-        testDeserializeObjectWithContainerTypes(ObjectType.CLASS);
+        testDeserialize(new ObjectWithContainerTypesFactory(), ObjectWithContainerTypes.class);
     }
 
     @Test
     public void testDeserializeJsonWithIgnoredProperties() throws Exception
     {
-        testDeserializeObjectWithIgnoredProperties(ObjectType.TYPE);
-        testDeserializeObjectWithIgnoredProperties(ObjectType.CLASS);
+        testDeserialize(new ObjectWithIgnoredPropertiesFactory(), ObjectWithIgnoredProperties.class);
     }
 
     @Test
     public void testDeserializeJsonWithRenamedProperties() throws Exception
     {
-        testDeserializeObjectWithRenamedProperties(ObjectType.TYPE);
-        testDeserializeObjectWithRenamedProperties(ObjectType.CLASS);
+        testDeserialize(new ObjectWithRenamedPropertiesFactory(), ObjectWithRenamedProperties.class);
     }
 
     @Test
     public void testDeserializeJsonWithPrivateAccess() throws Exception
     {
-        testDeserializeObjectWithPrivateAccess(ObjectType.TYPE);
-        testDeserializeObjectWithPrivateAccess(ObjectType.CLASS);
+        testDeserialize(new ObjectWithPrivateAccessFactory(), ObjectWithPrivateAccess.class);
+    }
+
+    @Test
+    public void testDeserializeJsonWithSelfReference() throws Exception
+    {
+        testDeserialize(new ObjectWithSelfReferenceFactory(), ObjectWithSelfReference.class);
+    }
+
+    @Test
+    public void testDeserializeJsonWithReusedReferences() throws Exception
+    {
+        testDeserialize(new ObjectWithReusedReferencesFactory(), ObjectWithReusedReferences.class);
     }
 
     @Test(expectedExceptions = JsonMappingException.class)
     public void testDeserializeJsonWithoutTypeToPolymorphicType() throws Exception
     {
-        testDeserializeObjectWithType(ObjectType.NONE, ObjectWithType.class);
+        Object object =
+                new ObjectWithTypeFactory().createMapToDeserialize(new ObjectCounter(),
+                        ObjectType.NONE);
+        testDeserialize(object, ObjectWithType.class);
     }
 
     @Test
     public void testDeserializeJsonWithTypeToPolymorphicType() throws Exception
     {
-        testDeserializeObjectWithType(ObjectType.TYPE, ObjectWithType.class);
-        testDeserializeObjectWithType(ObjectType.CLASS, ObjectWithType.class);
+        testDeserialize(new ObjectWithTypeFactory(), ObjectWithType.class);
     }
 
     @Test
     public void testDeserializeJsonWithoutTypeToNotPolymorphicType() throws Exception
     {
-        testDeserializeObjectWithTypeButNoSubtypes(ObjectType.NONE,
-                ObjectWithTypeButNoSubtypes.class);
+        Object object =
+                new ObjectWithTypeButNoSubtypesFactory().createMapToDeserialize(
+                        new ObjectCounter(), ObjectType.NONE);
+        testDeserialize(object, ObjectWithTypeButNoSubtypes.class);
     }
 
     @Test
     public void testDeserializeJsonWithTypeToNotPolymorphicType() throws Exception
     {
-        testDeserializeObjectWithTypeButNoSubtypes(ObjectType.TYPE,
-                ObjectWithTypeButNoSubtypes.class);
-        testDeserializeObjectWithTypeButNoSubtypes(ObjectType.CLASS,
-                ObjectWithTypeButNoSubtypes.class);
+        testDeserialize(new ObjectWithTypeButNoSubtypesFactory(), ObjectWithTypeButNoSubtypes.class);
     }
 
     @Test
     public void testDeserializeJsonWithLegacyClassDefinedInClassMapping() throws Exception
     {
-        testDeserializeObjectWithTypeA(ObjectType.CLASS, ObjectWithType.class);
+        Object object =
+                new ObjectWithTypeAFactory().createMapToDeserialize(new ObjectCounter(),
+                        ObjectType.CLASS);
+        testDeserialize(object, ObjectWithType.class);
     }
 
     @Test(expectedExceptions = JsonMappingException.class)
     public void testDeserializeJsonWithLegacyClassNotDefinedInClassMapping() throws Exception
     {
-        testDeserializeObjectWithTypeC(ObjectType.CLASS, ObjectWithType.class);
+        Object object =
+                new ObjectWithTypeCFactory().createMapToDeserialize(new ObjectCounter(),
+                        ObjectType.CLASS);
+        testDeserialize(object, ObjectWithType.class);
     }
 
+    @SuppressWarnings("unchecked")
     @Test(expectedExceptions = Exception.class)
     public void testDeserializeJsonWithLegacyClassNotDefinedInClassMappingButMatchingType()
             throws Exception
     {
-        ObjectMap map = ObjectWithTypeC.createMap(null, ObjectType.NONE);
-        map.putType(null, ".ObjectWithTypeC", ObjectType.CLASS);
-        deserialize(map.toMap(), ObjectWithTypeC.class);
+        Map<String, Object> map =
+                (Map<String, Object>) new ObjectWithTypeCFactory().createMapToDeserialize(
+                        new ObjectCounter(), ObjectType.NONE);
+        map.put(JsonConstants.getLegacyClassField(), ObjectWithTypeCFactory.TYPE);
+        testDeserialize(map, ObjectWithTypeC.class);
     }
 
     @Test
     public void testDeserializeJsonWithNotUniqueLegacyClassUsedInDifferentInheritanceTrees()
             throws Exception
     {
-        testDeserializeObjectWithTypeA(ObjectType.CLASS, ObjectWithType.class);
+        Object object =
+                new ObjectWithTypeAFactory().createMapToDeserialize(new ObjectCounter(),
+                        ObjectType.CLASS);
+        testDeserialize(object, ObjectWithType.class);
     }
 
     @Test(expectedExceptions = JsonMappingException.class)
     public void testDeserializeJsonWithNotUniqueLegacyClassUsedInSameInheritanceTree()
             throws Exception
     {
-        ObjectMap map = ObjectWithTypeB.createMap(null, ObjectType.CLASS);
-        deserialize(map.toMap(), ObjectWithType.class);
+        Object object =
+                new ObjectWithTypeCFactory().createMapToDeserialize(new ObjectCounter(),
+                        ObjectType.CLASS);
+        testDeserialize(object, ObjectWithType.class);
     }
 
     @Test
     public void testDeserializeJsonWithNotUniqueTypeUsedInDifferentInheritanceTrees()
             throws Exception
     {
-        testDeserializeObjectWithTypeA(ObjectType.TYPE, ObjectWithType.class);
+        Object object =
+                new ObjectWithTypeAFactory().createMapToDeserialize(new ObjectCounter(),
+                        ObjectType.TYPE);
+        testDeserialize(object, ObjectWithType.class);
     }
 
     @Test
     public void testDeserializeJsonWithNotUniqueTypeUsedInSameInheritanceTree() throws Exception
     {
-        ObjectMap map = ObjectWithTypeB.createMap(null, ObjectType.TYPE);
-        Object result = deserialize(map.toMap(), ObjectWithType.class);
-        Assert.assertFalse(ObjectWithTypeB.class.equals(result.getClass()));
+        Object object =
+                new ObjectWithTypeBFactory().createMapToDeserialize(new ObjectCounter(),
+                        ObjectType.TYPE);
+        testDeserialize(object, ObjectWithType.class);
     }
 
     @Test
     public void testDeserializeJsonWithNestedMapsInCollection() throws Exception
     {
-        testDeserializeJsonWithNestedMapsInCollection(ObjectType.TYPE);
-        testDeserializeJsonWithNestedMapsInCollection(ObjectType.CLASS);
-    }
-
-    private void testDeserializeJsonWithNestedMapsInCollection(ObjectType includeType)
-            throws Exception
-    {
-        ObjectWithContainerTypes object =
-                ObjectWithContainerTypes.createObjectWithIncorrectObjectsAsMaps();
-        ObjectMap map = ObjectWithContainerTypes.createMap(null, includeType);
-
-        List<Object> collectionWithObject = new ArrayList<Object>();
-        collectionWithObject.add(object);
-
-        List<Object> collectionWithMap = new ArrayList<Object>();
-        collectionWithMap.add(map.toMap());
-
-        Object result = deserialize(collectionWithMap, List.class);
-        Assert.assertTrue(collectionWithObject.equals(result));
+        testDeserialize(new ObjectWithNestedMapsInCollectionFactory(), Collection.class);
     }
 
     @Test
     public void testDeserializeJsonWithNestedMapsInMap() throws Exception
     {
-        testDeserializeJsonWithNestedMapsInMap(ObjectType.TYPE);
-        testDeserializeJsonWithNestedMapsInMap(ObjectType.CLASS);
-    }
-
-    private void testDeserializeJsonWithNestedMapsInMap(ObjectType includeType) throws Exception
-    {
-        ObjectWithContainerTypes object =
-                ObjectWithContainerTypes.createObjectWithIncorrectObjectsAsMaps();
-        ObjectMap map = ObjectWithContainerTypes.createMap(null, includeType);
-
-        Map<String, Object> mapWithObject = new HashMap<String, Object>();
-        mapWithObject.put("object", object);
-
-        Map<String, Object> mapWithMap = new HashMap<String, Object>();
-        mapWithMap.put("object", map.toMap());
-
-        Object result = deserialize(mapWithMap, Map.class);
-        Assert.assertTrue(mapWithObject.equals(result));
+        testDeserialize(new ObjectWithNestedMapsInMapFactory(), Map.class);
     }
 
     @Test
     public void testDeserializeJsonWithNestedMapsInList() throws Exception
     {
-        testDeserializeJsonWithNestedMapsInList(ObjectType.TYPE);
-        testDeserializeJsonWithNestedMapsInList(ObjectType.CLASS);
+        testDeserialize(new ObjectWithNestedMapsInListFactory(), List.class);
     }
 
-    private void testDeserializeJsonWithNestedMapsInList(ObjectType includeType) throws Exception
+    private void testDeserialize(ObjectFactory<?> factory, Class<?> rootClass) throws Exception
     {
-        ObjectWithContainerTypes object =
-                ObjectWithContainerTypes.createObjectWithIncorrectObjectsAsMaps();
-        ObjectMap map = ObjectWithContainerTypes.createMap(null, includeType);
-
-        List<Object> listWithObject = new ArrayList<Object>();
-        listWithObject.add(object);
-
-        List<Object> listWithMap = new ArrayList<Object>();
-        listWithMap.add(map.toMap());
+        Object expected = factory.createExpectedObjectAfterDeserialization();
 
-        Object result = deserialize(listWithMap, List.class);
-        Assert.assertTrue(listWithObject.equals(result));
-    }
-
-    private void testDeserializeObjectWithType(ObjectType includeType, Class<?> rootClass)
-            throws Exception
-    {
-        ObjectWithType object = ObjectWithType.createObject();
-        ObjectMap map = ObjectWithType.createMap(null, includeType);
-
-        Object result = deserialize(map.toMap(), rootClass);
-        Assert.assertTrue(object.equals(result));
-    }
-
-    private void testDeserializeObjectWithTypeA(ObjectType includeType, Class<?> rootClass)
-            throws Exception
-    {
-        ObjectWithTypeA object = ObjectWithTypeA.createObject();
-        ObjectMap map = ObjectWithTypeA.createMap(null, includeType);
-
-        Object result = deserialize(map.toMap(), rootClass);
-        Assert.assertTrue(object.equals(result));
-    }
-
-    private void testDeserializeObjectWithTypeC(ObjectType includeType, Class<?> rootClass)
-            throws Exception
-    {
-        ObjectWithTypeC object = ObjectWithTypeC.createObject();
-        ObjectMap map = ObjectWithTypeC.createMap(null, includeType);
-
-        Object result = deserialize(map.toMap(), rootClass);
-        Assert.assertTrue(object.equals(result));
-    }
-
-    private void testDeserializeObjectWithTypeAA(ObjectType includeType, Class<?> rootClass)
-            throws Exception
-    {
-        ObjectWithTypeAA object = ObjectWithTypeAA.createObject();
-        ObjectMap map = ObjectWithTypeAA.createMap(null, includeType);
-
-        Object result = deserialize(map.toMap(), rootClass);
-        Assert.assertTrue(object.equals(result));
-    }
-
-    private void testDeserializeObjectWithTypeButNoSubtypes(ObjectType includeType,
-            Class<?> rootClass) throws Exception
-    {
-        ObjectWithTypeButNoSubtypes object = ObjectWithTypeButNoSubtypes.createObject();
-        ObjectMap map = ObjectWithTypeButNoSubtypes.createMap(null, includeType);
-
-        Object result = deserialize(map.toMap(), rootClass);
-        Assert.assertTrue(object.equals(result));
-    }
-
-    private void testDeserializeObjectWithIgnoredProperties(ObjectType includeType)
-            throws Exception
-    {
-        ObjectWithIgnoredProperties object =
-                ObjectWithIgnoredProperties.createObjectWithIgnoredPropertiesNull();
-        ObjectMap map = ObjectWithIgnoredProperties.createMap(null, includeType);
-
-        Object result = deserialize(map.toMap(), ObjectWithIgnoredProperties.class);
-        Assert.assertTrue(object.equals(result));
-    }
-
-    private void testDeserializeObjectWithRenamedProperties(ObjectType includeType)
-            throws Exception
-    {
-        ObjectWithRenamedProperties object = ObjectWithRenamedProperties.createObject();
-        ObjectMap map = ObjectWithRenamedProperties.createMap(null, includeType);
-
-        Object result = deserialize(map.toMap(), ObjectWithRenamedProperties.class);
-        Assert.assertTrue(object.equals(result));
-    }
-
-    private void testDeserializeObjectWithPrivateAccess(ObjectType includeType) throws Exception
-    {
-        ObjectWithPrivateAccess object = ObjectWithPrivateAccess.createObject();
-        ObjectMap map = ObjectWithPrivateAccess.createMap(null, includeType);
-
-        Object result = deserialize(map.toMap(), ObjectWithPrivateAccess.class);
-        Assert.assertTrue(object.equals(result));
-    }
-
-    private void testDeserializeObjectWithPrimitiveTypes(ObjectType includeType) throws Exception
-    {
-        ObjectWithPrimitiveTypes object = ObjectWithPrimitiveTypes.createObject();
-        ObjectMap map = ObjectWithPrimitiveTypes.createMap(null, includeType);
-
-        Object result = deserialize(map.toMap(), ObjectWithPrimitiveTypes.class);
-        Assert.assertTrue(object.equals(result));
-    }
-
-    private void testDeserializeObjectWithEnumTypes(ObjectType includeType) throws Exception
-    {
-        ObjectWithEnumTypes object = ObjectWithEnumTypes.createObject();
-        ObjectMap map = ObjectWithEnumTypes.createMap(null, includeType);
-
-        Object result = deserialize(map.toMap(), ObjectWithEnumTypes.class);
-        Assert.assertTrue(object.equals(result));
-    }
-
-    private void testDeserializeObjectWithDateTypes(ObjectType includeType) throws Exception
-    {
-        ObjectWithDateTypes object = ObjectWithDateTypes.createObject();
-        ObjectMap map = ObjectWithDateTypes.createMap(null, includeType);
-
-        Object result = deserialize(map.toMap(), ObjectWithDateTypes.class);
-        Assert.assertTrue(object.equals(result));
-    }
-
-    private void testDeserializeObjectWithContainerTypes(ObjectType includeType) throws Exception
-    {
-        ObjectWithContainerTypes object =
-                ObjectWithContainerTypes.createObjectWithIncorrectObjectsAsMaps();
-        ObjectMap map = ObjectWithContainerTypes.createMap(null, includeType);
-
-        Object result = deserialize(map.toMap(), ObjectWithContainerTypes.class);
-        Assert.assertTrue(object.equals(result));
-    }
-
-    private void testDeserializeObjectWithNestedTypes(ObjectType includeType) throws Exception
-    {
-        ObjectWithNestedTypes object = ObjectWithNestedTypes.createObject();
-        ObjectMap map = ObjectWithNestedTypes.createMap(null, includeType);
-
-        Object result = deserialize(map.toMap(), ObjectWithNestedTypes.class);
-        Assert.assertTrue(object.equals(result));
-    }
-
-    private void testDeserializeObjectNested(ObjectType includeType, Class<?> rootClass)
-            throws Exception
-    {
-        ObjectNested object = ObjectNested.createObject();
-        ObjectMap map = ObjectNested.createMap(null, includeType);
-
-        Object result = deserialize(map.toMap(), rootClass);
-        Assert.assertTrue(object.equals(result));
-    }
-
-    private void testDeserializeObjectNestedChild(ObjectType includeType, Class<?> rootClass)
-            throws Exception
-    {
-        ObjectNestedChild object = ObjectNestedChild.createObject();
-        ObjectMap map = ObjectNestedChild.createMap(null, includeType);
-
-        Object result = deserialize(map.toMap(), rootClass);
-        Assert.assertTrue(object.equals(result));
+        for (ObjectType objectType : ObjectType.values())
+        {
+            if (ObjectType.NONE.equals(objectType))
+            {
+                continue;
+            }
+            Object object = factory.createMapToDeserialize(new ObjectCounter(), objectType);
+            Object result = testDeserialize(object, rootClass);
+            Assert.assertTrue(expected.equals(result));
+        }
     }
 
     @SuppressWarnings("unchecked")
-    private <T> T deserialize(Object object, Class<?> rootClass) throws Exception
+    private <T> T testDeserialize(Object object, Class<?> rootClass) throws Exception
     {
-        ObjectMapper mapper = new JsonTestObjectMapper();
-        Object result = mapper.readValue(mapper.writeValueAsString(object), rootClass);
-        return (T) result;
+        String jsonFromObject = new ObjectMapper().writeValueAsString(object);
+        Object objectFromJson = new JsonTestObjectMapper().readValue(jsonFromObject, rootClass);
+        return (T) objectFromJson;
     }
-
 }
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/JsonSerializationTest.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/JsonSerializationTest.java
index bfe7b8a5752..764187d692f 100644
--- a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/JsonSerializationTest.java
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/JsonSerializationTest.java
@@ -16,26 +16,31 @@
 
 package ch.systemsx.cisd.common.api.server.json;
 
-import java.util.Map;
-
 import org.testng.Assert;
 import org.testng.annotations.Test;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
 
 import ch.systemsx.cisd.common.api.server.json.common.ObjectCounter;
-import ch.systemsx.cisd.common.api.server.json.common.ObjectMap;
-import ch.systemsx.cisd.common.api.server.json.common.ObjectType;
-import ch.systemsx.cisd.common.api.server.json.object.ObjectWithEnumTypes;
-import ch.systemsx.cisd.common.api.server.json.object.ObjectWithNestedTypes;
-import ch.systemsx.cisd.common.api.server.json.object.ObjectWithNestedTypes.ObjectNested;
-import ch.systemsx.cisd.common.api.server.json.object.ObjectWithNestedTypes.ObjectNestedChild;
-import ch.systemsx.cisd.common.api.server.json.object.ObjectWithPrimitiveTypes;
-import ch.systemsx.cisd.common.api.server.json.object.ObjectWithSelfReference;
-import ch.systemsx.cisd.common.api.server.json.object.ObjectWithType;
-import ch.systemsx.cisd.common.api.server.json.object.ObjectWithTypeA;
-import ch.systemsx.cisd.common.api.server.json.object.ObjectWithTypeAA;
-import ch.systemsx.cisd.common.api.server.json.object.ObjectWithTypeButNoSubtypes;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectFactory;
+import ch.systemsx.cisd.common.api.server.json.object.ObjectNestedChildFactory;
+import ch.systemsx.cisd.common.api.server.json.object.ObjectNestedFactory;
+import ch.systemsx.cisd.common.api.server.json.object.ObjectWithContainerTypesFactory;
+import ch.systemsx.cisd.common.api.server.json.object.ObjectWithDateTypesFactory;
+import ch.systemsx.cisd.common.api.server.json.object.ObjectWithEnumTypesFactory;
+import ch.systemsx.cisd.common.api.server.json.object.ObjectWithIgnoredPropertiesFactory;
+import ch.systemsx.cisd.common.api.server.json.object.ObjectWithNestedMapsInCollectionFactory;
+import ch.systemsx.cisd.common.api.server.json.object.ObjectWithNestedMapsInListFactory;
+import ch.systemsx.cisd.common.api.server.json.object.ObjectWithNestedTypesFactory;
+import ch.systemsx.cisd.common.api.server.json.object.ObjectWithPrimitiveTypesFactory;
+import ch.systemsx.cisd.common.api.server.json.object.ObjectWithPrivateAccessFactory;
+import ch.systemsx.cisd.common.api.server.json.object.ObjectWithRenamedPropertiesFactory;
+import ch.systemsx.cisd.common.api.server.json.object.ObjectWithReusedReferencesFactory;
+import ch.systemsx.cisd.common.api.server.json.object.ObjectWithSelfReferenceFactory;
+import ch.systemsx.cisd.common.api.server.json.object.ObjectWithTypeAAFactory;
+import ch.systemsx.cisd.common.api.server.json.object.ObjectWithTypeAFactory;
+import ch.systemsx.cisd.common.api.server.json.object.ObjectWithTypeButNoSubtypesFactory;
+import ch.systemsx.cisd.common.api.server.json.object.ObjectWithTypeFactory;
 
 /**
  * @author pkupczyk
@@ -46,96 +51,132 @@ public class JsonSerializationTest
     @Test
     public void testSerializeRootType() throws Exception
     {
-        ObjectWithType object = ObjectWithType.createObject();
-        ObjectMap map = ObjectWithType.createMap(new ObjectCounter(), ObjectType.TYPE);
-        serializeObjectAndMapAndCompare(object, map.toMap());
+        testSerialize(new ObjectWithTypeFactory());
     }
 
     @Test
     public void testSerializeFirstLevelSubType() throws Exception
     {
-        ObjectWithTypeA object = ObjectWithTypeA.createObject();
-        ObjectMap map = ObjectWithTypeA.createMap(new ObjectCounter(), ObjectType.TYPE);
-        serializeObjectAndMapAndCompare(object, map.toMap());
+        testSerialize(new ObjectWithTypeAFactory());
     }
 
     @Test
     public void testSerializeSecondLevelSubType() throws Exception
     {
-        ObjectWithTypeAA object = ObjectWithTypeAA.createObject();
-        ObjectMap map = ObjectWithTypeAA.createMap(new ObjectCounter(), ObjectType.TYPE);
-        serializeObjectAndMapAndCompare(object, map.toMap());
+        testSerialize(new ObjectWithTypeAAFactory());
     }
 
     @Test
     public void testSerializeNestedRootType() throws Exception
     {
-        ObjectNested object = ObjectNested.createObject();
-        ObjectMap map = ObjectNested.createMap(new ObjectCounter(), ObjectType.TYPE);
-        serializeObjectAndMapAndCompare(object, map.toMap());
+        testSerialize(new ObjectNestedFactory());
     }
 
     @Test
     public void testSerializeNestedSubType() throws Exception
     {
-        ObjectNestedChild object = ObjectNestedChild.createObject();
-        ObjectMap map = ObjectNestedChild.createMap(new ObjectCounter(), ObjectType.TYPE);
-        serializeObjectAndMapAndCompare(object, map.toMap());
+        testSerialize(new ObjectNestedChildFactory());
     }
 
     @Test
     public void testSerializePolymorphicType() throws Exception
     {
-        ObjectWithType object = ObjectWithType.createObject();
-        ObjectMap map = ObjectWithType.createMap(new ObjectCounter(), ObjectType.TYPE);
-        serializeObjectAndMapAndCompare(object, map.toMap());
+        testSerialize(new ObjectWithTypeFactory());
     }
 
     @Test
     public void testSerializeNotPolymorphicType() throws Exception
     {
-        ObjectWithTypeButNoSubtypes object = ObjectWithTypeButNoSubtypes.createObject();
-        ObjectMap map = ObjectWithTypeButNoSubtypes.createMap(new ObjectCounter(), ObjectType.TYPE);
-        serializeObjectAndMapAndCompare(object, map.toMap());
+        testSerialize(new ObjectWithTypeButNoSubtypesFactory());
     }
 
     @Test
     public void testSerializeObjectWithPrimitiveTypes() throws Exception
     {
-        ObjectWithPrimitiveTypes object = ObjectWithPrimitiveTypes.createObject();
-        ObjectMap map = ObjectWithPrimitiveTypes.createMap(new ObjectCounter(), ObjectType.TYPE);
-        serializeObjectAndMapAndCompare(object, map.toMap());
+        testSerialize(new ObjectWithPrimitiveTypesFactory());
     }
 
     @Test
     public void testSerializeObjectWithNestedTypes() throws Exception
     {
-        ObjectWithNestedTypes object = ObjectWithNestedTypes.createObject();
-        ObjectMap map = ObjectWithNestedTypes.createMap(new ObjectCounter(), ObjectType.TYPE);
-        serializeObjectAndMapAndCompare(object, map.toMap());
+        testSerialize(new ObjectWithNestedTypesFactory());
     }
 
     @Test
     public void testSerializeObjectWithEnumTypes() throws Exception
     {
-        ObjectWithEnumTypes object = ObjectWithEnumTypes.createObject();
-        ObjectMap map = ObjectWithEnumTypes.createMap(new ObjectCounter(), ObjectType.TYPE);
-        serializeObjectAndMapAndCompare(object, map.toMap());
+        testSerialize(new ObjectWithEnumTypesFactory());
+    }
+
+    @Test
+    public void testSerializeObjectWithDateTypes() throws Exception
+    {
+        testSerialize(new ObjectWithDateTypesFactory());
+    }
+
+    @Test
+    public void testSerializeObjectWithIgnoredProperties() throws Exception
+    {
+        testSerialize(new ObjectWithIgnoredPropertiesFactory());
+    }
+
+    @Test
+    public void testSerializeObjectWithRenamedProperties() throws Exception
+    {
+        testSerialize(new ObjectWithRenamedPropertiesFactory());
+    }
+
+    @Test
+    public void testSerializeObjectWithPrivateAccess() throws Exception
+    {
+        testSerialize(new ObjectWithPrivateAccessFactory());
+    }
+
+    @Test
+    public void testSerializeObjectWithContainerTypes() throws Exception
+    {
+        testSerialize(new ObjectWithContainerTypesFactory());
+    }
+
+    @Test
+    public void testSerializeObjectWithNestedMapsInCollection() throws Exception
+    {
+        testSerialize(new ObjectWithNestedMapsInCollectionFactory());
+    }
+
+    @Test
+    public void testSerializeObjectWithNestedMapsInMap() throws Exception
+    {
+        testSerialize(new ObjectWithNestedMapsInMapFactory());
+    }
+
+    @Test
+    public void testSerializeObjectWithNestedMapsInList() throws Exception
+    {
+        testSerialize(new ObjectWithNestedMapsInListFactory());
     }
 
     @Test
     public void testSerializeObjectWithSelfReference() throws Exception
     {
-        ObjectWithSelfReference object = ObjectWithSelfReference.createObject();
-        ObjectMap map = ObjectWithSelfReference.createMap(new ObjectCounter(), ObjectType.TYPE);
-        serializeObjectAndMapAndCompare(object, map.toMap());
+        testSerialize(new ObjectWithSelfReferenceFactory());
+    }
+
+    @Test
+    public void testSerializeObjectWithReusedReferences() throws Exception
+    {
+        testSerialize(new ObjectWithReusedReferencesFactory());
     }
 
-    private void serializeObjectAndMapAndCompare(Object object, Map<String, Object> expectedMap)
-            throws Exception
+    private void testSerialize(ObjectFactory<?> factory) throws Exception
     {
+        Object object = factory.createObjectToSerialize();
         String jsonFromObject = new JsonTestObjectMapper().writeValueAsString(object);
-        String jsonFromExpectedMap = new ObjectMapper().writeValueAsString(expectedMap);
+
+        Object expectedObject = factory.createExpectedMapAfterSerialization(new ObjectCounter());
+        String jsonFromExpectedMap = new ObjectMapper().writeValueAsString(expectedObject);
+
         Assert.assertEquals(jsonFromObject, jsonFromExpectedMap);
     }
+
 }
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/JsonTestObjectMapper.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/JsonTestObjectMapper.java
index 028bac2a030..5ec35899eac 100644
--- a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/JsonTestObjectMapper.java
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/JsonTestObjectMapper.java
@@ -26,24 +26,42 @@ import ch.systemsx.cisd.common.api.server.json.mapping.IJsonBaseTypeToSubTypesMa
 import ch.systemsx.cisd.common.api.server.json.mapping.IJsonClassValueToClassObjectsMapping;
 import ch.systemsx.cisd.common.api.server.json.mapping.JsonReflectionsBaseTypeToSubTypesMapping;
 import ch.systemsx.cisd.common.api.server.json.mapping.JsonStaticClassValueToClassObjectsMapping;
+import ch.systemsx.cisd.common.api.server.json.object.ObjectNestedChildFactory;
+import ch.systemsx.cisd.common.api.server.json.object.ObjectNestedFactory;
 import ch.systemsx.cisd.common.api.server.json.object.ObjectWithContainerTypes;
+import ch.systemsx.cisd.common.api.server.json.object.ObjectWithContainerTypesFactory;
 import ch.systemsx.cisd.common.api.server.json.object.ObjectWithDateTypes;
+import ch.systemsx.cisd.common.api.server.json.object.ObjectWithDateTypesFactory;
 import ch.systemsx.cisd.common.api.server.json.object.ObjectWithEnumTypes;
+import ch.systemsx.cisd.common.api.server.json.object.ObjectWithEnumTypesFactory;
 import ch.systemsx.cisd.common.api.server.json.object.ObjectWithIgnoredProperties;
+import ch.systemsx.cisd.common.api.server.json.object.ObjectWithIgnoredPropertiesFactory;
 import ch.systemsx.cisd.common.api.server.json.object.ObjectWithNestedTypes;
 import ch.systemsx.cisd.common.api.server.json.object.ObjectWithNestedTypes.ObjectNested;
 import ch.systemsx.cisd.common.api.server.json.object.ObjectWithNestedTypes.ObjectNestedChild;
+import ch.systemsx.cisd.common.api.server.json.object.ObjectWithNestedTypesFactory;
 import ch.systemsx.cisd.common.api.server.json.object.ObjectWithPrimitiveTypes;
+import ch.systemsx.cisd.common.api.server.json.object.ObjectWithPrimitiveTypesFactory;
 import ch.systemsx.cisd.common.api.server.json.object.ObjectWithPrivateAccess;
+import ch.systemsx.cisd.common.api.server.json.object.ObjectWithPrivateAccessFactory;
 import ch.systemsx.cisd.common.api.server.json.object.ObjectWithRenamedProperties;
+import ch.systemsx.cisd.common.api.server.json.object.ObjectWithRenamedPropertiesFactory;
+import ch.systemsx.cisd.common.api.server.json.object.ObjectWithReusedReferences;
+import ch.systemsx.cisd.common.api.server.json.object.ObjectWithReusedReferencesFactory;
 import ch.systemsx.cisd.common.api.server.json.object.ObjectWithSelfReference;
+import ch.systemsx.cisd.common.api.server.json.object.ObjectWithSelfReferenceFactory;
 import ch.systemsx.cisd.common.api.server.json.object.ObjectWithType;
 import ch.systemsx.cisd.common.api.server.json.object.ObjectWithTypeA;
 import ch.systemsx.cisd.common.api.server.json.object.ObjectWithTypeAA;
+import ch.systemsx.cisd.common.api.server.json.object.ObjectWithTypeAAFactory;
+import ch.systemsx.cisd.common.api.server.json.object.ObjectWithTypeAFactory;
 import ch.systemsx.cisd.common.api.server.json.object.ObjectWithTypeALegalDuplicate;
 import ch.systemsx.cisd.common.api.server.json.object.ObjectWithTypeB;
+import ch.systemsx.cisd.common.api.server.json.object.ObjectWithTypeBFactory;
 import ch.systemsx.cisd.common.api.server.json.object.ObjectWithTypeBIllegalDuplicate;
 import ch.systemsx.cisd.common.api.server.json.object.ObjectWithTypeButNoSubtypes;
+import ch.systemsx.cisd.common.api.server.json.object.ObjectWithTypeButNoSubtypesFactory;
+import ch.systemsx.cisd.common.api.server.json.object.ObjectWithTypeFactory;
 import ch.systemsx.cisd.common.api.server.json.resolver.JsonReflectionsSubTypeResolver;
 import ch.systemsx.cisd.common.api.server.json.serializer.JsonSerializerFactory;
 
@@ -67,24 +85,31 @@ public class JsonTestObjectMapper extends ObjectMapper
     {
         JsonStaticClassValueToClassObjectsMapping classMapping =
                 new JsonStaticClassValueToClassObjectsMapping();
-        classMapping.addClass(ObjectWithType.CLASS, ObjectWithType.class);
-        classMapping.addClass(ObjectWithTypeA.CLASS, ObjectWithTypeA.class);
-        classMapping.addClass(ObjectWithTypeA.CLASS, ObjectWithTypeALegalDuplicate.class);
-        classMapping.addClass(ObjectWithTypeAA.CLASS, ObjectWithTypeAA.class);
-        classMapping.addClass(ObjectWithTypeB.CLASS, ObjectWithTypeB.class);
-        classMapping.addClass(ObjectWithTypeB.CLASS, ObjectWithTypeBIllegalDuplicate.class);
-        classMapping.addClass(ObjectWithTypeButNoSubtypes.CLASS, ObjectWithTypeButNoSubtypes.class);
-        classMapping.addClass(ObjectNested.CLASS, ObjectNested.class);
-        classMapping.addClass(ObjectNestedChild.CLASS, ObjectNestedChild.class);
-        classMapping.addClass(ObjectWithPrimitiveTypes.CLASS, ObjectWithPrimitiveTypes.class);
-        classMapping.addClass(ObjectWithNestedTypes.CLASS, ObjectWithNestedTypes.class);
-        classMapping.addClass(ObjectWithEnumTypes.CLASS, ObjectWithEnumTypes.class);
-        classMapping.addClass(ObjectWithContainerTypes.CLASS, ObjectWithContainerTypes.class);
-        classMapping.addClass(ObjectWithDateTypes.CLASS, ObjectWithDateTypes.class);
-        classMapping.addClass(ObjectWithIgnoredProperties.CLASS, ObjectWithIgnoredProperties.class);
-        classMapping.addClass(ObjectWithRenamedProperties.CLASS, ObjectWithRenamedProperties.class);
-        classMapping.addClass(ObjectWithPrivateAccess.CLASS, ObjectWithPrivateAccess.class);
-        classMapping.addClass(ObjectWithSelfReference.CLASS, ObjectWithSelfReference.class);
+        classMapping.addClass(ObjectWithTypeFactory.CLASS, ObjectWithType.class);
+        classMapping.addClass(ObjectWithTypeAFactory.CLASS, ObjectWithTypeA.class);
+        classMapping.addClass(ObjectWithTypeAFactory.CLASS, ObjectWithTypeALegalDuplicate.class);
+        classMapping.addClass(ObjectWithTypeAAFactory.CLASS, ObjectWithTypeAA.class);
+        classMapping.addClass(ObjectWithTypeBFactory.CLASS, ObjectWithTypeB.class);
+        classMapping.addClass(ObjectWithTypeBFactory.CLASS, ObjectWithTypeBIllegalDuplicate.class);
+        classMapping.addClass(ObjectWithTypeButNoSubtypesFactory.CLASS,
+                ObjectWithTypeButNoSubtypes.class);
+        classMapping.addClass(ObjectNestedFactory.CLASS, ObjectNested.class);
+        classMapping.addClass(ObjectNestedChildFactory.CLASS, ObjectNestedChild.class);
+        classMapping
+                .addClass(ObjectWithPrimitiveTypesFactory.CLASS, ObjectWithPrimitiveTypes.class);
+        classMapping.addClass(ObjectWithNestedTypesFactory.CLASS, ObjectWithNestedTypes.class);
+        classMapping.addClass(ObjectWithEnumTypesFactory.CLASS, ObjectWithEnumTypes.class);
+        classMapping
+                .addClass(ObjectWithContainerTypesFactory.CLASS, ObjectWithContainerTypes.class);
+        classMapping.addClass(ObjectWithDateTypesFactory.CLASS, ObjectWithDateTypes.class);
+        classMapping.addClass(ObjectWithIgnoredPropertiesFactory.CLASS,
+                ObjectWithIgnoredProperties.class);
+        classMapping.addClass(ObjectWithRenamedPropertiesFactory.CLASS,
+                ObjectWithRenamedProperties.class);
+        classMapping.addClass(ObjectWithPrivateAccessFactory.CLASS, ObjectWithPrivateAccess.class);
+        classMapping.addClass(ObjectWithSelfReferenceFactory.CLASS, ObjectWithSelfReference.class);
+        classMapping.addClass(ObjectWithReusedReferencesFactory.CLASS,
+                ObjectWithReusedReferences.class);
         return classMapping;
     }
 
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/ObjectWithNestedMapsInMapFactory.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/ObjectWithNestedMapsInMapFactory.java
new file mode 100644
index 00000000000..575774c3a75
--- /dev/null
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/ObjectWithNestedMapsInMapFactory.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * 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 ch.systemsx.cisd.common.api.server.json;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import ch.systemsx.cisd.common.api.server.json.common.ObjectCounter;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectFactory;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectType;
+import ch.systemsx.cisd.common.api.server.json.object.ObjectWithContainerTypesFactory;
+
+/**
+ * @author pkupczyk
+ */
+@SuppressWarnings(
+    { "rawtypes", "unchecked" })
+public class ObjectWithNestedMapsInMapFactory extends ObjectFactory<Map>
+{
+
+    public static final String OBJECT = "object";
+
+    @Override
+    public Map createObjectToSerialize()
+    {
+        Map map = new HashMap();
+        map.put(OBJECT, new ObjectWithContainerTypesFactory().createObjectToSerialize());
+        return map;
+    }
+
+    @Override
+    public Object createExpectedMapAfterSerialization(ObjectCounter objectCounter)
+    {
+        Map map = new HashMap();
+        map.put(OBJECT, new ObjectWithContainerTypesFactory()
+                .createExpectedMapAfterSerialization(objectCounter));
+        return map;
+    }
+
+    @Override
+    public Object createMapToDeserialize(ObjectCounter objectCounter,
+            ObjectType objectType)
+    {
+        Map map = new HashMap();
+        map.put(OBJECT, new ObjectWithContainerTypesFactory().createMapToDeserialize(objectCounter,
+                objectType));
+        return map;
+    }
+
+    @Override
+    public Map createExpectedObjectAfterDeserialization()
+    {
+        Map map = new HashMap();
+        map.put(OBJECT,
+                new ObjectWithContainerTypesFactory().createExpectedObjectAfterDeserialization());
+        return map;
+    }
+
+}
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/common/ObjectFactory.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/common/ObjectFactory.java
new file mode 100644
index 00000000000..356a9bd4562
--- /dev/null
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/common/ObjectFactory.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * 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 ch.systemsx.cisd.common.api.server.json.common;
+
+import java.util.Map;
+
+/**
+ * @author pkupczyk
+ */
+
+public abstract class ObjectFactory<T>
+{
+
+    public T createObjectToSerialize()
+    {
+        return createObject();
+    }
+
+    public Object createExpectedMapAfterSerialization(ObjectCounter objectCounter)
+    {
+        return createMap(objectCounter, ObjectType.TYPE);
+    }
+
+    public Object createMapToDeserialize(ObjectCounter objectCounter, ObjectType objectType)
+    {
+        return createMap(objectCounter, objectType);
+    }
+
+    public T createExpectedObjectAfterDeserialization()
+    {
+        return createObject();
+    }
+
+    protected T createObject()
+    {
+        throw new UnsupportedOperationException();
+    }
+
+    protected Map<String, Object> createMap(ObjectCounter objectCounter, ObjectType objectType)
+    {
+        throw new UnsupportedOperationException();
+    }
+
+}
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/common/ObjectMap.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/common/ObjectMap.java
index 8b901e6c7d1..de84e86be6c 100644
--- a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/common/ObjectMap.java
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/common/ObjectMap.java
@@ -61,11 +61,11 @@ public class ObjectMap
     {
         Map<String, Object> map = new LinkedHashMap<String, Object>();
 
-        if (ObjectType.TYPE.equals(objectType) || ObjectType.TYPE_AND_CLASS.equals(objectType))
+        if (ObjectType.TYPE.equals(objectType))
         {
             map.put("@type", type);
         }
-        if (ObjectType.CLASS.equals(objectType) || ObjectType.TYPE_AND_CLASS.equals(objectType))
+        if (ObjectType.CLASS.equals(objectType))
         {
             map.put("@class", clazz);
         }
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/common/ObjectType.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/common/ObjectType.java
index b5f2aaa33a1..8242a89883b 100644
--- a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/common/ObjectType.java
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/common/ObjectType.java
@@ -22,6 +22,6 @@ package ch.systemsx.cisd.common.api.server.json.common;
 public enum ObjectType
 {
 
-    NONE, TYPE, CLASS, TYPE_AND_CLASS
+    NONE, TYPE, CLASS
 
 }
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectNestedChildFactory.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectNestedChildFactory.java
new file mode 100644
index 00000000000..ebbd0188569
--- /dev/null
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectNestedChildFactory.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * 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 ch.systemsx.cisd.common.api.server.json.object;
+
+import static ch.systemsx.cisd.common.api.server.json.object.ObjectNestedFactory.NESTED;
+import static ch.systemsx.cisd.common.api.server.json.object.ObjectNestedFactory.NESTED_VALUE;
+
+import java.util.Map;
+
+import ch.systemsx.cisd.common.api.server.json.common.ObjectCounter;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectFactory;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectMap;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectType;
+import ch.systemsx.cisd.common.api.server.json.object.ObjectWithNestedTypes.ObjectNestedChild;
+
+/**
+ * @author pkupczyk
+ */
+public class ObjectNestedChildFactory extends ObjectFactory<ObjectNestedChild>
+{
+
+    public static final String TYPE = "ObjectNestedChild";
+
+    public static final String CLASS = ".LegacyObjectNestedChild";
+
+    public static final String NESTED_CHILD = "nestedChild";
+
+    public static final String NESTED_CHILD_VALUE = "nestedChildValue";
+
+    @Override
+    public ObjectNestedChild createObject()
+    {
+        ObjectNestedChild object = new ObjectNestedChild();
+        object.nested = NESTED_VALUE;
+        object.nestedChild = NESTED_CHILD_VALUE;
+        return object;
+    }
+
+    @Override
+    public Map<String, Object> createMap(ObjectCounter objectCounter, ObjectType objectType)
+    {
+        ObjectMap map = new ObjectMap();
+        map.putId(objectCounter);
+        map.putType(TYPE, CLASS, objectType);
+        map.putField(NESTED, NESTED_VALUE);
+        map.putField(NESTED_CHILD, NESTED_CHILD_VALUE);
+        return map.toMap();
+    }
+
+}
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectNestedFactory.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectNestedFactory.java
new file mode 100644
index 00000000000..ba476b9ce55
--- /dev/null
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectNestedFactory.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * 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 ch.systemsx.cisd.common.api.server.json.object;
+
+import java.util.Map;
+
+import ch.systemsx.cisd.common.api.server.json.common.ObjectCounter;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectFactory;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectMap;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectType;
+import ch.systemsx.cisd.common.api.server.json.object.ObjectWithNestedTypes.ObjectNested;
+
+/**
+ * @author pkupczyk
+ */
+public class ObjectNestedFactory extends ObjectFactory<ObjectNested>
+{
+
+    public static final String TYPE = "ObjectNested";
+
+    public static final String CLASS = ".LegacyObjectNested";
+
+    public static final String NESTED = "nested";
+
+    public static final String NESTED_VALUE = "nestedValue";
+
+    @Override
+    public ObjectNested createObject()
+    {
+        ObjectNested object = new ObjectNested();
+        object.nested = NESTED_VALUE;
+        return object;
+    }
+
+    @Override
+    public Map<String, Object> createMap(ObjectCounter objectCounter, ObjectType objectType)
+    {
+        ObjectMap map = new ObjectMap();
+        map.putId(objectCounter);
+        map.putType(TYPE, CLASS, objectType);
+        map.putField(NESTED, NESTED_VALUE);
+        return map.toMap();
+    }
+
+}
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithContainerTypes.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithContainerTypes.java
index 93f5e852a17..11cb731f0db 100644
--- a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithContainerTypes.java
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithContainerTypes.java
@@ -16,9 +16,7 @@
 
 package ch.systemsx.cisd.common.api.server.json.object;
 
-import java.util.ArrayList;
 import java.util.Collection;
-import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
 import java.util.LinkedList;
@@ -28,88 +26,15 @@ import java.util.Map;
 import org.testng.Assert;
 
 import ch.systemsx.cisd.base.annotation.JsonObject;
-import ch.systemsx.cisd.common.api.server.json.common.ObjectCounter;
-import ch.systemsx.cisd.common.api.server.json.common.ObjectMap;
-import ch.systemsx.cisd.common.api.server.json.common.ObjectType;
 
 /**
  * @author pkupczyk
  */
-
 @SuppressWarnings("rawtypes")
-@JsonObject(ObjectWithContainerTypes.TYPE)
+@JsonObject(ObjectWithContainerTypesFactory.TYPE)
 public class ObjectWithContainerTypes
 {
 
-    public static final String TYPE = "ObjectWithContainerTypes";
-
-    public static final String CLASS = ".LegacyObjectWithContainerTypes";
-
-    public static final String COLLECTION_WITHOUT_TYPE = "collectionWithoutType";
-
-    public static final String COLLECTION_WITH_OBJECT_TYPE = "collectionWithObjectType";
-
-    public static final String COLLECTION_WITH_SPECIFIC_TYPE = "collectionWithSpecificType";
-
-    public static final String LINKED_HASH_SET_WITHOUT_TYPE = "linkedHashSetWithoutType";
-
-    public static final String LINKED_HASH_SET_WITH_OBJECT_TYPE = "linkedHashSetWithObjectType";
-
-    public static final String LINKED_HASH_SET_WITH_SPECIFIC_TYPE = "linkedHashSetWithSpecificType";
-
-    public static final String LIST_WITHOUT_TYPE = "listWithoutType";
-
-    public static final String LIST_WITH_OBJECT_TYPE = "listWithObjectType";
-
-    public static final String LIST_WITH_SPECIFIC_TYPE = "listWithSpecificType";
-
-    public static final String LINKED_LIST_WITHOUT_TYPE = "linkedListWithoutType";
-
-    public static final String LINKED_LIST_WITH_OBJECT_TYPE = "linkedListWithObjectType";
-
-    public static final String LINKED_LIST_WITH_SPECIFIC_TYPE = "linkedListWithSpecificType";
-
-    public static final String MAP_WITHOUT_TYPE = "mapWithoutType";
-
-    public static final String MAP_WITH_OBJECT_TYPE = "mapWithObjectType";
-
-    public static final String MAP_WITH_SPECIFIC_TYPE = "mapWithSpecificType";
-
-    public static final String LINKED_HASH_MAP_WITHOUT_TYPE = "linkedHashMapWithoutType";
-
-    public static final String LINKED_HASH_MAP_WITH_OBJECT_TYPE = "linkedHashMapWithObjectType";
-
-    public static final String LINKED_HASH_MAP_WITH_SPECIFIC_TYPE = "linkedHashMapWithSpecificType";
-
-    public static final String ARRAY_WITH_OBJECT_TYPE = "arrayWithObjectType";
-
-    public static final String ARRAY_WITH_SPECIFIC_TYPE = "arrayWithSpecificType";
-
-    public static final String ITEM_WITH_KNOWN_TYPE = "itemWithKnownType";
-
-    public static final String ITEM_WITH_KNOWN_UNIQUE_CLASS = "itemWithKnownUniqueClass";
-
-    public static final String ITEM_WITH_RENAMED_PROPERTIES = "itemWithRenamedProperties";
-
-    public static final String ITEM_WITH_IGNORED_PROPERTIES = "itemWithIgnoredProperties";
-
-    public static final String ITEM_WITH_DATE_TYPES = "itemWithDateTypes";
-
-    public static final String ITEM_WITH_ENUM_TYPES = "itemWithEnumTypes";
-
-    public static final String ITEM_WITH_NESTED_TYPES = "itemWithNestedTypes";
-
-    public static final String ITEM_WITH_PRIMITIVE_TYPES = "itemWithPrimitiveTypes";
-
-    public static final String ITEM_WITH_PRIVATE_ACCESS = "itemWithPrivateAccess";
-
-    public static final String ITEM_WITH_UNKNOWN_CLASS = "itemWithUnknownClass";
-
-    public static final String ITEM_WITH_UNKNOWN_TYPE = "itemWithUnknownType";
-
-    public static final String ITEM_WITH_KNOWN_BUT_NOT_UNIQUE_CLASS =
-            "itemWithKnownButNotUniqueClass";
-
     public Collection collectionWithoutType;
 
     public Collection<Object> collectionWithObjectType;
@@ -150,225 +75,33 @@ public class ObjectWithContainerTypes
 
     public ObjectWithType[] arrayWithSpecificType;
 
-    public static ObjectWithContainerTypes createObject()
-    {
-        LinkedHashMap map = createItemsObjectsMap();
-        LinkedHashMap specificMap = createItemsObjectsSpecificMap();
-        return createObjectCommon(map, specificMap);
-    }
-
-    @SuppressWarnings(
-        { "unchecked" })
-    public static ObjectWithContainerTypes createObjectWithIncorrectObjectsAsMaps()
-    {
-        LinkedHashMap map = createItemsObjectsMap();
-        map.put(ITEM_WITH_KNOWN_BUT_NOT_UNIQUE_CLASS,
-                ObjectWithTypeA.createMap(null, ObjectType.CLASS).toMap());
-        map.put(ITEM_WITH_UNKNOWN_TYPE, ObjectWithUnknownType.createMap(null, ObjectType.TYPE)
-                .toMap());
-        map.put(ITEM_WITH_UNKNOWN_CLASS, ObjectWithUnknownType.createMap(null, ObjectType.CLASS)
-                .toMap());
-        LinkedHashMap specificMap = createItemsObjectsSpecificMap();
-        return createObjectCommon(map, specificMap);
-    }
-
-    @SuppressWarnings(
-        { "unchecked" })
-    private static ObjectWithContainerTypes createObjectCommon(Map aMap, Map aSpecificMap)
-    {
-        Map map = new HashMap(aMap);
-        LinkedHashMap linkedHashMap = new LinkedHashMap(aMap);
-        Collection collection = new ArrayList(aMap.values());
-        LinkedHashSet linkedHashSet = new LinkedHashSet(aMap.values());
-        List list = new ArrayList(aMap.values());
-        LinkedList linkedList = new LinkedList(aMap.values());
-        Object[] array = aMap.values().toArray(new Object[aMap.size()]);
-
-        Map specificMap = new HashMap(aSpecificMap);
-        LinkedHashMap specificLinkedHashMap = new LinkedHashMap(aSpecificMap);
-        Collection specificCollection = new ArrayList(aSpecificMap.values());
-        LinkedHashSet specificLinkedHashSet = new LinkedHashSet(aSpecificMap.values());
-        List specificList = new ArrayList(aSpecificMap.values());
-        LinkedList specificLinkedList = new LinkedList(aSpecificMap.values());
-        ObjectWithType[] specificArray =
-                (ObjectWithType[]) aSpecificMap.values().toArray(
-                        new ObjectWithType[aSpecificMap.size()]);
-
-        ObjectWithContainerTypes object = new ObjectWithContainerTypes();
-        object.collectionWithoutType = collection;
-        object.collectionWithObjectType = collection;
-        object.collectionWithSpecificType = specificCollection;
-        object.linkedHashSetWithoutType = linkedHashSet;
-        object.linkedHashSetWithObjectType = linkedHashSet;
-        object.linkedHashSetWithSpecificType = specificLinkedHashSet;
-        object.listWithoutType = list;
-        object.listWithObjectType = list;
-        object.listWithSpecificType = specificList;
-        object.linkedListWithoutType = linkedList;
-        object.linkedListWithObjectType = linkedList;
-        object.linkedListWithSpecificType = specificLinkedList;
-        object.mapWithoutType = map;
-        object.mapWithObjectType = map;
-        object.mapWithSpecificType = specificMap;
-        object.linkedHashMapWithoutType = linkedHashMap;
-        object.linkedHashMapWithObjectType = linkedHashMap;
-        object.linkedHashMapWithSpecificType = specificLinkedHashMap;
-        object.arrayWithObjectType = array;
-        object.arrayWithSpecificType = specificArray;
-        return object;
-    }
-
-    @SuppressWarnings(
-        { "unchecked" })
-    public static ObjectMap createMap(ObjectCounter objectCounter, ObjectType objectType)
-    {
-        Map map = createItemsMapsMap(objectCounter, objectType);
-        Collection collection = new ArrayList(map.values());
-        List list = new ArrayList(map.values());
-        Object[] array = map.values().toArray(new Object[map.size()]);
-
-        Map specificMap = createItemsMapsSpecificMap(objectCounter, objectType);
-        Collection specificCollection = new ArrayList(specificMap.values());
-        List specificList = new ArrayList(specificMap.values());
-        Object[] specificArray = specificMap.values().toArray(new Object[specificMap.size()]);
-
-        ObjectMap object = new ObjectMap();
-        object.putId(objectCounter);
-        object.putType(TYPE, CLASS, objectType);
-        object.putField(COLLECTION_WITHOUT_TYPE, collection);
-        object.putField(COLLECTION_WITH_OBJECT_TYPE, collection);
-        object.putField(COLLECTION_WITH_SPECIFIC_TYPE, specificCollection);
-
-        object.putField(LINKED_HASH_SET_WITHOUT_TYPE, collection);
-        object.putField(LINKED_HASH_SET_WITH_OBJECT_TYPE, collection);
-        object.putField(LINKED_HASH_SET_WITH_SPECIFIC_TYPE, specificCollection);
-
-        object.putField(MAP_WITHOUT_TYPE, map);
-        object.putField(MAP_WITH_OBJECT_TYPE, map);
-        object.putField(MAP_WITH_SPECIFIC_TYPE, specificMap);
-
-        object.putField(LINKED_HASH_MAP_WITHOUT_TYPE, map);
-        object.putField(LINKED_HASH_MAP_WITH_OBJECT_TYPE, map);
-        object.putField(LINKED_HASH_MAP_WITH_SPECIFIC_TYPE, specificMap);
-
-        object.putField(LIST_WITHOUT_TYPE, list);
-        object.putField(LIST_WITH_OBJECT_TYPE, list);
-        object.putField(LIST_WITH_SPECIFIC_TYPE, specificList);
-
-        object.putField(LINKED_LIST_WITHOUT_TYPE, list);
-        object.putField(LINKED_LIST_WITH_OBJECT_TYPE, list);
-        object.putField(LINKED_LIST_WITH_SPECIFIC_TYPE, specificList);
-
-        object.putField(ARRAY_WITH_OBJECT_TYPE, array);
-        object.putField(ARRAY_WITH_SPECIFIC_TYPE, specificArray);
-
-        return object;
-    }
-
-    @SuppressWarnings(
-        { "unchecked" })
-    private static LinkedHashMap createItemsObjectsMap()
-    {
-        LinkedHashMap map = new LinkedHashMap();
-        map.put(ITEM_WITH_KNOWN_TYPE, ObjectWithTypeA.createObject());
-        map.put(ITEM_WITH_KNOWN_UNIQUE_CLASS, ObjectWithTypeAA.createObject());
-        map.put(ITEM_WITH_KNOWN_BUT_NOT_UNIQUE_CLASS, ObjectWithTypeA.createObject());
-        map.put(ITEM_WITH_UNKNOWN_TYPE, ObjectWithUnknownType.createObject());
-        map.put(ITEM_WITH_UNKNOWN_CLASS, ObjectWithUnknownType.createObject());
-        map.put(ITEM_WITH_PRIVATE_ACCESS, ObjectWithPrivateAccess.createObject());
-        map.put(ITEM_WITH_PRIMITIVE_TYPES, ObjectWithPrimitiveTypes.createObject());
-        map.put(ITEM_WITH_NESTED_TYPES, ObjectWithNestedTypes.createObject());
-        map.put(ITEM_WITH_ENUM_TYPES, ObjectWithEnumTypes.createObject());
-        map.put(ITEM_WITH_DATE_TYPES, ObjectWithDateTypes.createObject());
-        map.put(ITEM_WITH_IGNORED_PROPERTIES,
-                ObjectWithIgnoredProperties.createObjectWithIgnoredPropertiesNull());
-        map.put(ITEM_WITH_RENAMED_PROPERTIES, ObjectWithRenamedProperties.createObject());
-        return map;
-    }
-
-    @SuppressWarnings(
-        { "unchecked" })
-    private static LinkedHashMap createItemsObjectsSpecificMap()
-    {
-        LinkedHashMap map = new LinkedHashMap();
-        map.put(ITEM_WITH_KNOWN_TYPE, ObjectWithTypeA.createObject());
-        map.put(ITEM_WITH_KNOWN_UNIQUE_CLASS, ObjectWithTypeAA.createObject());
-        return map;
-    }
-
-    @SuppressWarnings(
-        { "unchecked" })
-    private static LinkedHashMap createItemsMapsMap(ObjectCounter objectCounter,
-            ObjectType objectType)
-    {
-        LinkedHashMap map = new LinkedHashMap();
-        map.put(ITEM_WITH_KNOWN_TYPE, ObjectWithTypeA.createMap(objectCounter, ObjectType.TYPE)
-                .toMap());
-        map.put(ITEM_WITH_KNOWN_UNIQUE_CLASS,
-                ObjectWithTypeAA.createMap(objectCounter, ObjectType.CLASS).toMap());
-        map.put(ITEM_WITH_KNOWN_BUT_NOT_UNIQUE_CLASS,
-                ObjectWithTypeA.createMap(objectCounter, ObjectType.CLASS).toMap());
-        map.put(ITEM_WITH_UNKNOWN_TYPE,
-                ObjectWithUnknownType.createMap(objectCounter, ObjectType.TYPE).toMap());
-        map.put(ITEM_WITH_UNKNOWN_CLASS,
-                ObjectWithUnknownType.createMap(objectCounter, ObjectType.CLASS).toMap());
-        map.put(ITEM_WITH_PRIVATE_ACCESS,
-                ObjectWithPrivateAccess.createMap(objectCounter, objectType).toMap());
-        map.put(ITEM_WITH_PRIMITIVE_TYPES,
-                ObjectWithPrimitiveTypes.createMap(objectCounter, objectType).toMap());
-        map.put(ITEM_WITH_NESTED_TYPES, ObjectWithNestedTypes.createMap(objectCounter, objectType)
-                .toMap());
-        map.put(ITEM_WITH_ENUM_TYPES, ObjectWithEnumTypes.createMap(objectCounter, objectType)
-                .toMap());
-        map.put(ITEM_WITH_DATE_TYPES, ObjectWithDateTypes.createMap(objectCounter, objectType)
-                .toMap());
-        map.put(ITEM_WITH_IGNORED_PROPERTIES,
-                ObjectWithIgnoredProperties.createMap(objectCounter, objectType).toMap());
-        map.put(ITEM_WITH_RENAMED_PROPERTIES,
-                ObjectWithRenamedProperties.createMap(objectCounter, objectType).toMap());
-        return map;
-    }
-
-    @SuppressWarnings(
-        { "unchecked" })
-    private static Map createItemsMapsSpecificMap(ObjectCounter objectCounter, ObjectType objectType)
-    {
-        Map map = new LinkedHashMap();
-        map.put(ITEM_WITH_KNOWN_TYPE, ObjectWithTypeA.createMap(objectCounter, ObjectType.TYPE)
-                .toMap());
-        map.put(ITEM_WITH_KNOWN_UNIQUE_CLASS,
-                ObjectWithTypeAA.createMap(objectCounter, ObjectType.CLASS).toMap());
-        return map;
-    }
-
     @Override
     public boolean equals(Object obj)
     {
         Assert.assertNotNull(obj);
-        Assert.assertEquals(getClass(), obj.getClass());
+        Assert.assertEquals(obj.getClass(), getClass());
 
         ObjectWithContainerTypes casted = (ObjectWithContainerTypes) obj;
-        Assert.assertEquals(collectionWithoutType, casted.collectionWithoutType);
-        Assert.assertEquals(collectionWithObjectType, casted.collectionWithObjectType);
-        Assert.assertEquals(collectionWithSpecificType, casted.collectionWithSpecificType);
-        Assert.assertEquals(linkedHashSetWithoutType, casted.linkedHashSetWithoutType);
-        Assert.assertEquals(linkedHashSetWithObjectType, casted.linkedHashSetWithObjectType);
-        Assert.assertEquals(linkedHashSetWithSpecificType, casted.linkedHashSetWithSpecificType);
-        Assert.assertEquals(listWithoutType, casted.listWithoutType);
-        Assert.assertEquals(listWithObjectType, casted.listWithObjectType);
-        Assert.assertEquals(listWithSpecificType, casted.listWithSpecificType);
-        Assert.assertEquals(linkedListWithoutType, casted.linkedListWithoutType);
-        Assert.assertEquals(linkedListWithObjectType, casted.linkedListWithObjectType);
-        Assert.assertEquals(linkedListWithSpecificType, casted.linkedListWithSpecificType);
-        Assert.assertEquals(mapWithoutType, casted.mapWithoutType);
-        Assert.assertEquals(mapWithObjectType, casted.mapWithObjectType);
-        Assert.assertEquals(mapWithSpecificType, casted.mapWithSpecificType);
-        Assert.assertEquals(linkedHashMapWithoutType, casted.linkedHashMapWithoutType);
-        Assert.assertEquals(linkedHashMapWithObjectType, casted.linkedHashMapWithObjectType);
-        Assert.assertEquals(linkedHashMapWithSpecificType, casted.linkedHashMapWithSpecificType);
-        Assert.assertEquals(arrayWithObjectType, casted.arrayWithObjectType);
-        Assert.assertEquals(arrayWithSpecificType, casted.arrayWithSpecificType);
-
+        Assert.assertEquals(casted.collectionWithoutType, collectionWithoutType);
+        Assert.assertEquals(casted.collectionWithObjectType, collectionWithObjectType);
+        Assert.assertEquals(casted.collectionWithSpecificType, collectionWithSpecificType);
+        Assert.assertEquals(casted.linkedHashSetWithoutType, linkedHashSetWithoutType);
+        Assert.assertEquals(casted.linkedHashSetWithObjectType, linkedHashSetWithObjectType);
+        Assert.assertEquals(casted.linkedHashSetWithSpecificType, linkedHashSetWithSpecificType);
+        Assert.assertEquals(casted.listWithoutType, listWithoutType);
+        Assert.assertEquals(casted.listWithObjectType, listWithObjectType);
+        Assert.assertEquals(casted.listWithSpecificType, listWithSpecificType);
+        Assert.assertEquals(casted.linkedListWithoutType, linkedListWithoutType);
+        Assert.assertEquals(casted.linkedListWithObjectType, linkedListWithObjectType);
+        Assert.assertEquals(casted.linkedListWithSpecificType, linkedListWithSpecificType);
+        Assert.assertEquals(casted.mapWithoutType, mapWithoutType);
+        Assert.assertEquals(casted.mapWithObjectType, mapWithObjectType);
+        Assert.assertEquals(casted.mapWithSpecificType, mapWithSpecificType);
+        Assert.assertEquals(casted.linkedHashMapWithoutType, linkedHashMapWithoutType);
+        Assert.assertEquals(casted.linkedHashMapWithObjectType, linkedHashMapWithObjectType);
+        Assert.assertEquals(casted.linkedHashMapWithSpecificType, linkedHashMapWithSpecificType);
+        Assert.assertEquals(casted.arrayWithObjectType, arrayWithObjectType);
+        Assert.assertEquals(casted.arrayWithSpecificType, arrayWithSpecificType);
         return true;
     }
 
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithContainerTypesFactory.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithContainerTypesFactory.java
new file mode 100644
index 00000000000..10ff911a2f8
--- /dev/null
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithContainerTypesFactory.java
@@ -0,0 +1,265 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * 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 ch.systemsx.cisd.common.api.server.json.object;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+
+import ch.systemsx.cisd.common.api.server.json.common.ObjectCounter;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectMap;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectType;
+
+/**
+ * @author pkupczyk
+ */
+@SuppressWarnings(
+    { "unchecked", "rawtypes" })
+public class ObjectWithContainerTypesFactory extends
+        ObjectWithContainerTypesFactoryAbstract<ObjectWithContainerTypes>
+{
+
+    public static final String TYPE = "ObjectWithContainerTypes";
+
+    public static final String CLASS = ".LegacyObjectWithContainerTypes";
+
+    public static final String COLLECTION_WITHOUT_TYPE = "collectionWithoutType";
+
+    public static final String COLLECTION_WITH_OBJECT_TYPE = "collectionWithObjectType";
+
+    public static final String COLLECTION_WITH_SPECIFIC_TYPE = "collectionWithSpecificType";
+
+    public static final String LINKED_HASH_SET_WITHOUT_TYPE = "linkedHashSetWithoutType";
+
+    public static final String LINKED_HASH_SET_WITH_OBJECT_TYPE = "linkedHashSetWithObjectType";
+
+    public static final String LINKED_HASH_SET_WITH_SPECIFIC_TYPE = "linkedHashSetWithSpecificType";
+
+    public static final String LIST_WITHOUT_TYPE = "listWithoutType";
+
+    public static final String LIST_WITH_OBJECT_TYPE = "listWithObjectType";
+
+    public static final String LIST_WITH_SPECIFIC_TYPE = "listWithSpecificType";
+
+    public static final String LINKED_LIST_WITHOUT_TYPE = "linkedListWithoutType";
+
+    public static final String LINKED_LIST_WITH_OBJECT_TYPE = "linkedListWithObjectType";
+
+    public static final String LINKED_LIST_WITH_SPECIFIC_TYPE = "linkedListWithSpecificType";
+
+    public static final String MAP_WITHOUT_TYPE = "mapWithoutType";
+
+    public static final String MAP_WITH_OBJECT_TYPE = "mapWithObjectType";
+
+    public static final String MAP_WITH_SPECIFIC_TYPE = "mapWithSpecificType";
+
+    public static final String LINKED_HASH_MAP_WITHOUT_TYPE = "linkedHashMapWithoutType";
+
+    public static final String LINKED_HASH_MAP_WITH_OBJECT_TYPE = "linkedHashMapWithObjectType";
+
+    public static final String LINKED_HASH_MAP_WITH_SPECIFIC_TYPE = "linkedHashMapWithSpecificType";
+
+    public static final String ARRAY_WITH_OBJECT_TYPE = "arrayWithObjectType";
+
+    public static final String ARRAY_WITH_SPECIFIC_TYPE = "arrayWithSpecificType";
+
+    @Override
+    public ObjectWithContainerTypes createObjectToSerialize()
+    {
+        ObjectWithContainerTypes object = new ObjectWithContainerTypes();
+        object.collectionWithoutType = addObjectsToSerialize(new ArrayList(), false);
+        object.collectionWithObjectType = addObjectsToSerialize(new ArrayList(), false);
+        object.collectionWithSpecificType = addObjectsToSerialize(new ArrayList(), true);
+        object.linkedHashSetWithoutType = addObjectsToSerialize(new LinkedHashSet(), false);
+        object.linkedHashSetWithObjectType = addObjectsToSerialize(new LinkedHashSet(), false);
+        object.linkedHashSetWithSpecificType = addObjectsToSerialize(new LinkedHashSet(), true);
+        object.listWithoutType = addObjectsToSerialize(new ArrayList(), false);
+        object.listWithObjectType = addObjectsToSerialize(new ArrayList(), false);
+        object.listWithSpecificType = addObjectsToSerialize(new ArrayList(), true);
+        object.linkedListWithoutType = addObjectsToSerialize(new LinkedList(), false);
+        object.linkedListWithObjectType = addObjectsToSerialize(new LinkedList(), false);
+        object.linkedListWithSpecificType = addObjectsToSerialize(new LinkedList(), true);
+        object.mapWithoutType = putObjectsToSerialize(new LinkedHashMap(), false);
+        object.mapWithObjectType = putObjectsToSerialize(new LinkedHashMap(), false);
+        object.mapWithSpecificType = putObjectsToSerialize(new LinkedHashMap(), true);
+        object.linkedHashMapWithoutType = putObjectsToSerialize(new LinkedHashMap(), false);
+        object.linkedHashMapWithObjectType = putObjectsToSerialize(new LinkedHashMap(), false);
+        object.linkedHashMapWithSpecificType = putObjectsToSerialize(new LinkedHashMap(), true);
+
+        Collection arrayWithObjectTypeItems = addObjectsToSerialize(new ArrayList(), false);
+        Collection arrayWithSpecificTypeItems = addObjectsToSerialize(new ArrayList(), true);
+
+        object.arrayWithObjectType =
+                arrayWithObjectTypeItems.toArray(new Object[arrayWithObjectTypeItems.size()]);
+        object.arrayWithSpecificType =
+                (ObjectWithType[]) arrayWithSpecificTypeItems
+                        .toArray(new ObjectWithType[arrayWithSpecificTypeItems.size()]);
+
+        return object;
+    }
+
+    @Override
+    public Object createExpectedMapAfterSerialization(ObjectCounter objectCounter)
+    {
+        ObjectMap map = new ObjectMap();
+        map.putId(objectCounter);
+        map.putType(TYPE, CLASS, ObjectType.TYPE);
+        map.putField(ARRAY_WITH_OBJECT_TYPE,
+                addExpectedMapsAfterSerialization(new ArrayList(), objectCounter, false));
+        map.putField(ARRAY_WITH_SPECIFIC_TYPE,
+                addExpectedMapsAfterSerialization(new ArrayList(), objectCounter, true));
+        map.putField(COLLECTION_WITH_OBJECT_TYPE,
+                addExpectedMapsAfterSerialization(new ArrayList(), objectCounter, false));
+        map.putField(COLLECTION_WITH_SPECIFIC_TYPE,
+                addExpectedMapsAfterSerialization(new ArrayList(), objectCounter, true));
+        map.putField(COLLECTION_WITHOUT_TYPE,
+                addExpectedMapsAfterSerialization(new ArrayList(), objectCounter, false));
+        map.putField(LINKED_HASH_MAP_WITH_OBJECT_TYPE,
+                putExpectedMapsAfterSerialization(new LinkedHashMap(), objectCounter, false));
+        map.putField(LINKED_HASH_MAP_WITH_SPECIFIC_TYPE,
+                putExpectedMapsAfterSerialization(new LinkedHashMap(), objectCounter, true));
+        map.putField(LINKED_HASH_MAP_WITHOUT_TYPE,
+                putExpectedMapsAfterSerialization(new LinkedHashMap(), objectCounter, false));
+        map.putField(LINKED_HASH_SET_WITH_OBJECT_TYPE,
+                addExpectedMapsAfterSerialization(new ArrayList(), objectCounter, false));
+        map.putField(LINKED_HASH_SET_WITH_SPECIFIC_TYPE,
+                addExpectedMapsAfterSerialization(new ArrayList(), objectCounter, true));
+        map.putField(LINKED_HASH_SET_WITHOUT_TYPE,
+                addExpectedMapsAfterSerialization(new ArrayList(), objectCounter, false));
+        map.putField(LINKED_LIST_WITH_OBJECT_TYPE,
+                addExpectedMapsAfterSerialization(new ArrayList(), objectCounter, false));
+        map.putField(LINKED_LIST_WITH_SPECIFIC_TYPE,
+                addExpectedMapsAfterSerialization(new ArrayList(), objectCounter, true));
+        map.putField(LINKED_LIST_WITHOUT_TYPE,
+                addExpectedMapsAfterSerialization(new ArrayList(), objectCounter, false));
+        map.putField(LIST_WITH_OBJECT_TYPE,
+                addExpectedMapsAfterSerialization(new ArrayList(), objectCounter, false));
+        map.putField(LIST_WITH_SPECIFIC_TYPE,
+                addExpectedMapsAfterSerialization(new ArrayList(), objectCounter, true));
+        map.putField(LIST_WITHOUT_TYPE,
+                addExpectedMapsAfterSerialization(new ArrayList(), objectCounter, false));
+        map.putField(MAP_WITH_OBJECT_TYPE,
+                putExpectedMapsAfterSerialization(new LinkedHashMap(), objectCounter, false));
+        map.putField(MAP_WITH_SPECIFIC_TYPE,
+                putExpectedMapsAfterSerialization(new LinkedHashMap(), objectCounter, true));
+        map.putField(MAP_WITHOUT_TYPE,
+                putExpectedMapsAfterSerialization(new LinkedHashMap(), objectCounter, false));
+        return map.toMap();
+    }
+
+    @Override
+    public Object createMapToDeserialize(ObjectCounter objectCounter, ObjectType objectType)
+    {
+        ObjectMap map = new ObjectMap();
+        map.putId(objectCounter);
+        map.putType(TYPE, CLASS, objectType);
+        map.putField(ARRAY_WITH_OBJECT_TYPE,
+                addMapsToDeserialize(new ArrayList(), objectCounter, objectType, false));
+        map.putField(ARRAY_WITH_SPECIFIC_TYPE,
+                addMapsToDeserialize(new ArrayList(), objectCounter, objectType, true));
+        map.putField(COLLECTION_WITH_OBJECT_TYPE,
+                addMapsToDeserialize(new ArrayList(), objectCounter, objectType, false));
+        map.putField(COLLECTION_WITH_SPECIFIC_TYPE,
+                addMapsToDeserialize(new ArrayList(), objectCounter, objectType, true));
+        map.putField(COLLECTION_WITHOUT_TYPE,
+                addMapsToDeserialize(new ArrayList(), objectCounter, objectType, false));
+        map.putField(LINKED_HASH_MAP_WITH_OBJECT_TYPE,
+                putMapsToDeserialize(new LinkedHashMap(), objectCounter, objectType, false));
+        map.putField(LINKED_HASH_MAP_WITH_SPECIFIC_TYPE,
+                putMapsToDeserialize(new LinkedHashMap(), objectCounter, objectType, true));
+        map.putField(LINKED_HASH_MAP_WITHOUT_TYPE,
+                putMapsToDeserialize(new LinkedHashMap(), objectCounter, objectType, false));
+        map.putField(LINKED_HASH_SET_WITH_OBJECT_TYPE,
+                addMapsToDeserialize(new ArrayList(), objectCounter, objectType, false));
+        map.putField(LINKED_HASH_SET_WITH_SPECIFIC_TYPE,
+                addMapsToDeserialize(new ArrayList(), objectCounter, objectType, true));
+        map.putField(LINKED_HASH_SET_WITHOUT_TYPE,
+                addMapsToDeserialize(new ArrayList(), objectCounter, objectType, false));
+        map.putField(LINKED_LIST_WITH_OBJECT_TYPE,
+                addMapsToDeserialize(new ArrayList(), objectCounter, objectType, false));
+        map.putField(LINKED_LIST_WITH_SPECIFIC_TYPE,
+                addMapsToDeserialize(new ArrayList(), objectCounter, objectType, true));
+        map.putField(LINKED_LIST_WITHOUT_TYPE,
+                addMapsToDeserialize(new ArrayList(), objectCounter, objectType, false));
+        map.putField(LIST_WITH_OBJECT_TYPE,
+                addMapsToDeserialize(new ArrayList(), objectCounter, objectType, false));
+        map.putField(LIST_WITH_SPECIFIC_TYPE,
+                addMapsToDeserialize(new ArrayList(), objectCounter, objectType, true));
+        map.putField(LIST_WITHOUT_TYPE,
+                addMapsToDeserialize(new ArrayList(), objectCounter, objectType, false));
+        map.putField(MAP_WITH_OBJECT_TYPE,
+                putMapsToDeserialize(new LinkedHashMap(), objectCounter, objectType, false));
+        map.putField(MAP_WITH_SPECIFIC_TYPE,
+                putMapsToDeserialize(new LinkedHashMap(), objectCounter, objectType, true));
+        map.putField(MAP_WITHOUT_TYPE,
+                putMapsToDeserialize(new LinkedHashMap(), objectCounter, objectType, false));
+        return map.toMap();
+    }
+
+    @Override
+    public ObjectWithContainerTypes createExpectedObjectAfterDeserialization()
+    {
+        ObjectWithContainerTypes object = new ObjectWithContainerTypes();
+        object.collectionWithObjectType =
+                addExpectedObjectsAfterDeserialization(new ArrayList(), false);
+        object.collectionWithSpecificType =
+                addExpectedObjectsAfterDeserialization(new ArrayList(), true);
+        object.collectionWithoutType =
+                addExpectedObjectsAfterDeserialization(new ArrayList(), false);
+        object.linkedHashSetWithoutType =
+                addExpectedObjectsAfterDeserialization(new LinkedHashSet(), false);
+        object.linkedHashSetWithObjectType =
+                addExpectedObjectsAfterDeserialization(new LinkedHashSet(), false);
+        object.linkedHashSetWithSpecificType =
+                addExpectedObjectsAfterDeserialization(new LinkedHashSet(), true);
+        object.listWithoutType = addExpectedObjectsAfterDeserialization(new ArrayList(), false);
+        object.listWithObjectType = addExpectedObjectsAfterDeserialization(new ArrayList(), false);
+        object.listWithSpecificType = addExpectedObjectsAfterDeserialization(new ArrayList(), true);
+        object.linkedListWithoutType =
+                addExpectedObjectsAfterDeserialization(new LinkedList(), false);
+        object.linkedListWithObjectType =
+                addExpectedObjectsAfterDeserialization(new LinkedList(), false);
+        object.linkedListWithSpecificType =
+                addExpectedObjectsAfterDeserialization(new LinkedList(), true);
+        object.mapWithoutType = putExpectedObjectsAfterDeserialization(new HashMap(), false);
+        object.mapWithObjectType = putExpectedObjectsAfterDeserialization(new HashMap(), false);
+        object.mapWithSpecificType = putExpectedObjectsAfterDeserialization(new HashMap(), true);
+        object.linkedHashMapWithoutType =
+                putExpectedObjectsAfterDeserialization(new LinkedHashMap(), false);
+        object.linkedHashMapWithObjectType =
+                putExpectedObjectsAfterDeserialization(new LinkedHashMap(), false);
+        object.linkedHashMapWithSpecificType =
+                putExpectedObjectsAfterDeserialization(new LinkedHashMap(), true);
+
+        Collection arrayWithObjectTypeItems =
+                addExpectedObjectsAfterDeserialization(new ArrayList(), false);
+        Collection arrayWithSpecificTypeItems =
+                addExpectedObjectsAfterDeserialization(new ArrayList(), true);
+
+        object.arrayWithObjectType =
+                arrayWithObjectTypeItems.toArray(new Object[arrayWithObjectTypeItems.size()]);
+        object.arrayWithSpecificType =
+                (ObjectWithType[]) arrayWithSpecificTypeItems
+                        .toArray(new ObjectWithType[arrayWithSpecificTypeItems.size()]);
+
+        return object;
+    }
+
+}
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithContainerTypesFactoryAbstract.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithContainerTypesFactoryAbstract.java
new file mode 100644
index 00000000000..ad35ccb9e16
--- /dev/null
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithContainerTypesFactoryAbstract.java
@@ -0,0 +1,329 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * 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 ch.systemsx.cisd.common.api.server.json.object;
+
+import java.util.Collection;
+import java.util.Map;
+
+import ch.systemsx.cisd.common.api.server.json.common.ObjectCounter;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectFactory;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectType;
+
+/**
+ * @author pkupczyk
+ */
+public abstract class ObjectWithContainerTypesFactoryAbstract<T> extends ObjectFactory<T>
+{
+
+    public static final String ITEM_INTEGER = "itemInteger";
+
+    public static final Integer ITEM_INTEGER_VALUE = new Integer(123);
+
+    public static final String ITEM_STRING = "itemString";
+
+    public static final String ITEM_STRING_VALUE = "abc";
+
+    public static final String ITEM_WITH_KNOWN_TYPE = "itemWithKnownType";
+
+    public static final String ITEM_WITH_KNOWN_UNIQUE_CLASS = "itemWithKnownUniqueClass";
+
+    public static final String ITEM_WITH_RENAMED_PROPERTIES = "itemWithRenamedProperties";
+
+    public static final String ITEM_WITH_IGNORED_PROPERTIES = "itemWithIgnoredProperties";
+
+    public static final String ITEM_WITH_DATE_TYPES = "itemWithDateTypes";
+
+    public static final String ITEM_WITH_ENUM_TYPES = "itemWithEnumTypes";
+
+    public static final String ITEM_WITH_NESTED_TYPES = "itemWithNestedTypes";
+
+    public static final String ITEM_WITH_PRIMITIVE_TYPES = "itemWithPrimitiveTypes";
+
+    public static final String ITEM_WITH_PRIVATE_ACCESS = "itemWithPrivateAccess";
+
+    public static final String ITEM_WITH_UNKNOWN_TYPE = "itemWithUnknownType";
+
+    public static final String ITEM_WITH_KNOWN_BUT_NOT_UNIQUE_CLASS =
+            "itemWithKnownButNotUniqueClass";
+
+    @SuppressWarnings(
+        { "rawtypes", "unchecked" })
+    protected <C extends Collection> C addObjectsToSerialize(C collection, boolean specific)
+    {
+        collection.add(new ObjectWithKnownTypeFactory().createObjectToSerialize());
+        collection.add(new ObjectWithKnownUniqueClassFactory().createObjectToSerialize());
+        if (!specific)
+        {
+            collection.add(ITEM_STRING_VALUE);
+            collection.add(ITEM_INTEGER_VALUE);
+            collection.add(new ObjectWithKnownButNotUniqueClassFactory().createObjectToSerialize());
+            collection.add(new ObjectWithUnknownTypeFactory().createObjectToSerialize());
+            collection.add(new ObjectWithPrivateAccessFactory().createObjectToSerialize());
+            collection.add(new ObjectWithPrimitiveTypesFactory().createObjectToSerialize());
+            collection.add(new ObjectWithNestedTypesFactory().createObjectToSerialize());
+            collection.add(new ObjectWithEnumTypesFactory().createObjectToSerialize());
+            collection.add(new ObjectWithDateTypesFactory().createObjectToSerialize());
+            collection.add(new ObjectWithIgnoredPropertiesFactory().createObjectToSerialize());
+            collection.add(new ObjectWithRenamedPropertiesFactory().createObjectToSerialize());
+        }
+        return collection;
+    }
+
+    @SuppressWarnings(
+        { "rawtypes", "unchecked" })
+    protected <M extends Map> M putObjectsToSerialize(M map, boolean specific)
+    {
+        map.put(ITEM_WITH_KNOWN_TYPE, new ObjectWithKnownTypeFactory().createObjectToSerialize());
+        map.put(ITEM_WITH_KNOWN_UNIQUE_CLASS,
+                new ObjectWithKnownUniqueClassFactory().createObjectToSerialize());
+        if (!specific)
+        {
+            map.put(ITEM_STRING, ITEM_STRING_VALUE);
+            map.put(ITEM_INTEGER, ITEM_INTEGER_VALUE);
+            map.put(ITEM_WITH_KNOWN_BUT_NOT_UNIQUE_CLASS,
+                    new ObjectWithKnownButNotUniqueClassFactory().createObjectToSerialize());
+            map.put(ITEM_WITH_UNKNOWN_TYPE,
+                    new ObjectWithUnknownTypeFactory().createObjectToSerialize());
+            map.put(ITEM_WITH_PRIVATE_ACCESS,
+                    new ObjectWithPrivateAccessFactory().createObjectToSerialize());
+            map.put(ITEM_WITH_PRIMITIVE_TYPES,
+                    new ObjectWithPrimitiveTypesFactory().createObjectToSerialize());
+            map.put(ITEM_WITH_NESTED_TYPES,
+                    new ObjectWithNestedTypesFactory().createObjectToSerialize());
+            map.put(ITEM_WITH_ENUM_TYPES,
+                    new ObjectWithEnumTypesFactory().createObjectToSerialize());
+            map.put(ITEM_WITH_DATE_TYPES,
+                    new ObjectWithDateTypesFactory().createObjectToSerialize());
+            map.put(ITEM_WITH_IGNORED_PROPERTIES,
+                    new ObjectWithIgnoredPropertiesFactory().createObjectToSerialize());
+            map.put(ITEM_WITH_RENAMED_PROPERTIES,
+                    new ObjectWithRenamedPropertiesFactory().createObjectToSerialize());
+        }
+        return map;
+    }
+
+    @SuppressWarnings(
+        { "rawtypes", "unchecked" })
+    protected <C extends Collection> C addExpectedMapsAfterSerialization(C collection,
+            ObjectCounter objectCounter, boolean specific)
+    {
+        collection.add(new ObjectWithKnownTypeFactory()
+                .createExpectedMapAfterSerialization(objectCounter));
+        collection.add(new ObjectWithKnownUniqueClassFactory()
+                .createExpectedMapAfterSerialization(objectCounter));
+        if (!specific)
+        {
+            collection.add(ITEM_STRING_VALUE);
+            collection.add(ITEM_INTEGER_VALUE);
+            collection.add(new ObjectWithKnownButNotUniqueClassFactory()
+                    .createExpectedMapAfterSerialization(objectCounter));
+            collection.add(new ObjectWithUnknownTypeFactory()
+                    .createExpectedMapAfterSerialization(objectCounter));
+            collection.add(new ObjectWithPrivateAccessFactory()
+                    .createExpectedMapAfterSerialization(objectCounter));
+            collection.add(new ObjectWithPrimitiveTypesFactory()
+                    .createExpectedMapAfterSerialization(objectCounter));
+            collection.add(new ObjectWithNestedTypesFactory()
+                    .createExpectedMapAfterSerialization(objectCounter));
+            collection.add(new ObjectWithEnumTypesFactory()
+                    .createExpectedMapAfterSerialization(objectCounter));
+            collection.add(new ObjectWithDateTypesFactory()
+                    .createExpectedMapAfterSerialization(objectCounter));
+            collection.add(new ObjectWithIgnoredPropertiesFactory()
+                    .createExpectedMapAfterSerialization(objectCounter));
+            collection.add(new ObjectWithRenamedPropertiesFactory()
+                    .createExpectedMapAfterSerialization(objectCounter));
+        }
+        return collection;
+    }
+
+    @SuppressWarnings(
+        { "rawtypes", "unchecked" })
+    protected <M extends Map> M putExpectedMapsAfterSerialization(M map,
+            ObjectCounter objectCounter, boolean specific)
+    {
+        map.put(ITEM_WITH_KNOWN_TYPE,
+                new ObjectWithKnownTypeFactory().createExpectedMapAfterSerialization(objectCounter));
+        map.put(ITEM_WITH_KNOWN_UNIQUE_CLASS, new ObjectWithKnownUniqueClassFactory()
+                .createExpectedMapAfterSerialization(objectCounter));
+        if (!specific)
+        {
+            map.put(ITEM_STRING, ITEM_STRING_VALUE);
+            map.put(ITEM_INTEGER, ITEM_INTEGER_VALUE);
+            map.put(ITEM_WITH_KNOWN_BUT_NOT_UNIQUE_CLASS,
+                    new ObjectWithKnownButNotUniqueClassFactory()
+                            .createExpectedMapAfterSerialization(objectCounter));
+            map.put(ITEM_WITH_UNKNOWN_TYPE, new ObjectWithUnknownTypeFactory()
+                    .createExpectedMapAfterSerialization(objectCounter));
+            map.put(ITEM_WITH_PRIVATE_ACCESS, new ObjectWithPrivateAccessFactory()
+                    .createExpectedMapAfterSerialization(objectCounter));
+            map.put(ITEM_WITH_PRIMITIVE_TYPES, new ObjectWithPrimitiveTypesFactory()
+                    .createExpectedMapAfterSerialization(objectCounter));
+            map.put(ITEM_WITH_NESTED_TYPES, new ObjectWithNestedTypesFactory()
+                    .createExpectedMapAfterSerialization(objectCounter));
+            map.put(ITEM_WITH_ENUM_TYPES, new ObjectWithEnumTypesFactory()
+                    .createExpectedMapAfterSerialization(objectCounter));
+            map.put(ITEM_WITH_DATE_TYPES, new ObjectWithDateTypesFactory()
+                    .createExpectedMapAfterSerialization(objectCounter));
+            map.put(ITEM_WITH_IGNORED_PROPERTIES, new ObjectWithIgnoredPropertiesFactory()
+                    .createExpectedMapAfterSerialization(objectCounter));
+            map.put(ITEM_WITH_RENAMED_PROPERTIES, new ObjectWithRenamedPropertiesFactory()
+                    .createExpectedMapAfterSerialization(objectCounter));
+        }
+        return map;
+    }
+
+    @SuppressWarnings(
+        { "rawtypes", "unchecked" })
+    protected <C extends Collection> C addMapsToDeserialize(C collection,
+            ObjectCounter objectCounter, ObjectType objectType, boolean specific)
+    {
+        collection.add(new ObjectWithKnownTypeFactory().createMapToDeserialize(objectCounter,
+                objectType));
+        collection.add(new ObjectWithKnownUniqueClassFactory().createMapToDeserialize(
+                objectCounter, objectType));
+        if (!specific)
+        {
+            collection.add(ITEM_STRING_VALUE);
+            collection.add(ITEM_INTEGER_VALUE);
+            collection.add(new ObjectWithKnownButNotUniqueClassFactory().createMapToDeserialize(
+                    objectCounter, objectType));
+            collection.add(new ObjectWithUnknownTypeFactory().createMapToDeserialize(objectCounter,
+                    objectType));
+            collection.add(new ObjectWithPrivateAccessFactory().createMapToDeserialize(
+                    objectCounter, objectType));
+            collection.add(new ObjectWithPrimitiveTypesFactory().createMapToDeserialize(
+                    objectCounter, objectType));
+            collection.add(new ObjectWithNestedTypesFactory().createMapToDeserialize(objectCounter,
+                    objectType));
+            collection.add(new ObjectWithEnumTypesFactory().createMapToDeserialize(objectCounter,
+                    objectType));
+            collection.add(new ObjectWithDateTypesFactory().createMapToDeserialize(objectCounter,
+                    objectType));
+            collection.add(new ObjectWithIgnoredPropertiesFactory().createMapToDeserialize(
+                    objectCounter, objectType));
+            collection.add(new ObjectWithRenamedPropertiesFactory().createMapToDeserialize(
+                    objectCounter, objectType));
+        }
+        return collection;
+    }
+
+    @SuppressWarnings(
+        { "rawtypes", "unchecked" })
+    protected <M extends Map> M putMapsToDeserialize(M map, ObjectCounter objectCounter,
+            ObjectType objectType, boolean specific)
+    {
+        map.put(ITEM_WITH_KNOWN_TYPE,
+                new ObjectWithKnownTypeFactory().createMapToDeserialize(objectCounter, objectType));
+        map.put(ITEM_WITH_KNOWN_UNIQUE_CLASS, new ObjectWithKnownUniqueClassFactory()
+                .createMapToDeserialize(objectCounter, objectType));
+        if (!specific)
+        {
+            map.put(ITEM_STRING, ITEM_STRING_VALUE);
+            map.put(ITEM_INTEGER, ITEM_INTEGER_VALUE);
+            map.put(ITEM_WITH_KNOWN_BUT_NOT_UNIQUE_CLASS,
+                    new ObjectWithKnownButNotUniqueClassFactory().createMapToDeserialize(
+                            objectCounter, objectType));
+            map.put(ITEM_WITH_UNKNOWN_TYPE, new ObjectWithUnknownTypeFactory()
+                    .createMapToDeserialize(objectCounter, objectType));
+            map.put(ITEM_WITH_PRIVATE_ACCESS, new ObjectWithPrivateAccessFactory()
+                    .createMapToDeserialize(objectCounter, objectType));
+            map.put(ITEM_WITH_PRIMITIVE_TYPES, new ObjectWithPrimitiveTypesFactory()
+                    .createMapToDeserialize(objectCounter, objectType));
+            map.put(ITEM_WITH_NESTED_TYPES, new ObjectWithNestedTypesFactory()
+                    .createMapToDeserialize(objectCounter, objectType));
+            map.put(ITEM_WITH_ENUM_TYPES, new ObjectWithEnumTypesFactory().createMapToDeserialize(
+                    objectCounter, objectType));
+            map.put(ITEM_WITH_DATE_TYPES, new ObjectWithDateTypesFactory().createMapToDeserialize(
+                    objectCounter, objectType));
+            map.put(ITEM_WITH_IGNORED_PROPERTIES, new ObjectWithIgnoredPropertiesFactory()
+                    .createMapToDeserialize(objectCounter, objectType));
+            map.put(ITEM_WITH_RENAMED_PROPERTIES, new ObjectWithRenamedPropertiesFactory()
+                    .createMapToDeserialize(objectCounter, objectType));
+        }
+        return map;
+    }
+
+    @SuppressWarnings(
+        { "rawtypes", "unchecked" })
+    protected <C extends Collection> C addExpectedObjectsAfterDeserialization(C collection,
+            boolean specific)
+    {
+        collection.add(new ObjectWithKnownTypeFactory().createExpectedObjectAfterDeserialization());
+        collection.add(new ObjectWithKnownUniqueClassFactory()
+                .createExpectedObjectAfterDeserialization());
+        if (!specific)
+        {
+            collection.add(ITEM_STRING_VALUE);
+            collection.add(ITEM_INTEGER_VALUE);
+            collection.add(new ObjectWithKnownButNotUniqueClassFactory()
+                    .createExpectedObjectAfterDeserialization());
+            collection.add(new ObjectWithUnknownTypeFactory()
+                    .createExpectedObjectAfterDeserialization());
+            collection.add(new ObjectWithPrivateAccessFactory()
+                    .createExpectedObjectAfterDeserialization());
+            collection.add(new ObjectWithPrimitiveTypesFactory()
+                    .createExpectedObjectAfterDeserialization());
+            collection.add(new ObjectWithNestedTypesFactory()
+                    .createExpectedObjectAfterDeserialization());
+            collection.add(new ObjectWithEnumTypesFactory()
+                    .createExpectedObjectAfterDeserialization());
+            collection.add(new ObjectWithDateTypesFactory()
+                    .createExpectedObjectAfterDeserialization());
+            collection.add(new ObjectWithIgnoredPropertiesFactory()
+                    .createExpectedObjectAfterDeserialization());
+            collection.add(new ObjectWithRenamedPropertiesFactory()
+                    .createExpectedObjectAfterDeserialization());
+        }
+        return collection;
+    }
+
+    @SuppressWarnings(
+        { "rawtypes", "unchecked" })
+    protected <M extends Map> M putExpectedObjectsAfterDeserialization(M map, boolean specific)
+    {
+        map.put(ITEM_WITH_KNOWN_TYPE, new ObjectWithKnownTypeFactory().createObjectToSerialize());
+        map.put(ITEM_WITH_KNOWN_UNIQUE_CLASS,
+                new ObjectWithKnownUniqueClassFactory().createExpectedObjectAfterDeserialization());
+        if (!specific)
+        {
+            map.put(ITEM_STRING, ITEM_STRING_VALUE);
+            map.put(ITEM_INTEGER, ITEM_INTEGER_VALUE);
+            map.put(ITEM_WITH_KNOWN_BUT_NOT_UNIQUE_CLASS,
+                    new ObjectWithKnownButNotUniqueClassFactory()
+                            .createExpectedObjectAfterDeserialization());
+            map.put(ITEM_WITH_UNKNOWN_TYPE,
+                    new ObjectWithUnknownTypeFactory().createExpectedObjectAfterDeserialization());
+            map.put(ITEM_WITH_PRIVATE_ACCESS,
+                    new ObjectWithPrivateAccessFactory().createExpectedObjectAfterDeserialization());
+            map.put(ITEM_WITH_PRIMITIVE_TYPES, new ObjectWithPrimitiveTypesFactory()
+                    .createExpectedObjectAfterDeserialization());
+            map.put(ITEM_WITH_NESTED_TYPES,
+                    new ObjectWithNestedTypesFactory().createExpectedObjectAfterDeserialization());
+            map.put(ITEM_WITH_ENUM_TYPES,
+                    new ObjectWithEnumTypesFactory().createExpectedObjectAfterDeserialization());
+            map.put(ITEM_WITH_DATE_TYPES,
+                    new ObjectWithDateTypesFactory().createExpectedObjectAfterDeserialization());
+            map.put(ITEM_WITH_IGNORED_PROPERTIES, new ObjectWithIgnoredPropertiesFactory()
+                    .createExpectedObjectAfterDeserialization());
+            map.put(ITEM_WITH_RENAMED_PROPERTIES, new ObjectWithRenamedPropertiesFactory()
+                    .createExpectedObjectAfterDeserialization());
+        }
+        return map;
+    }
+
+}
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithDateTypes.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithDateTypes.java
index 9a5c7bcaffa..7d1ab95e556 100644
--- a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithDateTypes.java
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithDateTypes.java
@@ -19,73 +19,31 @@ package ch.systemsx.cisd.common.api.server.json.object;
 import org.testng.Assert;
 
 import ch.systemsx.cisd.base.annotation.JsonObject;
-import ch.systemsx.cisd.common.api.server.json.common.ObjectCounter;
-import ch.systemsx.cisd.common.api.server.json.common.ObjectMap;
-import ch.systemsx.cisd.common.api.server.json.common.ObjectType;
 
 /**
  * @author pkupczyk
  */
 
-@JsonObject(ObjectWithDateTypes.TYPE)
+@JsonObject(ObjectWithDateTypesFactory.TYPE)
 public class ObjectWithDateTypes
 {
 
-    private static final long DAY_IN_MILLIS = 24 * 3600 * 1000;
-
-    public static final String TYPE = "ObjectWithDateTypes";
-
-    public static final String CLASS = ".LegacyObjectWithDateTypes";
-
-    public static final String UTIL_DATE = "utilDate";
-
-    public static final java.util.Date UTIL_DATE_VALUE = new java.util.Date(DAY_IN_MILLIS);
-
-    public static final String SQL_DATE = "sqlDate";
-
-    public static final java.sql.Date SQL_DATE_VALUE = new java.sql.Date(DAY_IN_MILLIS * 2);
-
-    public static final String SQL_TIMESTAMP = "sqlTimestamp";
-
-    public static final java.sql.Timestamp SQL_TIMESTAMP_VALUE = new java.sql.Timestamp(
-            DAY_IN_MILLIS * 3);
-
     public java.util.Date utilDate;
 
     public java.sql.Date sqlDate;
 
     public java.sql.Timestamp sqlTimestamp;
 
-    public static ObjectWithDateTypes createObject()
-    {
-        ObjectWithDateTypes object = new ObjectWithDateTypes();
-        object.utilDate = UTIL_DATE_VALUE;
-        object.sqlDate = SQL_DATE_VALUE;
-        object.sqlTimestamp = SQL_TIMESTAMP_VALUE;
-        return object;
-    }
-
-    public static ObjectMap createMap(ObjectCounter objectCounter, ObjectType objectType)
-    {
-        ObjectMap map = new ObjectMap();
-        map.putId(objectCounter);
-        map.putType(TYPE, CLASS, objectType);
-        map.putField(UTIL_DATE, UTIL_DATE_VALUE);
-        map.putField(SQL_DATE, SQL_DATE_VALUE);
-        map.putField(SQL_TIMESTAMP, SQL_TIMESTAMP_VALUE);
-        return map;
-    }
-
     @Override
     public boolean equals(Object obj)
     {
         Assert.assertNotNull(obj);
-        Assert.assertEquals(getClass(), obj.getClass());
+        Assert.assertEquals(obj.getClass(), getClass());
 
         ObjectWithDateTypes casted = (ObjectWithDateTypes) obj;
-        Assert.assertEquals(utilDate, casted.utilDate);
-        Assert.assertEquals(sqlDate, casted.sqlDate);
-        Assert.assertEquals(sqlTimestamp, casted.sqlTimestamp);
+        Assert.assertEquals(casted.utilDate, utilDate);
+        Assert.assertEquals(casted.sqlDate, sqlDate);
+        Assert.assertEquals(casted.sqlTimestamp, sqlTimestamp);
         return true;
     }
 
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithDateTypesFactory.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithDateTypesFactory.java
new file mode 100644
index 00000000000..873177761f8
--- /dev/null
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithDateTypesFactory.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * 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 ch.systemsx.cisd.common.api.server.json.object;
+
+import java.util.Map;
+
+import ch.systemsx.cisd.common.api.server.json.common.ObjectCounter;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectFactory;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectMap;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectType;
+
+/**
+ * @author pkupczyk
+ */
+public class ObjectWithDateTypesFactory extends ObjectFactory<ObjectWithDateTypes>
+{
+
+    private static final long DAY_IN_MILLIS = 24 * 3600 * 1000;
+
+    public static final String TYPE = "ObjectWithDateTypes";
+
+    public static final String CLASS = ".LegacyObjectWithDateTypes";
+
+    public static final String UTIL_DATE = "utilDate";
+
+    public static final java.util.Date UTIL_DATE_VALUE = new java.util.Date(DAY_IN_MILLIS);
+
+    public static final String SQL_DATE = "sqlDate";
+
+    public static final java.sql.Date SQL_DATE_VALUE = new java.sql.Date(DAY_IN_MILLIS * 2);
+
+    public static final String SQL_TIMESTAMP = "sqlTimestamp";
+
+    public static final java.sql.Timestamp SQL_TIMESTAMP_VALUE = new java.sql.Timestamp(
+            DAY_IN_MILLIS * 3);
+
+    @Override
+    public ObjectWithDateTypes createObject()
+    {
+        ObjectWithDateTypes object = new ObjectWithDateTypes();
+        object.utilDate = UTIL_DATE_VALUE;
+        object.sqlDate = SQL_DATE_VALUE;
+        object.sqlTimestamp = SQL_TIMESTAMP_VALUE;
+        return object;
+    }
+
+    @Override
+    public Map<String, Object> createMap(ObjectCounter objectCounter, ObjectType objectType)
+    {
+        ObjectMap map = new ObjectMap();
+        map.putId(objectCounter);
+        map.putType(TYPE, CLASS, objectType);
+        map.putField(UTIL_DATE, UTIL_DATE_VALUE);
+        map.putField(SQL_DATE, SQL_DATE_VALUE);
+        map.putField(SQL_TIMESTAMP, SQL_TIMESTAMP_VALUE);
+        return map.toMap();
+    }
+
+}
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithEnumTypes.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithEnumTypes.java
index 400cb4be478..002bb04b968 100644
--- a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithEnumTypes.java
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithEnumTypes.java
@@ -16,43 +16,21 @@
 
 package ch.systemsx.cisd.common.api.server.json.object;
 
-import java.util.Collections;
 import java.util.EnumMap;
 import java.util.EnumSet;
 
 import org.testng.Assert;
 
 import ch.systemsx.cisd.base.annotation.JsonObject;
-import ch.systemsx.cisd.common.api.server.json.common.ObjectCounter;
-import ch.systemsx.cisd.common.api.server.json.common.ObjectMap;
-import ch.systemsx.cisd.common.api.server.json.common.ObjectType;
 
 /**
  * @author pkupczyk
  */
 
-@JsonObject(ObjectWithEnumTypes.TYPE)
+@JsonObject(ObjectWithEnumTypesFactory.TYPE)
 public class ObjectWithEnumTypes
 {
 
-    public static final String TYPE = "ObjectWithEnumTypes";
-
-    public static final String CLASS = ".LegacyObjectWithEnumTypes";
-
-    public static final String ENUM_FIELD = "enumField";
-
-    public static final NestedEnum ENUM_FIELD_VALUE = NestedEnum.VALUE1;
-
-    public static final String ENUM_SET = "enumSet";
-
-    public static final EnumSet<NestedEnum> ENUM_SET_VALUE = EnumSet.of(NestedEnum.VALUE1,
-            NestedEnum.VALUE3);
-
-    public static final String ENUM_MAP = "enumMap";
-
-    public static final EnumMap<NestedEnum, Object> ENUM_MAP_VALUE =
-            new EnumMap<NestedEnum, Object>(Collections.singletonMap(NestedEnum.VALUE2, "value2"));
-
     public NestedEnum enumField;
 
     public EnumSet<NestedEnum> enumSet;
@@ -65,36 +43,16 @@ public class ObjectWithEnumTypes
         VALUE1, VALUE2, VALUE3
     }
 
-    public static ObjectWithEnumTypes createObject()
-    {
-        ObjectWithEnumTypes object = new ObjectWithEnumTypes();
-        object.enumField = ENUM_FIELD_VALUE;
-        object.enumSet = ENUM_SET_VALUE;
-        object.enumMap = ENUM_MAP_VALUE;
-        return object;
-    }
-
-    public static ObjectMap createMap(ObjectCounter objectCounter, ObjectType objectType)
-    {
-        ObjectMap map = new ObjectMap();
-        map.putId(objectCounter);
-        map.putType(TYPE, CLASS, objectType);
-        map.putField(ENUM_FIELD, ENUM_FIELD_VALUE);
-        map.putField(ENUM_SET, ENUM_SET_VALUE);
-        map.putField(ENUM_MAP, ENUM_MAP_VALUE);
-        return map;
-    }
-
     @Override
     public boolean equals(Object obj)
     {
         Assert.assertNotNull(obj);
-        Assert.assertEquals(getClass(), obj.getClass());
+        Assert.assertEquals(obj.getClass(), getClass());
 
         ObjectWithEnumTypes casted = (ObjectWithEnumTypes) obj;
-        Assert.assertEquals(enumField, casted.enumField);
-        Assert.assertEquals(enumSet, casted.enumSet);
-        Assert.assertEquals(enumMap, casted.enumMap);
+        Assert.assertEquals(casted.enumField, enumField);
+        Assert.assertEquals(casted.enumSet, enumSet);
+        Assert.assertEquals(casted.enumMap, enumMap);
         return true;
     }
 
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithEnumTypesFactory.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithEnumTypesFactory.java
new file mode 100644
index 00000000000..6ad166a9d38
--- /dev/null
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithEnumTypesFactory.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * 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 ch.systemsx.cisd.common.api.server.json.object;
+
+import java.util.Collections;
+import java.util.EnumMap;
+import java.util.EnumSet;
+import java.util.Map;
+
+import ch.systemsx.cisd.common.api.server.json.common.ObjectCounter;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectFactory;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectMap;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectType;
+import ch.systemsx.cisd.common.api.server.json.object.ObjectWithEnumTypes.NestedEnum;
+
+/**
+ * @author pkupczyk
+ */
+public class ObjectWithEnumTypesFactory extends ObjectFactory<ObjectWithEnumTypes>
+{
+
+    public static final String TYPE = "ObjectWithEnumTypes";
+
+    public static final String CLASS = ".LegacyObjectWithEnumTypes";
+
+    public static final String ENUM_FIELD = "enumField";
+
+    public static final NestedEnum ENUM_FIELD_VALUE = NestedEnum.VALUE1;
+
+    public static final String ENUM_SET = "enumSet";
+
+    public static final EnumSet<NestedEnum> ENUM_SET_VALUE = EnumSet.of(NestedEnum.VALUE1,
+            NestedEnum.VALUE3);
+
+    public static final String ENUM_MAP = "enumMap";
+
+    public static final EnumMap<NestedEnum, Object> ENUM_MAP_VALUE =
+            new EnumMap<NestedEnum, Object>(Collections.singletonMap(NestedEnum.VALUE2, "value2"));
+
+    @Override
+    public ObjectWithEnumTypes createObject()
+    {
+        ObjectWithEnumTypes object = new ObjectWithEnumTypes();
+        object.enumField = ENUM_FIELD_VALUE;
+        object.enumSet = ENUM_SET_VALUE;
+        object.enumMap = ENUM_MAP_VALUE;
+        return object;
+    }
+
+    @Override
+    public Map<String, Object> createMap(ObjectCounter objectCounter, ObjectType objectType)
+    {
+        ObjectMap map = new ObjectMap();
+        map.putId(objectCounter);
+        map.putType(TYPE, CLASS, objectType);
+        map.putField(ENUM_FIELD, ENUM_FIELD_VALUE);
+        map.putField(ENUM_SET, ENUM_SET_VALUE);
+        map.putField(ENUM_MAP, ENUM_MAP_VALUE);
+        return map.toMap();
+    }
+
+}
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithIgnoredProperties.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithIgnoredProperties.java
index fc8a138b70d..33fc394582f 100644
--- a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithIgnoredProperties.java
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithIgnoredProperties.java
@@ -21,40 +21,14 @@ import org.testng.Assert;
 import com.fasterxml.jackson.annotation.JsonIgnore;
 
 import ch.systemsx.cisd.base.annotation.JsonObject;
-import ch.systemsx.cisd.common.api.server.json.common.ObjectCounter;
-import ch.systemsx.cisd.common.api.server.json.common.ObjectMap;
-import ch.systemsx.cisd.common.api.server.json.common.ObjectType;
 
 /**
  * @author pkupczyk
  */
-@JsonObject(ObjectWithIgnoredProperties.TYPE)
+@JsonObject(ObjectWithIgnoredPropertiesFactory.TYPE)
 public class ObjectWithIgnoredProperties
 {
 
-    public static final String TYPE = "ObjectWithIgnoredProperties";
-
-    public static final String CLASS = ".LegacyObjectWithIgnoredProperties";
-
-    public static final String PROPERTY = "property";
-
-    public static final String PROPERTY_VALUE = "propertyValue";
-
-    public static final String PROPERTY_WITH_GETTER_AND_SETTER = "propertyWithGetterAndSetter";
-
-    public static final String PROPERTY_WITH_GETTER_AND_SETTER_VALUE =
-            "propertyWithGetterAndSetterValue";
-
-    public static final String PROPERTY_IGNORED = "propertyIgnored";
-
-    public static final String PROPERTY_IGNORED_VALUE = "propertyIgnoredValue";
-
-    public static final String PROPERTY_WITH_GETTER_AND_SETTER_IGNORED =
-            "propertyWithGetterAndSetterIgnored";
-
-    public static final String PROPERTY_WITH_GETTER_AND_SETTER_IGNORED_VALUE =
-            "propertyWithGetterAndSetterIgnoredValue";
-
     public String property;
 
     private String propertyWithGetterAndSetter;
@@ -85,49 +59,18 @@ public class ObjectWithIgnoredProperties
         return propertyWithGetterAndSetterIgnored;
     }
 
-    public static ObjectWithIgnoredProperties createObject()
-    {
-        ObjectWithIgnoredProperties object = new ObjectWithIgnoredProperties();
-        object.property = PROPERTY_VALUE;
-        object.propertyIgnored = PROPERTY_IGNORED_VALUE;
-        object.propertyWithGetterAndSetter = PROPERTY_WITH_GETTER_AND_SETTER_VALUE;
-        object.propertyWithGetterAndSetterIgnored = PROPERTY_WITH_GETTER_AND_SETTER_IGNORED_VALUE;
-        return object;
-    }
-
-    public static ObjectWithIgnoredProperties createObjectWithIgnoredPropertiesNull()
-    {
-        ObjectWithIgnoredProperties object = new ObjectWithIgnoredProperties();
-        object.property = PROPERTY_VALUE;
-        object.propertyWithGetterAndSetter = PROPERTY_WITH_GETTER_AND_SETTER_VALUE;
-        return object;
-    }
-
-    public static ObjectMap createMap(ObjectCounter objectCounter, ObjectType objectType)
-    {
-        ObjectMap map = new ObjectMap();
-        map.putId(objectCounter);
-        map.putType(TYPE, CLASS, objectType);
-        map.putField(PROPERTY, PROPERTY_VALUE);
-        map.putField(PROPERTY_WITH_GETTER_AND_SETTER, PROPERTY_WITH_GETTER_AND_SETTER_VALUE);
-        map.putField(PROPERTY_IGNORED, PROPERTY_IGNORED_VALUE);
-        map.putField(PROPERTY_WITH_GETTER_AND_SETTER_IGNORED,
-                PROPERTY_WITH_GETTER_AND_SETTER_IGNORED_VALUE);
-        return map;
-    }
-
     @Override
     public boolean equals(Object obj)
     {
         Assert.assertNotNull(obj);
-        Assert.assertEquals(getClass(), obj.getClass());
+        Assert.assertEquals(obj.getClass(), getClass());
 
         ObjectWithIgnoredProperties casted = (ObjectWithIgnoredProperties) obj;
-        Assert.assertEquals(property, casted.property);
-        Assert.assertEquals(propertyIgnored, casted.propertyIgnored);
-        Assert.assertEquals(propertyWithGetterAndSetter, casted.propertyWithGetterAndSetter);
-        Assert.assertEquals(propertyWithGetterAndSetterIgnored,
-                casted.propertyWithGetterAndSetterIgnored);
+        Assert.assertEquals(casted.property, property);
+        Assert.assertEquals(casted.propertyIgnored, propertyIgnored);
+        Assert.assertEquals(casted.propertyWithGetterAndSetter, propertyWithGetterAndSetter);
+        Assert.assertEquals(casted.propertyWithGetterAndSetterIgnored,
+                propertyWithGetterAndSetterIgnored);
         return true;
     }
 
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithIgnoredPropertiesFactory.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithIgnoredPropertiesFactory.java
new file mode 100644
index 00000000000..bfb9b1daa34
--- /dev/null
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithIgnoredPropertiesFactory.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * 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 ch.systemsx.cisd.common.api.server.json.object;
+
+
+import ch.systemsx.cisd.common.api.server.json.common.ObjectCounter;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectFactory;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectMap;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectType;
+
+/**
+ * @author pkupczyk
+ */
+public class ObjectWithIgnoredPropertiesFactory extends ObjectFactory<ObjectWithIgnoredProperties>
+{
+
+    public static final String TYPE = "ObjectWithIgnoredProperties";
+
+    public static final String CLASS = ".LegacyObjectWithIgnoredProperties";
+
+    public static final String PROPERTY = "property";
+
+    public static final String PROPERTY_VALUE = "propertyValue";
+
+    public static final String PROPERTY_WITH_GETTER_AND_SETTER = "propertyWithGetterAndSetter";
+
+    public static final String PROPERTY_WITH_GETTER_AND_SETTER_VALUE =
+            "propertyWithGetterAndSetterValue";
+
+    public static final String PROPERTY_IGNORED = "propertyIgnored";
+
+    public static final String PROPERTY_IGNORED_VALUE = "propertyIgnoredValue";
+
+    public static final String PROPERTY_WITH_GETTER_AND_SETTER_IGNORED =
+            "propertyWithGetterAndSetterIgnored";
+
+    public static final String PROPERTY_WITH_GETTER_AND_SETTER_IGNORED_VALUE =
+            "propertyWithGetterAndSetterIgnoredValue";
+
+    @Override
+    public ObjectWithIgnoredProperties createObjectToSerialize()
+    {
+        ObjectWithIgnoredProperties object = new ObjectWithIgnoredProperties();
+        object.property = PROPERTY_VALUE;
+        object.propertyIgnored = PROPERTY_IGNORED_VALUE;
+        object.setPropertyWithGetterAndSetter(PROPERTY_WITH_GETTER_AND_SETTER_VALUE);
+        object.setPropertyWithGetterAndSetterIgnored(PROPERTY_WITH_GETTER_AND_SETTER_IGNORED_VALUE);
+        return object;
+    }
+
+    @Override
+    public Object createExpectedMapAfterSerialization(ObjectCounter objectCounter)
+    {
+        ObjectMap map = new ObjectMap();
+        map.putId(objectCounter);
+        map.putType(TYPE, CLASS, ObjectType.TYPE);
+        map.putField(PROPERTY, PROPERTY_VALUE);
+        map.putField(PROPERTY_WITH_GETTER_AND_SETTER, PROPERTY_WITH_GETTER_AND_SETTER_VALUE);
+        return map.toMap();
+    }
+
+    @Override
+    public Object createMapToDeserialize(ObjectCounter objectCounter,
+            ObjectType objectType)
+    {
+        ObjectMap map = new ObjectMap();
+        map.putId(objectCounter);
+        map.putType(TYPE, CLASS, objectType);
+        map.putField(PROPERTY, PROPERTY_VALUE);
+        map.putField(PROPERTY_WITH_GETTER_AND_SETTER, PROPERTY_WITH_GETTER_AND_SETTER_VALUE);
+        map.putField(PROPERTY_IGNORED, PROPERTY_IGNORED_VALUE);
+        map.putField(PROPERTY_WITH_GETTER_AND_SETTER_IGNORED,
+                PROPERTY_WITH_GETTER_AND_SETTER_IGNORED_VALUE);
+        return map.toMap();
+    }
+
+    @Override
+    public ObjectWithIgnoredProperties createExpectedObjectAfterDeserialization()
+    {
+        ObjectWithIgnoredProperties object = new ObjectWithIgnoredProperties();
+        object.property = PROPERTY_VALUE;
+        object.setPropertyWithGetterAndSetter(PROPERTY_WITH_GETTER_AND_SETTER_VALUE);
+        return object;
+    }
+
+}
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithKnownButNotUniqueClassFactory.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithKnownButNotUniqueClassFactory.java
new file mode 100644
index 00000000000..7336f4bd363
--- /dev/null
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithKnownButNotUniqueClassFactory.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * 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 ch.systemsx.cisd.common.api.server.json.object;
+
+import static ch.systemsx.cisd.common.api.server.json.object.ObjectWithTypeAFactory.CLASS;
+import static ch.systemsx.cisd.common.api.server.json.object.ObjectWithTypeAFactory.TYPE;
+import static ch.systemsx.cisd.common.api.server.json.object.ObjectWithTypeAFactory.A;
+import static ch.systemsx.cisd.common.api.server.json.object.ObjectWithTypeAFactory.A_VALUE;
+import static ch.systemsx.cisd.common.api.server.json.object.ObjectWithTypeFactory.BASE;
+import static ch.systemsx.cisd.common.api.server.json.object.ObjectWithTypeFactory.BASE_VALUE;
+
+import ch.systemsx.cisd.common.api.server.json.common.ObjectCounter;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectFactory;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectMap;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectType;
+
+/**
+ * @author pkupczyk
+ */
+public class ObjectWithKnownButNotUniqueClassFactory extends ObjectFactory<Object>
+{
+
+    @Override
+    public Object createObjectToSerialize()
+    {
+        return new ObjectWithTypeAFactory().createObjectToSerialize();
+    }
+
+    @Override
+    public Object createExpectedMapAfterSerialization(ObjectCounter objectCounter)
+    {
+        return new ObjectWithTypeAFactory().createExpectedMapAfterSerialization(objectCounter);
+    }
+
+    @Override
+    public Object createMapToDeserialize(ObjectCounter objectCounter, ObjectType objectType)
+    {
+        ObjectMap map = new ObjectMap();
+        map.putType(TYPE, CLASS, ObjectType.CLASS);
+        map.putField(BASE, BASE_VALUE);
+        map.putField(A, A_VALUE);
+        return map.toMap();
+    }
+
+    @Override
+    public Object createExpectedObjectAfterDeserialization()
+    {
+        ObjectMap map = new ObjectMap();
+        map.putType(TYPE, CLASS, ObjectType.CLASS);
+        map.putField(BASE, BASE_VALUE);
+        map.putField(A, A_VALUE);
+        return map.toMap();
+    }
+
+}
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithKnownTypeFactory.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithKnownTypeFactory.java
new file mode 100644
index 00000000000..5cc3e007f09
--- /dev/null
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithKnownTypeFactory.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * 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 ch.systemsx.cisd.common.api.server.json.object;
+
+import static ch.systemsx.cisd.common.api.server.json.object.ObjectWithTypeAFactory.A;
+import static ch.systemsx.cisd.common.api.server.json.object.ObjectWithTypeAFactory.A_VALUE;
+import static ch.systemsx.cisd.common.api.server.json.object.ObjectWithTypeAFactory.CLASS;
+import static ch.systemsx.cisd.common.api.server.json.object.ObjectWithTypeAFactory.TYPE;
+import static ch.systemsx.cisd.common.api.server.json.object.ObjectWithTypeFactory.BASE;
+import static ch.systemsx.cisd.common.api.server.json.object.ObjectWithTypeFactory.BASE_VALUE;
+
+import ch.systemsx.cisd.common.api.server.json.common.ObjectCounter;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectFactory;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectMap;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectType;
+
+/**
+ * @author pkupczyk
+ */
+public class ObjectWithKnownTypeFactory extends ObjectFactory<Object>
+{
+
+    @Override
+    public Object createObjectToSerialize()
+    {
+        return new ObjectWithTypeAFactory().createObjectToSerialize();
+    }
+
+    @Override
+    public Object createExpectedMapAfterSerialization(ObjectCounter objectCounter)
+    {
+        return new ObjectWithTypeAFactory().createExpectedMapAfterSerialization(objectCounter);
+    }
+
+    @Override
+    public Object createMapToDeserialize(ObjectCounter objectCounter, ObjectType objectType)
+    {
+        ObjectMap map = new ObjectMap();
+        map.putType(TYPE, CLASS, ObjectType.TYPE);
+        map.putField(BASE, BASE_VALUE);
+        map.putField(A, A_VALUE);
+        return map.toMap();
+    }
+
+    @Override
+    public Object createExpectedObjectAfterDeserialization()
+    {
+        return new ObjectWithTypeAFactory().createExpectedObjectAfterDeserialization();
+    }
+
+}
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithKnownUniqueClassFactory.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithKnownUniqueClassFactory.java
new file mode 100644
index 00000000000..dcd284c9377
--- /dev/null
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithKnownUniqueClassFactory.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * 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 ch.systemsx.cisd.common.api.server.json.object;
+
+import static ch.systemsx.cisd.common.api.server.json.object.ObjectWithTypeAFactory.A;
+import static ch.systemsx.cisd.common.api.server.json.object.ObjectWithTypeAFactory.A_VALUE;
+import static ch.systemsx.cisd.common.api.server.json.object.ObjectWithTypeFactory.BASE;
+import static ch.systemsx.cisd.common.api.server.json.object.ObjectWithTypeFactory.BASE_VALUE;
+
+import ch.systemsx.cisd.common.api.server.json.common.ObjectCounter;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectFactory;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectMap;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectType;
+
+import static ch.systemsx.cisd.common.api.server.json.object.ObjectWithTypeAAFactory.*;
+
+/**
+ * @author pkupczyk
+ */
+public class ObjectWithKnownUniqueClassFactory extends ObjectFactory<Object>
+{
+
+    @Override
+    public Object createObjectToSerialize()
+    {
+        return new ObjectWithTypeAAFactory().createObjectToSerialize();
+    }
+
+    @Override
+    public Object createExpectedMapAfterSerialization(ObjectCounter objectCounter)
+    {
+        return new ObjectWithTypeAAFactory().createExpectedMapAfterSerialization(objectCounter);
+    }
+
+    @Override
+    public Object createMapToDeserialize(ObjectCounter objectCounter, ObjectType objectType)
+    {
+        ObjectMap map = new ObjectMap();
+        map.putType(TYPE, CLASS, ObjectType.CLASS);
+        map.putField(BASE, BASE_VALUE);
+        map.putField(A, A_VALUE);
+        map.putField(AA, AA_VALUE);
+        return map.toMap();
+    }
+
+    @Override
+    public Object createExpectedObjectAfterDeserialization()
+    {
+        return new ObjectWithTypeAAFactory().createExpectedObjectAfterDeserialization();
+    }
+}
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithNestedMapsInCollectionFactory.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithNestedMapsInCollectionFactory.java
new file mode 100644
index 00000000000..365a31283c1
--- /dev/null
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithNestedMapsInCollectionFactory.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * 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 ch.systemsx.cisd.common.api.server.json.object;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+
+import ch.systemsx.cisd.common.api.server.json.common.ObjectCounter;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectFactory;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectType;
+
+/**
+ * @author pkupczyk
+ */
+@SuppressWarnings(
+    { "rawtypes", "unchecked" })
+public class ObjectWithNestedMapsInCollectionFactory extends ObjectFactory<Collection>
+{
+
+    @Override
+    public Collection createObjectToSerialize()
+    {
+        Collection collection = new HashSet();
+        collection.add(new ObjectWithContainerTypesFactory().createObjectToSerialize());
+        return collection;
+    }
+
+    @Override
+    public Object createExpectedMapAfterSerialization(ObjectCounter objectCounter)
+    {
+        Collection collection = new HashSet();
+        collection.add(new ObjectWithContainerTypesFactory()
+                .createExpectedMapAfterSerialization(objectCounter));
+        return collection;
+    }
+
+    @Override
+    public Object createMapToDeserialize(ObjectCounter objectCounter, ObjectType objectType)
+    {
+        Collection collection = new HashSet();
+        collection.add(new ObjectWithContainerTypesFactory().createMapToDeserialize(objectCounter,
+                objectType));
+        return collection;
+    }
+
+    @Override
+    public Collection createExpectedObjectAfterDeserialization()
+    {
+        Collection collection = new ArrayList();
+        collection.add(new ObjectWithContainerTypesFactory()
+                .createExpectedObjectAfterDeserialization());
+        return collection;
+    }
+
+}
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithNestedMapsInListFactory.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithNestedMapsInListFactory.java
new file mode 100644
index 00000000000..aa85dde7678
--- /dev/null
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithNestedMapsInListFactory.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * 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 ch.systemsx.cisd.common.api.server.json.object;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import ch.systemsx.cisd.common.api.server.json.common.ObjectCounter;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectFactory;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectType;
+
+/**
+ * @author pkupczyk
+ */
+@SuppressWarnings(
+    { "rawtypes", "unchecked" })
+public class ObjectWithNestedMapsInListFactory extends ObjectFactory<List>
+{
+
+    @Override
+    public List createObjectToSerialize()
+    {
+        List list = new ArrayList();
+        list.add(new ObjectWithContainerTypesFactory().createObjectToSerialize());
+        return list;
+    }
+
+    @Override
+    public Object createExpectedMapAfterSerialization(ObjectCounter objectCounter)
+    {
+        List list = new ArrayList();
+        list.add(new ObjectWithContainerTypesFactory()
+                .createExpectedMapAfterSerialization(objectCounter));
+        return list;
+    }
+
+    @Override
+    public Object createMapToDeserialize(ObjectCounter objectCounter, ObjectType objectType)
+    {
+        Collection list = new ArrayList();
+        list.add(new ObjectWithContainerTypesFactory().createMapToDeserialize(objectCounter,
+                objectType));
+        return list;
+    }
+
+    @Override
+    public List createExpectedObjectAfterDeserialization()
+    {
+        List list = new ArrayList();
+        list.add(new ObjectWithContainerTypesFactory().createExpectedObjectAfterDeserialization());
+        return list;
+    }
+
+}
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithNestedTypes.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithNestedTypes.java
index 6a5ba7f4426..52d926c7427 100644
--- a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithNestedTypes.java
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithNestedTypes.java
@@ -19,148 +19,69 @@ package ch.systemsx.cisd.common.api.server.json.object;
 import org.testng.Assert;
 
 import ch.systemsx.cisd.base.annotation.JsonObject;
-import ch.systemsx.cisd.common.api.server.json.common.ObjectCounter;
-import ch.systemsx.cisd.common.api.server.json.common.ObjectMap;
-import ch.systemsx.cisd.common.api.server.json.common.ObjectType;
 
 /**
  * @author pkupczyk
  */
-@SuppressWarnings("hiding")
-@JsonObject(ObjectWithNestedTypes.TYPE)
+@JsonObject(ObjectWithNestedTypesFactory.TYPE)
 public class ObjectWithNestedTypes
 {
 
-    public static final String TYPE = "ObjectWithNestedTypes";
-
-    public static final String CLASS = ".LegacyObjectWithNestedTypes";
-
-    public static final String PROPERTY_NESTED = "propertyNested";
-
-    public static final String PROPERTY_NESTED_CHILD = "propertyNestedChild";
-
-    // TODO: check why it doesn't work properly during both serialization and deserialization
-    // public Object propertyObject;
+    public Object propertyObject;
 
     public ObjectNested propertyNested;
 
     public ObjectNestedChild propertyNestedChild;
 
-    @JsonObject(ObjectNested.TYPE)
+    @JsonObject(ObjectNestedFactory.TYPE)
     public static class ObjectNested
     {
-        public static final String TYPE = "ObjectNested";
-
-        public static final String CLASS = ".LegacyObjectNested";
-
-        public static final String NESTED = "nested";
-
-        public static final String NESTED_VALUE = "nestedValue";
 
         public String nested;
 
-        public static ObjectNested createObject()
-        {
-            ObjectNested object = new ObjectNested();
-            object.nested = NESTED_VALUE;
-            return object;
-        }
-
-        public static ObjectMap createMap(ObjectCounter objectCounter, ObjectType objectType)
-        {
-            ObjectMap map = new ObjectMap();
-            map.putId(objectCounter);
-            map.putType(TYPE, CLASS, objectType);
-            map.putField(NESTED, NESTED_VALUE);
-            return map;
-        }
-
         @Override
         public boolean equals(Object obj)
         {
             Assert.assertNotNull(obj);
-            Assert.assertEquals(getClass(), obj.getClass());
+            Assert.assertEquals(obj.getClass(), getClass());
 
             ObjectNested casted = (ObjectNested) obj;
-            Assert.assertEquals(nested, casted.nested);
+            Assert.assertEquals(casted.nested, nested);
             return true;
         }
 
     }
 
-    @JsonObject(ObjectNestedChild.TYPE)
+    @JsonObject(ObjectNestedChildFactory.TYPE)
     public static class ObjectNestedChild extends ObjectNested
     {
-        public static final String TYPE = "ObjectNestedChild";
-
-        public static final String CLASS = ".LegacyObjectNestedChild";
-
-        public static final String NESTED_CHILD = "nestedChild";
-
-        public static final String NESTED_CHILD_VALUE = "nestedChildValue";
 
         public String nestedChild;
 
-        public static ObjectNestedChild createObject()
-        {
-            ObjectNestedChild object = new ObjectNestedChild();
-            object.nested = NESTED_VALUE;
-            object.nestedChild = NESTED_CHILD_VALUE;
-            return object;
-        }
-
-        public static ObjectMap createMap(ObjectCounter objectCounter, ObjectType objectType)
-        {
-            ObjectMap map = new ObjectMap();
-            map.putId(objectCounter);
-            map.putType(TYPE, CLASS, objectType);
-            map.putField(NESTED, NESTED_VALUE);
-            map.putField(NESTED_CHILD, NESTED_CHILD_VALUE);
-            return map;
-        }
-
         @Override
         public boolean equals(Object obj)
         {
             Assert.assertNotNull(obj);
-            Assert.assertEquals(getClass(), obj.getClass());
+            Assert.assertEquals(obj.getClass(), getClass());
 
             ObjectNestedChild casted = (ObjectNestedChild) obj;
-            Assert.assertEquals(nested, casted.nested);
-            Assert.assertEquals(nestedChild, casted.nestedChild);
+            Assert.assertEquals(casted.nested, nested);
+            Assert.assertEquals(casted.nestedChild, nestedChild);
             return true;
         }
 
     }
 
-    public static ObjectWithNestedTypes createObject()
-    {
-        ObjectWithNestedTypes object = new ObjectWithNestedTypes();
-        object.propertyNested = ObjectNested.createObject();
-        object.propertyNestedChild = ObjectNestedChild.createObject();
-        return object;
-    }
-
-    public static ObjectMap createMap(ObjectCounter objectCounter, ObjectType objectType)
-    {
-        ObjectMap map = new ObjectMap();
-        map.putId(objectCounter);
-        map.putType(TYPE, CLASS, objectType);
-        map.putField(PROPERTY_NESTED, ObjectNested.createMap(objectCounter, objectType).toMap());
-        map.putField(PROPERTY_NESTED_CHILD, ObjectNestedChild.createMap(objectCounter, objectType)
-                .toMap());
-        return map;
-    }
-
     @Override
     public boolean equals(Object obj)
     {
         Assert.assertNotNull(obj);
-        Assert.assertEquals(getClass(), obj.getClass());
+        Assert.assertEquals(obj.getClass(), getClass());
 
         ObjectWithNestedTypes casted = (ObjectWithNestedTypes) obj;
-        Assert.assertEquals(propertyNested, casted.propertyNested);
-        Assert.assertEquals(propertyNestedChild, casted.propertyNestedChild);
+        Assert.assertEquals(casted.propertyObject, propertyObject);
+        Assert.assertEquals(casted.propertyNested, propertyNested);
+        Assert.assertEquals(casted.propertyNestedChild, propertyNestedChild);
         return true;
     }
 
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithNestedTypesFactory.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithNestedTypesFactory.java
new file mode 100644
index 00000000000..66b786f3e61
--- /dev/null
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithNestedTypesFactory.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * 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 ch.systemsx.cisd.common.api.server.json.object;
+
+import java.util.Map;
+
+import ch.systemsx.cisd.common.api.server.json.common.ObjectCounter;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectFactory;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectMap;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectType;
+
+/**
+ * @author pkupczyk
+ */
+public class ObjectWithNestedTypesFactory extends ObjectFactory<ObjectWithNestedTypes>
+{
+
+    public static final String TYPE = "ObjectWithNestedTypes";
+
+    public static final String CLASS = ".LegacyObjectWithNestedTypes";
+
+    public static final String PROPERTY_OBJECT = "propertyObject";
+
+    public static final String PROPERTY_NESTED = "propertyNested";
+
+    public static final String PROPERTY_NESTED_CHILD = "propertyNestedChild";
+
+    @Override
+    public ObjectWithNestedTypes createObject()
+    {
+        ObjectWithNestedTypes object = new ObjectWithNestedTypes();
+        object.propertyNested = new ObjectNestedFactory().createObject();
+        object.propertyNestedChild = new ObjectNestedChildFactory().createObject();
+        object.propertyObject = new ObjectNestedFactory().createObject();
+        return object;
+    }
+
+    @Override
+    public Map<String, Object> createMap(ObjectCounter objectCounter, ObjectType objectType)
+    {
+        ObjectMap map = new ObjectMap();
+        map.putId(objectCounter);
+        map.putType(TYPE, CLASS, objectType);
+        map.putField(PROPERTY_NESTED,
+                new ObjectNestedFactory().createMap(objectCounter, objectType));
+        map.putField(PROPERTY_NESTED_CHILD,
+                new ObjectNestedChildFactory().createMap(objectCounter, objectType));
+        map.putField(PROPERTY_OBJECT,
+                new ObjectNestedFactory().createMap(objectCounter, objectType));
+        return map.toMap();
+    }
+
+}
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithPrimitiveTypes.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithPrimitiveTypes.java
index b5cf25f051f..73a05be9960 100644
--- a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithPrimitiveTypes.java
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithPrimitiveTypes.java
@@ -19,49 +19,14 @@ package ch.systemsx.cisd.common.api.server.json.object;
 import org.testng.Assert;
 
 import ch.systemsx.cisd.base.annotation.JsonObject;
-import ch.systemsx.cisd.common.api.server.json.common.ObjectCounter;
-import ch.systemsx.cisd.common.api.server.json.common.ObjectMap;
-import ch.systemsx.cisd.common.api.server.json.common.ObjectType;
 
 /**
  * @author pkupczyk
  */
-@JsonObject(ObjectWithPrimitiveTypes.TYPE)
+@JsonObject(ObjectWithPrimitiveTypesFactory.TYPE)
 public class ObjectWithPrimitiveTypes
 {
 
-    public static final String TYPE = "ObjectWithPrimitiveTypes";
-
-    public static final String CLASS = ".LegacyObjectWithPrimitiveTypes";
-
-    public static final String STRING_FIELD = "stringField";
-
-    public static final String STRING_FIELD_VALUE = "stringValue";
-
-    public static final String INTEGER_OBJECT_FIELD = "integerObjectField";
-
-    public static final Integer INTEGER_OBJECT_FIELD_VALUE = new Integer(1);
-
-    public static final String FLOAT_OBJECT_FIELD = "floatObjectField";
-
-    public static final Float FLOAT_OBJECT_FIELD_VALUE = new Float(2.5f);
-
-    public static final String DOUBLE_OBJECT_FIELD = "doubleObjectField";
-
-    public static final Double DOUBLE_OBJECT_FIELD_VALUE = new Double(3.5d);
-
-    public static final String INTEGER_FIELD = "integerField";
-
-    public static final int INTEGER_FIELD_VALUE = 4;
-
-    public static final String FLOAT_FIELD = "floatField";
-
-    public static final float FLOAT_FIELD_VALUE = 5.5f;
-
-    public static final String DOUBLE_FIELD = "doubleField";
-
-    public static final double DOUBLE_FIELD_VALUE = 6.5d;
-
     public String stringField;
 
     public Integer integerObjectField;
@@ -76,48 +41,20 @@ public class ObjectWithPrimitiveTypes
 
     public double doubleField;
 
-    public static ObjectWithPrimitiveTypes createObject()
-    {
-        ObjectWithPrimitiveTypes object = new ObjectWithPrimitiveTypes();
-        object.stringField = STRING_FIELD_VALUE;
-        object.integerObjectField = INTEGER_OBJECT_FIELD_VALUE;
-        object.floatObjectField = FLOAT_OBJECT_FIELD_VALUE;
-        object.doubleObjectField = DOUBLE_OBJECT_FIELD_VALUE;
-        object.integerField = INTEGER_FIELD_VALUE;
-        object.floatField = FLOAT_FIELD_VALUE;
-        object.doubleField = DOUBLE_FIELD_VALUE;
-        return object;
-    }
-
-    public static ObjectMap createMap(ObjectCounter objectCounter, ObjectType objectType)
-    {
-        ObjectMap map = new ObjectMap();
-        map.putId(objectCounter);
-        map.putType(TYPE, CLASS, objectType);
-        map.putField(STRING_FIELD, STRING_FIELD_VALUE);
-        map.putField(INTEGER_OBJECT_FIELD, INTEGER_OBJECT_FIELD_VALUE);
-        map.putField(FLOAT_OBJECT_FIELD, FLOAT_OBJECT_FIELD_VALUE);
-        map.putField(DOUBLE_OBJECT_FIELD, DOUBLE_OBJECT_FIELD_VALUE);
-        map.putField(INTEGER_FIELD, INTEGER_FIELD_VALUE);
-        map.putField(FLOAT_FIELD, FLOAT_FIELD_VALUE);
-        map.putField(DOUBLE_FIELD, DOUBLE_FIELD_VALUE);
-        return map;
-    }
-
     @Override
     public boolean equals(Object obj)
     {
         Assert.assertNotNull(obj);
-        Assert.assertEquals(getClass(), obj.getClass());
+        Assert.assertEquals(obj.getClass(), getClass());
 
         ObjectWithPrimitiveTypes casted = (ObjectWithPrimitiveTypes) obj;
-        Assert.assertEquals(stringField, casted.stringField);
-        Assert.assertEquals(integerObjectField, casted.integerObjectField);
-        Assert.assertEquals(floatObjectField, casted.floatObjectField);
-        Assert.assertEquals(doubleObjectField, casted.doubleObjectField);
-        Assert.assertEquals(integerField, casted.integerField);
-        Assert.assertEquals(floatField, casted.floatField);
-        Assert.assertEquals(doubleField, casted.doubleField);
+        Assert.assertEquals(casted.stringField, stringField);
+        Assert.assertEquals(casted.integerObjectField, integerObjectField);
+        Assert.assertEquals(casted.floatObjectField, floatObjectField);
+        Assert.assertEquals(casted.doubleObjectField, doubleObjectField);
+        Assert.assertEquals(casted.integerField, integerField);
+        Assert.assertEquals(casted.floatField, floatField);
+        Assert.assertEquals(casted.doubleField, doubleField);
         return true;
     }
 }
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithPrimitiveTypesFactory.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithPrimitiveTypesFactory.java
new file mode 100644
index 00000000000..6c4714b3dd8
--- /dev/null
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithPrimitiveTypesFactory.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * 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 ch.systemsx.cisd.common.api.server.json.object;
+
+import java.util.Map;
+
+import ch.systemsx.cisd.common.api.server.json.common.ObjectCounter;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectFactory;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectMap;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectType;
+
+/**
+ * @author pkupczyk
+ */
+public class ObjectWithPrimitiveTypesFactory extends ObjectFactory<ObjectWithPrimitiveTypes>
+{
+
+    public static final String TYPE = "ObjectWithPrimitiveTypes";
+
+    public static final String CLASS = ".LegacyObjectWithPrimitiveTypes";
+
+    public static final String STRING_FIELD = "stringField";
+
+    public static final String STRING_FIELD_VALUE = "stringValue";
+
+    public static final String INTEGER_OBJECT_FIELD = "integerObjectField";
+
+    public static final Integer INTEGER_OBJECT_FIELD_VALUE = new Integer(1);
+
+    public static final String FLOAT_OBJECT_FIELD = "floatObjectField";
+
+    public static final Float FLOAT_OBJECT_FIELD_VALUE = new Float(2.5f);
+
+    public static final String DOUBLE_OBJECT_FIELD = "doubleObjectField";
+
+    public static final Double DOUBLE_OBJECT_FIELD_VALUE = new Double(3.5d);
+
+    public static final String INTEGER_FIELD = "integerField";
+
+    public static final int INTEGER_FIELD_VALUE = 4;
+
+    public static final String FLOAT_FIELD = "floatField";
+
+    public static final float FLOAT_FIELD_VALUE = 5.5f;
+
+    public static final String DOUBLE_FIELD = "doubleField";
+
+    public static final double DOUBLE_FIELD_VALUE = 6.5d;
+
+    @Override
+    public ObjectWithPrimitiveTypes createObject()
+    {
+        ObjectWithPrimitiveTypes object = new ObjectWithPrimitiveTypes();
+        object.stringField = STRING_FIELD_VALUE;
+        object.integerObjectField = INTEGER_OBJECT_FIELD_VALUE;
+        object.floatObjectField = FLOAT_OBJECT_FIELD_VALUE;
+        object.doubleObjectField = DOUBLE_OBJECT_FIELD_VALUE;
+        object.integerField = INTEGER_FIELD_VALUE;
+        object.floatField = FLOAT_FIELD_VALUE;
+        object.doubleField = DOUBLE_FIELD_VALUE;
+        return object;
+    }
+
+    @Override
+    public Map<String, Object> createMap(ObjectCounter objectCounter, ObjectType objectType)
+    {
+        ObjectMap map = new ObjectMap();
+        map.putId(objectCounter);
+        map.putType(TYPE, CLASS, objectType);
+        map.putField(STRING_FIELD, STRING_FIELD_VALUE);
+        map.putField(INTEGER_OBJECT_FIELD, INTEGER_OBJECT_FIELD_VALUE);
+        map.putField(FLOAT_OBJECT_FIELD, FLOAT_OBJECT_FIELD_VALUE);
+        map.putField(DOUBLE_OBJECT_FIELD, DOUBLE_OBJECT_FIELD_VALUE);
+        map.putField(INTEGER_FIELD, INTEGER_FIELD_VALUE);
+        map.putField(FLOAT_FIELD, FLOAT_FIELD_VALUE);
+        map.putField(DOUBLE_FIELD, DOUBLE_FIELD_VALUE);
+        return map.toMap();
+    }
+
+}
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithPrivateAccess.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithPrivateAccess.java
index ccb660c3539..47106d4409a 100644
--- a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithPrivateAccess.java
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithPrivateAccess.java
@@ -18,68 +18,63 @@ package ch.systemsx.cisd.common.api.server.json.object;
 
 import org.testng.Assert;
 
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
 import ch.systemsx.cisd.base.annotation.JsonObject;
-import ch.systemsx.cisd.common.api.server.json.common.ObjectCounter;
-import ch.systemsx.cisd.common.api.server.json.common.ObjectMap;
-import ch.systemsx.cisd.common.api.server.json.common.ObjectType;
 
 /**
  * @author pkupczyk
  */
 
-@JsonObject(ObjectWithPrivateAccess.TYPE)
+@JsonObject(ObjectWithPrivateAccessFactory.TYPE)
 public class ObjectWithPrivateAccess
 {
 
-    public static final String TYPE = "ObjectWithPrivateAccess";
-
-    public static final String CLASS = ".LegacyObjectWithPrivateAccess";
-
-    public static final String FIELD = "field";
-
-    public static final String FIELD_VALUE = "fieldValue";
-
+    @JsonProperty
     private String field;
 
     private ObjectWithPrivateAccess()
     {
     }
 
-    public String getField()
+    public static ObjectWithPrivateAccess newInstance()
+    {
+        return new ObjectWithPrivateAccess();
+    }
+
+    @JsonIgnore
+    public String getFieldPublic()
     {
         return field;
     }
 
-    @SuppressWarnings("unused")
-    private void setField(String field)
+    @JsonIgnore
+    public void setFieldPublic(String field)
     {
         this.field = field;
     }
 
-    public static ObjectWithPrivateAccess createObject()
+    @SuppressWarnings("unused")
+    private String getField()
     {
-        ObjectWithPrivateAccess object = new ObjectWithPrivateAccess();
-        object.field = FIELD_VALUE;
-        return object;
+        return field;
     }
 
-    public static ObjectMap createMap(ObjectCounter objectCounter, ObjectType objectType)
+    @SuppressWarnings("unused")
+    private void setField(String field)
     {
-        ObjectMap map = new ObjectMap();
-        map.putId(objectCounter);
-        map.putType(TYPE, CLASS, objectType);
-        map.putField("field", "fieldValue");
-        return map;
+        this.field = field;
     }
 
     @Override
     public boolean equals(Object obj)
     {
         Assert.assertNotNull(obj);
-        Assert.assertEquals(getClass(), obj.getClass());
+        Assert.assertEquals(obj.getClass(), getClass());
 
         ObjectWithPrivateAccess casted = (ObjectWithPrivateAccess) obj;
-        Assert.assertEquals(field, casted.field);
+        Assert.assertEquals(casted.field, field);
         return true;
     }
 
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithPrivateAccessFactory.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithPrivateAccessFactory.java
new file mode 100644
index 00000000000..40e4eb0eeda
--- /dev/null
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithPrivateAccessFactory.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * 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 ch.systemsx.cisd.common.api.server.json.object;
+
+import java.util.Map;
+
+import ch.systemsx.cisd.common.api.server.json.common.ObjectCounter;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectFactory;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectMap;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectType;
+
+/**
+ * @author pkupczyk
+ */
+public class ObjectWithPrivateAccessFactory extends ObjectFactory<ObjectWithPrivateAccess>
+{
+
+    public static final String TYPE = "ObjectWithPrivateAccess";
+
+    public static final String CLASS = ".LegacyObjectWithPrivateAccess";
+
+    public static final String FIELD = "field";
+
+    public static final String FIELD_VALUE = "fieldValue";
+
+    @Override
+    public ObjectWithPrivateAccess createObject()
+    {
+        ObjectWithPrivateAccess object = ObjectWithPrivateAccess.newInstance();
+        object.setFieldPublic(FIELD_VALUE);
+        return object;
+    }
+
+    @Override
+    public Map<String, Object> createMap(ObjectCounter objectCounter, ObjectType objectType)
+    {
+        ObjectMap map = new ObjectMap();
+        map.putId(objectCounter);
+        map.putType(TYPE, CLASS, objectType);
+        map.putField(FIELD, FIELD_VALUE);
+        return map.toMap();
+    }
+
+}
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithRenamedProperties.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithRenamedProperties.java
index ad85cacd96c..43d4d8cc4d8 100644
--- a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithRenamedProperties.java
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithRenamedProperties.java
@@ -21,40 +21,14 @@ import org.testng.Assert;
 import com.fasterxml.jackson.annotation.JsonProperty;
 
 import ch.systemsx.cisd.base.annotation.JsonObject;
-import ch.systemsx.cisd.common.api.server.json.common.ObjectCounter;
-import ch.systemsx.cisd.common.api.server.json.common.ObjectMap;
-import ch.systemsx.cisd.common.api.server.json.common.ObjectType;
 
 /**
  * @author pkupczyk
  */
-@JsonObject(ObjectWithRenamedProperties.TYPE)
+@JsonObject(ObjectWithRenamedPropertiesFactory.TYPE)
 public class ObjectWithRenamedProperties
 {
 
-    public static final String TYPE = "ObjectWithRenamedProperties";
-
-    public static final String CLASS = ".LegacyObjectWithRenamedProperties";
-
-    public static final String PROPERTY = "property";
-
-    public static final String PROPERTY_VALUE = "propertyValue";
-
-    public static final String PROPERTY_RENAMED = "propertyRenamed";
-
-    public static final String PROPERTY_RENAMED_VALUE = "propertyRenamedValue";
-
-    public static final String PROPERTY_WITH_GETTER_AND_SETTER = "propertyWithGetterAndSetter";
-
-    public static final String PROPERTY_WITH_GETTER_AND_SETTER_VALUE =
-            "propertyWithGetterAndSetterValue";
-
-    public static final String PROPERTY_WITH_GETTER_AND_SETTER_RENAMED =
-            "propertyWithGetterAndSetterRenamed";
-
-    public static final String PROPERTY_WITH_GETTER_AND_SETTER_RENAMED_VALUE =
-            "propertyWithGetterAndSetterRenamedValue";
-
     public String property;
 
     private String propertyWithGetterAndSetter;
@@ -85,40 +59,17 @@ public class ObjectWithRenamedProperties
         this.y = y;
     }
 
-    public static ObjectWithRenamedProperties createObject()
-    {
-        ObjectWithRenamedProperties object = new ObjectWithRenamedProperties();
-        object.property = PROPERTY_VALUE;
-        object.x = PROPERTY_RENAMED_VALUE;
-        object.propertyWithGetterAndSetter = PROPERTY_WITH_GETTER_AND_SETTER_VALUE;
-        object.y = PROPERTY_WITH_GETTER_AND_SETTER_RENAMED_VALUE;
-        return object;
-    }
-
-    public static ObjectMap createMap(ObjectCounter objectCounter, ObjectType objectType)
-    {
-        ObjectMap map = new ObjectMap();
-        map.putId(objectCounter);
-        map.putType(TYPE, CLASS, objectType);
-        map.putField(PROPERTY, PROPERTY_VALUE);
-        map.putField(PROPERTY_RENAMED, PROPERTY_RENAMED_VALUE);
-        map.putField(PROPERTY_WITH_GETTER_AND_SETTER, PROPERTY_WITH_GETTER_AND_SETTER_VALUE);
-        map.putField(PROPERTY_WITH_GETTER_AND_SETTER_RENAMED,
-                PROPERTY_WITH_GETTER_AND_SETTER_RENAMED_VALUE);
-        return map;
-    }
-
     @Override
     public boolean equals(Object obj)
     {
         Assert.assertNotNull(obj);
-        Assert.assertEquals(getClass(), obj.getClass());
+        Assert.assertEquals(obj.getClass(), getClass());
 
         ObjectWithRenamedProperties casted = (ObjectWithRenamedProperties) obj;
-        Assert.assertEquals(property, casted.property);
-        Assert.assertEquals(x, casted.x);
-        Assert.assertEquals(propertyWithGetterAndSetter, casted.propertyWithGetterAndSetter);
-        Assert.assertEquals(y, casted.y);
+        Assert.assertEquals(casted.property, property);
+        Assert.assertEquals(casted.x, x);
+        Assert.assertEquals(casted.propertyWithGetterAndSetter, propertyWithGetterAndSetter);
+        Assert.assertEquals(casted.y, y);
         return true;
     }
 
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithRenamedPropertiesFactory.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithRenamedPropertiesFactory.java
new file mode 100644
index 00000000000..f8c392e71bf
--- /dev/null
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithRenamedPropertiesFactory.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * 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 ch.systemsx.cisd.common.api.server.json.object;
+
+import java.util.Map;
+
+import ch.systemsx.cisd.common.api.server.json.common.ObjectCounter;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectFactory;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectMap;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectType;
+
+/**
+ * @author pkupczyk
+ */
+public class ObjectWithRenamedPropertiesFactory extends ObjectFactory<ObjectWithRenamedProperties>
+{
+
+    public static final String TYPE = "ObjectWithRenamedProperties";
+
+    public static final String CLASS = ".LegacyObjectWithRenamedProperties";
+
+    public static final String PROPERTY = "property";
+
+    public static final String PROPERTY_VALUE = "propertyValue";
+
+    public static final String PROPERTY_RENAMED = "propertyRenamed";
+
+    public static final String PROPERTY_RENAMED_VALUE = "propertyRenamedValue";
+
+    public static final String PROPERTY_WITH_GETTER_AND_SETTER = "propertyWithGetterAndSetter";
+
+    public static final String PROPERTY_WITH_GETTER_AND_SETTER_VALUE =
+            "propertyWithGetterAndSetterValue";
+
+    public static final String PROPERTY_WITH_GETTER_AND_SETTER_RENAMED =
+            "propertyWithGetterAndSetterRenamed";
+
+    public static final String PROPERTY_WITH_GETTER_AND_SETTER_RENAMED_VALUE =
+            "propertyWithGetterAndSetterRenamedValue";
+
+    @Override
+    public ObjectWithRenamedProperties createObject()
+    {
+        ObjectWithRenamedProperties object = new ObjectWithRenamedProperties();
+        object.property = PROPERTY_VALUE;
+        object.x = PROPERTY_RENAMED_VALUE;
+        object.setPropertyWithGetterAndSetter(PROPERTY_WITH_GETTER_AND_SETTER_VALUE);
+        object.setY(PROPERTY_WITH_GETTER_AND_SETTER_RENAMED_VALUE);
+        return object;
+    }
+
+    @Override
+    public Map<String, Object> createMap(ObjectCounter objectCounter, ObjectType objectType)
+    {
+        ObjectMap map = new ObjectMap();
+        map.putId(objectCounter);
+        map.putType(TYPE, CLASS, objectType);
+        map.putField(PROPERTY, PROPERTY_VALUE);
+        map.putField(PROPERTY_RENAMED, PROPERTY_RENAMED_VALUE);
+        map.putField(PROPERTY_WITH_GETTER_AND_SETTER, PROPERTY_WITH_GETTER_AND_SETTER_VALUE);
+        map.putField(PROPERTY_WITH_GETTER_AND_SETTER_RENAMED,
+                PROPERTY_WITH_GETTER_AND_SETTER_RENAMED_VALUE);
+        return map.toMap();
+    }
+
+}
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithReusedReferences.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithReusedReferences.java
new file mode 100644
index 00000000000..97870e9ee75
--- /dev/null
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithReusedReferences.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * 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 ch.systemsx.cisd.common.api.server.json.object;
+
+import org.testng.Assert;
+
+import ch.systemsx.cisd.base.annotation.JsonObject;
+
+/**
+ * @author pkupczyk
+ */
+@JsonObject(ObjectWithReusedReferencesFactory.TYPE)
+public class ObjectWithReusedReferences
+{
+
+    public ObjectWithType reference1;
+
+    public ObjectWithType reference2;
+
+    @Override
+    public boolean equals(Object obj)
+    {
+        Assert.assertNotNull(obj);
+        Assert.assertEquals(obj.getClass(), getClass());
+
+        ObjectWithReusedReferences casted = (ObjectWithReusedReferences) obj;
+        Assert.assertEquals(casted.reference1, reference1);
+        Assert.assertEquals(casted.reference2, reference2);
+        Assert.assertTrue(casted.reference1 == casted.reference2);
+        return true;
+    }
+
+}
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithReusedReferencesFactory.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithReusedReferencesFactory.java
new file mode 100644
index 00000000000..765a36e3e6c
--- /dev/null
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithReusedReferencesFactory.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * 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 ch.systemsx.cisd.common.api.server.json.object;
+
+import java.util.Map;
+
+import ch.systemsx.cisd.common.api.server.json.common.ObjectCounter;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectFactory;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectMap;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectType;
+
+/**
+ * @author pkupczyk
+ */
+public class ObjectWithReusedReferencesFactory extends ObjectFactory<ObjectWithReusedReferences>
+{
+
+    public static final String TYPE = "ObjectWithReusedReferences";
+
+    public static final String CLASS = ".LegacyObjectWithReusedReferences";
+
+    public static final String REFERENCE_1 = "reference1";
+
+    public static final String REFERENCE_2 = "reference2";
+
+    @Override
+    public ObjectWithReusedReferences createObject()
+    {
+        ObjectWithReusedReferences object = new ObjectWithReusedReferences();
+
+        ObjectWithType reference = new ObjectWithTypeFactory().createObject();
+        object.reference1 = reference;
+        object.reference2 = reference;
+
+        return object;
+    }
+
+    @Override
+    public Map<String, Object> createMap(ObjectCounter objectCounter, ObjectType objectType)
+    {
+        ObjectMap map = new ObjectMap();
+        map.putId(objectCounter);
+        map.putType(TYPE, CLASS, objectType);
+
+        Integer referenceId = objectCounter.current();
+        Object reference = new ObjectWithTypeFactory().createMap(objectCounter, objectType);
+
+        map.putField(REFERENCE_1, reference);
+        map.putField(REFERENCE_2, referenceId);
+
+        return map.toMap();
+    }
+
+}
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithSelfReference.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithSelfReference.java
index 57d66967f63..6beb0e09f18 100644
--- a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithSelfReference.java
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithSelfReference.java
@@ -19,56 +19,24 @@ package ch.systemsx.cisd.common.api.server.json.object;
 import org.testng.Assert;
 
 import ch.systemsx.cisd.base.annotation.JsonObject;
-import ch.systemsx.cisd.common.api.server.json.common.ObjectCounter;
-import ch.systemsx.cisd.common.api.server.json.common.ObjectMap;
-import ch.systemsx.cisd.common.api.server.json.common.ObjectType;
 
 /**
  * @author pkupczyk
  */
-@JsonObject(ObjectWithSelfReference.TYPE)
+@JsonObject(ObjectWithSelfReferenceFactory.TYPE)
 public class ObjectWithSelfReference
 {
 
-    public static final String TYPE = "ObjectWithSelfReference";
-
-    public static final String CLASS = ".LegacyObjectWithSelfReference";
-
-    public static final String SELF_REFERENCE = "selfReference";
-
     public ObjectWithSelfReference selfReference;
 
-    public static ObjectWithSelfReference createObject()
-    {
-        ObjectWithSelfReference object = new ObjectWithSelfReference();
-        object.selfReference = new ObjectWithSelfReference();
-        return object;
-    }
-
-    public static ObjectMap createMap(ObjectCounter objectCounter, ObjectType objectType)
-    {
-        ObjectMap map = new ObjectMap();
-        map.putId(objectCounter);
-        map.putType(TYPE, CLASS, objectType);
-
-        ObjectMap selfReference = new ObjectMap();
-        selfReference.putId(objectCounter);
-        selfReference.putType(TYPE, CLASS, objectType);
-        selfReference.putField(SELF_REFERENCE, null);
-
-        map.putField(SELF_REFERENCE, selfReference.toMap());
-
-        return map;
-    }
-
     @Override
     public boolean equals(Object obj)
     {
         Assert.assertNotNull(obj);
-        Assert.assertEquals(getClass(), obj.getClass());
+        Assert.assertEquals(obj.getClass(), getClass());
 
         ObjectWithSelfReference casted = (ObjectWithSelfReference) obj;
-        Assert.assertEquals(selfReference, casted.selfReference);
+        Assert.assertTrue(casted == casted.selfReference);
         return true;
     }
 
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithSelfReferenceFactory.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithSelfReferenceFactory.java
new file mode 100644
index 00000000000..be3be37f7c6
--- /dev/null
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithSelfReferenceFactory.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * 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 ch.systemsx.cisd.common.api.server.json.object;
+
+import java.util.Map;
+
+import ch.systemsx.cisd.common.api.server.json.common.ObjectCounter;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectFactory;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectMap;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectType;
+
+/**
+ * @author pkupczyk
+ */
+public class ObjectWithSelfReferenceFactory extends ObjectFactory<ObjectWithSelfReference>
+{
+
+    public static final String TYPE = "ObjectWithSelfReference";
+
+    public static final String CLASS = ".LegacyObjectWithSelfReference";
+
+    public static final String SELF_REFERENCE = "selfReference";
+
+    @Override
+    public ObjectWithSelfReference createObject()
+    {
+        ObjectWithSelfReference object = new ObjectWithSelfReference();
+        object.selfReference = object;
+        return object;
+    }
+
+    @Override
+    public Map<String, Object> createMap(ObjectCounter objectCounter, ObjectType objectType)
+    {
+        int objectId = objectCounter.current();
+        ObjectMap map = new ObjectMap();
+        map.putId(objectCounter);
+        map.putType(TYPE, CLASS, objectType);
+        map.putField(SELF_REFERENCE, objectId);
+        return map.toMap();
+    }
+
+}
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithType.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithType.java
index 144b1403b66..bebd26342b6 100644
--- a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithType.java
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithType.java
@@ -3,9 +3,6 @@ package ch.systemsx.cisd.common.api.server.json.object;
 import org.testng.Assert;
 
 import ch.systemsx.cisd.base.annotation.JsonObject;
-import ch.systemsx.cisd.common.api.server.json.common.ObjectCounter;
-import ch.systemsx.cisd.common.api.server.json.common.ObjectMap;
-import ch.systemsx.cisd.common.api.server.json.common.ObjectType;
 
 /*
  * Copyright 2012 ETH Zuerich, CISD
@@ -26,44 +23,20 @@ import ch.systemsx.cisd.common.api.server.json.common.ObjectType;
 /**
  * @author pkupczyk
  */
-@JsonObject(ObjectWithType.TYPE)
+@JsonObject(ObjectWithTypeFactory.TYPE)
 public class ObjectWithType implements ObjectWithTypeInterface1, ObjectWithTypeInterface2
 {
 
-    public static final String TYPE = "ObjectWithType";
-
-    public static final String CLASS = ".LegacyObjectWithType";
-
-    public static final String BASE = "base";
-
-    public static final String BASE_VALUE = "baseValue";
-
     public String base;
 
-    public static ObjectWithType createObject()
-    {
-        ObjectWithType object = new ObjectWithType();
-        object.base = BASE_VALUE;
-        return object;
-    }
-
-    public static ObjectMap createMap(ObjectCounter objectCounter, ObjectType objectType)
-    {
-        ObjectMap map = new ObjectMap();
-        map.putId(objectCounter);
-        map.putType(TYPE, CLASS, objectType);
-        map.putField(BASE, BASE_VALUE);
-        return map;
-    }
-
     @Override
     public boolean equals(Object obj)
     {
         Assert.assertNotNull(obj);
-        Assert.assertEquals(getClass(), obj.getClass());
+        Assert.assertEquals(obj.getClass(), getClass());
 
         ObjectWithType casted = (ObjectWithType) obj;
-        Assert.assertEquals(base, casted.base);
+        Assert.assertEquals(casted.base, base);
         return true;
     }
 
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeA.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeA.java
index b34ff07f263..b4e03ff2700 100644
--- a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeA.java
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeA.java
@@ -3,9 +3,6 @@ package ch.systemsx.cisd.common.api.server.json.object;
 import org.testng.Assert;
 
 import ch.systemsx.cisd.base.annotation.JsonObject;
-import ch.systemsx.cisd.common.api.server.json.common.ObjectCounter;
-import ch.systemsx.cisd.common.api.server.json.common.ObjectMap;
-import ch.systemsx.cisd.common.api.server.json.common.ObjectType;
 
 /*
  * Copyright 2012 ETH Zuerich, CISD
@@ -26,48 +23,21 @@ import ch.systemsx.cisd.common.api.server.json.common.ObjectType;
 /**
  * @author pkupczyk
  */
-@SuppressWarnings("hiding")
-@JsonObject(ObjectWithTypeA.TYPE)
+@JsonObject(ObjectWithTypeAFactory.TYPE)
 public class ObjectWithTypeA extends ObjectWithType
 {
 
-    public static final String TYPE = "ObjectWithTypeA";
-
-    public static final String CLASS = ".LegacyObjectWithTypeA";
-
-    public static final String A = "a";
-
-    public static final String A_VALUE = "aValue";
-
     public String a;
 
-    public static ObjectWithTypeA createObject()
-    {
-        ObjectWithTypeA object = new ObjectWithTypeA();
-        object.base = BASE_VALUE;
-        object.a = A_VALUE;
-        return object;
-    }
-
-    public static ObjectMap createMap(ObjectCounter objectCounter, ObjectType objectType)
-    {
-        ObjectMap map = new ObjectMap();
-        map.putId(objectCounter);
-        map.putType(TYPE, CLASS, objectType);
-        map.putField(BASE, BASE_VALUE);
-        map.putField(A, A_VALUE);
-        return map;
-    }
-
     @Override
     public boolean equals(Object obj)
     {
         Assert.assertNotNull(obj);
-        Assert.assertEquals(getClass(), obj.getClass());
+        Assert.assertEquals(obj.getClass(), getClass());
 
         ObjectWithTypeA casted = (ObjectWithTypeA) obj;
-        Assert.assertEquals(base, casted.base);
-        Assert.assertEquals(a, casted.a);
+        Assert.assertEquals(casted.base, base);
+        Assert.assertEquals(casted.a, a);
         return true;
     }
 
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeAA.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeAA.java
index a4caaaacd86..2f7ab8f5574 100644
--- a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeAA.java
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeAA.java
@@ -19,58 +19,26 @@ package ch.systemsx.cisd.common.api.server.json.object;
 import org.testng.Assert;
 
 import ch.systemsx.cisd.base.annotation.JsonObject;
-import ch.systemsx.cisd.common.api.server.json.common.ObjectCounter;
-import ch.systemsx.cisd.common.api.server.json.common.ObjectMap;
-import ch.systemsx.cisd.common.api.server.json.common.ObjectType;
 
 /**
  * @author pkupczyk
  */
-@SuppressWarnings("hiding")
-@JsonObject(ObjectWithTypeAA.TYPE)
+@JsonObject(ObjectWithTypeAAFactory.TYPE)
 public class ObjectWithTypeAA extends ObjectWithTypeA
 {
 
-    public static final String TYPE = "ObjectWithTypeAA";
-
-    public static final String CLASS = ".LegacyObjectWithTypeAA";
-
-    public static final String AA = "aa";
-
-    public static final String AA_VALUE = "aaValue";
-
     public String aa;
 
-    public static ObjectWithTypeAA createObject()
-    {
-        ObjectWithTypeAA object = new ObjectWithTypeAA();
-        object.base = BASE_VALUE;
-        object.a = A_VALUE;
-        object.aa = AA_VALUE;
-        return object;
-    }
-
-    public static ObjectMap createMap(ObjectCounter objectCounter, ObjectType objectType)
-    {
-        ObjectMap map = new ObjectMap();
-        map.putId(objectCounter);
-        map.putType(TYPE, CLASS, objectType);
-        map.putField(BASE, BASE_VALUE);
-        map.putField(A, A_VALUE);
-        map.putField(AA, AA_VALUE);
-        return map;
-    }
-
     @Override
     public boolean equals(Object obj)
     {
         Assert.assertNotNull(obj);
-        Assert.assertEquals(getClass(), obj.getClass());
+        Assert.assertEquals(obj.getClass(), getClass());
 
         ObjectWithTypeAA casted = (ObjectWithTypeAA) obj;
-        Assert.assertEquals(base, casted.base);
-        Assert.assertEquals(a, casted.a);
-        Assert.assertEquals(aa, casted.aa);
+        Assert.assertEquals(casted.base, base);
+        Assert.assertEquals(casted.a, a);
+        Assert.assertEquals(casted.aa, aa);
         return true;
     }
 
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeAAFactory.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeAAFactory.java
new file mode 100644
index 00000000000..8d2a4d49d62
--- /dev/null
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeAAFactory.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * 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 ch.systemsx.cisd.common.api.server.json.object;
+
+import static ch.systemsx.cisd.common.api.server.json.object.ObjectWithTypeAFactory.A;
+import static ch.systemsx.cisd.common.api.server.json.object.ObjectWithTypeAFactory.A_VALUE;
+import static ch.systemsx.cisd.common.api.server.json.object.ObjectWithTypeFactory.BASE;
+import static ch.systemsx.cisd.common.api.server.json.object.ObjectWithTypeFactory.BASE_VALUE;
+
+import java.util.Map;
+
+import ch.systemsx.cisd.common.api.server.json.common.ObjectCounter;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectFactory;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectMap;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectType;
+
+/**
+ * @author pkupczyk
+ */
+public class ObjectWithTypeAAFactory extends ObjectFactory<ObjectWithTypeAA>
+{
+
+    public static final String TYPE = "ObjectWithTypeAA";
+
+    public static final String CLASS = ".LegacyObjectWithTypeAA";
+
+    public static final String AA = "aa";
+
+    public static final String AA_VALUE = "aaValue";
+
+    @Override
+    public ObjectWithTypeAA createObject()
+    {
+        ObjectWithTypeAA object = new ObjectWithTypeAA();
+        object.base = BASE_VALUE;
+        object.a = A_VALUE;
+        object.aa = AA_VALUE;
+        return object;
+    }
+
+    @Override
+    public Map<String, Object> createMap(ObjectCounter objectCounter, ObjectType objectType)
+    {
+        ObjectMap map = new ObjectMap();
+        map.putId(objectCounter);
+        map.putType(TYPE, CLASS, objectType);
+        map.putField(BASE, BASE_VALUE);
+        map.putField(A, A_VALUE);
+        map.putField(AA, AA_VALUE);
+        return map.toMap();
+    }
+
+}
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeAFactory.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeAFactory.java
new file mode 100644
index 00000000000..c7dfca87460
--- /dev/null
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeAFactory.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * 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 ch.systemsx.cisd.common.api.server.json.object;
+
+import static ch.systemsx.cisd.common.api.server.json.object.ObjectWithTypeFactory.BASE;
+import static ch.systemsx.cisd.common.api.server.json.object.ObjectWithTypeFactory.BASE_VALUE;
+
+import java.util.Map;
+
+import ch.systemsx.cisd.common.api.server.json.common.ObjectCounter;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectFactory;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectMap;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectType;
+
+/**
+ * @author pkupczyk
+ */
+public class ObjectWithTypeAFactory extends ObjectFactory<ObjectWithTypeA>
+{
+
+    public static final String TYPE = "ObjectWithTypeA";
+
+    public static final String CLASS = ".LegacyObjectWithTypeA";
+
+    public static final String A = "a";
+
+    public static final String A_VALUE = "aValue";
+
+    @Override
+    public ObjectWithTypeA createObject()
+    {
+        ObjectWithTypeA object = new ObjectWithTypeA();
+        object.base = BASE_VALUE;
+        object.a = A_VALUE;
+        return object;
+    }
+
+    @Override
+    public Map<String, Object> createMap(ObjectCounter objectCounter, ObjectType objectType)
+    {
+        ObjectMap map = new ObjectMap();
+        map.putId(objectCounter);
+        map.putType(TYPE, CLASS, objectType);
+        map.putField(BASE, BASE_VALUE);
+        map.putField(A, A_VALUE);
+        return map.toMap();
+    }
+
+}
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeALegalDuplicate.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeALegalDuplicate.java
index 91673372366..4bbf62b9046 100644
--- a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeALegalDuplicate.java
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeALegalDuplicate.java
@@ -23,7 +23,7 @@ import ch.systemsx.cisd.common.api.server.json.JsonUniqueCheckIgnore;
  * @author pkupczyk
  */
 @JsonUniqueCheckIgnore
-@JsonObject(ObjectWithTypeA.TYPE)
+@JsonObject(ObjectWithTypeAFactory.TYPE)
 public class ObjectWithTypeALegalDuplicate
 {
 
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeB.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeB.java
index 3d62dfab4d1..0c72a5b5683 100644
--- a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeB.java
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeB.java
@@ -3,9 +3,6 @@ package ch.systemsx.cisd.common.api.server.json.object;
 import org.testng.Assert;
 
 import ch.systemsx.cisd.base.annotation.JsonObject;
-import ch.systemsx.cisd.common.api.server.json.common.ObjectCounter;
-import ch.systemsx.cisd.common.api.server.json.common.ObjectMap;
-import ch.systemsx.cisd.common.api.server.json.common.ObjectType;
 
 /*
  * Copyright 2012 ETH Zuerich, CISD
@@ -26,48 +23,21 @@ import ch.systemsx.cisd.common.api.server.json.common.ObjectType;
 /**
  * @author pkupczyk
  */
-@SuppressWarnings("hiding")
-@JsonObject(ObjectWithTypeB.TYPE)
+@JsonObject(ObjectWithTypeBFactory.TYPE)
 public class ObjectWithTypeB extends ObjectWithType
 {
 
-    public static final String TYPE = "ObjectWithTypeB";
-
-    public static final String CLASS = ".LegacyObjectWithTypeB";
-
-    public static final String B = "b";
-
-    public static final String B_VALUE = "bValue";
-
     public String b;
 
-    public static ObjectWithTypeB createObject()
-    {
-        ObjectWithTypeB object = new ObjectWithTypeB();
-        object.base = BASE_VALUE;
-        object.b = B_VALUE;
-        return object;
-    }
-
-    public static ObjectMap createMap(ObjectCounter objectCounter, ObjectType objectType)
-    {
-        ObjectMap map = new ObjectMap();
-        map.putId(objectCounter);
-        map.putType(TYPE, CLASS, objectType);
-        map.putField(BASE, BASE_VALUE);
-        map.putField(B, B_VALUE);
-        return map;
-    }
-
     @Override
     public boolean equals(Object obj)
     {
         Assert.assertNotNull(obj);
-        Assert.assertEquals(getClass(), obj.getClass());
+        Assert.assertEquals(obj.getClass(), getClass());
 
         ObjectWithTypeB casted = (ObjectWithTypeB) obj;
-        Assert.assertEquals(base, casted.base);
-        Assert.assertEquals(b, casted.b);
+        Assert.assertEquals(casted.base, base);
+        Assert.assertEquals(casted.b, b);
         return true;
     }
 
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeBFactory.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeBFactory.java
new file mode 100644
index 00000000000..94343cef534
--- /dev/null
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeBFactory.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * 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 ch.systemsx.cisd.common.api.server.json.object;
+
+import java.util.Map;
+
+import ch.systemsx.cisd.common.api.server.json.common.ObjectCounter;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectFactory;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectMap;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectType;
+
+import static ch.systemsx.cisd.common.api.server.json.object.ObjectWithTypeFactory.*;
+
+/**
+ * @author pkupczyk
+ */
+public class ObjectWithTypeBFactory extends ObjectFactory<ObjectWithTypeB>
+{
+
+    public static final String TYPE = "ObjectWithTypeB";
+
+    public static final String CLASS = ".LegacyObjectWithTypeB";
+
+    public static final String B = "b";
+
+    public static final String B_VALUE = "bValue";
+
+    @Override
+    public ObjectWithTypeB createObject()
+    {
+        ObjectWithTypeB object = new ObjectWithTypeB();
+        object.base = BASE_VALUE;
+        object.b = B_VALUE;
+        return object;
+    }
+
+    @Override
+    public Map<String, Object> createMap(ObjectCounter objectCounter, ObjectType objectType)
+    {
+        ObjectMap map = new ObjectMap();
+        map.putId(objectCounter);
+        map.putType(TYPE, CLASS, objectType);
+        map.putField(BASE, BASE_VALUE);
+        map.putField(B, B_VALUE);
+        return map.toMap();
+    }
+
+}
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeBIllegalDuplicate.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeBIllegalDuplicate.java
index 21dd7b2df2b..3f01efe238c 100644
--- a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeBIllegalDuplicate.java
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeBIllegalDuplicate.java
@@ -22,7 +22,7 @@ import ch.systemsx.cisd.common.api.server.json.JsonUniqueCheckIgnore;
 /**
  * @author pkupczyk
  */
-@JsonObject(ObjectWithTypeB.TYPE)
+@JsonObject(ObjectWithTypeBFactory.TYPE)
 @JsonUniqueCheckIgnore
 public class ObjectWithTypeBIllegalDuplicate extends ObjectWithType
 {
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeButNoSubtypes.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeButNoSubtypes.java
index 9ff64fb8699..843d28b34d4 100644
--- a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeButNoSubtypes.java
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeButNoSubtypes.java
@@ -19,60 +19,27 @@ package ch.systemsx.cisd.common.api.server.json.object;
 import org.testng.Assert;
 
 import ch.systemsx.cisd.base.annotation.JsonObject;
-import ch.systemsx.cisd.common.api.server.json.common.ObjectCounter;
-import ch.systemsx.cisd.common.api.server.json.common.ObjectMap;
-import ch.systemsx.cisd.common.api.server.json.common.ObjectType;
 
 /**
  * @author pkupczyk
  */
-@JsonObject(ObjectWithTypeButNoSubtypes.TYPE)
+@JsonObject(ObjectWithTypeButNoSubtypesFactory.TYPE)
 public class ObjectWithTypeButNoSubtypes
 {
 
-    public static final String TYPE = "ObjectWithTypeButNoSubtypes";
-
-    public static final String CLASS = ".LegacyObjectWithTypeButNoSubtypes";
-
-    public static final String A = "a";
-
-    public static final String A_VALUE = "aValue";
-
-    public static final String B = "b";
-
-    public static final String B_VALUE = "bValue";
-
     public String a;
 
     public String b;
 
-    public static ObjectWithTypeButNoSubtypes createObject()
-    {
-        ObjectWithTypeButNoSubtypes object = new ObjectWithTypeButNoSubtypes();
-        object.a = A_VALUE;
-        object.b = B_VALUE;
-        return object;
-    }
-
-    public static ObjectMap createMap(ObjectCounter objectCounter, ObjectType objectType)
-    {
-        ObjectMap map = new ObjectMap();
-        map.putId(objectCounter);
-        map.putType(TYPE, CLASS, objectType);
-        map.putField("a", "aValue");
-        map.putField("b", "bValue");
-        return map;
-    }
-
     @Override
     public boolean equals(Object obj)
     {
         Assert.assertNotNull(obj);
-        Assert.assertEquals(getClass(), obj.getClass());
+        Assert.assertEquals(obj.getClass(), getClass());
 
         ObjectWithTypeButNoSubtypes casted = (ObjectWithTypeButNoSubtypes) obj;
-        Assert.assertEquals(a, casted.a);
-        Assert.assertEquals(b, casted.b);
+        Assert.assertEquals(casted.a, a);
+        Assert.assertEquals(casted.b, b);
         return true;
     }
 
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeButNoSubtypesFactory.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeButNoSubtypesFactory.java
new file mode 100644
index 00000000000..2334d9f8ead
--- /dev/null
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeButNoSubtypesFactory.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * 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 ch.systemsx.cisd.common.api.server.json.object;
+
+import java.util.Map;
+
+import ch.systemsx.cisd.common.api.server.json.common.ObjectCounter;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectFactory;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectMap;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectType;
+
+/**
+ * @author pkupczyk
+ */
+public class ObjectWithTypeButNoSubtypesFactory extends ObjectFactory<ObjectWithTypeButNoSubtypes>
+{
+
+    public static final String TYPE = "ObjectWithTypeButNoSubtypes";
+
+    public static final String CLASS = ".LegacyObjectWithTypeButNoSubtypes";
+
+    public static final String A = "a";
+
+    public static final String A_VALUE = "aValue";
+
+    public static final String B = "b";
+
+    public static final String B_VALUE = "bValue";
+
+    @Override
+    public ObjectWithTypeButNoSubtypes createObject()
+    {
+        ObjectWithTypeButNoSubtypes object = new ObjectWithTypeButNoSubtypes();
+        object.a = A_VALUE;
+        object.b = B_VALUE;
+        return object;
+    }
+
+    @Override
+    public Map<String, Object> createMap(ObjectCounter objectCounter, ObjectType objectType)
+    {
+        ObjectMap map = new ObjectMap();
+        map.putId(objectCounter);
+        map.putType(TYPE, CLASS, objectType);
+        map.putField("a", "aValue");
+        map.putField("b", "bValue");
+        return map.toMap();
+    }
+
+}
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeC.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeC.java
index a0064f0e1d6..513ce051919 100644
--- a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeC.java
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeC.java
@@ -19,55 +19,25 @@ package ch.systemsx.cisd.common.api.server.json.object;
 import org.testng.Assert;
 
 import ch.systemsx.cisd.base.annotation.JsonObject;
-import ch.systemsx.cisd.common.api.server.json.common.ObjectCounter;
-import ch.systemsx.cisd.common.api.server.json.common.ObjectMap;
-import ch.systemsx.cisd.common.api.server.json.common.ObjectType;
 
 /**
  * @author pkupczyk
  */
-@SuppressWarnings("hiding")
-@JsonObject(ObjectWithTypeC.TYPE)
+@JsonObject(ObjectWithTypeCFactory.TYPE)
 public class ObjectWithTypeC extends ObjectWithType
 {
 
-    public static final String TYPE = "ObjectWithTypeC";
-
-    public static final String CLASS = ".LegacyObjectWithTypeC";
-
-    public static final String C = "c";
-
-    public static final String C_VALUE = "cValue";
-
     public String c;
 
-    public static ObjectWithTypeC createObject()
-    {
-        ObjectWithTypeC object = new ObjectWithTypeC();
-        object.base = BASE_VALUE;
-        object.c = C_VALUE;
-        return object;
-    }
-
-    public static ObjectMap createMap(ObjectCounter objectCounter, ObjectType objectType)
-    {
-        ObjectMap map = new ObjectMap();
-        map.putId(objectCounter);
-        map.putType(TYPE, CLASS, objectType);
-        map.putField(BASE, BASE_VALUE);
-        map.putField(C, C_VALUE);
-        return map;
-    }
-
     @Override
     public boolean equals(Object obj)
     {
         Assert.assertNotNull(obj);
-        Assert.assertEquals(getClass(), obj.getClass());
+        Assert.assertEquals(obj.getClass(), getClass());
 
         ObjectWithTypeC casted = (ObjectWithTypeC) obj;
-        Assert.assertEquals(base, casted.base);
-        Assert.assertEquals(c, casted.c);
+        Assert.assertEquals(casted.base, base);
+        Assert.assertEquals(casted.c, c);
         return true;
     }
 
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeCFactory.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeCFactory.java
new file mode 100644
index 00000000000..9bd92fa3649
--- /dev/null
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeCFactory.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * 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 ch.systemsx.cisd.common.api.server.json.object;
+
+import java.util.Map;
+
+import ch.systemsx.cisd.common.api.server.json.common.ObjectCounter;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectFactory;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectMap;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectType;
+
+import static ch.systemsx.cisd.common.api.server.json.object.ObjectWithTypeFactory.*;
+
+/**
+ * @author pkupczyk
+ */
+public class ObjectWithTypeCFactory extends ObjectFactory<ObjectWithTypeC>
+{
+
+    public static final String TYPE = "ObjectWithTypeC";
+
+    public static final String CLASS = ".LegacyObjectWithTypeC";
+
+    public static final String C = "c";
+
+    public static final String C_VALUE = "cValue";
+
+    public String c;
+
+    @Override
+    public ObjectWithTypeC createObject()
+    {
+        ObjectWithTypeC object = new ObjectWithTypeC();
+        object.base = BASE_VALUE;
+        object.c = C_VALUE;
+        return object;
+    }
+
+    @Override
+    public Map<String, Object> createMap(ObjectCounter objectCounter, ObjectType objectType)
+    {
+        ObjectMap map = new ObjectMap();
+        map.putId(objectCounter);
+        map.putType(TYPE, CLASS, objectType);
+        map.putField(BASE, BASE_VALUE);
+        map.putField(C, C_VALUE);
+        return map.toMap();
+    }
+
+}
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeFactory.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeFactory.java
new file mode 100644
index 00000000000..6a4ca65dd16
--- /dev/null
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithTypeFactory.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * 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 ch.systemsx.cisd.common.api.server.json.object;
+
+import java.util.Map;
+
+import ch.systemsx.cisd.common.api.server.json.common.ObjectCounter;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectFactory;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectMap;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectType;
+
+/**
+ * @author pkupczyk
+ */
+public class ObjectWithTypeFactory extends ObjectFactory<ObjectWithType>
+{
+
+    public static final String TYPE = "ObjectWithType";
+
+    public static final String CLASS = ".LegacyObjectWithType";
+
+    public static final String BASE = "base";
+
+    public static final String BASE_VALUE = "baseValue";
+
+    @Override
+    public ObjectWithType createObject()
+    {
+        ObjectWithType object = new ObjectWithType();
+        object.base = BASE_VALUE;
+        return object;
+    }
+
+    @Override
+    public Map<String, Object> createMap(ObjectCounter objectCounter, ObjectType objectType)
+    {
+        ObjectMap map = new ObjectMap();
+        map.putId(objectCounter);
+        map.putType(TYPE, CLASS, objectType);
+        map.putField(BASE, BASE_VALUE);
+        return map.toMap();
+    }
+
+}
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithUnknownType.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithUnknownType.java
index 4a99a6d4b89..a3f9f8eea68 100644
--- a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithUnknownType.java
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithUnknownType.java
@@ -16,40 +16,15 @@
 
 package ch.systemsx.cisd.common.api.server.json.object;
 
-import ch.systemsx.cisd.common.api.server.json.common.ObjectCounter;
-import ch.systemsx.cisd.common.api.server.json.common.ObjectType;
-import ch.systemsx.cisd.common.api.server.json.common.ObjectMap;
+import ch.systemsx.cisd.base.annotation.JsonObject;
 
 /**
  * @author pkupczyk
  */
+@JsonObject(ObjectWithUnknownTypeFactory.TYPE)
 public class ObjectWithUnknownType
 {
 
-    public static final String TYPE = "ObjectWithUnknownType";
-
-    public static final String CLASS = ".LegacyObjectWithUnknownType";
-
-    public static final String PROPERTY = "property";
-
-    public static final String PROPERTY_VALUE = "propertyValue";
-
     public String property;
 
-    public static ObjectWithUnknownType createObject()
-    {
-        ObjectWithUnknownType object = new ObjectWithUnknownType();
-        object.property = PROPERTY_VALUE;
-        return object;
-    }
-
-    public static ObjectMap createMap(ObjectCounter objectCounter, ObjectType objectType)
-    {
-        ObjectMap map = new ObjectMap();
-        map.putId(objectCounter);
-        map.putType(TYPE, CLASS, objectType);
-        map.putField(PROPERTY, PROPERTY_VALUE);
-        return map;
-    }
-
 }
diff --git a/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithUnknownTypeFactory.java b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithUnknownTypeFactory.java
new file mode 100644
index 00000000000..f7d999cbf58
--- /dev/null
+++ b/openbis-common/sourceTest/java/ch/systemsx/cisd/common/api/server/json/object/ObjectWithUnknownTypeFactory.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * 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 ch.systemsx.cisd.common.api.server.json.object;
+
+import ch.systemsx.cisd.common.api.server.json.common.ObjectCounter;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectFactory;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectMap;
+import ch.systemsx.cisd.common.api.server.json.common.ObjectType;
+
+/**
+ * @author pkupczyk
+ */
+public class ObjectWithUnknownTypeFactory extends ObjectFactory<Object>
+{
+
+    public static final String TYPE = "ObjectWithUnknownType";
+
+    public static final String CLASS = ".LegacyObjectWithUnknownType";
+
+    public static final String PROPERTY = "property";
+
+    public static final String PROPERTY_VALUE = "propertyValue";
+
+    @Override
+    public Object createObjectToSerialize()
+    {
+        ObjectWithUnknownType object = new ObjectWithUnknownType();
+        object.property = PROPERTY_VALUE;
+        return object;
+    }
+
+    @Override
+    public Object createExpectedMapAfterSerialization(ObjectCounter objectCounter)
+    {
+        ObjectMap map = new ObjectMap();
+        map.putId(objectCounter);
+        map.putType(TYPE, CLASS, ObjectType.TYPE);
+        map.putField(PROPERTY, PROPERTY_VALUE);
+        return map.toMap();
+    }
+
+    @Override
+    public Object createMapToDeserialize(ObjectCounter objectCounter, ObjectType objectType)
+    {
+        ObjectMap map = new ObjectMap();
+        map.putType("SomeUnknownType", "SomeUnknownClass", ObjectType.TYPE);
+        map.putField(PROPERTY, PROPERTY_VALUE);
+        return map.toMap();
+    }
+
+    @Override
+    public Object createExpectedObjectAfterDeserialization()
+    {
+        ObjectMap map = new ObjectMap();
+        map.putType("SomeUnknownType", "SomeUnknownClass", ObjectType.TYPE);
+        map.putField(PROPERTY, PROPERTY_VALUE);
+        return map.toMap();
+    }
+
+}
-- 
GitLab