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/03/13 15:28:37 UTC

[14/48] polygene-java git commit: New (de)serialization API and SPI & new implementations

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/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 09b4663..79e1583 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,9 +22,12 @@ package org.apache.polygene.migration;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
+import javax.json.Json;
+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;
 import org.apache.polygene.api.configuration.Configuration;
@@ -39,14 +42,18 @@ import org.apache.polygene.api.structure.Application;
 import org.apache.polygene.api.unitofwork.UnitOfWorkFactory;
 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.spi.entitystore.EntityStore;
 import org.apache.polygene.spi.entitystore.helpers.JSONKeys;
 import org.apache.polygene.spi.entitystore.helpers.Migration;
 import org.apache.polygene.spi.entitystore.helpers.StateStore;
+import org.apache.polygene.spi.serialization.JsonSerialization;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import static java.util.Arrays.asList;
+
 /**
  * Migration service. This is used by MapEntityStore EntityStore implementations to
  * migrate JSON state for Entities. To use it register the service so that the EntityStore
@@ -63,24 +70,21 @@ import org.slf4j.LoggerFactory;
 public interface MigrationService
     extends Migration
 {
-
     void initialize()
         throws Exception;
 
     class Activator
         extends ActivatorAdapter<ServiceReference<MigrationService>>
     {
-
         @Override
         public void afterActivation( ServiceReference<MigrationService> activated )
             throws Exception
         {
             activated.get().initialize();
         }
-
     }
 
-    public class MigrationMixin
+    class MigrationMixin
         implements MigrationService, Migrator
     {
         @Structure
@@ -98,6 +102,9 @@ public interface MigrationService
         @Service
         EntityStore entityStore;
 
+        @Service
+        JsonSerialization serialization;
+
         @Structure
         UnitOfWorkFactory uowf;
 
@@ -111,38 +118,61 @@ public interface MigrationService
         Iterable<MigrationEvents> migrationEvents;
 
         @Override
-        public boolean migrate( JSONObject state, String toVersion, StateStore stateStore )
-            throws JSONException
+        public JsonObject migrate( final JsonObject state, String toVersion, StateStore stateStore )
+            throws JsonException
         {
             // Get current version
-            String fromVersion = state.optString( JSONKeys.APPLICATION_VERSION, "0.0" );
+            String fromVersion = state.getString( JSONKeys.APPLICATION_VERSION, "0.0" );
 
-            Iterable<EntityMigrationRule> matchedRules = builder.entityMigrationRules().rulesBetweenVersions( fromVersion, toVersion );
+            Iterable<EntityMigrationRule> matchedRules = builder.entityMigrationRules()
+                                                                .rulesBetweenVersions( fromVersion, toVersion );
 
+            JsonObject migratedState = state;
             boolean changed = false;
+            List<String> failures = new ArrayList<>();
             if( matchedRules != null )
             {
                 for( EntityMigrationRule matchedRule : matchedRules )
                 {
-                    boolean ruleExecuted = matchedRule.upgrade( state, stateStore, migrator );
+                    MigrationContext context = new MigrationContext();
 
-                    if( ruleExecuted && log.isDebugEnabled() )
+                    migratedState = matchedRule.upgrade( context, migratedState, stateStore, migrator );
+
+                    if( context.isSuccess() && context.hasChanged() && log.isDebugEnabled() )
                     {
                         log.debug( matchedRule.toString() );
                     }
 
-                    changed = ruleExecuted || changed;
+                    failures.addAll( context.failures() );
+                    changed = context.hasChanged() || changed;
                 }
             }
 
-            state.put( JSONKeys.APPLICATION_VERSION, toVersion );
+            JsonObjectBuilder appVersionBuilder = Json.createObjectBuilder();
+            for( Map.Entry<String, JsonValue> entry : migratedState.entrySet() )
+            {
+                appVersionBuilder.add( entry.getKey(), entry.getValue() );
+            }
+            appVersionBuilder.add( JSONKeys.APPLICATION_VERSION, toVersion );
+            migratedState = appVersionBuilder.build();
+
+            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 ) );
+                return state;
+            }
 
             if( changed )
             {
-                log.info( "Migrated " + state.getString( JSONKeys.IDENTITY ) + " from " + fromVersion + " to " + toVersion );
+                log.info( "Migrated {} from {} to {}",
+                          migratedState.getString( JSONKeys.IDENTITY ), fromVersion, toVersion );
+                return migratedState;
             }
 
-            return changed;
+            // Nothing done
+            return state;
         }
 
         @Override
@@ -193,304 +223,571 @@ public interface MigrationService
 
         // Migrator implementation
         @Override
-        public boolean addProperty( JSONObject state, String name, Object defaultValue )
-            throws JSONException
+        public JsonObject addProperty( MigrationContext context, JsonObject state, String name, Object defaultValue )
+            throws JsonException
         {
-            JSONObject properties = state.getJSONObject( JSONKeys.PROPERTIES );
-            if( !properties.has( name ) )
+            JsonObject properties = state.getJsonObject( JSONKeys.PROPERTIES );
+            if( !properties.containsKey( name ) )
             {
-                if( defaultValue == null )
+                JsonValue value = serialization.toJson( defaultValue );
+                JsonObjectBuilder builder = Json.createObjectBuilder();
+                for( Map.Entry<String, JsonValue> entry : state.entrySet() )
                 {
-                    properties.put( name, JSONObject.NULL );
+                    String key = entry.getKey();
+                    if( !JSONKeys.PROPERTIES.equals( key ) )
+                    {
+                        builder.add( key, entry.getValue() );
+                    }
                 }
-                else
+                JsonObjectBuilder propBuilder = Json.createObjectBuilder();
+                for( Map.Entry<String, JsonValue> entry : properties.entrySet() )
                 {
-                    properties.put( name, defaultValue );
+                    propBuilder.add( entry.getKey(), entry.getValue() );
                 }
+                propBuilder.add( name, value );
+                builder.add( JSONKeys.PROPERTIES, propBuilder.build() );
+                context.markAsChanged();
 
                 for( MigrationEvents migrationEvent : migrationEvents )
                 {
                     migrationEvent.propertyAdded( state.getString( JSONKeys.IDENTITY ), name, defaultValue );
                 }
 
-                return true;
+                return builder.build();
             }
             else
             {
-                return false;
+                context.addFailure( "Add property " + name + ", default:" + defaultValue );
+                return state;
             }
         }
 
         @Override
-        public boolean removeProperty( JSONObject state, String name )
-            throws JSONException
+        public JsonObject removeProperty( MigrationContext context, JsonObject state, String name )
+            throws JsonException
         {
-            JSONObject properties = state.getJSONObject( JSONKeys.PROPERTIES );
-            if( properties.has( name ) )
+            JsonObject properties = state.getJsonObject( JSONKeys.PROPERTIES );
+            if( properties.containsKey( name ) )
             {
-                properties.remove( name );
-                for( MigrationEvents migrationEvent : migrationEvents )
+                JsonObjectBuilder builder = Json.createObjectBuilder();
+                for( Map.Entry<String, JsonValue> entry : state.entrySet() )
                 {
-                    migrationEvent.propertyRemoved( state.getString( JSONKeys.IDENTITY ), name );
+                    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() );
 
-                return true;
+                if( context.hasChanged() )
+                {
+                    for( MigrationEvents migrationEvent : migrationEvents )
+                    {
+                        migrationEvent.propertyRemoved( state.getString( JSONKeys.IDENTITY ), name );
+                    }
+                }
+
+                return builder.build();
             }
             else
             {
-                return false;
+                context.addFailure( "Remove property " + name );
+                return state;
             }
         }
 
         @Override
-        public boolean renameProperty( JSONObject state, String from, String to )
-            throws JSONException
+        public JsonObject renameProperty( MigrationContext context, JsonObject state, String from, String to )
+            throws JsonException
         {
-            JSONObject properties = state.getJSONObject( JSONKeys.PROPERTIES );
-            if( properties.has( from ) )
+            JsonObject properties = state.getJsonObject( JSONKeys.PROPERTIES );
+            if( properties.containsKey( from ) )
             {
-                Object value = properties.remove( from );
-                properties.put( to, value );
+                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() );
+
                 for( MigrationEvents migrationEvent : migrationEvents )
                 {
                     migrationEvent.propertyRenamed( state.getString( JSONKeys.IDENTITY ), from, to );
                 }
 
-                return true;
+                return builder.build();
             }
             else
             {
-                return false;
+                context.addFailure( "Rename property " + from + " to " + to );
+                return state;
             }
         }
 
         @Override
-        public boolean addAssociation( JSONObject state, String name, String defaultReference )
-            throws JSONException
+        public JsonObject addAssociation( MigrationContext context, JsonObject state, String name,
+                                          String defaultReference )
+            throws JsonException
         {
-            JSONObject associations = state.getJSONObject( JSONKeys.ASSOCIATIONS );
-            if( !associations.has( name ) )
+            JsonObject associations = state.getJsonObject( JSONKeys.ASSOCIATIONS );
+            if( !associations.containsKey( name ) )
             {
-                if( defaultReference == null )
+                JsonObjectBuilder builder = Json.createObjectBuilder();
+                for( Map.Entry<String, JsonValue> entry : state.entrySet() )
                 {
-                    associations.put( name, JSONObject.NULL );
+                    String key = entry.getKey();
+                    if( !JSONKeys.ASSOCIATIONS.equals( key ) )
+                    {
+                        builder.add( key, entry.getValue() );
+                    }
                 }
-                else
+                JsonObjectBuilder assocBuilder = Json.createObjectBuilder();
+                for( Map.Entry<String, JsonValue> entry : associations.entrySet() )
                 {
-                    associations.put( name, defaultReference );
+                    assocBuilder.add( entry.getKey(), entry.getValue() );
                 }
+                JsonValue value = serialization.toJson( defaultReference );
+                assocBuilder.add( name, value );
+                builder.add( JSONKeys.ASSOCIATIONS, assocBuilder.build() );
+                context.markAsChanged();
 
                 for( MigrationEvents migrationEvent : migrationEvents )
                 {
                     migrationEvent.associationAdded( state.getString( JSONKeys.IDENTITY ), name, defaultReference );
                 }
 
-                return true;
+                return builder.build();
             }
             else
             {
-                return false;
+                context.addFailure( "Add association " + name + ", default:" + defaultReference );
+                return state;
             }
         }
 
         @Override
-        public boolean removeAssociation( JSONObject state, String name )
-            throws JSONException
+        public JsonObject removeAssociation( MigrationContext context, JsonObject state, String name )
+            throws JsonException
         {
-            JSONObject associations = state.getJSONObject( JSONKeys.ASSOCIATIONS );
-            if( associations.has( name ) )
+            JsonObject associations = state.getJsonObject( JSONKeys.ASSOCIATIONS );
+            if( associations.containsKey( name ) )
             {
-                associations.remove( 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() );
+
                 for( MigrationEvents migrationEvent : migrationEvents )
                 {
                     migrationEvent.associationRemoved( state.getString( JSONKeys.IDENTITY ), name );
                 }
 
-                return true;
+                return builder.build();
             }
             else
             {
-                return false;
+                context.addFailure( "Remove association " + name );
+                return state;
             }
         }
 
         @Override
-        public boolean renameAssociation( JSONObject state, String from, String to )
-            throws JSONException
+        public JsonObject renameAssociation( MigrationContext context, JsonObject state, String from, String to )
+            throws JsonException
         {
-            JSONObject associations = state.getJSONObject( JSONKeys.ASSOCIATIONS );
-            if( associations.has( from ) )
+            JsonObject associations = state.getJsonObject( JSONKeys.ASSOCIATIONS );
+            if( associations.containsKey( from ) )
             {
-                Object value = associations.remove( from );
-                associations.put( to, value );
+                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() );
 
                 for( MigrationEvents migrationEvent : migrationEvents )
                 {
                     migrationEvent.associationRenamed( state.getString( JSONKeys.IDENTITY ), from, to );
                 }
 
-                return true;
+                return builder.build();
             }
             else
             {
-                return false;
+                context.addFailure( "Rename association " + from + " to " + to );
+                return state;
             }
         }
 
         @Override
-        public boolean addManyAssociation( JSONObject state, String name, String... defaultReferences )
-            throws JSONException
+        public JsonObject addManyAssociation( MigrationContext context, JsonObject state, String name,
+                                              String... defaultReferences )
+            throws JsonException
         {
-            JSONObject manyAssociations = state.getJSONObject( JSONKeys.MANY_ASSOCIATIONS );
-            if( !manyAssociations.has( name ) )
+            JsonObject manyAssociations = state.getJsonObject( JSONKeys.MANY_ASSOCIATIONS );
+            if( !manyAssociations.containsKey( name ) )
             {
-                JSONArray references = new JSONArray();
-                for( String reference : defaultReferences )
+                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() )
                 {
-                    references.put( reference );
+                    assocBuilder.add( entry.getKey(), entry.getValue() );
                 }
-                manyAssociations.put( name, references );
+                JsonValue value = serialization.toJson( defaultReferences );
+                assocBuilder.add( name, value );
+                builder.add( JSONKeys.MANY_ASSOCIATIONS, assocBuilder.build() );
+                context.markAsChanged();
 
                 for( MigrationEvents migrationEvent : migrationEvents )
                 {
-                    migrationEvent.manyAssociationAdded( state.getString( JSONKeys.IDENTITY ), name, defaultReferences );
+                    migrationEvent.manyAssociationAdded( state.getString( JSONKeys.IDENTITY ), name,
+                                                         defaultReferences );
                 }
 
-                return true;
+                return builder.build();
             }
             else
             {
-                return false;
+                context.addFailure( "Add many-association " + name + ", default:" + asList( defaultReferences ) );
+                return state;
             }
         }
 
         @Override
-        public boolean removeManyAssociation( JSONObject state, String name )
-            throws JSONException
+        public JsonObject removeManyAssociation( MigrationContext context, JsonObject state, String name )
+            throws JsonException
         {
-            JSONObject manyAssociations = state.getJSONObject( JSONKeys.MANY_ASSOCIATIONS );
-            if( manyAssociations.has( name ) )
+            JsonObject manyAssociations = state.getJsonObject( JSONKeys.MANY_ASSOCIATIONS );
+            if( manyAssociations.containsKey( name ) )
             {
-                manyAssociations.remove( 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() );
+
                 for( MigrationEvents migrationEvent : migrationEvents )
                 {
                     migrationEvent.manyAssociationRemoved( state.getString( JSONKeys.IDENTITY ), name );
                 }
 
-                return true;
+                return builder.build();
             }
             else
             {
-                return false;
+                context.addFailure( "Remove many-association " + name );
+                return state;
             }
         }
 
         @Override
-        public boolean renameManyAssociation( JSONObject state, String from, String to )
-            throws JSONException
+        public JsonObject renameManyAssociation( MigrationContext context, JsonObject state, String from, String to )
+            throws JsonException
         {
-            JSONObject manyAssociations = state.getJSONObject( JSONKeys.MANY_ASSOCIATIONS );
-            if( manyAssociations.has( from ) )
+            JsonObject manyAssociations = state.getJsonObject( JSONKeys.MANY_ASSOCIATIONS );
+            if( manyAssociations.containsKey( from ) )
             {
-                Object value = manyAssociations.remove( from );
-                manyAssociations.put( to, value );
+                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() );
 
                 for( MigrationEvents migrationEvent : migrationEvents )
                 {
                     migrationEvent.manyAssociationRenamed( state.getString( JSONKeys.IDENTITY ), from, to );
                 }
 
-                return true;
+                return builder.build();
             }
             else
             {
-                return false;
+                context.addFailure( "Rename many-association " + from + " to " + to );
+                return state;
             }
         }
 
         @Override
-        public boolean addNamedAssociation( JSONObject state, String name, Map<String, String> defaultReferences )
-            throws JSONException
+        public JsonObject addNamedAssociation( MigrationContext context, JsonObject state, String name,
+                                               Map<String, String> defaultReferences )
+            throws JsonException
         {
-            JSONObject namedAssociations = state.getJSONObject( JSONKeys.NAMED_ASSOCIATIONS );
-            if( !namedAssociations.has( name ) )
+            JsonObject namedAssociations = state.getJsonObject( JSONKeys.NAMED_ASSOCIATIONS );
+            if( !namedAssociations.containsKey( name ) )
             {
-                JSONObject references = new JSONObject();
-                for( Map.Entry<String, String> namedRef : defaultReferences.entrySet() )
+                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() )
                 {
-                    references.put( namedRef.getKey(), namedRef.getValue() );
+                    assocBuilder.add( entry.getKey(), entry.getValue() );
                 }
-                namedAssociations.put( name, references );
+                JsonValue value = serialization.toJson( defaultReferences );
+                assocBuilder.add( name, value );
+                builder.add( JSONKeys.NAMED_ASSOCIATIONS, assocBuilder.build() );
+                context.markAsChanged();
 
                 for( MigrationEvents migrationEvent : migrationEvents )
                 {
-                    migrationEvent.namedAssociationAdded( state.getString( JSONKeys.IDENTITY ), name, defaultReferences );
+                    migrationEvent.namedAssociationAdded( state.getString( JSONKeys.IDENTITY ), name,
+                                                          defaultReferences );
                 }
 
-                return true;
+                return builder.build();
             }
             else
             {
-                return false;
+                context.addFailure( "Add named-association " + name + ", default:" + defaultReferences );
+                return state;
             }
         }
 
         @Override
-        public boolean removeNamedAssociation( JSONObject state, String name )
-            throws JSONException
+        public JsonObject removeNamedAssociation( MigrationContext context, JsonObject state, String name )
+            throws JsonException
         {
-            JSONObject namedAssociations = state.getJSONObject( JSONKeys.NAMED_ASSOCIATIONS );
-            if( namedAssociations.has( name ) )
+            JsonObject namedAssociations = state.getJsonObject( JSONKeys.NAMED_ASSOCIATIONS );
+            if( namedAssociations.containsKey( name ) )
             {
-                namedAssociations.remove( 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() );
 
                 for( MigrationEvents migrationEvent : migrationEvents )
                 {
                     migrationEvent.namedAssociationRemoved( state.getString( JSONKeys.IDENTITY ), name );
                 }
 
-                return true;
+                return builder.build();
             }
             else
             {
-                return false;
+                context.addFailure( "Remove named-association " + name );
+                return state;
             }
         }
 
         @Override
-        public boolean renameNamedAssociation( JSONObject state, String from, String to )
-            throws JSONException
+        public JsonObject renameNamedAssociation( MigrationContext context, JsonObject state, String from, String to )
+            throws JsonException
         {
-            JSONObject namedAssociations = state.getJSONObject( JSONKeys.NAMED_ASSOCIATIONS );
-            if( namedAssociations.has( from ) )
+            JsonObject namedAssociations = state.getJsonObject( JSONKeys.NAMED_ASSOCIATIONS );
+            if( namedAssociations.containsKey( from ) )
             {
-                Object value = namedAssociations.remove( from );
-                namedAssociations.put( to, value );
+                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() );
 
                 for( MigrationEvents migrationEvent : migrationEvents )
                 {
                     migrationEvent.namedAssociationRenamed( state.getString( JSONKeys.IDENTITY ), from, to );
                 }
 
-                return true;
+                return builder.build();
             }
             else
             {
-                return false;
+                context.addFailure( "Rename named-association " + from + " to " + to );
+                return state;
             }
         }
 
         @Override
-        public void changeEntityType( JSONObject state, String newEntityType )
-            throws JSONException
+        public JsonObject changeEntityType( MigrationContext context, JsonObject state,
+                                            String fromType, String toType )
+            throws JsonException
         {
-            state.put( JSONKeys.TYPE, newEntityType );
+            JsonObjectBuilder builder = Json.createObjectBuilder();
+            for( Map.Entry<String, JsonValue> entry : state.entrySet() )
+            {
+                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
+                {
+                    builder.add( key, entry.getValue() );
+                }
+            }
 
             for( MigrationEvents migrationEvent : migrationEvents )
             {
-                migrationEvent.entityTypeChanged( state.getString( JSONKeys.IDENTITY ), newEntityType );
+                migrationEvent.entityTypeChanged( state.getString( JSONKeys.IDENTITY ), toType );
             }
+
+            return builder.build();
         }
     }
-
 }

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/extensions/migration/src/main/java/org/apache/polygene/migration/Migrator.java
----------------------------------------------------------------------
diff --git a/extensions/migration/src/main/java/org/apache/polygene/migration/Migrator.java b/extensions/migration/src/main/java/org/apache/polygene/migration/Migrator.java
index 7880946..a09b891 100644
--- a/extensions/migration/src/main/java/org/apache/polygene/migration/Migrator.java
+++ b/extensions/migration/src/main/java/org/apache/polygene/migration/Migrator.java
@@ -20,8 +20,8 @@
 package org.apache.polygene.migration;
 
 import java.util.Map;
-import org.json.JSONException;
-import org.json.JSONObject;
+import javax.json.JsonObject;
+import org.apache.polygene.migration.assembly.MigrationContext;
 
 /**
  * The Migrator implements this interface, which is invoked by MigrationOperation implementations
@@ -29,42 +29,42 @@ import org.json.JSONObject;
  */
 public interface Migrator
 {
-    boolean addProperty( JSONObject state, String name, Object defaultValue )
-        throws JSONException;
+    JsonObject addProperty( MigrationContext content, JsonObject state,
+                            String name, Object defaultValue );
 
-    boolean removeProperty( JSONObject state, String name )
-        throws JSONException;
+    JsonObject removeProperty( MigrationContext content, JsonObject state,
+                               String name );
 
-    boolean renameProperty( JSONObject state, String from, String to )
-        throws JSONException;
+    JsonObject renameProperty( MigrationContext content, JsonObject state,
+                               String from, String to );
 
-    boolean addAssociation( JSONObject state, String name, String defaultReference )
-        throws JSONException;
+    JsonObject addAssociation( MigrationContext content, JsonObject state,
+                               String name, String defaultReference );
 
-    boolean removeAssociation( JSONObject state, String name )
-        throws JSONException;
+    JsonObject removeAssociation( MigrationContext content, JsonObject state,
+                                  String name );
 
-    boolean renameAssociation( JSONObject state, String from, String to )
-        throws JSONException;
+    JsonObject renameAssociation( MigrationContext content, JsonObject state,
+                                  String from, String to );
 
-    boolean addManyAssociation( JSONObject state, String name, String... defaultReferences )
-        throws JSONException;
+    JsonObject addManyAssociation( MigrationContext content, JsonObject state,
+                                   String name, String... defaultReferences );
 
-    boolean removeManyAssociation( JSONObject state, String name )
-        throws JSONException;
+    JsonObject removeManyAssociation( MigrationContext content, JsonObject state,
+                                      String name );
 
-    boolean renameManyAssociation( JSONObject state, String from, String to )
-        throws JSONException;
+    JsonObject renameManyAssociation( MigrationContext content, JsonObject state,
+                                      String from, String to );
 
-    boolean addNamedAssociation( JSONObject state, String name, Map<String, String> defaultReferences )
-        throws JSONException;
+    JsonObject addNamedAssociation( MigrationContext content, JsonObject state,
+                                    String name, Map<String, String> defaultReferences );
 
-    boolean removeNamedAssociation( JSONObject state, String name )
-        throws JSONException;
+    JsonObject removeNamedAssociation( MigrationContext content, JsonObject state,
+                                       String name );
 
-    boolean renameNamedAssociation( JSONObject state, String from, String to )
-        throws JSONException;
+    JsonObject renameNamedAssociation( MigrationContext content, JsonObject state,
+                                       String from, String to );
 
-    void changeEntityType( JSONObject state, String newEntityType )
-        throws JSONException;
+    JsonObject changeEntityType( MigrationContext content, JsonObject state,
+                                 String fromType, String toType );
 }

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/extensions/migration/src/main/java/org/apache/polygene/migration/assembly/AbstractMigrationRule.java
----------------------------------------------------------------------
diff --git a/extensions/migration/src/main/java/org/apache/polygene/migration/assembly/AbstractMigrationRule.java b/extensions/migration/src/main/java/org/apache/polygene/migration/assembly/AbstractMigrationRule.java
index 80f9612..df5e929 100644
--- a/extensions/migration/src/main/java/org/apache/polygene/migration/assembly/AbstractMigrationRule.java
+++ b/extensions/migration/src/main/java/org/apache/polygene/migration/assembly/AbstractMigrationRule.java
@@ -43,4 +43,10 @@ public class AbstractMigrationRule
     {
         return toVersion;
     }
