You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@polygene.apache.org by pa...@apache.org on 2017/04/23 11:07:32 UTC

[2/7] polygene-java git commit: POLYGENE-247 Change Entity state JSON serialization format

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/b2ff271b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/SQLMapEntityStoreService.java
----------------------------------------------------------------------
diff --git a/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/SQLMapEntityStoreService.java b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/SQLMapEntityStoreService.java
index 7c770df..341de3b 100644
--- a/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/SQLMapEntityStoreService.java
+++ b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/SQLMapEntityStoreService.java
@@ -19,10 +19,8 @@ package org.apache.polygene.entitystore.sql;
 
 import org.apache.polygene.api.concern.Concerns;
 import org.apache.polygene.api.configuration.Configuration;
-import org.apache.polygene.api.injection.scope.Uses;
 import org.apache.polygene.api.mixin.Mixins;
 import org.apache.polygene.api.service.ServiceActivation;
-import org.apache.polygene.api.service.ServiceDescriptor;
 import org.apache.polygene.spi.entitystore.ConcurrentModificationCheckConcern;
 import org.apache.polygene.spi.entitystore.EntityStateVersions;
 import org.apache.polygene.spi.entitystore.EntityStore;

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/b2ff271b/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/ElasticSearchIndexer.java
----------------------------------------------------------------------
diff --git a/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/ElasticSearchIndexer.java b/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/ElasticSearchIndexer.java
index 344f9d7..c8caa7d 100644
--- a/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/ElasticSearchIndexer.java
+++ b/extensions/indexing-elasticsearch/src/main/java/org/apache/polygene/index/elasticsearch/ElasticSearchIndexer.java
@@ -19,11 +19,10 @@
  */
 package org.apache.polygene.index.elasticsearch;
 
-import java.io.StringReader;
 import java.util.HashMap;
 import java.util.Map;
-import javax.json.Json;
 import javax.json.JsonArrayBuilder;
+import javax.json.JsonObject;
 import javax.json.JsonObjectBuilder;
 import javax.json.JsonValue;
 import org.apache.polygene.api.entity.EntityDescriptor;
@@ -38,7 +37,7 @@ import org.apache.polygene.api.structure.ModuleDescriptor;
 import org.apache.polygene.api.time.SystemTime;
 import org.apache.polygene.api.usecase.UsecaseBuilder;
 import org.apache.polygene.api.util.Classes;
-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;
@@ -74,6 +73,9 @@ public interface ElasticSearchIndexer extends StateChangeListener
         @Service
         private JsonSerializer jsonSerializer;
 
+        @Service
+        private JavaxJsonFactories jsonFactories;
+
         @This
         private ElasticSearchSupport support;
 
@@ -118,13 +120,13 @@ public interface ElasticSearchIndexer extends StateChangeListener
                         case UPDATED:
                             LOGGER.trace( "Updating Entity State in Index: {}", changedState );
                             remove( bulkBuilder, changedState.entityReference().identity().toString() );
-                            String updatedJson = toJSON( changedState, newStates, uow );
+                            String updatedJson = toJSON( changedState, newStates, uow ).toString();
                             LOGGER.trace( "Will index: {}", updatedJson );
                             index( bulkBuilder, changedState.entityReference().identity().toString(), updatedJson );
                             break;
                         case NEW:
                             LOGGER.trace( "Creating Entity State in Index: {}", changedState );
-                            String newJson = toJSON( changedState, newStates, uow );
+                            String newJson = toJSON( changedState, newStates, uow ).toString();
                             LOGGER.trace( "Will index: {}", newJson );
                             index( bulkBuilder, changedState.entityReference().identity().toString(), newJson );
                             break;
@@ -182,13 +184,13 @@ public interface ElasticSearchIndexer extends StateChangeListener
          * }
          * </pre>
          */
-        private String toJSON( EntityState state, Map<String, EntityState> newStates, EntityStoreUnitOfWork uow )
+        private JsonObject toJSON( EntityState state, Map<String, EntityState> newStates, EntityStoreUnitOfWork uow )
         {
-            JsonObjectBuilder builder = Json.createObjectBuilder();
+            JsonObjectBuilder builder = jsonFactories.builderFactory().createObjectBuilder();
 
             builder.add( "_identity", state.entityReference().identity().toString() );
 
-            JsonArrayBuilder typesBuilder = Json.createArrayBuilder();
+            JsonArrayBuilder typesBuilder = jsonFactories.builderFactory().createArrayBuilder();
             state.entityDescriptor().mixinTypes().map( Classes.toClassName() ).forEach( typesBuilder::add );
             builder.add( "_types", typesBuilder.build() );
 
@@ -225,26 +227,20 @@ public interface ElasticSearchIndexer extends StateChangeListener
                             {
                                 if( newStates.containsKey( associated.identity().toString() ) )
                                 {
-                                    builder.add( key,
-                                                 Json.createReader( new StringReader(
-                                                     toJSON( newStates.get( associated.identity().toString() ),
-                                                             newStates, uow )
-                                                 ) ).readObject() );
+                                    builder.add( key, toJSON( newStates.get( associated.identity().toString() ),
+                                                              newStates, uow ) );
                                 }
                                 else
                                 {
                                     EntityReference reference = EntityReference.create( associated.identity() );
                                     EntityState assocState = uow.entityStateOf( entityType.module(), reference );
-                                    builder.add( key,
-                                                 Json.createReader( new StringReader(
-                                                     toJSON( assocState, newStates, uow )
-                                                 ) ).readObject() );
+                                    builder.add( key, toJSON( assocState, newStates, uow ) );
                                 }
                             }
                             else
                             {
-                                builder.add( key, Json.createObjectBuilder()
-                                                      .add( "reference", associated.identity().toString() ) );
+                                builder.add( key, jsonFactories.builderFactory().createObjectBuilder()
+                                                               .add( "reference", associated.identity().toString() ) );
                             }
                         }
                     }
@@ -257,7 +253,7 @@ public interface ElasticSearchIndexer extends StateChangeListener
                     if( manyAssocDesc.queryable() )
                     {
                         String key = manyAssocDesc.qualifiedName().name();
-                        JsonArrayBuilder assBuilder = Json.createArrayBuilder();
+                        JsonArrayBuilder assBuilder = jsonFactories.builderFactory().createArrayBuilder();
                         ManyAssociationState assocs = state.manyAssociationValueOf( manyAssocDesc.qualifiedName() );
                         for( EntityReference associated : assocs )
                         {
@@ -265,25 +261,21 @@ public interface ElasticSearchIndexer extends StateChangeListener
                             {
                                 if( newStates.containsKey( associated.identity().toString() ) )
                                 {
-                                    assBuilder.add(
-                                        Json.createReader( new StringReader(
-                                            toJSON( newStates.get( associated.identity().toString() ), newStates, uow )
-                                        ) ).readObject() );
+                                    assBuilder.add( toJSON( newStates.get( associated.identity().toString() ),
+                                                            newStates, uow ) );
                                 }
                                 else
                                 {
                                     EntityReference reference = EntityReference.create( associated.identity() );
                                     EntityState assocState = uow.entityStateOf( entityType.module(), reference );
-                                    assBuilder.add(
-                                        Json.createReader( new StringReader(
-                                            toJSON( assocState, newStates, uow )
-                                        ) ).readObject() );
+                                    assBuilder.add( toJSON( assocState, newStates, uow ) );
                                 }
                             }
                             else
                             {
-                                assBuilder.add( Json.createObjectBuilder().add( "reference",
-                                                                                associated.identity().toString() ) );
+                                assBuilder.add( jsonFactories.builderFactory().createObjectBuilder()
+                                                             .add( "reference",
+                                                                   associated.identity().toString() ) );
                             }
                         }
                         builder.add( key, assBuilder.build() );
@@ -297,7 +289,7 @@ public interface ElasticSearchIndexer extends StateChangeListener
                     if( namedAssocDesc.queryable() )
                     {
                         String key = namedAssocDesc.qualifiedName().name();
-                        JsonArrayBuilder assBuilder = Json.createArrayBuilder();
+                        JsonArrayBuilder assBuilder = jsonFactories.builderFactory().createArrayBuilder();
                         NamedAssociationState assocs = state.namedAssociationValueOf(
                             namedAssocDesc.qualifiedName() );
                         for( String name : assocs )
@@ -309,36 +301,32 @@ public interface ElasticSearchIndexer extends StateChangeListener
                                 if( newStates.containsKey( identityString ) )
                                 {
                                     assBuilder.add(
-                                        JavaxJson.toBuilder(
-                                            Json.createReader( new StringReader(
-                                                toJSON( newStates.get( identityString ), newStates, uow ) )
-                                            ).readObject()
-                                        ).add( "_named", name ).build() );
+                                        jsonFactories.cloneBuilder( toJSON( newStates.get( identityString ),
+                                                                            newStates, uow ) )
+                                                     .add( "_named", name )
+                                                     .build() );
                                 }
                                 else
                                 {
                                     EntityReference reference = EntityReference.create( identity );
                                     EntityState assocState = uow.entityStateOf( entityType.module(), reference );
                                     assBuilder.add(
-                                        JavaxJson.toBuilder(
-                                            Json.createReader( new StringReader(
-                                                toJSON( assocState, newStates, uow )
-                                            ) ).readObject()
-                                        ).add( "_named", name ).build() );
+                                        jsonFactories.cloneBuilder( toJSON( assocState, newStates, uow ) )
+                                                     .add( "_named", name ).build() );
                                 }
                             }
                             else
                             {
-                                assBuilder.add( Json.createObjectBuilder()
-                                                    .add( "_named", name )
-                                                    .add( "reference", identity.toString() )
-                                                    .build() );
+                                assBuilder.add( jsonFactories.builderFactory().createObjectBuilder()
+                                                             .add( "_named", name )
+                                                             .add( "reference", identity.toString() )
+                                                             .build() );
                             }
                         }
                         builder.add( key, assBuilder.build() );
                     }
                 } );
