polygene-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From paulmer...@apache.org
Subject [3/7] polygene-java git commit: POLYGENE-247 Change Entity state JSON serialization format
Date Sun, 23 Apr 2017 11:07:33 GMT
http://git-wip-us.apache.org/repos/asf/polygene-java/blob/b2ff271b/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonSerializer.java
----------------------------------------------------------------------
diff --git a/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonSerializer.java b/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonSerializer.java
index 1835dce..02b88a9 100644
--- a/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonSerializer.java
+++ b/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonSerializer.java
@@ -35,7 +35,9 @@ import javax.json.JsonValue;
 import org.apache.polygene.api.PolygeneAPI;
 import org.apache.polygene.api.association.AssociationStateHolder;
 import org.apache.polygene.api.common.Optional;
+import org.apache.polygene.api.composite.Composite;
 import org.apache.polygene.api.composite.CompositeInstance;
+import org.apache.polygene.api.composite.StatefulAssociationCompositeDescriptor;
 import org.apache.polygene.api.injection.scope.Structure;
 import org.apache.polygene.api.injection.scope.This;
 import org.apache.polygene.api.injection.scope.Uses;
@@ -43,15 +45,13 @@ import org.apache.polygene.api.mixin.Initializable;
 import org.apache.polygene.api.serialization.ConvertedBy;
 import org.apache.polygene.api.serialization.Converter;
 import org.apache.polygene.api.serialization.Converters;
+import org.apache.polygene.api.serialization.SerializationException;
 import org.apache.polygene.api.service.ServiceDescriptor;
 import org.apache.polygene.api.structure.Module;
 import org.apache.polygene.api.type.ArrayType;
 import org.apache.polygene.api.type.MapType;
-import org.apache.polygene.api.type.ValueCompositeType;
+import org.apache.polygene.api.type.StatefulAssociationValueType;
 import org.apache.polygene.api.type.ValueType;
-import org.apache.polygene.api.util.Annotations;
-import org.apache.polygene.api.value.ValueComposite;
-import org.apache.polygene.api.value.ValueDescriptor;
 import org.apache.polygene.spi.serialization.AbstractTextSerializer;
 import org.apache.polygene.spi.serialization.JsonSerializer;
 import org.apache.polygene.spi.util.ArrayIterable;
@@ -127,11 +127,6 @@ public class JavaxJsonSerializer extends AbstractTextSerializer
             return JsonValue.NULL;
         }
         Class<?> objectClass = object.getClass();
-        ConvertedBy convertedBy = Annotations.annotationOn( objectClass, ConvertedBy.class );
-        if( convertedBy != null )
-        {
-            return doSerialize( options, module.newObject( convertedBy.value() ).toString( object ), false );
-        }
         Converter<Object> converter = converters.converterFor( objectClass );
         if( converter != null )
         {
@@ -140,12 +135,11 @@ public class JavaxJsonSerializer extends AbstractTextSerializer
         JavaxJsonAdapter<?> adapter = adapters.adapterFor( objectClass );
         if( adapter != null )
         {
-            return adapter.serialize( jsonFactories.builderFactory(), object,
-                                      obj -> doSerialize( options, obj, false ) );
+            return adapter.serialize( jsonFactories, object, obj -> doSerialize( options, obj, false ) );
         }
-        if( ValueCompositeType.isValueComposite( objectClass ) )
+        if( StatefulAssociationValueType.isStatefulAssociationValue( objectClass ) )
         {
-            return serializeValueComposite( options, object, root );
+            return serializeStatefulAssociationValue( options, object, root );
         }
         if( MapType.isMap( objectClass ) )
         {
@@ -163,17 +157,16 @@ public class JavaxJsonSerializer extends AbstractTextSerializer
         {
             return serializeStream( options, (Stream<?>) object );
         }
-        // Fallback to Java Serialization in Base 64
-        byte[] bytes = Base64.getEncoder().encode( serializeJava( object ) );
-        return JavaxJson.toJsonString( new String( bytes, UTF_8 ) );
+        throw new SerializationException( "Don't know how to serialize " + object );
     }
 
-    private JsonObject serializeValueComposite( Options options, Object composite, boolean root )
+    private JsonObject serializeStatefulAssociationValue( Options options, Object composite, boolean root )
     {
-        CompositeInstance instance = PolygeneAPI.FUNCTION_COMPOSITE_INSTANCE_OF.apply( (ValueComposite) composite );
-        ValueDescriptor descriptor = (ValueDescriptor) instance.descriptor();
+        CompositeInstance instance = PolygeneAPI.FUNCTION_COMPOSITE_INSTANCE_OF.apply( (Composite) composite );
+        StatefulAssociationCompositeDescriptor descriptor =
+            (StatefulAssociationCompositeDescriptor) instance.descriptor();
         AssociationStateHolder state = (AssociationStateHolder) instance.state();
-        ValueCompositeType valueType = descriptor.valueType();
+        StatefulAssociationValueType<?> valueType = descriptor.valueType();
 
         JsonObjectBuilder builder = jsonFactories.builderFactory().createObjectBuilder();
         valueType.properties().forEach(
@@ -204,16 +197,16 @@ public class JavaxJsonSerializer extends AbstractTextSerializer
                              state.namedAssociationFor( association.accessor() ).references()
                                   .collect( toMap() ),
                              false ) ) );
-        if( !root && options.includeTypeInfo() )
+        if( ( root && options.rootTypeInfo() ) || ( !root && options.nestedTypeInfo() ) )
         {
             withTypeInfo( builder, valueType );
         }
         return builder.build();
     }
 