+
+    @Override
+    public String toString()
+    {
+        return fromVersion + "=>" + toVersion + ": " + getClass();
+    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/extensions/migration/src/main/java/org/apache/polygene/migration/assembly/EntityMigrationOperation.java
----------------------------------------------------------------------
diff --git a/extensions/migration/src/main/java/org/apache/polygene/migration/assembly/EntityMigrationOperation.java b/extensions/migration/src/main/java/org/apache/polygene/migration/assembly/EntityMigrationOperation.java
index 0bff1aa..a5b5741 100644
--- a/extensions/migration/src/main/java/org/apache/polygene/migration/assembly/EntityMigrationOperation.java
+++ b/extensions/migration/src/main/java/org/apache/polygene/migration/assembly/EntityMigrationOperation.java
@@ -20,8 +20,8 @@
 
 package org.apache.polygene.migration.assembly;
 
-import org.json.JSONException;
-import org.json.JSONObject;
+import javax.json.JsonException;
+import javax.json.JsonObject;
 import org.apache.polygene.migration.Migrator;
 import org.apache.polygene.spi.entitystore.helpers.StateStore;
 
@@ -30,9 +30,9 @@ import org.apache.polygene.spi.entitystore.helpers.StateStore;
  */
 public interface EntityMigrationOperation
 {
-    boolean upgrade( JSONObject state, StateStore stateStore, Migrator migrator )
-        throws JSONException;
+    JsonObject upgrade( MigrationContext context, JsonObject state, StateStore stateStore, Migrator migrator )
+        throws JsonException;
 
-    boolean downgrade( JSONObject state, StateStore stateStore, Migrator migrator )
-        throws JSONException;
+    JsonObject downgrade( MigrationContext context, JsonObject state, StateStore stateStore, Migrator migrator )
+        throws JsonException;
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/extensions/migration/src/main/java/org/apache/polygene/migration/assembly/EntityMigrationRule.java
----------------------------------------------------------------------
diff --git a/extensions/migration/src/main/java/org/apache/polygene/migration/assembly/EntityMigrationRule.java b/extensions/migration/src/main/java/org/apache/polygene/migration/assembly/EntityMigrationRule.java
index f238f93..291ae0d 100644
--- a/extensions/migration/src/main/java/org/apache/polygene/migration/assembly/EntityMigrationRule.java
+++ b/extensions/migration/src/main/java/org/apache/polygene/migration/assembly/EntityMigrationRule.java
@@ -20,8 +20,7 @@
 package org.apache.polygene.migration.assembly;
 
 import java.util.Arrays;
-import org.json.JSONException;
-import org.json.JSONObject;
+import javax.json.JsonObject;
 import org.apache.polygene.migration.Migrator;
 import org.apache.polygene.spi.entitystore.helpers.JSONKeys;
 import org.apache.polygene.spi.entitystore.helpers.StateStore;
@@ -33,17 +32,17 @@ public class EntityMigrationRule
     extends AbstractMigrationRule
 {
     private final String[] entityTypes;
-    private final EntityMigrationOperation operationEntity;
+    private final EntityMigrationOperation entityOperation;
 
     public EntityMigrationRule( String fromVersion,
                                 String toVersion,
                                 String[] entityTypes,
-                                EntityMigrationOperation operationEntity
+                                EntityMigrationOperation entityOperation
     )
     {
         super( fromVersion, toVersion );
         this.entityTypes = entityTypes;
-        this.operationEntity = operationEntity;
+        this.entityOperation = entityOperation;
     }
 
     public String[] entityTypes()
@@ -51,29 +50,29 @@ public class EntityMigrationRule
         return entityTypes;
     }
 
-    public boolean upgrade( JSONObject state, StateStore stateStore, Migrator migrator )
-        throws JSONException
+    public JsonObject upgrade( MigrationContext context, JsonObject state, StateStore stateStore, Migrator migrator )
     {
         if( appliesTo( state.getString( JSONKeys.TYPE ) ) )
         {
-            return operationEntity.upgrade( state, stateStore, migrator );
+            return entityOperation.upgrade( context, state, stateStore, migrator );
         }
         else
         {
-            return false;
+            context.addFailure( entityOperation.toString() );
+            return state;
         }
     }
 
-    public boolean downgrade( JSONObject state, StateStore stateStore, Migrator migrator )
-        throws JSONException
+    public JsonObject downgrade( MigrationContext context, JsonObject state, StateStore stateStore, Migrator migrator )
     {
         if( appliesTo( state.getString( JSONKeys.TYPE ) ) )
         {
-            return operationEntity.downgrade( state, stateStore, migrator );
+            return entityOperation.downgrade( context, state, stateStore, migrator );
         }
         else
         {
-            return false;
+            context.addFailure( entityOperation.toString() );
+            return state;
         }
     }
 
@@ -92,6 +91,6 @@ public class EntityMigrationRule
     @Override
     public String toString()
     {
-        return fromVersion + "->" + toVersion + ": on " + Arrays.asList( entityTypes ) + " do " + operationEntity;
+        return fromVersion + "=>" + toVersion + ": on " + Arrays.asList( entityTypes ) + " do " + entityOperation;
     }
 }

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/extensions/migration/src/main/java/org/apache/polygene/migration/assembly/MigrationContext.java
----------------------------------------------------------------------
diff --git a/extensions/migration/src/main/java/org/apache/polygene/migration/assembly/MigrationContext.java b/extensions/migration/src/main/java/org/apache/polygene/migration/assembly/MigrationContext.java
new file mode 100644
index 0000000..8ee057f
--- /dev/null
+++ b/extensions/migration/src/main/java/org/apache/polygene/migration/assembly/MigrationContext.java
@@ -0,0 +1,60 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *
+ */
+package org.apache.polygene.migration.assembly;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class MigrationContext
+{
+    private boolean changed;
+    private final List<String> failures = new ArrayList<>();
+
+    public boolean hasChanged()
+    {
+        return changed;
+    }
+
+    public void markAsChanged()
+    {
+        changed = true;
+    }
+
+    public boolean isSuccess()
+    {
+        return failures.isEmpty();
+    }
+
+    public boolean hasFailures()
+    {
+        return failures.size() > 0;
+    }
+
+    public List<String> failures()
+    {
+        return Collections.unmodifiableList( failures );
+    }
+
+    public void addFailure( String operation )
+    {
+        failures.add( operation );
+    }
+}

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/extensions/migration/src/main/java/org/apache/polygene/migration/operation/AddAssociation.java
----------------------------------------------------------------------
diff --git a/extensions/migration/src/main/java/org/apache/polygene/migration/operation/AddAssociation.java b/extensions/migration/src/main/java/org/apache/polygene/migration/operation/AddAssociation.java
index 9873ae3..471843b 100644
--- a/extensions/migration/src/main/java/org/apache/polygene/migration/operation/AddAssociation.java
+++ b/extensions/migration/src/main/java/org/apache/polygene/migration/operation/AddAssociation.java
@@ -20,8 +20,8 @@
 
 package org.apache.polygene.migration.operation;
 
-import org.json.JSONException;
-import org.json.JSONObject;
+import javax.json.JsonObject;
+import org.apache.polygene.migration.assembly.MigrationContext;
 import org.apache.polygene.migration.Migrator;
 import org.apache.polygene.migration.assembly.EntityMigrationOperation;
 import org.apache.polygene.spi.entitystore.helpers.StateStore;
@@ -42,17 +42,15 @@ public class AddAssociation
     }
 
     @Override