-            return builder.build().toString();
+            return builder.build();
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/b2ff271b/extensions/indexing-solr/src/main/java/org/apache/polygene/index/solr/internal/SolrEntityIndexerMixin.java
----------------------------------------------------------------------
diff --git a/extensions/indexing-solr/src/main/java/org/apache/polygene/index/solr/internal/SolrEntityIndexerMixin.java b/extensions/indexing-solr/src/main/java/org/apache/polygene/index/solr/internal/SolrEntityIndexerMixin.java
index 14335d0..1c4e372 100644
--- a/extensions/indexing-solr/src/main/java/org/apache/polygene/index/solr/internal/SolrEntityIndexerMixin.java
+++ b/extensions/indexing-solr/src/main/java/org/apache/polygene/index/solr/internal/SolrEntityIndexerMixin.java
@@ -26,7 +26,6 @@ import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
-import javax.json.Json;
 import javax.json.JsonArray;
 import javax.json.JsonNumber;
 import javax.json.JsonObject;
@@ -39,6 +38,7 @@ import org.apache.polygene.api.injection.scope.Uses;
 import org.apache.polygene.index.solr.EmbeddedSolrService;
 import org.apache.polygene.index.solr.SolrQueryService;
 import org.apache.polygene.library.rdf.entity.EntityStateSerializer;
+import org.apache.polygene.serialization.javaxjson.JavaxJsonFactories;
 import org.apache.polygene.spi.entity.EntityState;
 import org.apache.polygene.spi.entity.EntityStatus;
 import org.apache.solr.client.solrj.SolrServer;
@@ -66,6 +66,9 @@ public abstract class SolrEntityIndexerMixin
     @Service
     private EmbeddedSolrService solr;
 
+    @Service
+    private JavaxJsonFactories jsonFactories;
+
     @Uses
     private EntityStateSerializer stateSerializer;
 