-    private JsonObjectBuilder withTypeInfo( JsonObjectBuilder builder, ValueType valueType )
+    private void withTypeInfo( JsonObjectBuilder builder, ValueType valueType )
     {
-        return builder.add( settings.getTypeInfoPropertyName(), valueType.primaryType().getName() );
+        builder.add( settings.getTypeInfoPropertyName(), valueType.primaryType().getName() );
     }
 
     /**
@@ -258,7 +251,7 @@ public class JavaxJsonSerializer extends AbstractTextSerializer
         if( valueType.isArrayOfPrimitiveBytes() )
         {
             byte[] base64 = Base64.getEncoder().encode( (byte[]) object );
-            return JavaxJson.toJsonString( new String( base64, UTF_8 ) );
+            return jsonFactories.toJsonString( new String( base64, UTF_8 ) );
         }
         if( valueType.isArrayOfPrimitives() )
         {

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/b2ff271b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/JSONEntityState.java
----------------------------------------------------------------------
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/JSONEntityState.java b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/JSONEntityState.java
index 151f144..0c38436 100644
--- a/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/JSONEntityState.java
+++ b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/JSONEntityState.java
@@ -18,22 +18,20 @@
 package org.apache.polygene.spi.entitystore.helpers;
 
 import java.time.Instant;
-import java.util.Map;
-import javax.json.Json;
+import java.util.Objects;
 import javax.json.JsonArray;
 import javax.json.JsonArrayBuilder;
 import javax.json.JsonObject;
 import javax.json.JsonObjectBuilder;
+import javax.json.JsonString;
 import javax.json.JsonValue;
 import org.apache.polygene.api.common.QualifiedName;
 import org.apache.polygene.api.entity.EntityDescriptor;
 import org.apache.polygene.api.entity.EntityReference;
-import org.apache.polygene.api.property.PropertyDescriptor;
 import org.apache.polygene.api.serialization.SerializationException;
 import org.apache.polygene.api.structure.ModuleDescriptor;
 import org.apache.polygene.api.type.ValueType;
-import org.apache.polygene.api.value.ValueDescriptor;
-import org.apache.polygene.serialization.javaxjson.JavaxJson;
+import org.apache.polygene.serialization.javaxjson.JavaxJsonFactories;
 import org.apache.polygene.spi.entity.EntityState;
 import org.apache.polygene.spi.entity.EntityStatus;
 import org.apache.polygene.spi.entity.ManyAssociationState;
@@ -41,26 +39,20 @@ import org.apache.polygene.spi.entity.NamedAssociationState;
 import org.apache.polygene.spi.entitystore.EntityStoreException;
 import org.apache.polygene.spi.serialization.JsonSerialization;
 
+import static org.apache.polygene.api.serialization.Serializer.Options.ALL_TYPE_INFO;
+
 /**
  * Standard JSON implementation of EntityState.
  */
 public final class JSONEntityState
     implements EntityState
 {
-    private static final String[] CLONE_NAMES =
-        {
-            JSONKeys.IDENTITY,
-            JSONKeys.APPLICATION_VERSION,
-            JSONKeys.TYPE,
-            JSONKeys.VERSION,
-            JSONKeys.MODIFIED
-        };
-
     private final ModuleDescriptor module;
     private final String version;
     private final EntityReference reference;
     private final EntityDescriptor entityDescriptor;
     private final JsonSerialization serialization;
+    private final JavaxJsonFactories jsonFactories;
 
     private EntityStatus status;
     private Instant lastModified;
@@ -68,6 +60,7 @@ public final class JSONEntityState
 
     /* package */ JSONEntityState( ModuleDescriptor module,
                                    JsonSerialization serialization,
+                                   JavaxJsonFactories jsonFactories,
                                    String version,
                                    Instant lastModified,
                                    EntityReference reference,
@@ -78,6 +71,7 @@ public final class JSONEntityState
     {
         this.module = module;
         this.serialization = serialization;
+        this.jsonFactories = jsonFactories;
         this.version = version;
         this.lastModified = lastModified;
         this.reference = reference;
@@ -110,45 +104,9 @@ public final class JSONEntityState
     {
         try
         {
-            JsonValue json = state.getJsonObject( JSONKeys.PROPERTIES ).get( stateName.name() );
-            if( json == null || JsonValue.NULL.equals( json ) )
-            {
-                return null;
-            }
-            else
-            {
-                // TODO This rely on _type explicitely :(
-                // Needed because of this mess that is JsonEntityState
-                ValueType propertyValueType = null;
-                ModuleDescriptor propertyModule = module;
-                if( json.getValueType() == JsonValue.ValueType.OBJECT )
-                {
-                    String typeInfo = ( (JsonObject) json ).getString( "_type", null );
-                    if( typeInfo != null )
-                    {
-                        ValueDescriptor valueDescriptor = module.valueDescriptor( typeInfo );
-                        if( valueDescriptor != null )
-                        {
-                            propertyValueType = valueDescriptor.valueType();
-                            propertyModule = valueDescriptor.module();
-                        }
-                    }
-                }
-                if( propertyValueType == null )
-                {
-                    PropertyDescriptor descriptor = entityDescriptor.state()
-                                                                    .findPropertyModelByQualifiedName( stateName );
-                    if( descriptor != null )
-                    {
-                        propertyValueType = descriptor.valueType();
-                    }
-                }
-                if( propertyValueType == null )
-                {
-                    return null;
-                }
-                return serialization.fromJson( propertyModule, propertyValueType, json );
-            }
+            ValueType valueType = entityDescriptor.state().findPropertyModelByQualifiedName( stateName ).valueType();
+            JsonValue jsonValue = state.getJsonObject( JSONKeys.VALUE ).get( stateName.name() );
+            return serialization.fromJson( module, valueType, jsonValue );
         }
         catch( SerializationException e )
         {
@@ -161,9 +119,11 @@ public final class JSONEntityState
     {
         try
         {
-            JsonValue jsonValue = serialization.toJson( newValue );
-            stateCloneWithProperty( stateName.name(), jsonValue );
-            markUpdated();
+            JsonValue jsonValue = serialization.toJson( ALL_TYPE_INFO, newValue );
+            if( stateCloneWithProperty( stateName.name(), jsonValue ) )
+            {
+                markUpdated();
+            }
         }
         catch( SerializationException e )
         {
@@ -174,31 +134,33 @@ public final class JSONEntityState
     @Override
     public EntityReference associationValueOf( QualifiedName stateName )
     {
-        String jsonValue = state.getJsonObject( JSONKeys.ASSOCIATIONS ).getString( stateName.name(), null );
-        if( jsonValue == null )
+        JsonValue associationValue = state.getJsonObject( JSONKeys.VALUE ).get( stateName.name() );
+        if( associationValue == JsonValue.NULL )
         {
             return null;
         }
-        return EntityReference.parseEntityReference( jsonValue );
+        return EntityReference.parseEntityReference( ( (JsonString) associationValue ).getString() );
     }
 
     @Override
-    public void setAssociationValue( QualifiedName stateName, EntityReference newEntity )
+    public void setAssociationValue( QualifiedName stateName, EntityReference entityReference )
     {
-        stateCloneWithAssociation( stateName.name(), newEntity );
-        markUpdated();
+        if( stateCloneWithAssociation( stateName.name(), entityReference ) )
+        {
+            markUpdated();
+        }
     }
 
     @Override
     public ManyAssociationState manyAssociationValueOf( QualifiedName stateName )
     {
-        return new JSONManyAssociationState( this, stateName.name() );
+        return new JSONManyAssociationState( jsonFactories, this, stateName.name() );
     }
 
     @Override
     public NamedAssociationState namedAssociationValueOf( QualifiedName stateName )
     {
-        return new JSONNamedAssociationState( this, stateName.name() );
+        return new JSONNamedAssociationState( jsonFactories, this, stateName.name() );
     }
 
     @Override
@@ -233,7 +195,7 @@ public final class JSONEntityState
     @Override
     public String toString()
     {
-        return reference + "(" + state + ")";
+        return state.toString();
     }
 
     void markUpdated()
@@ -246,215 +208,133 @@ public final class JSONEntityState
 
     void stateCloneWithVersionAndModified( String version, Instant lastModified )
     {
-        JsonObjectBuilder builder = JavaxJson.toBuilder( state );
-        builder.add( JSONKeys.VERSION, version );
-        builder.add( JSONKeys.MODIFIED, lastModified.toEpochMilli() );
-        state = builder.build();
+        state = jsonFactories.cloneBuilderExclude( state, JSONKeys.VERSION, JSONKeys.MODIFIED )
+                             .add( JSONKeys.VERSION, version )
+                             .add( JSONKeys.MODIFIED, lastModified.toEpochMilli() )
+                             .build();
     }
 
-    void stateCloneWithProperty( String stateName, JsonValue value )
+    private boolean stateCloneWithProperty( String stateName, JsonValue value )
     {
-        JsonObjectBuilder builder = stateShallowClone();
-        JsonObjectBuilder propertiesBuilder = JavaxJson.toBuilder( state.getJsonObject( JSONKeys.PROPERTIES ) );
+        JsonObject valueState = state.getJsonObject( JSONKeys.VALUE );
+        if( Objects.equals( valueState.get( stateName ), value ) )
+        {
+            return false;
+        }
+        JsonObjectBuilder valueBuilder = jsonFactories.cloneBuilderExclude( valueState, stateName );
         if( value == null )
         {
-            propertiesBuilder.add( stateName, JsonValue.NULL );
+            valueBuilder.addNull( stateName );
         }
         else
         {
-            propertiesBuilder.add( stateName, value );
+            valueBuilder.add( stateName, value );
         }
-        builder.add( JSONKeys.PROPERTIES, propertiesBuilder.build() );
-        builder.add( JSONKeys.ASSOCIATIONS, state.get( JSONKeys.ASSOCIATIONS ) );
-        builder.add( JSONKeys.MANY_ASSOCIATIONS, state.get( JSONKeys.MANY_ASSOCIATIONS ) );
-        builder.add( JSONKeys.NAMED_ASSOCIATIONS, state.get( JSONKeys.NAMED_ASSOCIATIONS ) );
-        state = builder.build();
+        state = jsonFactories.cloneBuilderExclude( state, JSONKeys.VALUE )
+                             .add( JSONKeys.VALUE, valueBuilder.build() )
+                             .build();
+        return true;
     }
 
-    void stateCloneWithAssociation( String stateName, EntityReference ref )
+    private boolean stateCloneWithAssociation( String stateName, EntityReference ref )
     {
-        JsonObjectBuilder builder = stateShallowClone();
-        JsonObjectBuilder assocBuilder = JavaxJson.toBuilder( state.getJsonObject( JSONKeys.ASSOCIATIONS ) );
-        if( ref == null )
+        JsonObject valueState = state.getJsonObject( JSONKeys.VALUE );
+        JsonValue jsonRef = ref == null ? JsonValue.NULL : jsonFactories.toJsonString( ref.identity().toString() );
+        if( Objects.equals( valueState.get( stateName ), jsonRef ) )
         {
-            assocBuilder.add( stateName, JsonValue.NULL );
+            return false;
         }
-        else
-        {
-            assocBuilder.add( stateName, ref.identity().toString() );
-        }
-        builder.add( JSONKeys.PROPERTIES, state.get( JSONKeys.PROPERTIES ) );
-        builder.add( JSONKeys.ASSOCIATIONS, assocBuilder.build() );
-        builder.add( JSONKeys.MANY_ASSOCIATIONS, state.get( JSONKeys.MANY_ASSOCIATIONS ) );
-        builder.add( JSONKeys.NAMED_ASSOCIATIONS, state.get( JSONKeys.NAMED_ASSOCIATIONS ) );
-        state = builder.build();
+        valueState = jsonFactories.cloneBuilderExclude( valueState, stateName )
+                                  .add( stateName, jsonRef )
+                                  .build();
+        state = jsonFactories.cloneBuilderExclude( state, JSONKeys.VALUE )
+                             .add( JSONKeys.VALUE, valueState )
+                             .build();
+        return true;
     }
 
     void stateCloneAddManyAssociation( int idx, String stateName, EntityReference ref )
     {
-        JsonObjectBuilder builder = stateShallowClone();
-        JsonObjectBuilder manyAssociations = Json.createObjectBuilder();
-        JsonObject previousManyAssociations = state.getJsonObject( JSONKeys.MANY_ASSOCIATIONS );
-        for( Map.Entry<String, JsonValue> previousManyAssociation : previousManyAssociations.entrySet() )
+        JsonObject valueState = state.getJsonObject( JSONKeys.VALUE );
+        String identity = ref.identity().toString();
+        JsonArray manyAssoc;
+        if( valueState.containsKey( stateName ) )
         {
-            String key = previousManyAssociation.getKey();
-            if( !key.equals( stateName ) )
+            JsonArrayBuilder manyAssocBuilder = jsonFactories.builderFactory().createArrayBuilder();
+            JsonArray previousManyAssoc = valueState.getJsonArray( stateName );
+            int currentIdx = 0;
+            for( JsonValue jsonRef : previousManyAssoc )
             {
-                manyAssociations.add( key, previousManyAssociation.getValue() );
-            }
-        }
-        JsonValue previousReferences = previousManyAssociations.get( stateName );
-        JsonArrayBuilder references = Json.createArrayBuilder();
-        String newRef = ref.identity().toString();
-        if( previousReferences == null || previousReferences.getValueType() != JsonValue.ValueType.ARRAY )
-        {
-            references.add( newRef );
-        }
-        else
-        {
-            JsonArray previousReferencesArray = (JsonArray) previousReferences;
-            boolean insert = !previousReferencesArray.contains( newRef );
-            for( int i = 0; i < previousReferencesArray.size(); i++ )
-            {
-                if( insert && i == idx )
+                if( currentIdx == idx )
                 {
-                    references.add( newRef );
+                    manyAssocBuilder.add( identity );
                 }
-                references.add( previousReferencesArray.getString( i ) );
+                manyAssocBuilder.add( jsonRef );
+                currentIdx++;
             }
-            if( insert && idx >= previousReferencesArray.size() )
+            if( idx >= previousManyAssoc.size() )
             {
-                references.add( newRef );
+                manyAssocBuilder.add( identity );
             }
+            manyAssoc = manyAssocBuilder.build();
+        }
+        else
+        {
+            manyAssoc = jsonFactories.builderFactory().createArrayBuilder().add( identity ).build();
         }
-        manyAssociations.add( stateName, references.build() );
-        builder.add( JSONKeys.PROPERTIES, state.get( JSONKeys.PROPERTIES ) );
-        builder.add( JSONKeys.ASSOCIATIONS, state.get( JSONKeys.ASSOCIATIONS ) );
-        builder.add( JSONKeys.MANY_ASSOCIATIONS, manyAssociations.build() );
-        builder.add( JSONKeys.NAMED_ASSOCIATIONS, state.get( JSONKeys.NAMED_ASSOCIATIONS ) );
-        state = builder.build();
+        valueState = jsonFactories.cloneBuilderExclude( valueState, stateName )
+                                  .add( stateName, manyAssoc )
+                                  .build();
+        state = jsonFactories.cloneBuilderExclude( state, JSONKeys.VALUE )
+                             .add( JSONKeys.VALUE, valueState )
+                             .build();
     }
 
     void stateCloneRemoveManyAssociation( String stateName, EntityReference ref )
     {
-        String stringRef = ref.identity().toString();
-        JsonObjectBuilder builder = stateShallowClone();
-        JsonObjectBuilder manyAssociations = Json.createObjectBuilder();
-        JsonObject previousManyAssociations = state.getJsonObject( JSONKeys.MANY_ASSOCIATIONS );
-        for( Map.Entry<String, JsonValue> previousManyAssociation : previousManyAssociations.entrySet() )
+        JsonObject valueState = state.getJsonObject( JSONKeys.VALUE );
+        if( valueState.containsKey( stateName ) )
         {
-            String key = previousManyAssociation.getKey();
-            if( !key.equals( stateName ) )
-            {
-                manyAssociations.add( key, previousManyAssociation.getValue() );
-            }
+            String identity = ref.identity().toString();
+            JsonArray manyAssoc = jsonFactories.cloneBuilderExclude( valueState.getJsonArray( stateName ),
+                                                                     jsonFactories.toJsonString( identity ) )
+                                               .build();
+            valueState = jsonFactories.cloneBuilderExclude( valueState, stateName )
+                                      .add( stateName, manyAssoc ).build();
+            state = jsonFactories.cloneBuilderExclude( state, JSONKeys.VALUE )
+                                 .add( JSONKeys.VALUE, valueState )
+                                 .build();
         }
-        JsonValue previousReferences = previousManyAssociations.get( stateName );
-        JsonArrayBuilder references = Json.createArrayBuilder();
-        if( previousReferences != null && previousReferences.getValueType() == JsonValue.ValueType.ARRAY )
-        {
-            JsonArray previousReferencesArray = (JsonArray) previousReferences;
-            for( int idx = 0; idx < previousReferencesArray.size(); idx++ )
-            {
-                String previousRef = previousReferencesArray.getString( idx );
-                if( !stringRef.equals( previousRef ) )
-                {
-                    references.add( previousRef );
-                }
-            }
-        }
-        manyAssociations.add( stateName, references.build() );
-        builder.add( JSONKeys.PROPERTIES, state.get( JSONKeys.PROPERTIES ) );
-        builder.add( JSONKeys.ASSOCIATIONS, state.get( JSONKeys.ASSOCIATIONS ) );
-        builder.add( JSONKeys.MANY_ASSOCIATIONS, manyAssociations.build() );
-        builder.add( JSONKeys.NAMED_ASSOCIATIONS, state.get( JSONKeys.NAMED_ASSOCIATIONS ) );
-        state = builder.build();
     }
 
     void stateCloneAddNamedAssociation( String stateName, String name, EntityReference ref )
     {
-        JsonObjectBuilder builder = stateShallowClone();
-        JsonObject previousNamedAssociations = state.getJsonObject( JSONKeys.NAMED_ASSOCIATIONS );
-        JsonObjectBuilder namedAssociations = Json.createObjectBuilder();
-        for( Map.Entry<String, JsonValue> previousNamedAssociation : previousNamedAssociations.entrySet() )
-        {
-            String key = previousNamedAssociation.getKey();
-            if( !key.equals( stateName ) )
-            {
-                namedAssociations.add( key, previousNamedAssociation.getValue() );
-            }
-        }
-        JsonValue previousReferences = previousNamedAssociations.get( stateName );
-        JsonObjectBuilder references = Json.createObjectBuilder();
-        String newRef = ref.identity().toString();
-        if( previousReferences == null || !( previousReferences instanceof JsonObject ) )
-        {
-            references.add( name, newRef );
-        }
-        else
-        {
-            JsonObject previousReferencesObject = (JsonObject) previousReferences;
-            for( Map.Entry<String, JsonValue> previousNamedReference : previousReferencesObject.entrySet() )
-            {
-                String key = previousNamedReference.getKey();
-                if( !key.equals( name ) )
-                {
-                    references.add( key, previousNamedReference.getValue() );
-                }
-            }
-            references.add( name, ref.identity().toString() );
-        }
-        namedAssociations.add( stateName, references.build() );
-        builder.add( JSONKeys.PROPERTIES, state.get( JSONKeys.PROPERTIES ) );
-        builder.add( JSONKeys.ASSOCIATIONS, state.get( JSONKeys.ASSOCIATIONS ) );
-        builder.add( JSONKeys.MANY_ASSOCIATIONS, state.get( JSONKeys.MANY_ASSOCIATIONS ) );
-        builder.add( JSONKeys.NAMED_ASSOCIATIONS, namedAssociations.build() );
-        state = builder.build();
+        JsonObject valueState = state.getJsonObject( JSONKeys.VALUE );
+        JsonObjectBuilder namedAssoc = valueState.containsKey( stateName )
+                                       ? jsonFactories.cloneBuilder( valueState.getJsonObject( stateName ) )
+                                       : jsonFactories.builderFactory().createObjectBuilder();
+        namedAssoc.add( name, ref.identity().toString() );
+        valueState = jsonFactories.cloneBuilderExclude( valueState, stateName )
+                                  .add( stateName, namedAssoc.build() )
+                                  .build();
+        state = jsonFactories.cloneBuilderExclude( state, JSONKeys.VALUE )
+                             .add( JSONKeys.VALUE, valueState )
+                             .build();
     }
 
     void stateCloneRemoveNamedAssociation( String stateName, String name )
     {
-        JsonObjectBuilder builder = stateShallowClone();
-        JsonObjectBuilder namedAssociations = Json.createObjectBuilder();
-        JsonObject previousNamedAssociations = state.getJsonObject( JSONKeys.NAMED_ASSOCIATIONS );
-        for( Map.Entry<String, JsonValue> previousNamedAssociation : previousNamedAssociations.entrySet() )
-        {
-            String key = previousNamedAssociation.getKey();
-            if( !key.equals( stateName ) )
-            {
-                namedAssociations.add( key, previousNamedAssociation.getValue() );
-            }
-        }
-        JsonValue previousReferences = previousNamedAssociations.get( stateName );
-        JsonObjectBuilder references = Json.createObjectBuilder();
-        if( previousReferences != null && previousReferences.getValueType() == JsonValue.ValueType.OBJECT )
-        {
-            JsonObject previousReferencesObject = (JsonObject) previousReferences;
-            for( Map.Entry<String, JsonValue> previousNamedRef : previousReferencesObject.entrySet() )
-            {
-                String previousName = previousNamedRef.getKey();
-                if( !name.equals( previousName ) )
-                {
-                    references.add( previousName, previousNamedRef.getValue() );
-                }
-            }
-        }
-        namedAssociations.add( stateName, references.build() );
-        builder.add( JSONKeys.PROPERTIES, state.get( JSONKeys.PROPERTIES ) );
-        builder.add( JSONKeys.ASSOCIATIONS, state.get( JSONKeys.ASSOCIATIONS ) );
-        builder.add( JSONKeys.MANY_ASSOCIATIONS, state.get( JSONKeys.MANY_ASSOCIATIONS ) );
-        builder.add( JSONKeys.NAMED_ASSOCIATIONS, namedAssociations.build() );
-        state = builder.build();
-    }
-
-    private JsonObjectBuilder stateShallowClone()
-    {
-        JsonObjectBuilder builder = Json.createObjectBuilder();
-        for( String cloneName : CLONE_NAMES )
+        JsonObject valueState = state.getJsonObject( JSONKeys.VALUE );
+        if( valueState.containsKey( stateName ) )
         {
-            JsonValue cloneValue = state.get( cloneName );
-            builder.add( cloneName, cloneValue == null ? JsonValue.NULL : cloneValue );
+            JsonObject namedAssoc = jsonFactories.cloneBuilderExclude( valueState.getJsonObject( stateName ), name )
+                                                 .build();
+            valueState = jsonFactories.cloneBuilderExclude( valueState, stateName )
+                                      .add( stateName, namedAssoc )
+                                      .build();
+            state = jsonFactories.cloneBuilderExclude( state, JSONKeys.VALUE )
+                                 .add( JSONKeys.VALUE, valueState )
+                                 .build();
         }
-        return builder;
     }
 }

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/b2ff271b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/JSONKeys.java
----------------------------------------------------------------------
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/JSONKeys.java b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/JSONKeys.java
index 6e9984c..4c0fa0e 100644
--- a/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/JSONKeys.java
+++ b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/JSONKeys.java
@@ -47,19 +47,7 @@ public interface JSONKeys
      */
     String MODIFIED = "modified";
     /**
-     * Map of properties.
+     * Entity value state.
      */
-    String PROPERTIES = "properties";
-    /**
-     * Map of associations.
-     */
-    String ASSOCIATIONS = "associations";
-    /**
-     * Map of manyassociations.
-     */
-    String MANY_ASSOCIATIONS = "manyassociations";
-    /**
-     * Map of namedassociations.
-     */
-    String NAMED_ASSOCIATIONS = "namedassociations";
+    String VALUE = "value";
 }

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/b2ff271b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/JSONManyAssociationState.java
----------------------------------------------------------------------
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/JSONManyAssociationState.java b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/JSONManyAssociationState.java
index e9b99c4..3bdd047 100644
--- a/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/JSONManyAssociationState.java
+++ b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/JSONManyAssociationState.java
@@ -21,12 +21,11 @@ package org.apache.polygene.spi.entitystore.helpers;
 
 import java.util.Iterator;
 import java.util.NoSuchElementException;
-import javax.json.Json;
 import javax.json.JsonArray;
 import javax.json.JsonException;
-import javax.json.JsonObject;
 import javax.json.JsonValue;
 import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.serialization.javaxjson.JavaxJsonFactories;
 import org.apache.polygene.spi.entity.ManyAssociationState;
 import org.apache.polygene.spi.entitystore.EntityStoreException;
 
@@ -37,24 +36,27 @@ import org.apache.polygene.spi.entitystore.EntityStoreException;
 public final class JSONManyAssociationState
     implements ManyAssociationState
 {
+    private final JavaxJsonFactories jsonFactories;
     private final JSONEntityState entityState;
     private final String stateName;
 
-    /* package */ JSONManyAssociationState( JSONEntityState entityState, String stateName )
+    /* package */ JSONManyAssociationState( JavaxJsonFactories jsonFactories,
+                                            JSONEntityState entityState,
+                                            String stateName )
     {
+        this.jsonFactories = jsonFactories;
         this.entityState = entityState;
         this.stateName = stateName;
     }
 
     private JsonArray getReferences()
     {
-        JsonObject manyAssociations = entityState.state().getJsonObject( JSONKeys.MANY_ASSOCIATIONS );
-        JsonValue references = manyAssociations.get( stateName );
+        JsonValue references = entityState.state().getJsonObject( JSONKeys.VALUE ).get( stateName );
         if( references != null && references.getValueType() == JsonValue.ValueType.ARRAY )
         {
             return (JsonArray) references;
         }
-        return Json.createArrayBuilder().build();
+        return jsonFactories.builderFactory().createArrayBuilder().build();
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/b2ff271b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/JSONMapEntityStoreMixin.java
----------------------------------------------------------------------
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/JSONMapEntityStoreMixin.java b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/JSONMapEntityStoreMixin.java
index 2a0ddc3..d593eb0 100644
--- a/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/JSONMapEntityStoreMixin.java
+++ b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/JSONMapEntityStoreMixin.java
@@ -17,6 +17,7 @@
  */
 package org.apache.polygene.spi.entitystore.helpers;
 
+import java.io.BufferedReader;
 import java.io.Externalizable;
 import java.io.IOException;
 import java.io.ObjectInput;
@@ -30,7 +31,6 @@ import java.util.List;
 import java.util.UUID;
 import java.util.function.Function;
 import java.util.stream.Stream;
-import javax.json.Json;
 import javax.json.JsonObject;
 import javax.json.JsonObjectBuilder;
 import javax.json.JsonReader;
@@ -50,7 +50,7 @@ import org.apache.polygene.api.structure.Application;
 import org.apache.polygene.api.structure.ModuleDescriptor;
 import org.apache.polygene.api.unitofwork.NoSuchEntityTypeException;
 import org.apache.polygene.api.usecase.Usecase;
-import org.apache.polygene.serialization.javaxjson.JavaxJson;
+import org.apache.polygene.serialization.javaxjson.JavaxJsonFactories;
 import org.apache.polygene.spi.cache.Cache;
 import org.apache.polygene.spi.cache.CachePool;
 import org.apache.polygene.spi.cache.NullCache;
@@ -64,6 +64,8 @@ import org.apache.polygene.spi.entitystore.EntityStoreUnitOfWork;
 import org.apache.polygene.spi.entitystore.StateCommitter;
 import org.apache.polygene.spi.serialization.JsonSerialization;
 
+import static java.util.stream.Collectors.joining;
+
 /**
  * Implementation of EntityStore that works with an implementation of MapEntityStore.
  *
@@ -88,6 +90,9 @@ public class JSONMapEntityStoreMixin
     private JsonSerialization serialization;
 
     @Service
+    private JavaxJsonFactories jsonFactories;
+
+    @Service
     IdentityGenerator identityGenerator;
 
     @Optional
@@ -152,19 +157,16 @@ public class JSONMapEntityStoreMixin
     {
         try
         {
-            JsonObjectBuilder builder = Json.createObjectBuilder();
+            JsonObjectBuilder builder = jsonFactories.builderFactory().createObjectBuilder();
             builder.add( JSONKeys.IDENTITY, reference.identity().toString() );
             builder.add( JSONKeys.APPLICATION_VERSION, application.version() );
             builder.add( JSONKeys.TYPE, entityDescriptor.types().findFirst().get().getName() );
             builder.add( JSONKeys.VERSION, uow.identity().toString() );
             builder.add( JSONKeys.MODIFIED, uow.currentTime().toEpochMilli() );
-            builder.add( JSONKeys.PROPERTIES, Json.createObjectBuilder().build() );
-            builder.add( JSONKeys.ASSOCIATIONS, Json.createObjectBuilder().build() );
-            builder.add( JSONKeys.MANY_ASSOCIATIONS, Json.createObjectBuilder().build() );
-            builder.add( JSONKeys.NAMED_ASSOCIATIONS, Json.createObjectBuilder().build() );
+            builder.add( JSONKeys.VALUE, jsonFactories.builderFactory().createObjectBuilder().build() );
             JsonObject state = builder.build();
-            return new JSONEntityState( entityDescriptor.module(), serialization,
-                                        "", uow.currentTime(),
+            return new JSONEntityState( entityDescriptor.module(), serialization, jsonFactories,
+                                        uow.identity().toString(), uow.currentTime(),
                                         reference,
                                         EntityStatus.NEW, entityDescriptor,
                                         state );
@@ -199,7 +201,7 @@ public class JSONMapEntityStoreMixin
                 }
                 if( doCacheOnRead( uow ) )
                 {
-                    cache.put( reference.identity().toString(), new CacheState( loadedState.state() ) );
+                    cache.put( reference.identity().toString(), new CacheState( loadedState.state().toString() ) );
                 }
                 return loadedState;
             }
@@ -220,13 +222,13 @@ public class JSONMapEntityStoreMixin
         CacheState cacheState = cache.get( reference.identity().toString() );
         if( cacheState != null )
         {
-            return cacheState.json.getString( JSONKeys.VERSION );
+            return jsonFactories.readerFactory().createReader( new StringReader( cacheState.string ) ).readObject()
+                                .getString( JSONKeys.VERSION );
         }
-        try
+        // Get state
+        try( JsonReader reader = jsonFactories.readerFactory().createReader( mapEntityStore.get( reference ) ) )
         {
-            // Get state
-            Reader entityState = mapEntityStore.get( reference );
-            return Json.createReader( entityState ).readObject().getString( JSONKeys.VERSION );
+            return reader.readObject().getString( JSONKeys.VERSION );
         }
         catch( EntityStoreException ex )
         {
@@ -275,7 +277,7 @@ public class JSONMapEntityStoreMixin
                                     if( options.cacheOnNew() )
                                     {
                                         cache.put( state.entityReference().identity().toString(),
-                                                   new CacheState( state.state() ) );
+                                                   new CacheState( state.state().toString() ) );
                                     }
                                 }
                                 else if( state.status().equals( EntityStatus.UPDATED ) )
@@ -291,7 +293,7 @@ public class JSONMapEntityStoreMixin
                                     if( options.cacheOnWrite() )
                                     {
                                         cache.put( state.entityReference().identity().toString(),
-                                                   new CacheState( state.state() ) );
+                                                   new CacheState( state.state().toString() ) );
                                     }
                                 }
                                 else if( state.status().equals( EntityStatus.REMOVED ) )
@@ -412,10 +414,10 @@ public class JSONMapEntityStoreMixin
     protected JSONEntityState readEntityState( ModuleDescriptor module, Reader entityState )
         throws EntityStoreException
     {
-        try
+        try( JsonReader reader = jsonFactories.readerFactory().createReader( entityState ) )
         {
-            JsonObject parsedState = Json.createReader( entityState ).readObject();
-            JsonObjectBuilder jsonStateBuilder = JavaxJson.toBuilder( parsedState );
+            JsonObject parsedState = reader.readObject();
+            JsonObjectBuilder jsonStateBuilder = jsonFactories.cloneBuilder( parsedState );
             EntityStatus status = EntityStatus.LOADED;
 
             String version = parsedState.getString( JSONKeys.VERSION );
@@ -453,7 +455,7 @@ public class JSONMapEntityStoreMixin
                 throw new NoSuchEntityTypeException( type, module.name(), module.typeLookup() );
             }
 
-            return new JSONEntityState( entityDescriptor.module(), serialization,
+            return new JSONEntityState( entityDescriptor.module(), serialization, jsonFactories,
                                         version, modified,
                                         EntityReference.create( identity ),
                                         status, entityDescriptor,
@@ -473,12 +475,10 @@ public class JSONMapEntityStoreMixin
     @Override
     public JsonObject jsonStateOf( String id )
     {
-        try( Reader reader = mapEntityStore.get( EntityReference.parseEntityReference( id ) ) )
+        try( JsonReader jsonReader = jsonFactories
+            .readerFactory().createReader( mapEntityStore.get( EntityReference.parseEntityReference( id ) ) ) )
         {
-            try( JsonReader jsonReader = Json.createReader( reader ) )
-            {
-                return jsonReader.readObject();
-            }
+            return jsonReader.readObject();
         }
         catch( EntityStoreException ex )
         {
@@ -495,18 +495,19 @@ public class JSONMapEntityStoreMixin
         CacheState cacheState = cache.get( reference.identity().toString() );
         if( cacheState != null )
         {
-            JsonObject data = cacheState.json;
+            JsonObject state = jsonFactories.readerFactory().createReader( new StringReader( cacheState.string ) )
+                                            .readObject();
             try
             {
-                String type = data.getString( JSONKeys.TYPE );
+                String type = state.getString( JSONKeys.TYPE );
                 EntityDescriptor entityDescriptor = module.entityDescriptor( type );
-                String version = data.getString( JSONKeys.VERSION );
-                Instant lastModified = Instant.ofEpochMilli( data.getJsonNumber( JSONKeys.MODIFIED ).longValueExact() );
-                return new JSONEntityState( entityDescriptor.module(), serialization,
-                                            version, lastModified,
+                String version = state.getString( JSONKeys.VERSION );
+                Instant modified = Instant.ofEpochMilli( state.getJsonNumber( JSONKeys.MODIFIED ).longValueExact() );
+                return new JSONEntityState( entityDescriptor.module(), serialization, jsonFactories,
+                                            version, modified,
                                             reference,
                                             EntityStatus.LOADED, entityDescriptor,
-                                            data );
+                                            state );
             }
             catch( Exception e )
             {
@@ -526,29 +527,32 @@ public class JSONMapEntityStoreMixin
     public static class CacheState
         implements Externalizable
     {
-        public JsonObject json;
+        public String string;
 
         public CacheState()
         {
         }
 
-        private CacheState( JsonObject state )
+        private CacheState( String string )
         {
-            json = state;
+            this.string = string;
         }
 
         @Override
         public void writeExternal( ObjectOutput out )
             throws IOException
         {
-            out.writeUTF( json.toString() );
+            out.writeUTF( string );
         }
 
         @Override
         public void readExternal( ObjectInput in )
             throws IOException, ClassNotFoundException
         {
-            json = Json.createReader( new StringReader( in.readUTF() ) ).readObject();
+            try( BufferedReader reader = new BufferedReader( new StringReader( in.readUTF() ) ) )
+            {
+                string = reader.lines().collect( joining( "\n" ) );
+            }
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/b2ff271b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/JSONNamedAssociationState.java
----------------------------------------------------------------------
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/JSONNamedAssociationState.java b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/JSONNamedAssociationState.java
index 74ea667..a59f50d 100644
--- a/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/JSONNamedAssociationState.java
+++ b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/JSONNamedAssociationState.java
@@ -23,11 +23,11 @@ import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
 import java.util.NoSuchElementException;
-import javax.json.Json;
 import javax.json.JsonException;
 import javax.json.JsonObject;
 import javax.json.JsonValue;
 import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.serialization.javaxjson.JavaxJsonFactories;
 import org.apache.polygene.spi.entity.NamedAssociationState;
 import org.apache.polygene.spi.entitystore.EntityStoreException;
 
@@ -38,25 +38,27 @@ import org.apache.polygene.spi.entitystore.EntityStoreException;
 public final class JSONNamedAssociationState
     implements NamedAssociationState
 {
-
+    private final JavaxJsonFactories jsonFactories;
     private final JSONEntityState entityState;
     private final String stateName;
 
-    /* package */ JSONNamedAssociationState( JSONEntityState entityState, String stateName )
+    /* package */ JSONNamedAssociationState( JavaxJsonFactories jsonFactories,
+                                             JSONEntityState entityState,
+                                             String stateName )
     {
+        this.jsonFactories = jsonFactories;
         this.entityState = entityState;
         this.stateName = stateName;
     }
 
     private JsonObject getReferences()
     {
-        JsonObject namedAssociations = entityState.state().getJsonObject( JSONKeys.NAMED_ASSOCIATIONS );
-        JsonValue references = namedAssociations.get( stateName );
+        JsonValue references = entityState.state().getJsonObject( JSONKeys.VALUE ).get( stateName );
         if( references != null && references.getValueType() == JsonValue.ValueType.OBJECT )
         {
             return (JsonObject) references;
         }
-        return Json.createObjectBuilder().build();
+        return jsonFactories.builderFactory().createObjectBuilder().build();
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/b2ff271b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/MapEntityStoreMixin.java
----------------------------------------------------------------------
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/MapEntityStoreMixin.java b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/MapEntityStoreMixin.java
index ef9816c..c8bd163 100644
--- a/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/MapEntityStoreMixin.java
+++ b/core/spi/src/main/java/org/apache/polygene/spi/entitystore/helpers/MapEntityStoreMixin.java
@@ -27,13 +27,14 @@ import java.util.List;
 import java.util.Map;
 import java.util.function.Function;
 import java.util.stream.Stream;
-import javax.json.Json;
 import javax.json.JsonArray;
 import javax.json.JsonArrayBuilder;
 import javax.json.JsonException;
 import javax.json.JsonObject;
 import javax.json.JsonObjectBuilder;
+import javax.json.JsonReader;
 import javax.json.JsonValue;
+import javax.json.JsonWriter;
 import org.apache.polygene.api.common.Optional;
 import org.apache.polygene.api.common.QualifiedName;
 import org.apache.polygene.api.entity.EntityDescriptor;
@@ -48,7 +49,7 @@ import org.apache.polygene.api.structure.Application;
 import org.apache.polygene.api.structure.ModuleDescriptor;
 import org.apache.polygene.api.unitofwork.NoSuchEntityTypeException;
 import org.apache.polygene.api.usecase.Usecase;
-import org.apache.polygene.serialization.javaxjson.JavaxJson;
+import org.apache.polygene.serialization.javaxjson.JavaxJsonFactories;
 import org.apache.polygene.spi.entity.EntityState;
 import org.apache.polygene.spi.entity.EntityStatus;
 import org.apache.polygene.spi.entitystore.DefaultEntityStoreUnitOfWork;
@@ -59,6 +60,8 @@ import org.apache.polygene.spi.entitystore.EntityStoreUnitOfWork;
 import org.apache.polygene.spi.entitystore.StateCommitter;
 import org.apache.polygene.spi.serialization.JsonSerialization;
 
+import static org.apache.polygene.api.entity.EntityReference.parseEntityReference;
+
 /**
  * Implementation of EntityStore that works with an implementation of MapEntityStore.
  *
@@ -82,6 +85,9 @@ public class MapEntityStoreMixin
     @Service
     private JsonSerialization jsonSerialization;
 
+    @Service
+    private JavaxJsonFactories jsonFactories;
+
     @Optional
     @Service
     private Migration migration;
@@ -137,10 +143,9 @@ public class MapEntityStoreMixin
     @Override
     public synchronized String versionOf( EntityStoreUnitOfWork uow, EntityReference reference )
     {
-        try
+        try( JsonReader jsonReader = jsonFactories.readerFactory().createReader( mapEntityStore.get( reference ) ) )
         {
-            Reader in = mapEntityStore.get( reference );
-            return Json.createReader( in ).readObject().getString( JSONKeys.VERSION );
+            return jsonReader.readObject().getString( JSONKeys.VERSION );
         }
         catch( EntityStoreException ex )
         {
@@ -312,56 +317,53 @@ public class MapEntityStoreMixin
     {
         try
         {
-            JsonObjectBuilder json = Json.createObjectBuilder();
+            JsonObjectBuilder json = jsonFactories.builderFactory().createObjectBuilder();
             json.add( JSONKeys.IDENTITY, state.entityReference().identity().toString() );
             json.add( JSONKeys.APPLICATION_VERSION, application.version() );
             json.add( JSONKeys.TYPE, state.entityDescriptor().primaryType().getName() );
             json.add( JSONKeys.VERSION, version );
             json.add( JSONKeys.MODIFIED, lastModified.toEpochMilli() );
-            JsonObjectBuilder properties = Json.createObjectBuilder();
+            JsonObjectBuilder valueBuilder = jsonFactories.builderFactory().createObjectBuilder();
             EntityDescriptor entityType = state.entityDescriptor();
             entityType.state().properties().forEach(
                 persistentProperty ->
                 {
                     Object value = state.properties().get( persistentProperty.qualifiedName() );
                     JsonValue jsonValue = jsonSerialization.toJson( value );
-                    properties.add( persistentProperty.qualifiedName().name(), jsonValue );
+                    valueBuilder.add( persistentProperty.qualifiedName().name(), jsonValue );
                 } );
-            json.add( JSONKeys.PROPERTIES, properties.build() );
 
-            JsonObjectBuilder associations = Json.createObjectBuilder();
             for( Map.Entry<QualifiedName, EntityReference> entry : state.associations().entrySet() )
             {
                 EntityReference value = entry.getValue();
-                associations.add( entry.getKey().name(), value == null ? null : value.identity().toString() );
+                valueBuilder.add( entry.getKey().name(), value == null ? null : value.identity().toString() );
             }
-            json.add( JSONKeys.ASSOCIATIONS, associations.build() );
 
-            JsonObjectBuilder manyAssociations = Json.createObjectBuilder();
             for( Map.Entry<QualifiedName, List<EntityReference>> entry : state.manyAssociations().entrySet() )
             {
-                JsonArrayBuilder arrayBuilder = Json.createArrayBuilder();
+                JsonArrayBuilder arrayBuilder = jsonFactories.builderFactory().createArrayBuilder();
                 for( EntityReference entityReference : entry.getValue() )
                 {
                     arrayBuilder.add( entityReference.identity().toString() );
                 }
-                manyAssociations.add( entry.getKey().name(), arrayBuilder.build() );
+                valueBuilder.add( entry.getKey().name(), arrayBuilder.build() );
             }
-            json.add( JSONKeys.MANY_ASSOCIATIONS, manyAssociations.build() );
 
-            JsonObjectBuilder namedAssociations = Json.createObjectBuilder();
             for( Map.Entry<QualifiedName, Map<String, EntityReference>> entry : state.namedAssociations().entrySet() )
             {
-                JsonObjectBuilder objectBuilder = Json.createObjectBuilder();
+                JsonObjectBuilder objectBuilder = jsonFactories.builderFactory().createObjectBuilder();
                 for( Map.Entry<String, EntityReference> namedRef : entry.getValue().entrySet() )
                 {
                     objectBuilder.add( namedRef.getKey(), namedRef.getValue().identity().toString() );
                 }
-                namedAssociations.add( entry.getKey().name(), objectBuilder.build() );
+                valueBuilder.add( entry.getKey().name(), objectBuilder.build() );
             }
-            json.add( JSONKeys.NAMED_ASSOCIATIONS, namedAssociations.build() );
+            json.add( JSONKeys.VALUE, valueBuilder.build() );
             JsonObject jsonState = json.build();
-            Json.createWriter( writer ).write( jsonState );
+            try( JsonWriter jsonWriter = jsonFactories.writerFactory().createWriter( writer ) )
+            {
+                jsonWriter.write( jsonState );
+            }
         }
         catch( Exception e )
         {
@@ -372,10 +374,10 @@ public class MapEntityStoreMixin
     protected EntityState readEntityState( ModuleDescriptor module, Reader entityState )
         throws EntityStoreException
     {
-        try
+        try( JsonReader jsonReader = jsonFactories.readerFactory().createReader( entityState ) )
         {
-            JsonObject parsedState = Json.createReader( entityState ).readObject();
-            JsonObjectBuilder jsonStateBuilder = JavaxJson.toBuilder( parsedState );
+            JsonObject parsedState = jsonReader.readObject();
+            JsonObjectBuilder jsonStateBuilder = jsonFactories.cloneBuilder( parsedState );
             final EntityStatus[] status = { EntityStatus.LOADED };
 
             String version = parsedState.getString( JSONKeys.VERSION );
@@ -414,13 +416,13 @@ public class MapEntityStoreMixin
             }
 
             Map<QualifiedName, Object> properties = new HashMap<>();
-            JsonObject props = state.getJsonObject( JSONKeys.PROPERTIES );
+            JsonObject valueState = state.getJsonObject( JSONKeys.VALUE );
             entityDescriptor.state().properties().forEach(
                 property ->
                 {
                     try
                     {
-                        JsonValue jsonValue = props.get( property.qualifiedName().name() );
+                        JsonValue jsonValue = valueState.get( property.qualifiedName().name() );
                         Object value = jsonSerialization.fromJson( module, property.valueType(), jsonValue );
                         properties.put( property.qualifiedName(), value );
                     }
@@ -434,16 +436,15 @@ public class MapEntityStoreMixin
                 } );
 
             Map<QualifiedName, EntityReference> associations = new HashMap<>();
-            JsonObject assocs = state.getJsonObject( JSONKeys.ASSOCIATIONS );
             entityDescriptor.state().associations().forEach(
                 association ->
                 {
                     try
                     {
-                        String jsonValue = assocs.getString( association.qualifiedName().name(), null );
+                        String jsonValue = valueState.getString( association.qualifiedName().name(), null );
                         EntityReference value = jsonValue == null
                                                 ? null
-                                                : EntityReference.parseEntityReference( jsonValue );
+                                                : parseEntityReference( jsonValue );
                         associations.put( association.qualifiedName(), value );
                     }
                     catch( JsonException e )
@@ -454,7 +455,6 @@ public class MapEntityStoreMixin
                     }
                 } );
 
-            JsonObject manyAssocs = state.getJsonObject( JSONKeys.MANY_ASSOCIATIONS );
             Map<QualifiedName, List<EntityReference>> manyAssociations = new HashMap<>();
             entityDescriptor.state().manyAssociations().forEach(
                 association ->
@@ -462,13 +462,13 @@ public class MapEntityStoreMixin
                     List<EntityReference> references = new ArrayList<>();
                     try
                     {
-                        JsonArray jsonValues = manyAssocs.getJsonArray( association.qualifiedName().name() );
+                        JsonArray jsonValues = valueState.getJsonArray( association.qualifiedName().name() );
                         for( int i = 0; i < jsonValues.size(); i++ )
                         {
                             String jsonValue = jsonValues.getString( i, null );
                             EntityReference value = jsonValue == null
                                                     ? null
-                                                    : EntityReference.parseEntityReference( jsonValue );
+                                                    : parseEntityReference( jsonValue );
                             references.add( value );
                         }
                         manyAssociations.put( association.qualifiedName(), references );
@@ -480,7 +480,6 @@ public class MapEntityStoreMixin
                     }
                 } );
 
-            JsonObject namedAssocs = state.getJsonObject( JSONKeys.NAMED_ASSOCIATIONS );
             Map<QualifiedName, Map<String, EntityReference>> namedAssociations = new HashMap<>();
             entityDescriptor.state().namedAssociations().forEach(
                 association ->
@@ -488,13 +487,13 @@ public class MapEntityStoreMixin
                     Map<String, EntityReference> references = new LinkedHashMap<>();
                     try
                     {
-                        JsonObject jsonValues = namedAssocs.getJsonObject( association.qualifiedName().name() );
+                        JsonObject jsonValues = valueState.getJsonObject( association.qualifiedName().name() );
                         for( String name : jsonValues.keySet() )
                         {
                             String value = jsonValues.getString( name, null );
                             EntityReference ref = value == null
                                                   ? null
-                                                  : EntityReference.parseEntityReference( value );
+                                                  : parseEntityReference( value );
                             references.put( name, ref );
                         }
                         namedAssociations.put( association.qualifiedName(), references );
@@ -526,9 +525,10 @@ public class MapEntityStoreMixin
     @Override
     public JsonObject jsonStateOf( String id )
     {
-        try( Reader reader = mapEntityStore.get( EntityReference.parseEntityReference( id ) ) )
+        try( JsonReader reader = jsonFactories.readerFactory()
+                                              .createReader( mapEntityStore.get( parseEntityReference( id ) ) ) )
         {
-            return Json.createReader( reader ).readObject();
+            return reader.readObject();
         }
         catch( EntityStoreException ex )
         {

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/b2ff271b/core/spi/src/main/java/org/apache/polygene/spi/serialization/AbstractDeserializer.java
----------------------------------------------------------------------
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/serialization/AbstractDeserializer.java b/core/spi/src/main/java/org/apache/polygene/spi/serialization/AbstractDeserializer.java
index 4edd044..0b604aa 100644
--- a/core/spi/src/main/java/org/apache/polygene/spi/serialization/AbstractDeserializer.java
+++ b/core/spi/src/main/java/org/apache/polygene/spi/serialization/AbstractDeserializer.java
@@ -18,17 +18,16 @@
 package org.apache.polygene.spi.serialization;
 
 import java.io.ByteArrayInputStream;
-import java.io.IOException;
 import java.io.InputStream;
-import java.io.ObjectInputStream;
 import java.io.Reader;
 import java.io.StringReader;
 import java.util.function.Function;
 import java.util.stream.Stream;
 import java.util.stream.StreamSupport;
+import org.apache.polygene.api.composite.AmbiguousTypeException;
+import org.apache.polygene.api.composite.StatefulAssociationCompositeDescriptor;
 import org.apache.polygene.api.entity.EntityReference;
 import org.apache.polygene.api.serialization.Deserializer;
-import org.apache.polygene.api.serialization.SerializationException;
 import org.apache.polygene.api.structure.ModuleDescriptor;
 import org.apache.polygene.api.type.CollectionType;
 import org.apache.polygene.api.type.MapType;
@@ -163,15 +162,23 @@ public abstract class AbstractDeserializer implements Deserializer
         return ( (ModuleSpi) module.instance() ).valueTypeFactory().valueTypeOf( module, type );
     }
 
-    protected Object deserializeJava( byte[] bytes )
+    protected final StatefulAssociationCompositeDescriptor statefulCompositeDescriptorFor( ModuleDescriptor module,
+                                                                                           String typeName )
     {
-        try( ObjectInputStream oin = new ObjectInputStream( new ByteArrayInputStream( bytes ) ) )
+        StatefulAssociationCompositeDescriptor descriptor = null;
+        try
         {
-            return oin.readObject();
+            descriptor = module.valueDescriptor( typeName );
         }
-        catch( IOException | ClassNotFoundException ex )
+        catch( AmbiguousTypeException ex ) { }
+        if( descriptor == null )
         {
-            throw new SerializationException( "Unable to deserialize using Java serialization", ex );
+            try
+            {
+                descriptor = module.entityDescriptor( typeName );
+            }
+            catch( AmbiguousTypeException ex ) { }
         }
+        return descriptor;
     }
 }

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/b2ff271b/core/spi/src/main/java/org/apache/polygene/spi/serialization/AbstractSerializer.java
----------------------------------------------------------------------
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/serialization/AbstractSerializer.java b/core/spi/src/main/java/org/apache/polygene/spi/serialization/AbstractSerializer.java
index 4db3548..3269adb 100644
--- a/core/spi/src/main/java/org/apache/polygene/spi/serialization/AbstractSerializer.java
+++ b/core/spi/src/main/java/org/apache/polygene/spi/serialization/AbstractSerializer.java
@@ -18,8 +18,6 @@
 package org.apache.polygene.spi.serialization;
 
 import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.ObjectOutputStream;
 import java.io.OutputStream;
 import java.io.StringWriter;
 import java.io.Writer;
@@ -27,7 +25,6 @@ import java.util.function.Function;
 import java.util.stream.Stream;
 import java.util.stream.StreamSupport;
 import org.apache.polygene.api.common.Optional;
-import org.apache.polygene.api.serialization.SerializationException;
 import org.apache.polygene.api.serialization.Serializer;
 
 /**
@@ -154,19 +151,4 @@ public abstract class AbstractSerializer implements Serializer
     {
         return Stream.of( objects ).map( object -> toBytes( Options.DEFAULT, object ) );
     }
-
-    protected byte[] serializeJava( Object object )
-    {
-        ByteArrayOutputStream bout = new ByteArrayOutputStream();
-        try( ObjectOutputStream out = new ObjectOutputStream( bout ) )
-        {
-            out.writeUnshared( object );
-            out.flush();
-            return bout.toByteArray();
-        }
-        catch( IOException ex )
-        {
-            throw new SerializationException( "Unable to serialize using Java serialization", ex );
-        }
-    }
 }

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/b2ff271b/core/spi/src/main/java/org/apache/polygene/spi/serialization/JsonDeserializer.java
----------------------------------------------------------------------
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/serialization/JsonDeserializer.java b/core/spi/src/main/java/org/apache/polygene/spi/serialization/JsonDeserializer.java
index fdec10c..61a39c9 100644
--- a/core/spi/src/main/java/org/apache/polygene/spi/serialization/JsonDeserializer.java
+++ b/core/spi/src/main/java/org/apache/polygene/spi/serialization/JsonDeserializer.java
@@ -21,6 +21,7 @@ import java.util.function.Function;
 import java.util.stream.Stream;
 import java.util.stream.StreamSupport;
 import javax.json.JsonValue;
+import org.apache.polygene.api.common.Optional;
 import org.apache.polygene.api.serialization.Deserializer;
 import org.apache.polygene.api.structure.ModuleDescriptor;
 import org.apache.polygene.api.type.ValueType;
@@ -31,7 +32,7 @@ import org.apache.polygene.spi.module.ModuleSpi;
  */
 public interface JsonDeserializer extends Deserializer
 {
-    <T> T fromJson( ModuleDescriptor module, ValueType valueType, JsonValue state );
+    <T> T fromJson( ModuleDescriptor module, ValueType valueType, @Optional JsonValue state );
 
     default <T> Function<JsonValue, T> fromJsonFunction( ModuleDescriptor module, ValueType valueType )
     {
@@ -53,7 +54,7 @@ public interface JsonDeserializer extends Deserializer
         return fromJsonEach( module, valueType, Stream.of( states ) );
     }
 
-    default <T> T fromJson( ModuleDescriptor module, Class<T> type, JsonValue state )
+    default <T> T fromJson( ModuleDescriptor module, Class<T> type, @Optional JsonValue state )
     {
         // TODO Remove (ModuleSpi) cast
         ValueType valueType = ( (ModuleSpi) module.instance() ).valueTypeFactory().valueTypeOf( module, type );

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/b2ff271b/core/spi/src/main/java/org/apache/polygene/spi/serialization/XmlDeserializer.java
----------------------------------------------------------------------
diff --git a/core/spi/src/main/java/org/apache/polygene/spi/serialization/XmlDeserializer.java b/core/spi/src/main/java/org/apache/polygene/spi/serialization/XmlDeserializer.java
index 4ea4fe1..cc5ddc6 100644
--- a/core/spi/src/main/java/org/apache/polygene/spi/serialization/XmlDeserializer.java
+++ b/core/spi/src/main/java/org/apache/polygene/spi/serialization/XmlDeserializer.java
@@ -20,6 +20,7 @@ package org.apache.polygene.spi.serialization;
 import java.util.function.Function;
 import java.util.stream.Stream;
 import java.util.stream.StreamSupport;
+import org.apache.polygene.api.common.Optional;
 import org.apache.polygene.api.serialization.Deserializer;
 import org.apache.polygene.api.structure.ModuleDescriptor;
 import org.apache.polygene.api.type.ValueType;
@@ -31,7 +32,7 @@ import org.w3c.dom.Node;
  */
 public interface XmlDeserializer extends Deserializer
 {
-    <T> T fromXml( ModuleDescriptor module, ValueType valueType, Node state );
+    <T> T fromXml( ModuleDescriptor module, ValueType valueType, @Optional Node state );
 
     default <T> Function<Node, T> fromXmlFunction( ModuleDescriptor module, ValueType valueType )
     {
@@ -53,7 +54,7 @@ public interface XmlDeserializer extends Deserializer
         return fromXmlEach( module, valueType, Stream.of( states ) );
     }
 
-    default <T> T fromXml( ModuleDescriptor module, Class<T> type, Node state )
+    default <T> T fromXml( ModuleDescriptor module, Class<T> type, @Optional Node state )
     {
         // TODO Remove (ModuleSpi) cast
         ValueType valueType = ( (ModuleSpi) module.instance() ).valueTypeFactory().valueTypeOf( module, type );

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/b2ff271b/core/spi/src/test/java/org/apache/polygene/spi/entitystore/helpers/JSONManyAssociationStateTest.java
----------------------------------------------------------------------
diff --git a/core/spi/src/test/java/org/apache/polygene/spi/entitystore/helpers/JSONManyAssociationStateTest.java b/core/spi/src/test/java/org/apache/polygene/spi/entitystore/helpers/JSONManyAssociationStateTest.java
index 67af1f8..a55c642 100644
--- a/core/spi/src/test/java/org/apache/polygene/spi/entitystore/helpers/JSONManyAssociationStateTest.java
+++ b/core/spi/src/test/java/org/apache/polygene/spi/entitystore/helpers/JSONManyAssociationStateTest.java
@@ -25,8 +25,13 @@ import javax.json.Json;
 import javax.json.JsonObject;
 import javax.json.JsonObjectBuilder;
 import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.injection.scope.Service;
 import org.apache.polygene.api.time.SystemTime;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.serialization.javaxjson.JavaxJsonFactories;
 import org.apache.polygene.spi.entity.EntityStatus;
+import org.apache.polygene.spi.serialization.JsonSerialization;
+import org.apache.polygene.test.AbstractPolygeneTest;
 import org.junit.Test;
 
 import static org.hamcrest.CoreMatchers.equalTo;
@@ -34,28 +39,36 @@ import static org.hamcrest.CoreMatchers.is;
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertThat;
 
-public class JSONManyAssociationStateTest
+public class JSONManyAssociationStateTest extends AbstractPolygeneTest
 {
+    @Override
+    public void assemble( ModuleAssembly module )
+    {
+    }
+
+    @Service
+    private JsonSerialization serialization;
+
+    @Service
+    private JavaxJsonFactories jsonFactories;
 
     @Test
     public void givenEmptyJSONManyAssociationStateWhenAddingTwoRefsAtZeroIndexExpectCorrectOrder()
     {
         // Fake JSONManyAssociationState
         JsonObjectBuilder builder = Json.createObjectBuilder();
-        builder.add( JSONKeys.PROPERTIES, Json.createObjectBuilder().build() );
-        builder.add( JSONKeys.ASSOCIATIONS, Json.createObjectBuilder().build() );
-        builder.add( JSONKeys.MANY_ASSOCIATIONS, Json.createObjectBuilder().build() );
-        builder.add( JSONKeys.NAMED_ASSOCIATIONS, Json.createObjectBuilder().build() );
+        builder.add( JSONKeys.VALUE, Json.createObjectBuilder().build() );
         JsonObject state = builder.build();
-        JSONEntityState entityState = new JSONEntityState( null,
-                                                           null,
+        JSONEntityState entityState = new JSONEntityState( module,
+                                                           serialization,
+                                                           jsonFactories,
                                                            "0",
                                                            SystemTime.now(),
                                                            EntityReference.parseEntityReference( "123" ),
                                                            EntityStatus.NEW,
                                                            null,
                                                            state );
-        JSONManyAssociationState jsonState = new JSONManyAssociationState( entityState, "under-test" );
+        JSONManyAssociationState jsonState = new JSONManyAssociationState( jsonFactories, entityState, "under-test" );
 
         jsonState.add( 0, EntityReference.parseEntityReference( "first" ) );
         jsonState.add( 0, EntityReference.parseEntityReference( "second" ) );
@@ -68,20 +81,18 @@ public class JSONManyAssociationStateTest
     {
         // Fake JSONManyAssociationState
         JsonObjectBuilder builder = Json.createObjectBuilder();
-        builder.add( JSONKeys.PROPERTIES, Json.createObjectBuilder().build() );
-        builder.add( JSONKeys.ASSOCIATIONS, Json.createObjectBuilder().build() );
-        builder.add( JSONKeys.MANY_ASSOCIATIONS, Json.createObjectBuilder().build() );
-        builder.add( JSONKeys.NAMED_ASSOCIATIONS, Json.createObjectBuilder().build() );
+        builder.add( JSONKeys.VALUE, Json.createObjectBuilder().build() );
         JsonObject state = builder.build();
-        JSONEntityState entityState = new JSONEntityState( null,
-                                                           null,
+        JSONEntityState entityState = new JSONEntityState( module,
+                                                           serialization,
+                                                           jsonFactories,
                                                            "0",
                                                            SystemTime.now(),
                                                            EntityReference.parseEntityReference( "123" ),
                                                            EntityStatus.NEW,
                                                            null,
                                                            state );
-        JSONManyAssociationState jsonState = new JSONManyAssociationState( entityState, "under-test" );
+        JSONManyAssociationState jsonState = new JSONManyAssociationState( jsonFactories, entityState, "under-test" );
 
         assertThat( jsonState.contains( EntityReference.parseEntityReference( "NOT_PRESENT" ) ), is( false ) );
 
@@ -132,8 +143,8 @@ public class JSONManyAssociationStateTest
         }
         assertThat( refList.isEmpty(), is( false ) );
         assertArrayEquals( new String[]
-        {
-            "C", "B", "A", "0", "2", "1"
-        }, refList.toArray() );
+                               {
+                                   "C", "B", "A", "0", "2", "1"
+                               }, refList.toArray() );
     }
 }

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/b2ff271b/core/spi/src/test/java/org/apache/polygene/spi/entitystore/helpers/JsonNamedAssociationStateTest.java
----------------------------------------------------------------------
diff --git a/core/spi/src/test/java/org/apache/polygene/spi/entitystore/helpers/JsonNamedAssociationStateTest.java b/core/spi/src/test/java/org/apache/polygene/spi/entitystore/helpers/JsonNamedAssociationStateTest.java
index 8a4b7db..5bab0c1 100644
--- a/core/spi/src/test/java/org/apache/polygene/spi/entitystore/helpers/JsonNamedAssociationStateTest.java
+++ b/core/spi/src/test/java/org/apache/polygene/spi/entitystore/helpers/JsonNamedAssociationStateTest.java
@@ -25,8 +25,13 @@ import javax.json.Json;
 import javax.json.JsonObject;
 import javax.json.JsonObjectBuilder;
 import org.apache.polygene.api.entity.EntityReference;
+import org.apache.polygene.api.injection.scope.Service;
 import org.apache.polygene.api.time.SystemTime;
+import org.apache.polygene.bootstrap.ModuleAssembly;
+import org.apache.polygene.serialization.javaxjson.JavaxJsonFactories;
 import org.apache.polygene.spi.entity.EntityStatus;
+import org.apache.polygene.spi.serialization.JsonSerialization;
+import org.apache.polygene.test.AbstractPolygeneTest;
 import org.junit.Test;
 
 import static org.hamcrest.CoreMatchers.equalTo;
@@ -34,27 +39,36 @@ import static org.hamcrest.CoreMatchers.hasItems;
 import static org.hamcrest.CoreMatchers.is;
 import static org.junit.Assert.assertThat;
 
-public class JsonNamedAssociationStateTest
+public class JsonNamedAssociationStateTest extends AbstractPolygeneTest
 {
+    @Override
+    public void assemble( ModuleAssembly module )
+    {
+    }
+
+    @Service
+    private JsonSerialization serialization;
+
+    @Service
+    private JavaxJsonFactories jsonFactories;
+
     @Test
     public void givenJsonNamedAssociationStateWhenChangingReferencesExpectCorrectBehavior()
     {
         // Fake JsonNamedAssociationState
         JsonObjectBuilder builder = Json.createObjectBuilder();
-        builder.add( JSONKeys.PROPERTIES, Json.createObjectBuilder().build() );
-        builder.add( JSONKeys.ASSOCIATIONS, Json.createObjectBuilder().build() );
-        builder.add( JSONKeys.MANY_ASSOCIATIONS, Json.createObjectBuilder().build() );
-        builder.add( JSONKeys.NAMED_ASSOCIATIONS, Json.createObjectBuilder().build() );
+        builder.add( JSONKeys.VALUE, Json.createObjectBuilder().build() );
         JsonObject state = builder.build();
-        JSONEntityState entityState = new JSONEntityState( null,
-                                                           null,
+        JSONEntityState entityState = new JSONEntityState( module,
+                                                           serialization,
+                                                           jsonFactories,
                                                            "0",
                                                            SystemTime.now(),
                                                            EntityReference.parseEntityReference( "123" ),
                                                            EntityStatus.NEW,
                                                            null,
                                                            state );
-        JSONNamedAssociationState jsonState = new JSONNamedAssociationState( entityState, "under-test" );
+        JSONNamedAssociationState jsonState = new JSONNamedAssociationState( jsonFactories, entityState, "under-test" );
 
 
         assertThat( jsonState.containsName( "foo" ), is( false ) );

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/b2ff271b/core/testsupport/src/main/java/org/apache/polygene/test/serialization/AbstractPlainValueSerializationTest.java
----------------------------------------------------------------------
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/serialization/AbstractPlainValueSerializationTest.java b/core/testsupport/src/main/java/org/apache/polygene/test/serialization/AbstractPlainValueSerializationTest.java
index cd4bc37..4b34b64 100644
--- a/core/testsupport/src/main/java/org/apache/polygene/test/serialization/AbstractPlainValueSerializationTest.java
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/serialization/AbstractPlainValueSerializationTest.java
@@ -36,6 +36,7 @@ import org.apache.polygene.api.entity.EntityReference;
 import org.apache.polygene.api.injection.scope.Service;
 import org.apache.polygene.api.serialization.Converter;
 import org.apache.polygene.api.serialization.Serialization;
+import org.apache.polygene.api.serialization.SerializationException;
 import org.apache.polygene.api.type.EnumType;
 import org.apache.polygene.api.type.ValueType;
 import org.apache.polygene.bootstrap.ModuleAssembly;
@@ -45,9 +46,11 @@ import org.junit.Test;
 
 import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.CoreMatchers.nullValue;
+import static org.hamcrest.Matchers.startsWith;
 import static org.hamcrest.core.IsEqual.equalTo;
 import static org.hamcrest.core.IsNot.not;
 import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
 
 /**
  * Assert that Serialization behaviour on plain values is correct.
@@ -76,6 +79,20 @@ public abstract class AbstractPlainValueSerializationTest extends AbstractPolyge
     protected abstract String getSingleStringRawState( String state ) throws Exception;
 
     @Test
+    public void dontKnowHowToSerializeJavaLangObject()
+    {
+        try
+        {
+            serialization.serialize( new Object() );
+            fail( "serialization.serialize( new Object() ) should have failed" );
+        }
+        catch( SerializationException ex )
+        {
+            assertThat( ex.getMessage(), startsWith( "Don't know how to serialize" ) );
+        }
+    }
+
+    @Test
     public void givenNullValueWhenSerializingAndDeserializingExpectNull()
     {
         String output = serialization.serialize( null );

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/b2ff271b/core/testsupport/src/main/java/org/apache/polygene/test/serialization/AbstractValueCompositeSerializationTest.java
----------------------------------------------------------------------
diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/serialization/AbstractValueCompositeSerializationTest.java b/core/testsupport/src/main/java/org/apache/polygene/test/serialization/AbstractValueCompositeSerializationTest.java
index 221a788..3741fd2 100644
--- a/core/testsupport/src/main/java/org/apache/polygene/test/serialization/AbstractValueCompositeSerializationTest.java
+++ b/core/testsupport/src/main/java/org/apache/polygene/test/serialization/AbstractValueCompositeSerializationTest.java
@@ -45,6 +45,8 @@ import org.apache.polygene.api.injection.scope.Structure;
 import org.apache.polygene.api.injection.scope.This;
 import org.apache.polygene.api.mixin.Mixins;
 import org.apache.polygene.api.property.Property;
+import org.apache.polygene.api.serialization.ConvertedBy;
+import org.apache.polygene.api.serialization.JavaSerializationConverter;
 import org.apache.polygene.api.serialization.Serialization;
 import org.apache.polygene.api.structure.Module;
 import org.apache.polygene.api.unitofwork.UnitOfWork;
@@ -91,12 +93,13 @@ public abstract class AbstractValueCompositeSerializationTest
     @Override
     public void assemble( ModuleAssembly module )
     {
+        module.objects( JavaSerializationConverter.class );
         module.values( Some.class, SomeExtended.class, SomeShuffled.class,
                        AnotherValue.class, FooValue.class, CustomFooValue.class,
                        SpecificCollection.class /*, SpecificValue.class, GenericValue.class */ );
+        module.entities( Some.class, BarEntity.class );
 
         new EntityTestAssembler().visibleIn( Visibility.layer ).assemble( module.layer().module( "persistence" ) );
-        module.entities( Some.class, BarEntity.class );
     }
 
     @Structure
@@ -145,6 +148,45 @@ public abstract class AbstractValueCompositeSerializationTest
     }
 
     @Test
+    public void givenEntityCompositeWhenSerializingAndDeserializingExpectEquals()
+        throws Exception
+    {
+        try( UnitOfWork uow = unitOfWorkFactory.newUnitOfWork() )
+        {
+            Some some = buildSomeEntity( moduleInstance, uow, "23" );
+
+            // Serialize using injected service
+            String stateString = serialization.serialize( some );
+            System.out.println( stateString );
+
+            // Deserialize using Module API
+            Some some2 = moduleInstance.newValueFromSerializedState( Some.class, stateString );
+
+            assertThat( "Map<String, Integer>",
+                        some2.stringIntMap().get().get( "foo" ),
+                        equalTo( 42 ) );
+            assertThat( "Map<String, Value>",
+                        some2.stringValueMap().get().get( "foo" ).internalVal(),
+                        equalTo( "Bar" ) );
+
+            assertThat( "Nested Entities",
+                        some2.barAssociation().get().cathedral().get(),
+                        equalTo( "bazar in barAssociation" ) );
+
+            assertThat( "Polymorphic deserialization of value type NOT extending ValueComposite",
+                        some.customFoo().get() instanceof CustomFooValue,
+                        is( true ) );
+            assertThat( "Polymorphic deserialization of value type extending ValueComposite",
+                        some.customFooValue().get() instanceof CustomFooValue,
+                        is( true ) );
+
+            assertThat( "Value equality", some, equalTo( some2 ) );
+
+            uow.complete();
+        }
+    }
+
+    @Test
     public void canDeserializeUsingSuperTypeWithLessState()
     {
         try( UnitOfWork uow = unitOfWorkFactory.newUnitOfWork() )
@@ -255,6 +297,15 @@ public abstract class AbstractValueCompositeSerializationTest
                     createdValue, equalTo( loadedValue ) );
     }
 
+    protected static Some buildSomeEntity( Module module, UnitOfWork uow, String identity )
+    {
+        EntityBuilder<Some> builder = uow.newEntityBuilder( Some.class );
+        Some proto = builder.instance();
+        proto.identity().set( StringIdentity.fromString( identity ) );
+        setSomeValueState( module, uow, proto );
+        return builder.newInstance();
+    }
+
     /**
      * @return a Some ValueComposite whose state is populated with test data.
      */
@@ -436,7 +487,7 @@ public abstract class AbstractValueCompositeSerializationTest
         @Optional
         Property<Byte[]> byteArrayNull();
 
-        Property<Object> serializable();
+        Property<SerializableObject> serializable();
 
         Property<Foo> foo();
 
@@ -591,6 +642,7 @@ public abstract class AbstractValueCompositeSerializationTest
     {
     }
 
+    @ConvertedBy( JavaSerializationConverter.class )
     public static class SerializableObject
         implements Serializable
     {

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/b2ff271b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/SQLMapEntityStoreMixin.java
----------------------------------------------------------------------
diff --git a/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/SQLMapEntityStoreMixin.java b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/SQLMapEntityStoreMixin.java
index f1a852f..682a5f7 100644
--- a/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/SQLMapEntityStoreMixin.java
+++ b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/SQLMapEntityStoreMixin.java
@@ -26,7 +26,6 @@ import java.sql.SQLException;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.stream.Stream;
-import javax.json.Json;
 import javax.sql.DataSource;
 import liquibase.Contexts;
 import liquibase.Liquibase;
@@ -42,6 +41,7 @@ import org.apache.polygene.api.injection.scope.Uses;
 import org.apache.polygene.api.service.ServiceActivation;
 import org.apache.polygene.api.service.ServiceDescriptor;
 import org.apache.polygene.library.sql.liquibase.LiquibaseService;
+import org.apache.polygene.serialization.javaxjson.JavaxJsonFactories;
 import org.apache.polygene.spi.entitystore.EntityNotFoundException;
 import org.apache.polygene.spi.entitystore.helpers.JSONKeys;
 import org.apache.polygene.spi.entitystore.helpers.MapEntityStore;
@@ -69,6 +69,9 @@ public class SQLMapEntityStoreMixin
     @Service
     private LiquibaseService liquibaseService;
 
+    @Service
+    private JavaxJsonFactories jsonFactories;
+
     @Uses
     private ServiceDescriptor descriptor;
 
@@ -194,8 +197,9 @@ public class SQLMapEntityStoreMixin
                     {
                         super.close();
                         String state = toString();
-                        String version = Json.createReader( new StringReader( state ) ).readObject()
-                                             .getString( JSONKeys.VERSION );
+                        String version = jsonFactories.readerFactory().createReader( new StringReader( state ) )
+                                                      .readObject()
+                                                      .getString( JSONKeys.VERSION );
                         operations.add(
                             dsl.insertInto( table )
                                .columns( identityColumn, versionColumn, stateColumn )


Mime
View raw message