-    public boolean upgrade( JSONObject state, StateStore stateStore, Migrator migrator )
-        throws JSONException
+    public JsonObject upgrade( MigrationContext context, JsonObject state, StateStore stateStore, Migrator migrator )
     {
-        return migrator.addAssociation( state, association, defaultValue );
+        return migrator.addAssociation( context, state, association, defaultValue );
     }
 
     @Override
-    public boolean downgrade( JSONObject state, StateStore stateStore, Migrator migrator )
-        throws JSONException
+    public JsonObject downgrade( MigrationContext context, JsonObject state, StateStore stateStore, Migrator migrator )
     {
-        return migrator.removeAssociation( state, association );
+        return migrator.removeAssociation( context, state, association );
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/extensions/migration/src/main/java/org/apache/polygene/migration/operation/AddManyAssociation.java
----------------------------------------------------------------------
diff --git a/extensions/migration/src/main/java/org/apache/polygene/migration/operation/AddManyAssociation.java b/extensions/migration/src/main/java/org/apache/polygene/migration/operation/AddManyAssociation.java
index 0f71acc..82610fe 100644
--- a/extensions/migration/src/main/java/org/apache/polygene/migration/operation/AddManyAssociation.java
+++ b/extensions/migration/src/main/java/org/apache/polygene/migration/operation/AddManyAssociation.java
@@ -21,8 +21,8 @@
 package org.apache.polygene.migration.operation;
 
 import java.util.Arrays;
-import org.json.JSONException;
-import org.json.JSONObject;
+import javax.json.JsonObject;
+import org.apache.polygene.migration.assembly.MigrationContext;
 import org.apache.polygene.migration.Migrator;
 import org.apache.polygene.migration.assembly.EntityMigrationOperation;
 import org.apache.polygene.spi.entitystore.helpers.StateStore;
@@ -43,17 +43,15 @@ public class AddManyAssociation
     }
 
     @Override