@@ -177,19 +180,22 @@ public abstract class SolrEntityIndexerMixin
                     String value = statement.getObject().stringValue();
                     if( field.getType().getTypeName().equals( "json" ) )
                     {
-                        try( JsonParser parser = Json.createParser( new StringReader( value ) ) )
+                        try( JsonParser parser = jsonFactories.parserFactory()
+                                                              .createParser( new StringReader( value ) ) )
                         {
                             JsonParser.Event event = parser.next();
                             switch( event )
                             {
                                 case START_ARRAY:
-                                    try( JsonReader reader = Json.createReader( new StringReader( value ) ) )
+                                    try( JsonReader reader = jsonFactories.readerFactory()
+                                                                          .createReader( new StringReader( value ) ) )
                                     {
                                         indexJson( input, reader.readArray() );
                                     }
                                     break;
                                 case START_OBJECT:
-                                    try( JsonReader reader = Json.createReader( new StringReader( value ) ) )
+                                    try( JsonReader reader = jsonFactories.readerFactory()
+                                                                          .createReader( new StringReader( value ) ) )
                                     {
                                         indexJson( input, reader.readObject() );
                                     }

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/b2ff271b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/skeletons/SQLCompatEntityStateWrapper.java
----------------------------------------------------------------------
diff --git a/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/skeletons/SQLCompatEntityStateWrapper.java b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/skeletons/SQLCompatEntityStateWrapper.java
index 2584600..bf665c6 100644
--- a/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/skeletons/SQLCompatEntityStateWrapper.java
+++ b/extensions/indexing-sql/src/main/java/org/apache/polygene/index/sql/support/skeletons/SQLCompatEntityStateWrapper.java
@@ -33,6 +33,7 @@ import org.apache.polygene.api.identity.Identity;
 import org.apache.polygene.api.property.PropertyDescriptor;
 import org.apache.polygene.api.structure.ModuleDescriptor;
 import org.apache.polygene.api.type.CollectionType;
+import org.apache.polygene.api.type.EntityCompositeType;
 import org.apache.polygene.api.type.ValueCompositeType;
 import org.apache.polygene.api.type.ValueType;
 import org.apache.polygene.api.value.ValueComposite;
@@ -191,6 +192,12 @@ class SQLCompatEntityStateWrapper
         return wrappedEntityState.hashCode();
     }
 
+    @Override
+    public String toString()
+    {
+        return wrappedEntityState.toString();
+    }
+
     private static class CompatEntityDescriptorWrapper
         implements EntityDescriptor
     {
@@ -202,6 +209,12 @@ class SQLCompatEntityStateWrapper
         }
 
         @Override
+        public EntityCompositeType valueType()
+        {
+            return wrappedEntityDescriptor.valueType();
+        }
+
+        @Override
         public ModuleDescriptor module()
         {
             return wrappedEntityDescriptor.module();

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/b2ff271b/extensions/migration/src/main/java/org/apache/polygene/migration/MigrationService.java
----------------------------------------------------------------------
diff --git a/extensions/migration/src/main/java/org/apache/polygene/migration/MigrationService.java b/extensions/migration/src/main/java/org/apache/polygene/migration/MigrationService.java
index 79e1583..f361801 100644
--- a/extensions/migration/src/main/java/org/apache/polygene/migration/MigrationService.java
+++ b/extensions/migration/src/main/java/org/apache/polygene/migration/MigrationService.java
@@ -22,11 +22,10 @@ package org.apache.polygene.migration;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
-import javax.json.Json;
+import javax.json.JsonArrayBuilder;
 import javax.json.JsonException;
 import javax.json.JsonObject;
 import javax.json.JsonObjectBuilder;
-import javax.json.JsonString;
 import javax.json.JsonValue;
 import org.apache.polygene.api.activation.ActivatorAdapter;
 import org.apache.polygene.api.activation.Activators;
@@ -44,6 +43,7 @@ import org.apache.polygene.migration.assembly.EntityMigrationRule;
 import org.apache.polygene.migration.assembly.MigrationBuilder;
 import org.apache.polygene.migration.assembly.MigrationContext;
 import org.apache.polygene.migration.assembly.MigrationRule;
+import org.apache.polygene.serialization.javaxjson.JavaxJsonFactories;
 import org.apache.polygene.spi.entitystore.EntityStore;
 import org.apache.polygene.spi.entitystore.helpers.JSONKeys;
 import org.apache.polygene.spi.entitystore.helpers.Migration;
@@ -87,35 +87,84 @@ public interface MigrationService
     class MigrationMixin
         implements MigrationService, Migrator
     {
+        private static final Logger LOGGER = LoggerFactory.getLogger( MigrationService.class );
+
         @Structure
-        Application app;
+        private Application app;
 
         @This
-        Configuration<MigrationConfiguration> config;
+        private Configuration<MigrationConfiguration> config;
 
         @Uses
-        ServiceDescriptor descriptor;
+        private ServiceDescriptor descriptor;
+
+        @Service
+        private StateStore store;
 
         @Service
-        StateStore store;
+        private EntityStore entityStore;
 
         @Service
-        EntityStore entityStore;
+        private JsonSerialization serialization;
 
         @Service
-        JsonSerialization serialization;
+        private JavaxJsonFactories jsonFactories;
 
         @Structure
-        UnitOfWorkFactory uowf;
+        private UnitOfWorkFactory uowf;
 
         @This
-        Migrator migrator;
-
-        public MigrationBuilder builder;
-        public Logger log;
+        private Migrator migrator;
 
         @Service
-        Iterable<MigrationEvents> migrationEvents;
+        private Iterable<MigrationEvents> migrationEvents;
+
+        private MigrationBuilder builder;
+
+
+        @Override
+        public void initialize()
+            throws Exception
+        {
+            builder = descriptor.metaInfo( MigrationBuilder.class );
+
+            String version = app.version();
+            String lastVersion = config.get().lastStartupVersion().get();
+
+            // Run general rules if version has changed
+            if( !app.version().equals( lastVersion ) )
+            {
+                Iterable<MigrationRule> rules = builder.migrationRules().rulesBetweenVersions( lastVersion, version );
+                List<MigrationRule> executedRules = new ArrayList<>();
+                try
+                {
+                    if( rules != null )
+                    {
+                        for( MigrationRule rule : rules )
+                        {
+                            rule.upgrade( store, this );
+                            executedRules.add( rule );
+                            LOGGER.debug( rule.toString() );
+                        }
+
+                        LOGGER.info( "Migrated to " + version );
+                    }
+
+                    config.get().lastStartupVersion().set( version );
+                    config.save();
+                }
+                catch( Exception e )
+                {
+                    LOGGER.error( "Upgrade failed", e );
+
+                    // Downgrade the migrated rules
+                    for( MigrationRule executedRule : executedRules )
+                    {
+                        executedRule.downgrade( store, this );
+                    }
+                }
+            }
+        }
 
         @Override
         public JsonObject migrate( final JsonObject state, String toVersion, StateStore stateStore )
@@ -138,9 +187,9 @@ public interface MigrationService
 
                     migratedState = matchedRule.upgrade( context, migratedState, stateStore, migrator );
 
-                    if( context.isSuccess() && context.hasChanged() && log.isDebugEnabled() )
+                    if( context.isSuccess() && context.hasChanged() && LOGGER.isDebugEnabled() )
                     {
-                        log.debug( matchedRule.toString() );
+                        LOGGER.debug( matchedRule.toString() );
                     }
 
                     failures.addAll( context.failures() );
@@ -148,7 +197,7 @@ public interface MigrationService
                 }
             }
 
-            JsonObjectBuilder appVersionBuilder = Json.createObjectBuilder();
+            JsonObjectBuilder appVersionBuilder = jsonFactories.builderFactory().createObjectBuilder();
             for( Map.Entry<String, JsonValue> entry : migratedState.entrySet() )
             {
                 appVersionBuilder.add( entry.getKey(), entry.getValue() );
@@ -158,16 +207,16 @@ public interface MigrationService
 
             if( failures.size() > 0 )
             {
-                log.warn( "Migration of {} from {} to {} aborted, failed operation(s):\n{}",
-                          state.getString( JSONKeys.IDENTITY ), fromVersion, toVersion,
-                          String.join( "\n\t", failures ) );
+                LOGGER.warn( "Migration of {} from {} to {} aborted, failed operation(s):\n{}",
+                             state.getString( JSONKeys.IDENTITY ), fromVersion, toVersion,
+                             String.join( "\n\t", failures ) );
                 return state;
             }
 
             if( changed )
             {
-                log.info( "Migrated {} from {} to {}",
-                          migratedState.getString( JSONKeys.IDENTITY ), fromVersion, toVersion );
+                LOGGER.info( "Migrated {} from {} to {}",
+                             migratedState.getString( JSONKeys.IDENTITY ), fromVersion, toVersion );
                 return migratedState;
             }
 
@@ -175,77 +224,20 @@ public interface MigrationService
             return state;
         }
 
-        @Override
-        public void initialize()
-            throws Exception
-        {
-            builder = descriptor.metaInfo( MigrationBuilder.class );
-
-            log = LoggerFactory.getLogger( MigrationService.class );
-
-            String version = app.version();
-            String lastVersion = config.get().lastStartupVersion().get();
-
-            // Run general rules if version has changed
-            if( !app.version().equals( lastVersion ) )
-            {
-                Iterable<MigrationRule> rules = builder.migrationRules().rulesBetweenVersions( lastVersion, version );
-                List<MigrationRule> executedRules = new ArrayList<>();
-                try
-                {
-                    if( rules != null )
-                    {
-                        for( MigrationRule rule : rules )
-                        {
-                            rule.upgrade( store, this );
-                            executedRules.add( rule );
-                            log.debug( rule.toString() );
-                        }
-
-                        log.info( "Migrated to " + version );
-                    }
-
-                    config.get().lastStartupVersion().set( version );
-                    config.save();
-                }
-                catch( Exception e )
-                {
-                    log.error( "Upgrade failed", e );
-
-                    // Downgrade the migrated rules
-                    for( MigrationRule executedRule : executedRules )
-                    {
-                        executedRule.downgrade( store, this );
-                    }
-                }
-            }
-        }
-
         // Migrator implementation
         @Override
         public JsonObject addProperty( MigrationContext context, JsonObject state, String name, Object defaultValue )
             throws JsonException
         {
-            JsonObject properties = state.getJsonObject( JSONKeys.PROPERTIES );
-            if( !properties.containsKey( name ) )
+            JsonObject valueState = state.getJsonObject( JSONKeys.VALUE );
+            if( !valueState.containsKey( name ) )
             {
-                JsonValue value = serialization.toJson( defaultValue );
-                JsonObjectBuilder builder = Json.createObjectBuilder();
-                for( Map.Entry<String, JsonValue> entry : state.entrySet() )
-                {
-                    String key = entry.getKey();
-                    if( !JSONKeys.PROPERTIES.equals( key ) )
-                    {
-                        builder.add( key, entry.getValue() );
-                    }
-                }
-                JsonObjectBuilder propBuilder = Json.createObjectBuilder();
-                for( Map.Entry<String, JsonValue> entry : properties.entrySet() )
-                {
-                    propBuilder.add( entry.getKey(), entry.getValue() );
-                }
-                propBuilder.add( name, value );
-                builder.add( JSONKeys.PROPERTIES, propBuilder.build() );
+                valueState = jsonFactories.cloneBuilder( valueState )
+                                          .add( name, serialization.toJson( defaultValue ) )
+                                          .build();
+                JsonObject migratedState = jsonFactories.cloneBuilderExclude( state, JSONKeys.VALUE )
+                                                        .add( JSONKeys.VALUE, valueState )
+                                                        .build();
                 context.markAsChanged();
 
                 for( MigrationEvents migrationEvent : migrationEvents )
@@ -253,7 +245,7 @@ public interface MigrationService
                     migrationEvent.propertyAdded( state.getString( JSONKeys.IDENTITY ), name, defaultValue );
                 }
 
-                return builder.build();
+                return migratedState;
             }
             else
             {
@@ -266,42 +258,20 @@ public interface MigrationService
         public JsonObject removeProperty( MigrationContext context, JsonObject state, String name )
             throws JsonException
         {
-            JsonObject properties = state.getJsonObject( JSONKeys.PROPERTIES );
-            if( properties.containsKey( name ) )
+            JsonObject valueState = state.getJsonObject( JSONKeys.VALUE );
+            if( valueState.containsKey( name ) )
             {
-                JsonObjectBuilder builder = Json.createObjectBuilder();
-                for( Map.Entry<String, JsonValue> entry : state.entrySet() )
-                {
-                    String key = entry.getKey();
-                    if( !JSONKeys.PROPERTIES.equals( key ) )
-                    {
-                        builder.add( key, entry.getValue() );
-                    }
-                }
-                JsonObjectBuilder propBuilder = Json.createObjectBuilder();
-                for( Map.Entry<String, JsonValue> entry : properties.entrySet() )
-                {
-                    String key = entry.getKey();
-                    if( !name.equals( key ) )
-                    {
-                        propBuilder.add( key, entry.getValue() );
-                    }
-                    else
-                    {
-                        context.markAsChanged();
-                    }
-                }
-                builder.add( JSONKeys.PROPERTIES, propBuilder.build() );
-
-                if( context.hasChanged() )
+                valueState = jsonFactories.cloneBuilderExclude( valueState, name ).build();
+                JsonObject migratedState = jsonFactories
+                    .cloneBuilderExclude( state, JSONKeys.VALUE )
+                    .add( JSONKeys.VALUE, valueState )
+                    .build();
+                context.markAsChanged();
+                for( MigrationEvents migrationEvent : migrationEvents )
                 {
-                    for( MigrationEvents migrationEvent : migrationEvents )
-                    {
-                        migrationEvent.propertyRemoved( state.getString( JSONKeys.IDENTITY ), name );
-                    }
+                    migrationEvent.propertyRemoved( state.getString( JSONKeys.IDENTITY ), name );
                 }
-
-                return builder.build();
+                return migratedState;
             }
             else
             {
@@ -314,40 +284,22 @@ public interface MigrationService
         public JsonObject renameProperty( MigrationContext context, JsonObject state, String from, String to )
             throws JsonException
         {
-            JsonObject properties = state.getJsonObject( JSONKeys.PROPERTIES );
-            if( properties.containsKey( from ) )
+            JsonObject valueState = state.getJsonObject( JSONKeys.VALUE );
+            if( valueState.containsKey( from ) )
             {
-                JsonObjectBuilder builder = Json.createObjectBuilder();
-                for( Map.Entry<String, JsonValue> entry : state.entrySet() )
-                {
-                    String key = entry.getKey();
-                    if( !JSONKeys.PROPERTIES.equals( key ) )
-                    {
-                        builder.add( key, entry.getValue() );
-                    }
-                }
-                JsonObjectBuilder propBuilder = Json.createObjectBuilder();
-                for( Map.Entry<String, JsonValue> entry : properties.entrySet() )
-                {
-                    String key = entry.getKey();
-                    if( from.equals( key ) )
-                    {
-                        propBuilder.add( to, entry.getValue() );
-                        context.markAsChanged();
-                    }
-                    else
-                    {
-                        propBuilder.add( key, entry.getValue() );
-                    }
-                }
-                builder.add( JSONKeys.PROPERTIES, propBuilder.build() );
-
+                JsonValue jsonValue = valueState.get( from );
+                valueState = jsonFactories.cloneBuilderExclude( valueState, from )
+                                          .add( to, jsonValue )
+                                          .build();
+                JsonObject migratedState = jsonFactories.cloneBuilderExclude( state, JSONKeys.VALUE )
+                                                        .add( JSONKeys.VALUE, valueState )
+                                                        .build();
+                context.markAsChanged();
                 for( MigrationEvents migrationEvent : migrationEvents )
                 {
                     migrationEvent.propertyRenamed( state.getString( JSONKeys.IDENTITY ), from, to );
                 }
-
-                return builder.build();
+                return migratedState;
             }
             else
             {
@@ -361,34 +313,21 @@ public interface MigrationService
                                           String defaultReference )
             throws JsonException
         {
-            JsonObject associations = state.getJsonObject( JSONKeys.ASSOCIATIONS );
-            if( !associations.containsKey( name ) )
+            JsonObject valueState = state.getJsonObject( JSONKeys.VALUE );
+            if( !valueState.containsKey( name ) )
             {
-                JsonObjectBuilder builder = Json.createObjectBuilder();
-                for( Map.Entry<String, JsonValue> entry : state.entrySet() )
-                {
-                    String key = entry.getKey();
-                    if( !JSONKeys.ASSOCIATIONS.equals( key ) )
-                    {
-                        builder.add( key, entry.getValue() );
-                    }
-                }
-                JsonObjectBuilder assocBuilder = Json.createObjectBuilder();
-                for( Map.Entry<String, JsonValue> entry : associations.entrySet() )
-                {
-                    assocBuilder.add( entry.getKey(), entry.getValue() );
-                }
-                JsonValue value = serialization.toJson( defaultReference );
-                assocBuilder.add( name, value );
-                builder.add( JSONKeys.ASSOCIATIONS, assocBuilder.build() );
+                valueState = jsonFactories.cloneBuilder( valueState )
+                                          .add( name, defaultReference )
+                                          .build();
+                JsonObject migratedState = jsonFactories.cloneBuilderExclude( state, JSONKeys.VALUE )
+                                                        .add( JSONKeys.VALUE, valueState )
+                                                        .build();
                 context.markAsChanged();
-
                 for( MigrationEvents migrationEvent : migrationEvents )
                 {
                     migrationEvent.associationAdded( state.getString( JSONKeys.IDENTITY ), name, defaultReference );
                 }
-
-                return builder.build();
+                return migratedState;
             }
             else
             {
@@ -401,39 +340,19 @@ public interface MigrationService
         public JsonObject removeAssociation( MigrationContext context, JsonObject state, String name )
             throws JsonException
         {
-            JsonObject associations = state.getJsonObject( JSONKeys.ASSOCIATIONS );
-            if( associations.containsKey( name ) )
+            JsonObject valueState = state.getJsonObject( JSONKeys.VALUE );
+            if( valueState.containsKey( name ) )
             {
-                JsonObjectBuilder builder = Json.createObjectBuilder();
-                for( Map.Entry<String, JsonValue> entry : state.entrySet() )
-                {
-                    String key = entry.getKey();
-                    if( !JSONKeys.ASSOCIATIONS.equals( key ) )
-                    {
-                        builder.add( key, entry.getValue() );
-                    }
-                }
-                JsonObjectBuilder assocBuilder = Json.createObjectBuilder();
-                for( Map.Entry<String, JsonValue> entry : associations.entrySet() )
-                {
-                    String key = entry.getKey();
-                    if( !name.equals( key ) )
-                    {
-                        assocBuilder.add( key, entry.getValue() );
-                    }
-                    else
-                    {
-                        context.markAsChanged();
-                    }
-                }
-                builder.add( JSONKeys.ASSOCIATIONS, assocBuilder.build() );
-
+                valueState = jsonFactories.cloneBuilderExclude( valueState, name ).build();
+                JsonObject migratedState = jsonFactories.cloneBuilderExclude( state, JSONKeys.VALUE )
+                                                        .add( JSONKeys.VALUE, valueState )
+                                                        .build();
+                context.markAsChanged();
                 for( MigrationEvents migrationEvent : migrationEvents )
                 {
                     migrationEvent.associationRemoved( state.getString( JSONKeys.IDENTITY ), name );
                 }
-
-                return builder.build();
+                return migratedState;
             }
             else
             {
@@ -446,40 +365,22 @@ public interface MigrationService
         public JsonObject renameAssociation( MigrationContext context, JsonObject state, String from, String to )
             throws JsonException
         {
-            JsonObject associations = state.getJsonObject( JSONKeys.ASSOCIATIONS );
-            if( associations.containsKey( from ) )
+            JsonObject valueState = state.getJsonObject( JSONKeys.VALUE );
+            if( valueState.containsKey( from ) )
             {
-                JsonObjectBuilder builder = Json.createObjectBuilder();
-                for( Map.Entry<String, JsonValue> entry : state.entrySet() )
-                {
-                    String key = entry.getKey();
-                    if( !JSONKeys.ASSOCIATIONS.equals( key ) )
-                    {
-                        builder.add( key, entry.getValue() );
-                    }
-                }
-                JsonObjectBuilder assocBuilder = Json.createObjectBuilder();
-                for( Map.Entry<String, JsonValue> entry : associations.entrySet() )
-                {
-                    String key = entry.getKey();
-                    if( from.equals( key ) )
-                    {
-                        assocBuilder.add( to, entry.getValue() );
-                        context.markAsChanged();
-                    }
-                    else
-                    {
-                        assocBuilder.add( to, entry.getValue() );
-                    }
-                }
-                builder.add( JSONKeys.ASSOCIATIONS, assocBuilder.build() );
-
+                JsonValue jsonValue = valueState.get( from );
+                valueState = jsonFactories.cloneBuilderExclude( valueState, from )
+                                          .add( to, jsonValue )
+                                          .build();
+                JsonObject migratedState = jsonFactories.cloneBuilderExclude( state, JSONKeys.VALUE )
+                                                        .add( JSONKeys.VALUE, valueState )
+                                                        .build();
+                context.markAsChanged();
                 for( MigrationEvents migrationEvent : migrationEvents )
                 {
                     migrationEvent.associationRenamed( state.getString( JSONKeys.IDENTITY ), from, to );
                 }
-
-                return builder.build();
+                return migratedState;
             }
             else
             {
@@ -493,35 +394,27 @@ public interface MigrationService
                                               String... defaultReferences )
             throws JsonException
         {
-            JsonObject manyAssociations = state.getJsonObject( JSONKeys.MANY_ASSOCIATIONS );
-            if( !manyAssociations.containsKey( name ) )
+            JsonObject valueState = state.getJsonObject( JSONKeys.VALUE );
+            if( !valueState.containsKey( name ) )
             {
-                JsonObjectBuilder builder = Json.createObjectBuilder();
-                for( Map.Entry<String, JsonValue> entry : state.entrySet() )
-                {
-                    String key = entry.getKey();
-                    if( !JSONKeys.MANY_ASSOCIATIONS.equals( key ) )
-                    {
-                        builder.add( key, entry.getValue() );
-                    }
-                }
-                JsonObjectBuilder assocBuilder = Json.createObjectBuilder();
-                for( Map.Entry<String, JsonValue> entry : manyAssociations.entrySet() )
+                JsonArrayBuilder refArrayBuilder = jsonFactories.builderFactory().createArrayBuilder();
+                for( String ref : defaultReferences )
                 {
-                    assocBuilder.add( entry.getKey(), entry.getValue() );
+                    refArrayBuilder.add( ref );
                 }
-                JsonValue value = serialization.toJson( defaultReferences );
-                assocBuilder.add( name, value );
-                builder.add( JSONKeys.MANY_ASSOCIATIONS, assocBuilder.build() );
+                valueState = jsonFactories.cloneBuilder( valueState )
+                                          .add( name, refArrayBuilder.build() )
+                                          .build();
+                JsonObject migratedState = jsonFactories.cloneBuilderExclude( state, JSONKeys.VALUE )
+                                                        .add( JSONKeys.VALUE, valueState )
+                                                        .build();
                 context.markAsChanged();
-
                 for( MigrationEvents migrationEvent : migrationEvents )
                 {
                     migrationEvent.manyAssociationAdded( state.getString( JSONKeys.IDENTITY ), name,
                                                          defaultReferences );
                 }
-
-                return builder.build();
+                return migratedState;
             }
             else
             {
@@ -534,39 +427,19 @@ public interface MigrationService
         public JsonObject removeManyAssociation( MigrationContext context, JsonObject state, String name )
             throws JsonException
         {
-            JsonObject manyAssociations = state.getJsonObject( JSONKeys.MANY_ASSOCIATIONS );
-            if( manyAssociations.containsKey( name ) )
+            JsonObject valueState = state.getJsonObject( JSONKeys.VALUE );
+            if( valueState.containsKey( name ) )
             {
-                JsonObjectBuilder builder = Json.createObjectBuilder();
-                for( Map.Entry<String, JsonValue> entry : state.entrySet() )
-                {
-                    String key = entry.getKey();
-                    if( !JSONKeys.MANY_ASSOCIATIONS.equals( key ) )
-                    {
-                        builder.add( key, entry.getValue() );
-                    }
-                }
-                JsonObjectBuilder assocBuilder = Json.createObjectBuilder();
-                for( Map.Entry<String, JsonValue> entry : manyAssociations.entrySet() )
-                {
-                    String key = entry.getKey();
-                    if( !name.equals( key ) )
-                    {
-                        assocBuilder.add( key, entry.getValue() );
-                    }
-                    else
-                    {
-                        context.markAsChanged();
-                    }
-                }
-                builder.add( JSONKeys.MANY_ASSOCIATIONS, assocBuilder.build() );
-
+                valueState = jsonFactories.cloneBuilderExclude( valueState, name ).build();
+                JsonObject migratedState = jsonFactories.cloneBuilderExclude( state, JSONKeys.VALUE )
+                                                        .add( JSONKeys.VALUE, valueState )
+                                                        .build();
+                context.markAsChanged();
                 for( MigrationEvents migrationEvent : migrationEvents )
                 {
                     migrationEvent.manyAssociationRemoved( state.getString( JSONKeys.IDENTITY ), name );
                 }
-
-                return builder.build();
+                return migratedState;
             }
             else
             {
@@ -579,40 +452,22 @@ public interface MigrationService
         public JsonObject renameManyAssociation( MigrationContext context, JsonObject state, String from, String to )
             throws JsonException
         {
-            JsonObject manyAssociations = state.getJsonObject( JSONKeys.MANY_ASSOCIATIONS );
-            if( manyAssociations.containsKey( from ) )
+            JsonObject valueState = state.getJsonObject( JSONKeys.VALUE );
+            if( valueState.containsKey( from ) )
             {
-                JsonObjectBuilder builder = Json.createObjectBuilder();
-                for( Map.Entry<String, JsonValue> entry : state.entrySet() )
-                {
-                    String key = entry.getKey();
-                    if( !JSONKeys.MANY_ASSOCIATIONS.equals( key ) )
-                    {
-                        builder.add( key, entry.getValue() );
-                    }
-                }
-                JsonObjectBuilder assocBuilder = Json.createObjectBuilder();
-                for( Map.Entry<String, JsonValue> entry : manyAssociations.entrySet() )
-                {
-                    String key = entry.getKey();
-                    if( from.equals( key ) )
-                    {
-                        context.markAsChanged();
-                        assocBuilder.add( to, entry.getValue() );
-                    }
-                    else
-                    {
-                        assocBuilder.add( key, entry.getValue() );
-                    }
-                }
-                builder.add( JSONKeys.MANY_ASSOCIATIONS, assocBuilder.build() );
-
+                JsonValue jsonValue = valueState.get( from );
+                valueState = jsonFactories.cloneBuilderExclude( valueState, from )
+                                          .add( to, jsonValue )
+                                          .build();
+                JsonObject migratedState = jsonFactories.cloneBuilderExclude( state, JSONKeys.VALUE )
+                                                        .add( JSONKeys.VALUE, valueState )
+                                                        .build();
+                context.markAsChanged();
                 for( MigrationEvents migrationEvent : migrationEvents )
                 {
                     migrationEvent.manyAssociationRenamed( state.getString( JSONKeys.IDENTITY ), from, to );
                 }
-
-                return builder.build();
+                return migratedState;
             }
             else
             {
@@ -626,35 +481,27 @@ public interface MigrationService
                                                Map<String, String> defaultReferences )
             throws JsonException
         {
-            JsonObject namedAssociations = state.getJsonObject( JSONKeys.NAMED_ASSOCIATIONS );
-            if( !namedAssociations.containsKey( name ) )
+            JsonObject valueState = state.getJsonObject( JSONKeys.VALUE );
+            if( !valueState.containsKey( name ) )
             {
-                JsonObjectBuilder builder = Json.createObjectBuilder();
-                for( Map.Entry<String, JsonValue> entry : state.entrySet() )
+                JsonObjectBuilder refBuilder = jsonFactories.builderFactory().createObjectBuilder();
+                for( Map.Entry<String, String> entry : defaultReferences.entrySet() )
                 {
-                    String key = entry.getKey();
-                    if( !JSONKeys.NAMED_ASSOCIATIONS.equals( key ) )
-                    {
-                        builder.add( key, entry.getValue() );
-                    }
-                }
-                JsonObjectBuilder assocBuilder = Json.createObjectBuilder();
-                for( Map.Entry<String, JsonValue> entry : namedAssociations.entrySet() )
-                {
-                    assocBuilder.add( entry.getKey(), entry.getValue() );
+                    refBuilder.add( entry.getKey(), entry.getValue() );
                 }
-                JsonValue value = serialization.toJson( defaultReferences );
-                assocBuilder.add( name, value );
-                builder.add( JSONKeys.NAMED_ASSOCIATIONS, assocBuilder.build() );
+                valueState = jsonFactories.cloneBuilder( valueState )
+                                          .add( name, refBuilder.build() )
+                                          .build();
+                JsonObject migratedState = jsonFactories.cloneBuilderExclude( state, JSONKeys.VALUE )
+                                                        .add( JSONKeys.VALUE, valueState )
+                                                        .build();
                 context.markAsChanged();
-
                 for( MigrationEvents migrationEvent : migrationEvents )
                 {
                     migrationEvent.namedAssociationAdded( state.getString( JSONKeys.IDENTITY ), name,
                                                           defaultReferences );
                 }
-
-                return builder.build();
+                return migratedState;
             }
             else
             {
@@ -667,39 +514,19 @@ public interface MigrationService
         public JsonObject removeNamedAssociation( MigrationContext context, JsonObject state, String name )
             throws JsonException
         {
-            JsonObject namedAssociations = state.getJsonObject( JSONKeys.NAMED_ASSOCIATIONS );
-            if( namedAssociations.containsKey( name ) )
+            JsonObject valueState = state.getJsonObject( JSONKeys.VALUE );
+            if( !valueState.containsKey( name ) )
             {
-                JsonObjectBuilder builder = Json.createObjectBuilder();
-                for( Map.Entry<String, JsonValue> entry : state.entrySet() )
-                {
-                    String key = entry.getKey();
-                    if( !JSONKeys.NAMED_ASSOCIATIONS.equals( key ) )
-                    {
-                        builder.add( key, entry.getValue() );
-                    }
-                }
-                JsonObjectBuilder assocBuilder = Json.createObjectBuilder();
-                for( Map.Entry<String, JsonValue> entry : namedAssociations.entrySet() )
-                {
-                    String key = entry.getKey();
-                    if( !name.equals( key ) )
-                    {
-                        assocBuilder.add( key, entry.getValue() );
-                    }
-                    else
-                    {
-                        context.markAsChanged();
-                    }
-                }
-                builder.add( JSONKeys.NAMED_ASSOCIATIONS, assocBuilder.build() );
-
+                valueState = jsonFactories.cloneBuilderExclude( valueState, name ).build();
+                JsonObject migratedState = jsonFactories.cloneBuilderExclude( state, JSONKeys.VALUE )
+                                                        .add( JSONKeys.VALUE, valueState )
+                                                        .build();
+                context.markAsChanged();
                 for( MigrationEvents migrationEvent : migrationEvents )
                 {
                     migrationEvent.namedAssociationRemoved( state.getString( JSONKeys.IDENTITY ), name );
                 }
-
-                return builder.build();
+                return migratedState;
             }
             else
             {
@@ -712,40 +539,22 @@ public interface MigrationService
         public JsonObject renameNamedAssociation( MigrationContext context, JsonObject state, String from, String to )
             throws JsonException
         {
-            JsonObject namedAssociations = state.getJsonObject( JSONKeys.NAMED_ASSOCIATIONS );
-            if( namedAssociations.containsKey( from ) )
+            JsonObject valueState = state.getJsonObject( JSONKeys.VALUE );
+            if( valueState.containsKey( from ) )
             {
-                JsonObjectBuilder builder = Json.createObjectBuilder();
-                for( Map.Entry<String, JsonValue> entry : state.entrySet() )
-                {
-                    String key = entry.getKey();
-                    if( !JSONKeys.NAMED_ASSOCIATIONS.equals( key ) )
-                    {
-                        builder.add( key, entry.getValue() );
-                    }
-                }
-                JsonObjectBuilder assocBuilder = Json.createObjectBuilder();
-                for( Map.Entry<String, JsonValue> entry : namedAssociations.entrySet() )
-                {
-                    String key = entry.getKey();
-                    if( from.equals( key ) )
-                    {
-                        assocBuilder.add( to, entry.getValue() );
-                        context.markAsChanged();
-                    }
-                    else
-                    {
-                        assocBuilder.add( key, entry.getValue() );
-                    }
-                }
-                builder.add( JSONKeys.NAMED_ASSOCIATIONS, assocBuilder.build() );
-
+                JsonValue jsonValue = valueState.get( from );
+                valueState = jsonFactories.cloneBuilderExclude( valueState, from )
+                                          .add( to, jsonValue )
+                                          .build();
+                JsonObject migratedState = jsonFactories.cloneBuilderExclude( state, JSONKeys.VALUE )
+                                                        .add( JSONKeys.VALUE, valueState )
+                                                        .build();
+                context.markAsChanged();
                 for( MigrationEvents migrationEvent : migrationEvents )
                 {
                     migrationEvent.namedAssociationRenamed( state.getString( JSONKeys.IDENTITY ), from, to );
                 }
-
-                return builder.build();
+                return migratedState;
             }
             else
             {
@@ -759,35 +568,23 @@ public interface MigrationService
                                             String fromType, String toType )
             throws JsonException
         {
-            JsonObjectBuilder builder = Json.createObjectBuilder();
-            for( Map.Entry<String, JsonValue> entry : state.entrySet() )
+            String currentType = state.getString( JSONKeys.TYPE );
+            if( fromType.equals( currentType ) )
             {
-                String key = entry.getKey();
-                if( JSONKeys.TYPE.equals( key ) )
-                {
-                    String oldValue = entry.getValue().getValueType() == JsonValue.ValueType.STRING
-                                      ? ( (JsonString) entry.getValue() ).getString()
-                                      : entry.getValue().toString();
-                    if( !fromType.equals( oldValue ) )
-                    {
-                        context.addFailure( "Change entity type from " + fromType + " to " + toType );
-                        return state;
-                    }
-                    builder.add( JSONKeys.TYPE, toType );
-                    context.markAsChanged();
-                }
-                else
+                JsonObject migratedState = jsonFactories.cloneBuilder( state )
+                                                        .add( JSONKeys.TYPE, toType )
+                                                        .build();
+                for( MigrationEvents migrationEvent : migrationEvents )
                 {
-                    builder.add( key, entry.getValue() );
+                    migrationEvent.entityTypeChanged( state.getString( JSONKeys.IDENTITY ), toType );
                 }
+                return migratedState;
             }
-
-            for( MigrationEvents migrationEvent : migrationEvents )
+            else
             {
-                migrationEvent.entityTypeChanged( state.getString( JSONKeys.IDENTITY ), toType );
+                context.addFailure( "Change entity type from " + fromType + " to " + toType );
+                return state;
             }
-
-            return builder.build();
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/b2ff271b/extensions/migration/src/test/java/org/apache/polygene/migration/MigrationTest.java
----------------------------------------------------------------------
diff --git a/extensions/migration/src/test/java/org/apache/polygene/migration/MigrationTest.java b/extensions/migration/src/test/java/org/apache/polygene/migration/MigrationTest.java
index 1068abb..27fe187 100644
--- a/extensions/migration/src/test/java/org/apache/polygene/migration/MigrationTest.java
+++ b/extensions/migration/src/test/java/org/apache/polygene/migration/MigrationTest.java
@@ -221,8 +221,8 @@ public class MigrationTest
         @Override
         public JsonObject upgrade( MigrationContext context, JsonObject state, StateStore store, Migrator migrator )
         {
-            JsonObject properties = state.getJsonObject( JSONKeys.PROPERTIES );
-            return migrator.addProperty( context, state, "customBar", "Hello " + properties.getString( "bar" ) );
+            JsonObject valueState = state.getJsonObject( JSONKeys.VALUE );
+            return migrator.addProperty( context, state, "customBar", "Hello " + valueState.getString( "bar" ) );
         }
 
         @Override

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/b2ff271b/extensions/serialization-javaxjson/src/main/java/org/apache/polygene/serialization/javaxjson/assembly/JavaxJsonSerializationAssembler.java
----------------------------------------------------------------------
diff --git a/extensions/serialization-javaxjson/src/main/java/org/apache/polygene/serialization/javaxjson/assembly/JavaxJsonSerializationAssembler.java b/extensions/serialization-javaxjson/src/main/java/org/apache/polygene/serialization/javaxjson/assembly/JavaxJsonSerializationAssembler.java
index 5152f1b..10a8622 100644
--- a/extensions/serialization-javaxjson/src/main/java/org/apache/polygene/serialization/javaxjson/assembly/JavaxJsonSerializationAssembler.java
+++ b/extensions/serialization-javaxjson/src/main/java/org/apache/polygene/serialization/javaxjson/assembly/JavaxJsonSerializationAssembler.java
@@ -17,12 +17,14 @@
  */
 package org.apache.polygene.serialization.javaxjson.assembly;
 
+import org.apache.polygene.api.serialization.Converters;
 import org.apache.polygene.api.serialization.Deserializer;
 import org.apache.polygene.api.serialization.Serialization;
 import org.apache.polygene.api.serialization.Serializer;
 import org.apache.polygene.bootstrap.Assemblers;
 import org.apache.polygene.bootstrap.ModuleAssembly;
 import org.apache.polygene.bootstrap.ServiceDeclaration;
+import org.apache.polygene.serialization.javaxjson.JavaxJsonAdapters;
 import org.apache.polygene.serialization.javaxjson.JavaxJsonFactories;
 import org.apache.polygene.serialization.javaxjson.JavaxJsonSerialization;
 import org.apache.polygene.serialization.javaxjson.JavaxJsonSettings;
@@ -46,9 +48,10 @@ public class JavaxJsonSerializationAssembler extends Assemblers.VisibilityIdenti
         ServiceDeclaration declaration = module.services( JavaxJsonSerialization.class )
                                                .withTypes( Serialization.class,
                                                            Serializer.class, Deserializer.class,
+                                                           Converters.class,
                                                            JsonSerialization.class,
                                                            JsonSerializer.class, JsonDeserializer.class,
-                                                           JavaxJsonFactories.class )
+                                                           JavaxJsonFactories.class, JavaxJsonAdapters.class )
                                                .taggedWith( Serialization.Format.JSON )
                                                .visibleIn( visibility() );
         if( hasIdentity() )

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/b2ff271b/extensions/serialization-javaxjson/src/test/java/org/apache/polygene/serialization/javaxjson/CustomJsonAdapterTest.java
----------------------------------------------------------------------
diff --git a/extensions/serialization-javaxjson/src/test/java/org/apache/polygene/serialization/javaxjson/CustomJsonAdapterTest.java b/extensions/serialization-javaxjson/src/test/java/org/apache/polygene/serialization/javaxjson/CustomJsonAdapterTest.java
index 57ad62b..85db21e 100644
--- a/extensions/serialization-javaxjson/src/test/java/org/apache/polygene/serialization/javaxjson/CustomJsonAdapterTest.java
+++ b/extensions/serialization-javaxjson/src/test/java/org/apache/polygene/serialization/javaxjson/CustomJsonAdapterTest.java
@@ -20,7 +20,6 @@ package org.apache.polygene.serialization.javaxjson;
 import java.time.LocalDate;
 import java.util.function.BiFunction;
 import java.util.function.Function;
-import javax.json.JsonBuilderFactory;
 import javax.json.JsonObject;
 import javax.json.JsonString;
 import javax.json.JsonValue;
@@ -86,11 +85,10 @@ public class CustomJsonAdapterTest extends AbstractPolygeneTest
         public Class<CustomValue> type() { return CustomValue.class; }
 
         @Override
-        public JsonValue serialize( JsonBuilderFactory builderFactory,
+        public JsonValue serialize( JavaxJsonFactories jsonFactories,
                                     Object object, Function<Object, JsonValue> serialize )
         {
-            // TODO FUCK JSON
-            return JavaxJson.toJsonString( type().cast( object ).state );
+            return jsonFactories.toJsonString( type().cast( object ).state );
         }
 
         @Override
@@ -112,14 +110,14 @@ public class CustomJsonAdapterTest extends AbstractPolygeneTest
         public Class<CustomStructure> type() { return CustomStructure.class; }
 
         @Override
-        public JsonValue serialize( JsonBuilderFactory builderFactory,
+        public JsonValue serialize( JavaxJsonFactories jsonFactories,
                                     Object object, Function<Object, JsonValue> serialize )
         {
             CustomStructure customStructure = type().cast( object );
-            return builderFactory.createObjectBuilder()
-                                 .add( "foo", customStructure.foo )
-                                 .add( "bar", serialize.apply( customStructure.bar ) )
-                                 .build();
+            return jsonFactories.builderFactory().createObjectBuilder()
+                                .add( "foo", customStructure.foo )
+                                .add( "bar", serialize.apply( customStructure.bar ) )
+                                .build();
         }
 
         @Override

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/b2ff271b/extensions/serialization-javaxjson/src/test/java/org/apache/polygene/serialization/javaxjson/JavaxJsonValueCompositeSerializationTest.java
----------------------------------------------------------------------
diff --git a/extensions/serialization-javaxjson/src/test/java/org/apache/polygene/serialization/javaxjson/JavaxJsonValueCompositeSerializationTest.java b/extensions/serialization-javaxjson/src/test/java/org/apache/polygene/serialization/javaxjson/JavaxJsonValueCompositeSerializationTest.java
index 34b81c5..d628cb2 100644
--- a/extensions/serialization-javaxjson/src/test/java/org/apache/polygene/serialization/javaxjson/JavaxJsonValueCompositeSerializationTest.java
+++ b/extensions/serialization-javaxjson/src/test/java/org/apache/polygene/serialization/javaxjson/JavaxJsonValueCompositeSerializationTest.java
@@ -18,10 +18,10 @@
 package org.apache.polygene.serialization.javaxjson;
 
 import java.io.StringReader;
-import javax.json.Json;
 import javax.json.JsonObject;
 import javax.json.JsonValue;
 import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.serialization.Serializer;
 import org.apache.polygene.api.unitofwork.UnitOfWork;
 import org.apache.polygene.bootstrap.ModuleAssembly;
 import org.apache.polygene.serialization.javaxjson.assembly.JavaxJsonSerializationAssembler;
@@ -50,27 +50,33 @@ public class JavaxJsonValueCompositeSerializationTest extends AbstractValueCompo
     JsonSerialization jsonSerialization;
     // END SNIPPET: json-serialization
 
+    @Service
+    JavaxJsonFactories jsonFactories;
+
     @Test
     public void valueCompositeJsonEquality()
     {
         // START SNIPPET: json-serialization
         try( UnitOfWork uow = unitOfWorkFactory.newUnitOfWork() )
         {
-            Some some = buildSomeValue( moduleInstance, uow, "42" );
+            Some valueInstance = buildSomeValue( moduleInstance, uow, "42" );
 
             // Serialize using injected service
-            JsonValue jsonState = jsonSerialization.toJson( some );
-            String stateString = jsonState.toString();
-            System.out.println( jsonState.toString() );
+            JsonValue serializedJson = jsonSerialization.toJson( valueInstance );
+            System.out.println( serializedJson.toString() );
 
             // Deserialize using Module API
-            Some some2 = moduleInstance.newValueFromSerializedState( Some.class, stateString );
-
-            assertThat( "Deserialized Value equality", some, equalTo( some2 ) );
-
-            JsonObject jsonState2 = Json.createReader( new StringReader( some2.toString() ) ).readObject();
+            Some valueFromSerializedState = moduleInstance.newValueFromSerializedState( Some.class, serializedJson.toString() );
+            assertThat( "Deserialized Value equality", valueInstance, equalTo( valueFromSerializedState ) );
+            // END SNIPPET: json-serialization
 
-            assertThat( "value.toString() JSON equality", jsonState, equalTo( jsonState2 ) );
+            // value.toString()
+            JsonValue valueJsonWithoutTypeInfo = jsonSerialization.toJson( Serializer.Options.NO_TYPE_INFO, valueFromSerializedState );
+            JsonObject valueToStringJson = jsonFactories.readerFactory()
+                                                        .createReader( new StringReader( valueFromSerializedState.toString() ) )
+                                                        .readObject();
+            assertThat( "value.toString() JSON equality", valueJsonWithoutTypeInfo, equalTo( valueToStringJson ) );
+            // START SNIPPET: json-serialization
         }
         // END SNIPPET: json-serialization
     }

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/b2ff271b/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXmlDeserializer.java
----------------------------------------------------------------------
diff --git a/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXmlDeserializer.java b/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXmlDeserializer.java
index 3561d1e..a4863c0 100644
--- a/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXmlDeserializer.java
+++ b/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXmlDeserializer.java
@@ -38,6 +38,8 @@ import javax.xml.transform.TransformerException;
 import javax.xml.transform.dom.DOMResult;
 import javax.xml.transform.stream.StreamSource;
 import org.apache.polygene.api.association.AssociationDescriptor;
+import org.apache.polygene.api.composite.CompositeDescriptor;
+import org.apache.polygene.api.composite.StatefulAssociationCompositeDescriptor;
 import org.apache.polygene.api.entity.EntityReference;
 import org.apache.polygene.api.injection.scope.This;
 import org.apache.polygene.api.injection.scope.Uses;
@@ -53,11 +55,10 @@ import org.apache.polygene.api.type.ArrayType;
 import org.apache.polygene.api.type.CollectionType;
 import org.apache.polygene.api.type.EnumType;
 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.ValueBuilder;
-import org.apache.polygene.api.value.ValueDescriptor;
 import org.apache.polygene.spi.serialization.AbstractTextDeserializer;
 import org.apache.polygene.spi.serialization.XmlDeserializer;
 import org.w3c.dom.Element;
@@ -149,35 +150,38 @@ public class JavaxXmlDeserializer extends AbstractTextDeserializer
         {
             return (T) adapter.deserialize( xml, ( element, type ) -> doDeserialize( module, type, element ) );
         }
-        if( EnumType.class.isAssignableFrom( valueType.getClass() ) )
+        Class<? extends ValueType> valueTypeClass = valueType.getClass();
+        if( EnumType.class.isAssignableFrom( valueTypeClass ) )
         {
             return (T) Enum.valueOf( (Class) valueType.primaryType(), xml.getNodeValue() );
         }
-        if( ArrayType.class.isAssignableFrom( valueType.getClass() ) )
+        if( ArrayType.class.isAssignableFrom( valueTypeClass ) )
         {
             return (T) deserializeArray( module, (ArrayType) valueType, xml );
         }
-        if( CollectionType.class.isAssignableFrom( valueType.getClass() ) )
+        if( CollectionType.class.isAssignableFrom( valueTypeClass ) )
         {
             return (T) deserializeCollection( module, (CollectionType) valueType, xml );
         }
-        if( MapType.class.isAssignableFrom( valueType.getClass() ) )
+        if( MapType.class.isAssignableFrom( valueTypeClass ) )
         {
             return (T) deserializeMap( module, (MapType) valueType, xml );
         }
-        if( ValueCompositeType.class.isAssignableFrom( valueType.getClass() ) )
+        if( StatefulAssociationValueType.class.isAssignableFrom( valueTypeClass ) )
         {
-            return (T) deserializeValueComposite( module, (ValueCompositeType) valueType, xml );
+            return (T) deserializeStatefulAssociationValue( module, (StatefulAssociationValueType<?>) valueType, xml );
         }
         return (T) doGuessDeserialize( module, valueType, xml );
     }
 
-    private Object deserializeValueComposite( ModuleDescriptor module, ValueCompositeType valueType, Node xml )
+    private Object deserializeStatefulAssociationValue( ModuleDescriptor module,
+                                                        StatefulAssociationValueType<?> valueType, Node xml )
     {
         Optional<String> typeInfo = getTypeInfo( xml );
         if( typeInfo.isPresent() )
         {
-            ValueDescriptor descriptor = module.valueDescriptor( typeInfo.get() );
+            StatefulAssociationCompositeDescriptor descriptor = statefulCompositeDescriptorFor( module,
+                                                                                                typeInfo.get() );
             if( descriptor == null )
             {
                 String typeInfoName = settings.getTypeInfoTagName();
@@ -354,22 +358,12 @@ public class JavaxXmlDeserializer extends AbstractTextDeserializer
         Optional<String> typeInfo = getTypeInfo( xml );
         if( typeInfo.isPresent() )
         {
-            ValueDescriptor valueDescriptor = module.valueDescriptor( typeInfo.get() );
-            if( valueDescriptor != null )
+            StatefulAssociationCompositeDescriptor descriptor = statefulCompositeDescriptorFor( module,
+                                                                                                typeInfo.get() );
+            if( descriptor != null )
             {
-                return deserializeValueComposite( valueDescriptor.module(), valueDescriptor.valueType(), xml );
-            }
-        }
-        if( xml.getNodeType() == Node.CDATA_SECTION_NODE || xml.getNodeType() == Node.TEXT_NODE )
-        {
-            byte[] bytes = Base64.getDecoder().decode( xml.getNodeValue().getBytes( UTF_8 ) );
-            try
-            {
-                return deserializeJava( bytes );
-            }
-            catch( SerializationException ex )
-            {
-                throw new SerializationException( "Don't know how to deserialize " + valueType + " from " + xml, ex );
+                return deserializeStatefulAssociationValue( ( (CompositeDescriptor) descriptor ).module(),
+                                                            descriptor.valueType(), xml );
             }
         }
         throw new SerializationException( "Don't know how to deserialize " + valueType + " from " + xml );

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/b2ff271b/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXmlSerializer.java
----------------------------------------------------------------------
diff --git a/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXmlSerializer.java b/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXmlSerializer.java
index fa50019..927359a 100644
--- a/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXmlSerializer.java
+++ b/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/JavaxXmlSerializer.java
@@ -31,7 +31,9 @@ import javax.xml.transform.stream.StreamResult;
 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.entity.EntityReference;
 import org.apache.polygene.api.injection.scope.Structure;
 import org.apache.polygene.api.injection.scope.This;
@@ -46,10 +48,7 @@ import org.apache.polygene.api.structure.Module;
 import org.apache.polygene.api.type.ArrayType;
 import org.apache.polygene.api.type.EnumType;
 import org.apache.polygene.api.type.MapType;
-import org.apache.polygene.api.type.ValueCompositeType;
-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.api.type.StatefulAssociationValueType;
 import org.apache.polygene.spi.serialization.AbstractTextSerializer;
 import org.apache.polygene.spi.serialization.XmlSerializer;
 import org.apache.polygene.spi.util.ArrayIterable;
@@ -146,11 +145,6 @@ public class JavaxXmlSerializer extends AbstractTextSerializer
             return document.createElement( NULL_ELEMENT_NAME );
         }
         Class<?> objectClass = object.getClass();
-        ConvertedBy convertedBy = Annotations.annotationOn( objectClass, ConvertedBy.class );
-        if( convertedBy != null )
-        {
-            return doSerialize( document, options, module.newObject( convertedBy.value() ).toString( object ), false );
-        }
         Converter<Object> converter = converters.converterFor( objectClass );
         if( converter != null )
         {
@@ -165,9 +159,9 @@ public class JavaxXmlSerializer extends AbstractTextSerializer
         {
             return document.createTextNode( object.toString() );
         }
-        if( ValueCompositeType.isValueComposite( objectClass ) )
+        if( StatefulAssociationValueType.isStatefulAssociationValue( objectClass ) )
         {
-            return serializeValueComposite( document, options, object, root );
+            return serializeStatefulAssociationValue( document, options, object, root );
         }
         if( MapType.isMap( objectClass ) )
         {
@@ -185,17 +179,16 @@ public class JavaxXmlSerializer extends AbstractTextSerializer
         {
             return serializeStream( document, options, (Stream<?>) object );
         }
-        // Fallback to Java Serialization in Base 64
-        byte[] bytes = Base64.getEncoder().encode( serializeJava( object ) );
-        return document.createCDATASection( new String( bytes, UTF_8 ) );
+        throw new SerializationException( "Don't know how to serialize " + object );
     }
 
-    private <T> Node serializeValueComposite( Document document, Options options, T composite, boolean root )
+    private <T> Node serializeStatefulAssociationValue( Document document, Options options, T 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();
 
         Element valueElement = document.createElement( settings.getValueTagName() );
         valueType.properties().forEach(
@@ -239,7 +232,7 @@ public class JavaxXmlSerializer extends AbstractTextSerializer
                 valueElement.appendChild( element );
             }
         );
-        if( !root && options.includeTypeInfo() )
+        if( ( root && options.rootTypeInfo() ) || ( !root && options.nestedTypeInfo() ) )
         {
             valueElement.setAttribute( settings.getTypeInfoTagName(), valueType.primaryType().getName() );
         }

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/b2ff271b/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/assembly/JavaxXmlSerializationAssembler.java
----------------------------------------------------------------------
diff --git a/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/assembly/JavaxXmlSerializationAssembler.java b/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/assembly/JavaxXmlSerializationAssembler.java
index 1f57450..e6a69f5 100644
--- a/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/assembly/JavaxXmlSerializationAssembler.java
+++ b/extensions/serialization-javaxxml/src/main/java/org/apache/polygene/serialization/javaxxml/assembly/JavaxXmlSerializationAssembler.java
@@ -17,12 +17,14 @@
  */
 package org.apache.polygene.serialization.javaxxml.assembly;
 
+import org.apache.polygene.api.serialization.Converters;
 import org.apache.polygene.api.serialization.Deserializer;
 import org.apache.polygene.api.serialization.Serialization;
 import org.apache.polygene.api.serialization.Serializer;
 import org.apache.polygene.bootstrap.Assemblers;
 import org.apache.polygene.bootstrap.ModuleAssembly;
 import org.apache.polygene.bootstrap.ServiceDeclaration;
+import org.apache.polygene.serialization.javaxxml.JavaxXmlAdapters;
 import org.apache.polygene.serialization.javaxxml.JavaxXmlFactories;
 import org.apache.polygene.serialization.javaxxml.JavaxXmlSerialization;
 import org.apache.polygene.serialization.javaxxml.JavaxXmlSettings;
@@ -46,9 +48,10 @@ public class JavaxXmlSerializationAssembler extends Assemblers.VisibilityIdentit
         ServiceDeclaration declaration = module.services( JavaxXmlSerialization.class )
                                                .withTypes( Serialization.class,
                                                            Serializer.class, Deserializer.class,
+                                                           Converters.class,
                                                            XmlSerialization.class,
                                                            XmlSerializer.class, XmlDeserializer.class,
-                                                           JavaxXmlFactories.class )
+                                                           JavaxXmlFactories.class, JavaxXmlAdapters.class )
                                                .taggedWith( Serialization.Format.XML )
                                                .visibleIn( visibility() );
         if( hasIdentity() )

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/b2ff271b/extensions/serialization-javaxxml/src/test/java/org/apache/polygene/serialization/javaxxml/JavaxXmlValueCompositeSerializationTest.java
----------------------------------------------------------------------
diff --git a/extensions/serialization-javaxxml/src/test/java/org/apache/polygene/serialization/javaxxml/JavaxXmlValueCompositeSerializationTest.java b/extensions/serialization-javaxxml/src/test/java/org/apache/polygene/serialization/javaxxml/JavaxXmlValueCompositeSerializationTest.java
index 5c5679f..7ded112 100644
--- a/extensions/serialization-javaxxml/src/test/java/org/apache/polygene/serialization/javaxxml/JavaxXmlValueCompositeSerializationTest.java
+++ b/extensions/serialization-javaxxml/src/test/java/org/apache/polygene/serialization/javaxxml/JavaxXmlValueCompositeSerializationTest.java
@@ -18,6 +18,7 @@
 package org.apache.polygene.serialization.javaxxml;
 
 import org.apache.polygene.api.injection.scope.Service;
+import org.apache.polygene.api.serialization.Serializer;
 import org.apache.polygene.api.unitofwork.UnitOfWork;
 import org.apache.polygene.bootstrap.ModuleAssembly;
 import org.apache.polygene.serialization.javaxxml.assembly.JavaxXmlSerializationAssembler;
@@ -55,22 +56,25 @@ public class JavaxXmlValueCompositeSerializationTest extends AbstractValueCompos
         // START SNIPPET: xml-serialization
         try( UnitOfWork uow = unitOfWorkFactory.newUnitOfWork() )
         {
-            Some some = buildSomeValue( moduleInstance, uow, "23" );
+            Some valueInstance = buildSomeValue( moduleInstance, uow, "42" );
 
             // Serialize using injected service
-            String stateString = serialization.serialize( some );
-            System.out.println( stateString );
+            String serializedXml = xmlSerialization.serialize( valueInstance );
+            System.out.println( serializedXml );
 
             // Deserialize using Module API
-            Some some2 = moduleInstance.newValueFromSerializedState( Some.class, stateString );
-
-            assertThat( "Deserialized Value equality", some, equalTo( some2 ) );
+            Some valueFromSerializedState = moduleInstance.newValueFromSerializedState( Some.class, serializedXml );
+            assertThat( "Deserialized Value equality", valueInstance, equalTo( valueFromSerializedState ) );
+            // END SNIPPET: xml-serialization
 
+            // value.toString()
             // Need to loosely compare because of HashMaps not retaining order
+            String valueXmlWithoutTypeInfo = xmlSerialization.serialize( Serializer.Options.NO_TYPE_INFO, valueFromSerializedState );
             assertThat( "value.toString() XML equality",
-                        stateString,
-                        isSimilarTo( some2.toString() )
+                        valueFromSerializedState.toString(),
+                        isSimilarTo( valueXmlWithoutTypeInfo )
                             .withNodeMatcher( new DefaultNodeMatcher( ElementSelectors.byNameAndAllAttributes ) ) );
+            // START SNIPPET: xml-serialization
         }
         // END SNIPPET: xml-serialization
     }