-    public boolean upgrade( JSONObject state, StateStore stateStore, Migrator migrator )
-        throws JSONException
+    public JsonObject upgrade( MigrationContext context, JsonObject state, StateStore stateStore, Migrator migrator )
     {
-        return migrator.addManyAssociation( state, association, defaultReferences );
+        return migrator.addManyAssociation( context, state, association, defaultReferences );
     }
 
     @Override
-    public boolean downgrade( JSONObject state, StateStore stateStore, Migrator migrator )
-        throws JSONException
+    public JsonObject downgrade( MigrationContext context, JsonObject state, StateStore stateStore, Migrator migrator )
     {
-        return migrator.removeManyAssociation( state, association );
+        return migrator.removeManyAssociation( context, state, association );
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/extensions/migration/src/main/java/org/apache/polygene/migration/operation/AddNamedAssociation.java
----------------------------------------------------------------------
diff --git a/extensions/migration/src/main/java/org/apache/polygene/migration/operation/AddNamedAssociation.java b/extensions/migration/src/main/java/org/apache/polygene/migration/operation/AddNamedAssociation.java
index cfd1c96..90725e8 100644
--- a/extensions/migration/src/main/java/org/apache/polygene/migration/operation/AddNamedAssociation.java
+++ b/extensions/migration/src/main/java/org/apache/polygene/migration/operation/AddNamedAssociation.java
@@ -20,8 +20,8 @@
 package org.apache.polygene.migration.operation;
 
 import java.util.Map;
-import org.json.JSONException;
-import org.json.JSONObject;
+import javax.json.JsonObject;
+import org.apache.polygene.migration.assembly.MigrationContext;
 import org.apache.polygene.migration.Migrator;
 import org.apache.polygene.migration.assembly.EntityMigrationOperation;
 import org.apache.polygene.spi.entitystore.helpers.StateStore;
@@ -42,17 +42,15 @@ public class AddNamedAssociation
     }
 
     @Override
-    public boolean upgrade( JSONObject state, StateStore stateStore, Migrator migrator )
-        throws JSONException
+    public JsonObject upgrade( MigrationContext context, JsonObject state, StateStore stateStore, Migrator migrator )
     {
-        return migrator.addNamedAssociation( state, association, defaultReferences );
+        return migrator.addNamedAssociation( context, state, association, defaultReferences );
     }
 
     @Override
-    public boolean downgrade( JSONObject state, StateStore stateStore, Migrator migrator )
-        throws JSONException
+    public JsonObject downgrade( MigrationContext context, JsonObject state, StateStore stateStore, Migrator migrator )
     {
-        return migrator.removeNamedAssociation( state, association );
+        return migrator.removeNamedAssociation( context, state, association );
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/extensions/migration/src/main/java/org/apache/polygene/migration/operation/AddProperty.java
----------------------------------------------------------------------
diff --git a/extensions/migration/src/main/java/org/apache/polygene/migration/operation/AddProperty.java b/extensions/migration/src/main/java/org/apache/polygene/migration/operation/AddProperty.java
index 6bef0b9..8f8898a 100644
--- a/extensions/migration/src/main/java/org/apache/polygene/migration/operation/AddProperty.java
+++ b/extensions/migration/src/main/java/org/apache/polygene/migration/operation/AddProperty.java
@@ -20,8 +20,8 @@
 
 package org.apache.polygene.migration.operation;
 
-import org.json.JSONException;
-import org.json.JSONObject;
+import javax.json.JsonObject;
+import org.apache.polygene.migration.assembly.MigrationContext;
 import org.apache.polygene.migration.Migrator;
 import org.apache.polygene.migration.assembly.EntityMigrationOperation;
 import org.apache.polygene.spi.entitystore.helpers.StateStore;
@@ -42,17 +42,15 @@ public class AddProperty
     }
 
     @Override
-    public boolean upgrade( JSONObject state, StateStore stateStore, Migrator migrator )
-        throws JSONException
+    public JsonObject upgrade( MigrationContext context, JsonObject state, StateStore stateStore, Migrator migrator )
     {
-        return migrator.addProperty( state, property, defaultValue );
+        return migrator.addProperty( context, state, property, defaultValue );
     }
 
     @Override
-    public boolean downgrade( JSONObject state, StateStore stateStore, Migrator migrator )
-        throws JSONException
+    public JsonObject downgrade( MigrationContext context, JsonObject state, StateStore stateStore, Migrator migrator )
     {
-        return migrator.removeProperty( state, property );
+        return migrator.removeProperty( context, state, property );
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RemoveAssociation.java
----------------------------------------------------------------------
diff --git a/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RemoveAssociation.java b/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RemoveAssociation.java
index 5d9f8bb..d1f8771 100644
--- a/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RemoveAssociation.java
+++ b/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RemoveAssociation.java
@@ -20,10 +20,10 @@
 
 package org.apache.polygene.migration.operation;
 
-import org.json.JSONException;
-import org.json.JSONObject;
+import javax.json.JsonObject;
 import org.apache.polygene.migration.Migrator;
 import org.apache.polygene.migration.assembly.EntityMigrationOperation;
+import org.apache.polygene.migration.assembly.MigrationContext;
 import org.apache.polygene.spi.entitystore.helpers.StateStore;
 
 /**
@@ -43,17 +43,15 @@ public class RemoveAssociation
     }
 
     @Override
-    public boolean upgrade( JSONObject state, StateStore stateStore, Migrator migrator )
-        throws JSONException
+    public JsonObject upgrade( MigrationContext context, JsonObject state, StateStore stateStore, Migrator migrator )
     {
-        return migrator.removeAssociation( state, association );
+        return migrator.removeAssociation( context, state, association );
     }
 
     @Override
-    public boolean downgrade( JSONObject state, StateStore stateStore, Migrator migrator )
-        throws JSONException
+    public JsonObject downgrade( MigrationContext context, JsonObject state, StateStore stateStore, Migrator migrator )
     {
-        return migrator.addAssociation( state, association, defaultValue );
+        return migrator.addAssociation( context, state, association, defaultValue );
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RemoveManyAssociation.java
----------------------------------------------------------------------
diff --git a/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RemoveManyAssociation.java b/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RemoveManyAssociation.java
index dd4a0c8..d063338 100644
--- a/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RemoveManyAssociation.java
+++ b/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RemoveManyAssociation.java
@@ -21,10 +21,10 @@
 package org.apache.polygene.migration.operation;
 
 import java.util.Arrays;
-import org.json.JSONException;
-import org.json.JSONObject;
+import javax.json.JsonObject;
 import org.apache.polygene.migration.Migrator;
 import org.apache.polygene.migration.assembly.EntityMigrationOperation;
+import org.apache.polygene.migration.assembly.MigrationContext;
 import org.apache.polygene.spi.entitystore.helpers.StateStore;
 
 /**
@@ -43,17 +43,15 @@ public class RemoveManyAssociation
     }
 
     @Override
-    public boolean upgrade( JSONObject state, StateStore stateStore, Migrator migrator )
-        throws JSONException
+    public JsonObject upgrade( MigrationContext context, JsonObject state, StateStore stateStore, Migrator migrator )
     {
-        return migrator.removeManyAssociation( state, association );
+        return migrator.removeManyAssociation( context, state, association );
     }
 
     @Override
-    public boolean downgrade( JSONObject state, StateStore stateStore, Migrator migrator )
-        throws JSONException
+    public JsonObject downgrade( MigrationContext context, JsonObject state, StateStore stateStore, Migrator migrator )
     {
-        return migrator.addManyAssociation( state, association, defaultReferences );
+        return migrator.addManyAssociation( context, state, association, defaultReferences );
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RemoveNamedAssociation.java
----------------------------------------------------------------------
diff --git a/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RemoveNamedAssociation.java b/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RemoveNamedAssociation.java
index 33260bf..f97dbea 100644
--- a/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RemoveNamedAssociation.java
+++ b/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RemoveNamedAssociation.java
@@ -20,10 +20,10 @@
 package org.apache.polygene.migration.operation;
 
 import java.util.Map;
-import org.json.JSONException;
-import org.json.JSONObject;
+import javax.json.JsonObject;
 import org.apache.polygene.migration.Migrator;
 import org.apache.polygene.migration.assembly.EntityMigrationOperation;
+import org.apache.polygene.migration.assembly.MigrationContext;
 import org.apache.polygene.spi.entitystore.helpers.StateStore;
 
 /**
@@ -42,17 +42,15 @@ public class RemoveNamedAssociation
     }
 
     @Override
-    public boolean upgrade( JSONObject state, StateStore stateStore, Migrator migrator )
-        throws JSONException
+    public JsonObject upgrade( MigrationContext context, JsonObject state, StateStore stateStore, Migrator migrator )
     {
-        return migrator.removeNamedAssociation( state, association );
+        return migrator.removeNamedAssociation( context, state, association );
     }
 
     @Override
-    public boolean downgrade( JSONObject state, StateStore stateStore, Migrator migrator )
-        throws JSONException
+    public JsonObject downgrade( MigrationContext context, JsonObject state, StateStore stateStore, Migrator migrator )
     {
-        return migrator.addNamedAssociation( state, association, defaultReferences );
+        return migrator.addNamedAssociation( context, state, association, defaultReferences );
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RemoveProperty.java
----------------------------------------------------------------------
diff --git a/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RemoveProperty.java b/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RemoveProperty.java
index 1563928..9ad8673 100644
--- a/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RemoveProperty.java
+++ b/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RemoveProperty.java
@@ -20,8 +20,8 @@
 
 package org.apache.polygene.migration.operation;
 
-import org.json.JSONException;
-import org.json.JSONObject;
+import javax.json.JsonObject;
+import org.apache.polygene.migration.assembly.MigrationContext;
 import org.apache.polygene.migration.Migrator;
 import org.apache.polygene.migration.assembly.EntityMigrationOperation;
 import org.apache.polygene.spi.entitystore.helpers.StateStore;
@@ -43,17 +43,15 @@ public class RemoveProperty
     }
 
     @Override
-    public boolean upgrade( JSONObject state, StateStore stateStore, Migrator migrator )
-        throws JSONException
+    public JsonObject upgrade( MigrationContext context, JsonObject state, StateStore stateStore, Migrator migrator )
     {
-        return migrator.removeProperty( state, property );
+        return migrator.removeProperty( context, state, property );
     }
 
     @Override
-    public boolean downgrade( JSONObject state, StateStore stateStore, Migrator migrator )
-        throws JSONException
+    public JsonObject downgrade( MigrationContext context, JsonObject state, StateStore stateStore, Migrator migrator )
     {
-        return migrator.addProperty( state, property, defaultValue );
+        return migrator.addProperty( context, state, property, defaultValue );
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RenameAssociation.java
----------------------------------------------------------------------
diff --git a/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RenameAssociation.java b/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RenameAssociation.java
index 52ba536..277de57 100644
--- a/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RenameAssociation.java
+++ b/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RenameAssociation.java
@@ -20,10 +20,10 @@
 
 package org.apache.polygene.migration.operation;
 
-import org.json.JSONException;
-import org.json.JSONObject;
+import javax.json.JsonObject;
 import org.apache.polygene.migration.Migrator;
 import org.apache.polygene.migration.assembly.EntityMigrationOperation;
+import org.apache.polygene.migration.assembly.MigrationContext;
 import org.apache.polygene.spi.entitystore.helpers.StateStore;
 
 /**
@@ -42,17 +42,15 @@ public class RenameAssociation
     }
 
     @Override
-    public boolean upgrade( JSONObject state, StateStore stateStore, Migrator migrator )
-        throws JSONException
+    public JsonObject upgrade( MigrationContext context, JsonObject state, StateStore stateStore, Migrator migrator )
     {
-        return migrator.renameAssociation( state, from, to );
+        return migrator.renameAssociation( context, state, from, to );
     }
 
     @Override
-    public boolean downgrade( JSONObject state, StateStore stateStore, Migrator migrator )
-        throws JSONException
+    public JsonObject downgrade( MigrationContext context, JsonObject state, StateStore stateStore, Migrator migrator )
     {
-        return migrator.renameAssociation( state, to, from );
+        return migrator.renameAssociation( context, state, to, from );
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RenameEntity.java
----------------------------------------------------------------------
diff --git a/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RenameEntity.java b/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RenameEntity.java
index 37cdd59..716a6b1 100644
--- a/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RenameEntity.java
+++ b/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RenameEntity.java
@@ -19,11 +19,10 @@
  */
 package org.apache.polygene.migration.operation;
 
-import org.json.JSONException;
-import org.json.JSONObject;
+import javax.json.JsonObject;
 import org.apache.polygene.migration.Migrator;
 import org.apache.polygene.migration.assembly.EntityMigrationOperation;
-import org.apache.polygene.spi.entitystore.helpers.JSONKeys;
+import org.apache.polygene.migration.assembly.MigrationContext;
 import org.apache.polygene.spi.entitystore.helpers.StateStore;
 
 /**
@@ -42,37 +41,15 @@ public class RenameEntity
     }
 
     @Override
-    public boolean upgrade( JSONObject state, StateStore stateStore, Migrator migrator )
-        throws JSONException
+    public JsonObject upgrade( MigrationContext context, JsonObject state, StateStore stateStore, Migrator migrator )
     {
-        String type = state.getString( JSONKeys.TYPE );
-
-        if( type.equals( fromName ) )
-        {
-            migrator.changeEntityType( state, toName );
-            return true;
-        }
-        else
-        {
-            return false;
-        }
+        return migrator.changeEntityType( context, state, fromName, toName );
     }
 
     @Override
-    public boolean downgrade( JSONObject state, StateStore stateStore, Migrator migrator )
-        throws JSONException
+    public JsonObject downgrade( MigrationContext context, JsonObject state, StateStore stateStore, Migrator migrator )
     {
-        String type = state.getString( JSONKeys.TYPE );
-
-        if( type.equals( toName ) )
-        {
-            migrator.changeEntityType( state, fromName );
-            return true;
-        }
-        else
-        {
-            return false;
-        }
+        return migrator.changeEntityType( context, state, fromName, fromName );
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RenameManyAssociation.java
----------------------------------------------------------------------
diff --git a/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RenameManyAssociation.java b/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RenameManyAssociation.java
index dc207b6..cfc12c5 100644
--- a/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RenameManyAssociation.java
+++ b/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RenameManyAssociation.java
@@ -20,10 +20,10 @@
 
 package org.apache.polygene.migration.operation;
 
-import org.json.JSONException;
-import org.json.JSONObject;
+import javax.json.JsonObject;
 import org.apache.polygene.migration.Migrator;
 import org.apache.polygene.migration.assembly.EntityMigrationOperation;
+import org.apache.polygene.migration.assembly.MigrationContext;
 import org.apache.polygene.spi.entitystore.helpers.StateStore;
 
 /**
@@ -42,17 +42,15 @@ public class RenameManyAssociation
     }
 
     @Override
-    public boolean upgrade( JSONObject state, StateStore stateStore, Migrator migrator )
-        throws JSONException
+    public JsonObject upgrade( MigrationContext context, JsonObject state, StateStore stateStore, Migrator migrator )
     {
-        return migrator.renameManyAssociation( state, from, to );
+        return migrator.renameManyAssociation( context, state, from, to );
     }
 
     @Override
-    public boolean downgrade( JSONObject state, StateStore stateStore, Migrator migrator )
-        throws JSONException
+    public JsonObject downgrade( MigrationContext context, JsonObject state, StateStore stateStore, Migrator migrator )
     {
-        return migrator.renameManyAssociation( state, to, from );
+        return migrator.renameManyAssociation( context, state, to, from );
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RenameNamedAssociation.java
----------------------------------------------------------------------
diff --git a/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RenameNamedAssociation.java b/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RenameNamedAssociation.java
index 0045d15..05fb92a 100644
--- a/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RenameNamedAssociation.java
+++ b/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RenameNamedAssociation.java
@@ -19,10 +19,10 @@
  */
 package org.apache.polygene.migration.operation;
 
-import org.json.JSONException;
-import org.json.JSONObject;
+import javax.json.JsonObject;
 import org.apache.polygene.migration.Migrator;
 import org.apache.polygene.migration.assembly.EntityMigrationOperation;
+import org.apache.polygene.migration.assembly.MigrationContext;
 import org.apache.polygene.spi.entitystore.helpers.StateStore;
 
 /**
@@ -41,17 +41,15 @@ public class RenameNamedAssociation
     }
 
     @Override
-    public boolean upgrade( JSONObject state, StateStore stateStore, Migrator migrator )
-        throws JSONException
+    public JsonObject upgrade( MigrationContext context, JsonObject state, StateStore stateStore, Migrator migrator )
     {
-        return migrator.renameNamedAssociation( state, from, to );
+        return migrator.renameNamedAssociation( context, state, from, to );
     }
 
     @Override
-    public boolean downgrade( JSONObject state, StateStore stateStore, Migrator migrator )
-        throws JSONException
+    public JsonObject downgrade( MigrationContext context, JsonObject state, StateStore stateStore, Migrator migrator )
     {
-        return migrator.renameNamedAssociation( state, to, from );
+        return migrator.renameNamedAssociation( context, state, to, from );
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RenameProperty.java
----------------------------------------------------------------------
diff --git a/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RenameProperty.java b/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RenameProperty.java
index b373b76..4f0b80c 100644
--- a/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RenameProperty.java
+++ b/extensions/migration/src/main/java/org/apache/polygene/migration/operation/RenameProperty.java
@@ -20,8 +20,8 @@
 
 package org.apache.polygene.migration.operation;
 
-import org.json.JSONException;
-import org.json.JSONObject;
+import javax.json.JsonObject;
+import org.apache.polygene.migration.assembly.MigrationContext;
 import org.apache.polygene.migration.Migrator;
 import org.apache.polygene.migration.assembly.EntityMigrationOperation;
 import org.apache.polygene.spi.entitystore.helpers.StateStore;
@@ -42,17 +42,15 @@ public class RenameProperty
     }
 
     @Override
-    public boolean upgrade( JSONObject state, StateStore stateStore, Migrator migrator )
-        throws JSONException
+    public JsonObject upgrade( MigrationContext context, JsonObject state, StateStore stateStore, Migrator migrator )
     {
-        return migrator.renameProperty( state, fromProperty, toProperty );
+        return migrator.renameProperty( context, state, fromProperty, toProperty );
     }
 
     @Override
-    public boolean downgrade( JSONObject state, StateStore stateStore, Migrator migrator )
-        throws JSONException
+    public JsonObject downgrade( MigrationContext context, JsonObject state, StateStore stateStore, Migrator migrator )
     {
-        return migrator.renameProperty( state, toProperty, fromProperty );
+        return migrator.renameProperty( context, state, toProperty, fromProperty );
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/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 811d79f..1068abb 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
@@ -22,6 +22,7 @@ package org.apache.polygene.migration;
 import java.io.IOException;
 import java.util.List;
 import java.util.stream.Stream;
+import javax.json.JsonObject;
 import org.apache.polygene.api.activation.ActivationException;
 import org.apache.polygene.api.identity.Identity;
 import org.apache.polygene.api.service.importer.NewObjectImporter;
@@ -33,18 +34,17 @@ import org.apache.polygene.bootstrap.SingletonAssembler;
 import org.apache.polygene.bootstrap.unitofwork.DefaultUnitOfWorkAssembler;
 import org.apache.polygene.migration.assembly.EntityMigrationOperation;
 import org.apache.polygene.migration.assembly.MigrationBuilder;
+import org.apache.polygene.migration.assembly.MigrationContext;
 import org.apache.polygene.migration.assembly.MigrationOperation;
 import org.apache.polygene.spi.entitystore.BackupRestore;
 import org.apache.polygene.spi.entitystore.helpers.JSONKeys;
 import org.apache.polygene.spi.entitystore.helpers.StateStore;
 import org.apache.polygene.test.AbstractPolygeneTest;
 import org.apache.polygene.test.EntityTestAssembler;
-import org.hamcrest.CoreMatchers;
-import org.json.JSONException;
-import org.json.JSONObject;
 import org.junit.Test;
 
 import static java.util.stream.Collectors.toList;
+import static org.hamcrest.CoreMatchers.equalTo;
 import static org.junit.Assert.assertThat;
 
 /**
@@ -124,9 +124,7 @@ public class MigrationTest
             id = entity.identity().get();
             uow.complete();
 
-            BackupRestore backupRestore = v1.module()
-                .findService( BackupRestore.class )
-                .get();
+            BackupRestore backupRestore = v1.module().findService( BackupRestore.class ).get();
             try( Stream<String> backup = backupRestore.backup() )
             {
                 data_v1 = backup.collect( toList() );
@@ -152,9 +150,9 @@ public class MigrationTest
 
             UnitOfWork uow = v1_1.module().unitOfWorkFactory().newUnitOfWork();
             TestEntity1_1 entity = uow.get( TestEntity1_1.class, id );
-            assertThat( "Property has been renamed", entity.newFoo().get(), CoreMatchers.equalTo( "Some value" ) );
-            assertThat( "ManyAssociation has been renamed", entity.newFooManyAssoc().count(), CoreMatchers.equalTo( 1 ) );
-            assertThat( "Association has been renamed", entity.newFooAssoc().get(), CoreMatchers.equalTo( entity ) );
+            assertThat( "Property has been renamed", entity.newFoo().get(), equalTo( "Some value" ) );
+            assertThat( "ManyAssociation has been renamed", entity.newFooManyAssoc().count(), equalTo( 1 ) );
+            assertThat( "Association has been renamed", entity.newFooAssoc().get(), equalTo( entity ) );
             uow.complete();
 
             try( Stream<String> backup = testData.backup() )
@@ -183,10 +181,10 @@ public class MigrationTest
                 testData.restore( data_v1.stream() );
                 UnitOfWork uow = v2_0.module().unitOfWorkFactory().newUnitOfWork();
                 TestEntity2_0 entity = uow.get( TestEntity2_0.class, id );
-                assertThat( "Property has been created", entity.bar().get(), CoreMatchers.equalTo( "Some value" ) );
-                assertThat( "Custom Property has been created", entity.customBar().get(), CoreMatchers.equalTo( "Hello Some value" ) );
-                assertThat( "ManyAssociation has been renamed", entity.newFooManyAssoc().count(), CoreMatchers.equalTo( 1 ) );
-                assertThat( "Association has been renamed", entity.newFooAssoc().get(), CoreMatchers.equalTo( entity ) );
+                assertThat( "Property has been created", entity.bar().get(), equalTo( "Some value" ) );
+                assertThat( "Custom Property has been created", entity.customBar().get(), equalTo( "Hello Some value" ) );
+                assertThat( "ManyAssociation has been renamed", entity.newFooManyAssoc().count(), equalTo( 1 ) );
+                assertThat( "Association has been renamed", entity.newFooAssoc().get(), equalTo( entity ) );
                 uow.complete();
             }
         }
@@ -221,19 +219,16 @@ public class MigrationTest
         implements EntityMigrationOperation
     {
         @Override
-        public boolean upgrade( JSONObject state, StateStore stateStore, Migrator migrator )
-            throws JSONException
+        public JsonObject upgrade( MigrationContext context, JsonObject state, StateStore store, Migrator migrator )
         {
-            JSONObject properties = (JSONObject) state.get( JSONKeys.PROPERTIES );
-
-            return migrator.addProperty( state, "customBar", "Hello " + properties.getString( "bar" ) );
+            JsonObject properties = state.getJsonObject( JSONKeys.PROPERTIES );
+            return migrator.addProperty( context, state, "customBar", "Hello " + properties.getString( "bar" ) );
         }
 
         @Override
-        public boolean downgrade( JSONObject state, StateStore stateStore, Migrator migrator )
-            throws JSONException
+        public JsonObject downgrade( MigrationContext context, JsonObject state, StateStore store, Migrator migrator )
         {
-            return migrator.removeProperty( state, "customBar" );
+            return migrator.removeProperty( context, state, "customBar" );
         }
     }
 

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/extensions/reindexer/build.gradle
----------------------------------------------------------------------
diff --git a/extensions/reindexer/build.gradle b/extensions/reindexer/build.gradle
index 1315db1..f956f60 100644
--- a/extensions/reindexer/build.gradle
+++ b/extensions/reindexer/build.gradle
@@ -31,7 +31,6 @@ dependencies {
 
   testImplementation polygene.core.testsupport
   testImplementation polygene.extension( 'entitystore-jdbm' )
-  testImplementation polygene.extension( 'valueserialization-jackson' )
   testImplementation polygene.extension( 'indexing-rdf' )
 
   testRuntimeOnly libraries.logback

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/extensions/reindexer/src/test/java/org/apache/polygene/index/reindexer/ReindexerTest.java
----------------------------------------------------------------------
diff --git a/extensions/reindexer/src/test/java/org/apache/polygene/index/reindexer/ReindexerTest.java b/extensions/reindexer/src/test/java/org/apache/polygene/index/reindexer/ReindexerTest.java
index f3cd992..38c91a8 100644
--- a/extensions/reindexer/src/test/java/org/apache/polygene/index/reindexer/ReindexerTest.java
+++ b/extensions/reindexer/src/test/java/org/apache/polygene/index/reindexer/ReindexerTest.java
@@ -40,7 +40,6 @@ import org.apache.polygene.index.rdf.assembly.RdfNativeSesameStoreAssembler;
 import org.apache.polygene.library.rdf.repository.NativeConfiguration;
 import org.apache.polygene.test.AbstractPolygeneTest;
 import org.apache.polygene.test.EntityTestAssembler;
-import org.apache.polygene.valueserialization.jackson.assembly.JacksonValueSerializationAssembler;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
@@ -67,7 +66,6 @@ public class ReindexerTest
 
         // Native Sesame EntityFinder
         new RdfNativeSesameStoreAssembler().assemble( module );
-        new JacksonValueSerializationAssembler().assemble( module );
 
         // Reindexer
         // START SNIPPET: assembly

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/extensions/serialization-javaxjson/build.gradle
----------------------------------------------------------------------
diff --git a/extensions/serialization-javaxjson/build.gradle b/extensions/serialization-javaxjson/build.gradle
new file mode 100644
index 0000000..e93e5fc
--- /dev/null
+++ b/extensions/serialization-javaxjson/build.gradle
@@ -0,0 +1,34 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+apply plugin: 'polygene-extension'
+
+description = "Apache Polygene\u2122 javax.json Serialization Extension"
+
+jar { manifest { name = "Apache Polygene\u2122 Extension - Serialization - javax.json" } }
+
+dependencies {
+  api polygene.core.bootstrap
+
+  runtimeOnly polygene.core.runtime
+  runtimeOnly libraries.johnzon
+
+  testImplementation polygene.core.testsupport
+
+  testRuntimeOnly libraries.logback
+}

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/extensions/serialization-javaxjson/dev-status.xml
----------------------------------------------------------------------
diff --git a/extensions/serialization-javaxjson/dev-status.xml b/extensions/serialization-javaxjson/dev-status.xml
new file mode 100644
index 0000000..0d777be
--- /dev/null
+++ b/extensions/serialization-javaxjson/dev-status.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+  ~  Licensed to the Apache Software Foundation (ASF) under one
+  ~  or more contributor license agreements.  See the NOTICE file
+  ~  distributed with this work for additional information
+  ~  regarding copyright ownership.  The ASF licenses this file
+  ~  to you under the Apache License, Version 2.0 (the
+  ~  "License"); you may not use this file except in compliance
+  ~  with the License.  You may obtain a copy of the License at
+  ~
+  ~       http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~  Unless required by applicable law or agreed to in writing, software
+  ~  distributed under the License is distributed on an "AS IS" BASIS,
+  ~  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~  See the License for the specific language governing permissions and
+  ~  limitations under the License.
+  ~
+  ~
+  -->
+<module xmlns="http://polygene.apache.org/schemas/2008/dev-status/1"
+        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+        xsi:schemaLocation="http://polygene.apache.org/schemas/2008/dev-status/1
+        http://polygene.apache.org/schemas/2008/dev-status/1/dev-status.xsd">
+    <status>
+        <!--none,early,beta,stable,mature-->
+        <codebase>beta</codebase>
+
+        <!-- none, brief, good, complete -->
+        <documentation>none</documentation>
+
+        <!-- none, some, good, complete -->
+        <unittests>good</unittests>
+    </status>
+    <licenses>
+        <license>ALv2</license>
+    </licenses>
+</module>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/polygene-java/blob/7c2814ee/extensions/serialization-javaxjson/src/docs/serialization-javaxjson.txt
----------------------------------------------------------------------
diff --git a/extensions/serialization-javaxjson/src/docs/serialization-javaxjson.txt b/extensions/serialization-javaxjson/src/docs/serialization-javaxjson.txt
new file mode 100644
index 0000000..f9aee3f
--- /dev/null
+++ b/extensions/serialization-javaxjson/src/docs/serialization-javaxjson.txt
@@ -0,0 +1,31 @@
+///////////////////////////////////////////////////////////////
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+///////////////////////////////////////////////////////////////
+
+[[extension-serialization-javaxjson,javax.json serialization]]
+= javax.json serialization =
+
+[devstatus]
+--------------
+source=extensions/serialization-javaxjson/dev-status.xml
+--------------
+
+// TODO Preamble - link to <<core-api-serialization>> and <<core-spi-serialization>>
+// TODO Document usage of JsonSerialization
+// TODO Include sample model and its output from test code & resources
+// TODO Assembly - Serialization extension or sole Service, settings & adapters