You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@usergrid.apache.org by sn...@apache.org on 2015/03/30 21:58:22 UTC

[18/50] incubator-usergrid git commit: Switch back to giving each application_info entity it's own UUID instead of using the same UUID as the application itself.

Switch back to giving each application_info entity it's own UUID instead of using the same UUID as the application itself.


Project: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/commit/60785263
Tree: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/tree/60785263
Diff: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/diff/60785263

Branch: refs/heads/two-dot-o-dev
Commit: 607852637b7ae95bc8ef315d79787c6ca2fa44a9
Parents: 9eeb2b5
Author: Dave Johnson <dm...@apigee.com>
Authored: Thu Mar 12 11:53:36 2015 -0400
Committer: Dave Johnson <dm...@apigee.com>
Committed: Thu Mar 12 11:53:36 2015 -0400

----------------------------------------------------------------------
 .../corepersistence/ApplicationIdCache.java     |   2 +-
 .../corepersistence/ApplicationIdCacheImpl.java |  67 ++++++---
 .../corepersistence/CpEntityManagerFactory.java | 138 ++++++++++++-------
 .../usergrid/corepersistence/CpSetup.java       |   2 +-
 .../migration/AppInfoMigrationPlugin.java       |  55 ++++++--
 .../usergrid/exception/ConflictException.java   |  36 +++++
 .../persistence/EntityManagerFactory.java       |  22 ++-
 .../org/apache/usergrid/persistence/Schema.java |   5 +-
 .../cassandra/EntityManagerFactoryImpl.java     |  21 ++-
 .../index/impl/EsEntityIndexImpl.java           |   9 +-
 .../rest/applications/ApplicationResource.java  |   9 +-
 .../rest/applications/ServiceResource.java      |   8 +-
 .../exceptions/ConflictExceptionMapper.java     |   2 +-
 .../organizations/OrganizationResource.java     |  12 +-
 .../applications/ApplicationDeleteTest.java     |  50 +++++--
 .../endpoints/OrganizationResource.java         |   6 +-
 stack/rest/src/test/resources/log4j.properties  |   7 +-
 .../usergrid/management/ApplicationInfo.java    |   4 +
 .../usergrid/management/ManagementService.java  |   4 +-
 .../cassandra/ManagementServiceImpl.java        |  95 +++++--------
 .../exceptions/ConflictException.java           |  36 -----
 .../migration/AppInfoMigrationPluginTest.java   | 111 ++++++++++++---
 .../cassandra/ApplicationCreatorIT.java         |   1 +
 23 files changed, 466 insertions(+), 236 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/60785263/stack/core/src/main/java/org/apache/usergrid/corepersistence/ApplicationIdCache.java
----------------------------------------------------------------------
diff --git a/stack/core/src/main/java/org/apache/usergrid/corepersistence/ApplicationIdCache.java b/stack/core/src/main/java/org/apache/usergrid/corepersistence/ApplicationIdCache.java
index 71637bd..4aa1113 100644
--- a/stack/core/src/main/java/org/apache/usergrid/corepersistence/ApplicationIdCache.java
+++ b/stack/core/src/main/java/org/apache/usergrid/corepersistence/ApplicationIdCache.java
@@ -36,7 +36,7 @@ public interface ApplicationIdCache {
     /**
      * Evict the application by name
      */
-    public Optional<UUID> getApplicationId(final String applicationName);
+    public UUID getApplicationId(final String applicationName);
 
 
     /**

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/60785263/stack/core/src/main/java/org/apache/usergrid/corepersistence/ApplicationIdCacheImpl.java
----------------------------------------------------------------------
diff --git a/stack/core/src/main/java/org/apache/usergrid/corepersistence/ApplicationIdCacheImpl.java b/stack/core/src/main/java/org/apache/usergrid/corepersistence/ApplicationIdCacheImpl.java
index 202e68d..b03f422 100644
--- a/stack/core/src/main/java/org/apache/usergrid/corepersistence/ApplicationIdCacheImpl.java
+++ b/stack/core/src/main/java/org/apache/usergrid/corepersistence/ApplicationIdCacheImpl.java
@@ -24,15 +24,16 @@ import java.util.UUID;
 import java.util.concurrent.ExecutionException;
 
 import org.apache.usergrid.corepersistence.util.CpNamingUtils;
-import org.apache.usergrid.persistence.Entity;
-import org.apache.usergrid.persistence.EntityManager;
-import org.apache.usergrid.persistence.EntityManagerFactory;
-import org.apache.usergrid.persistence.EntityRef;
+import org.apache.usergrid.persistence.*;
 
 import com.google.common.base.Optional;
 import com.google.common.cache.CacheBuilder;
 import com.google.common.cache.CacheLoader;
 import com.google.common.cache.LoadingCache;
+import org.apache.usergrid.persistence.index.query.Query;
+import org.apache.usergrid.utils.UUIDUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 
 /**
@@ -40,6 +41,7 @@ import com.google.common.cache.LoadingCache;
  * full for the duration of the execution
  */
 public class ApplicationIdCacheImpl implements ApplicationIdCache {
+    private static final Logger logger = LoggerFactory.getLogger(ApplicationIdCacheImpl.class);
 
 
     /**
@@ -47,10 +49,10 @@ public class ApplicationIdCacheImpl implements ApplicationIdCache {
      */
     private final EntityManager rootEm;
 
-    private final LoadingCache<String, Optional<UUID>> appCache =
-        CacheBuilder.newBuilder().maximumSize( 10000 ).build( new CacheLoader<String, Optional<UUID>>() {
+    private final LoadingCache<String, UUID> appCache =
+        CacheBuilder.newBuilder().maximumSize( 10000 ).build( new CacheLoader<String, UUID>() {
             @Override
-            public Optional<UUID> load( final String key ) throws Exception {
+            public UUID load( final String key ) throws Exception {
                 return fetchApplicationId( key );
             }
         } );
@@ -61,12 +63,15 @@ public class ApplicationIdCacheImpl implements ApplicationIdCache {
     }
 
     @Override
-    public Optional<UUID> getApplicationId( final String applicationName ) {
+    public UUID getApplicationId( final String applicationName ) {
         try {
-            return appCache.get( applicationName );
+            UUID optionalUuid = appCache.get( applicationName.toLowerCase() );
+            logger.debug("Returning for key {} value {}", applicationName, optionalUuid );
+            return optionalUuid;
         }
-        catch ( ExecutionException e ) {
-            throw new RuntimeException( "Unable to load app cache", e );
+        catch ( Exception e ) {
+            logger.debug("Returning for key {} value null", applicationName );
+            return null;
         }
     }
 
@@ -74,18 +79,40 @@ public class ApplicationIdCacheImpl implements ApplicationIdCache {
     /**
      * Fetch our application id
      */
-    private Optional<UUID> fetchApplicationId( final String applicationName ) {
+    private UUID fetchApplicationId( final String applicationName ) {
+
+        UUID value = null;
+
+        try {
+            if ( rootEm.getApplication() == null ) {
+                return null;
+            }
+        } catch ( Exception e ) {
+            logger.error("Error looking up app", e);
+        }
 
         try {
-            UUID applicationId = null;
+            Query q = Query.fromQL( Schema.PROPERTY_NAME + " = '" + applicationName.toLowerCase() + "'" );
+
+            Results results = rootEm.searchCollection(
+                rootEm.getApplicationRef(), CpNamingUtils.APPLICATION_INFOS, q);
+
+            if ( !results.isEmpty() ) {
+
+                Entity entity = results.iterator().next();
+                Object uuidObject = entity.getProperty(Schema.PROPERTY_APPLICATION_ID);
+
+                if (uuidObject instanceof UUID) {
+                    value = (UUID) uuidObject;
+                } else {
+                    value = UUIDUtils.tryExtractUUID(
+                        entity.getProperty(Schema.PROPERTY_APPLICATION_ID).toString());
+                }
 
-            final EntityRef alias = rootEm.getAlias( CpNamingUtils.APPLICATION_INFO, applicationName );
-            if ( alias != null ) {
-                Entity entity = rootEm.get(alias);
-                applicationId = (UUID) entity.getProperty("uuid");
             }
 
-            return Optional.fromNullable( applicationId );
+            logger.debug("Loaded    for key {} value {}", applicationName, value );
+            return value;
         }
         catch ( Exception e ) {
             throw new RuntimeException( "Unable to retrieve application id", e );
@@ -95,12 +122,14 @@ public class ApplicationIdCacheImpl implements ApplicationIdCache {
 
     @Override
     public void evictAppId( final String applicationName ) {
-        appCache.invalidate( applicationName );
+        appCache.invalidate( applicationName.toLowerCase() );
+        logger.debug("Invalidated key {}", applicationName.toLowerCase());
     }
 
 
     @Override
     public void evictAll() {
         appCache.invalidateAll();
+        logger.debug("Invalidated all keys");
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/60785263/stack/core/src/main/java/org/apache/usergrid/corepersistence/CpEntityManagerFactory.java
----------------------------------------------------------------------
diff --git a/stack/core/src/main/java/org/apache/usergrid/corepersistence/CpEntityManagerFactory.java b/stack/core/src/main/java/org/apache/usergrid/corepersistence/CpEntityManagerFactory.java
index 1fb8a7b..8e432e8 100644
--- a/stack/core/src/main/java/org/apache/usergrid/corepersistence/CpEntityManagerFactory.java
+++ b/stack/core/src/main/java/org/apache/usergrid/corepersistence/CpEntityManagerFactory.java
@@ -25,6 +25,7 @@ import com.google.inject.TypeLiteral;
 import com.yammer.metrics.annotation.Metered;
 import org.apache.commons.lang.StringUtils;
 import org.apache.usergrid.corepersistence.util.CpNamingUtils;
+import org.apache.usergrid.exception.ConflictException;
 import org.apache.usergrid.persistence.*;
 import org.apache.usergrid.persistence.cassandra.CassandraService;
 import org.apache.usergrid.persistence.cassandra.CounterUtils;
@@ -81,10 +82,6 @@ public class CpEntityManagerFactory implements EntityManagerFactory, Application
     /** Have we already initialized the index for the management app? */
     private AtomicBoolean indexInitialized = new AtomicBoolean(  );
 
-    /** Keep track of applications that already have indexes to avoid redundant re-creation. */
-    private static final Set<UUID> applicationIndexesCreated = new HashSet<UUID>();
-
-
     // cache of already instantiated entity managers
     private LoadingCache<UUID, EntityManager> entityManagers
         = CacheBuilder.newBuilder().maximumSize(100).build(new CacheLoader<UUID, EntityManager>() {
@@ -93,14 +90,10 @@ public class CpEntityManagerFactory implements EntityManagerFactory, Application
             }
         });
 
-    private final ApplicationIdCache orgApplicationCache;
-
+    private final ApplicationIdCache applicationIdCache;
 
     private ManagerCache managerCache;
 
-
-
-
     private CassandraService cassandraService;
     private CounterUtils counterUtils;
     private Injector injector;
@@ -114,7 +107,7 @@ public class CpEntityManagerFactory implements EntityManagerFactory, Application
         this.injector = injector;
         this.managerCache = injector.getInstance( ManagerCache.class );
         this.metricsFactory = injector.getInstance( MetricsFactory.class );
-        this.orgApplicationCache = new ApplicationIdCacheImpl( this );
+        this.applicationIdCache = new ApplicationIdCacheImpl( this );
     }
 
 
@@ -189,21 +182,21 @@ public class CpEntityManagerFactory implements EntityManagerFactory, Application
     }
 
     @Override
-    public UUID createApplication(String organizationName, String name) throws Exception {
-        return createApplication( organizationName, name, null );
+    public Entity createApplicationV2(String organizationName, String name) throws Exception {
+        return createApplicationV2(organizationName, name, null);
     }
 
 
     @Override
-    public UUID createApplication(
+    public Entity createApplicationV2(
         String orgName, String name, Map<String, Object> properties) throws Exception {
 
         String appName = buildAppName( orgName, name );
 
 
-        final Optional<UUID> appId = orgApplicationCache.getApplicationId( appName );
+        final UUID appId = applicationIdCache.getApplicationId( appName );
 
-        if ( appId.isPresent() ) {
+        if ( appId != null ) {
             throw new ApplicationAlreadyExistsException( name );
         }
 
@@ -212,18 +205,21 @@ public class CpEntityManagerFactory implements EntityManagerFactory, Application
         logger.debug( "New application orgName {} orgAppName {} id {} ",
                 new Object[] { orgName, name, applicationId.toString() } );
 
-        initializeApplication( orgName, applicationId, appName, properties );
-        return applicationId;
+        return initializeApplicationV2(orgName, applicationId, appName, properties);
     }
 
 
+
     private String buildAppName( String organizationName, String name ) {
         return StringUtils.lowerCase( name.contains( "/" ) ? name : organizationName + "/" + name );
     }
 
 
+    /**
+     * @return UUID of newly created Entity of type application_info
+     */
     @Override
-    public UUID initializeApplication( String organizationName, UUID applicationId, String name,
+    public Entity initializeApplicationV2( String organizationName, final UUID applicationId, String name,
                                        Map<String, Object> properties ) throws Exception {
 
         EntityManager em = getEntityManager( CpNamingUtils.MANAGEMENT_APPLICATION_ID);
@@ -241,7 +237,7 @@ public class CpEntityManagerFactory implements EntityManagerFactory, Application
         getSetup().setupApplicationKeyspace( applicationId, appName );
 
         if ( properties == null ) {
-            properties = new TreeMap<String, Object>( CASE_INSENSITIVE_ORDER );
+            properties = new TreeMap<>( CASE_INSENSITIVE_ORDER );
         }
         properties.put( PROPERTY_NAME, appName );
         EntityManager appEm = getEntityManager( applicationId );
@@ -252,27 +248,28 @@ public class CpEntityManagerFactory implements EntityManagerFactory, Application
 
         // create application info entity in the management app
 
-        final UUID appId = applicationId;
         Map<String, Object> appInfoMap = new HashMap<String, Object>() {{
             put( PROPERTY_NAME, appName );
-            put( PROPERTY_UUID, appId );
+            put( PROPERTY_APPLICATION_ID, applicationId );
         }};
 
+        Entity appInfo;
         try {
-            em.create( appId, CpNamingUtils.APPLICATION_INFO, appInfoMap );
+            appInfo = em.create(CpNamingUtils.APPLICATION_INFO, appInfoMap);
         } catch (DuplicateUniquePropertyExistsException e) {
             throw new ApplicationAlreadyExistsException(appName);
         }
         em.refreshIndex();
 
-        //evict app Id from cache
-        orgApplicationCache.evictAppId( appName );
+        // evict app Id from cache
+        applicationIdCache.evictAppId(appName);
 
         logger.info("Initialized application {}", appName);
-        return applicationId;
+        return appInfo;
     }
 
 
+
     /**
      * Delete Application.
      *
@@ -286,77 +283,96 @@ public class CpEntityManagerFactory implements EntityManagerFactory, Application
     @Override
     public void deleteApplication(UUID applicationId) throws Exception {
 
-        // make a copy of the app to delete application_info entity
+        // find application_info for application to delete
+
+        EntityManager em = getEntityManager(getManagementAppId());
+
+        final Results results = em.searchCollection(em.getApplicationRef(), CpNamingUtils.APPLICATION_INFOS,
+            Query.fromQL("select * where " + PROPERTY_APPLICATION_ID + " = " + applicationId.toString()));
+        Entity appInfoToDelete = results.getEntity();
 
-        EntityManager em = getEntityManager( this.getManagementAppId() );
-        Entity appToDelete = em.get(new SimpleEntityRef(CpNamingUtils.APPLICATION_INFO, applicationId));
+        // ensure that there is not already a deleted app with the same name
 
+        final EntityRef alias = em.getAlias(
+            CpNamingUtils.DELETED_APPLICATION_INFO, appInfoToDelete.getName() );
+        if ( alias != null ) {
+            throw new ConflictException("Cannot delete app with same name as already deleted app");
+        }
+
+        // make a copy of the app to delete application_info entity
         // and put it in a deleted_application_info collection
 
         Entity deletedApp = em.create(
-            applicationId, CpNamingUtils.DELETED_APPLICATION_INFO, appToDelete.getProperties());
+            CpNamingUtils.DELETED_APPLICATION_INFO, appInfoToDelete.getProperties());
 
         // copy its connections too
 
-        final Set<String> connectionTypes = em.getConnectionTypes(appToDelete);
+        final Set<String> connectionTypes = em.getConnectionTypes(appInfoToDelete);
         for ( String connType : connectionTypes ) {
-            final Results results =
-                em.getConnectedEntities(appToDelete, connType, null, Query.Level.ALL_PROPERTIES);
-            for ( Entity entity : results.getEntities() ) {
+            final Results connResults =
+                em.getConnectedEntities(appInfoToDelete, connType, null, Query.Level.ALL_PROPERTIES);
+            for ( Entity entity : connResults.getEntities() ) {
                 em.createConnection( deletedApp, connType, entity );
             }
         }
 
         // delete the app from the application_info collection and delete its index
 
-        em.delete(appToDelete);
+        em.delete(appInfoToDelete);
         em.refreshIndex();
 
         final EntityIndex entityIndex = managerCache.getEntityIndex(
             new ApplicationScopeImpl(new SimpleId(applicationId, TYPE_APPLICATION)));
+
+        applicationIdCache.evictAppId(appInfoToDelete.getName());
+
         entityIndex.deleteIndex();
     }
 
 
     @Override
-    public void restoreApplication(UUID applicationId) throws Exception {
+    public Entity restoreApplication(UUID applicationId) throws Exception {
 
         // get the deleted_application_info for the deleted app
 
-        EntityManager em = getEntityManager(CpNamingUtils.MANAGEMENT_APPLICATION_ID);
-        Entity deletedApp = em.get(
-            new SimpleEntityRef(CpNamingUtils.DELETED_APPLICATION_INFO, applicationId));
+        EntityManager em = getEntityManager(getManagementAppId());
+
+        final Results results = em.searchCollection(em.getApplicationRef(), CpNamingUtils.DELETED_APPLICATION_INFOS,
+            Query.fromQL("select * where " + PROPERTY_APPLICATION_ID + " = " + applicationId.toString()));
+        Entity deletedAppInfo = results.getEntity();
 
-        if ( deletedApp == null ) {
+        if ( deletedAppInfo == null ) {
             throw new EntityNotFoundException("Cannot restore. Deleted Application not found: " + applicationId );
         }
 
         // create application_info for restored app
 
-        Entity restoredApp = em.create(
-            deletedApp.getUuid(), CpNamingUtils.APPLICATION_INFO, deletedApp.getProperties());
+        Entity restoredAppInfo = em.create(
+            deletedAppInfo.getUuid(), CpNamingUtils.APPLICATION_INFO, deletedAppInfo.getProperties());
 
         // copy connections from deleted app entity
 
-        final Set<String> connectionTypes = em.getConnectionTypes(deletedApp);
+        final Set<String> connectionTypes = em.getConnectionTypes(deletedAppInfo);
         for ( String connType : connectionTypes ) {
-            final Results results =
-                em.getConnectedEntities(deletedApp, connType, null, Query.Level.ALL_PROPERTIES);
-            for ( Entity entity : results.getEntities() ) {
-                em.createConnection( restoredApp, connType, entity );
+            final Results connResults =
+                em.getConnectedEntities(deletedAppInfo, connType, null, Query.Level.ALL_PROPERTIES);
+            for ( Entity entity : connResults.getEntities() ) {
+                em.createConnection( restoredAppInfo, connType, entity );
             }
         }
 
         // delete the deleted app entity rebuild the app index
 
-        em.delete(deletedApp);
+        em.delete(deletedAppInfo);
 
         this.rebuildApplicationIndexes(applicationId, new ProgressObserver() {
             @Override
             public void onProgress(EntityRef entity) {
-                logger.info( "Restored entity {}:{}", entity.getType(), entity.getUuid() );
+            logger.info( "Restored entity {}:{}", entity.getType(), entity.getUuid() );
             }
         });
+
+        return restoredAppInfo;
     }
 
 
@@ -370,7 +386,7 @@ public class CpEntityManagerFactory implements EntityManagerFactory, Application
 
 
     public UUID lookupApplication( String orgAppName ) throws Exception {
-        return orgApplicationCache.getApplicationId( orgAppName ).orNull();
+        return applicationIdCache.getApplicationId( orgAppName );
     }
 
 
@@ -690,8 +706,11 @@ public class CpEntityManagerFactory implements EntityManagerFactory, Application
 
     @Override
     public void flushEntityManagerCaches() {
+
         managerCache.invalidate();
-        orgApplicationCache.evictAll();
+
+        applicationIdCache.evictAll();
+
         Map<UUID, EntityManager>  entityManagersMap = entityManagers.asMap();
         for ( UUID appUuid : entityManagersMap.keySet() ) {
             EntityManager em = entityManagersMap.get(appUuid);
@@ -735,4 +754,23 @@ public class CpEntityManagerFactory implements EntityManagerFactory, Application
         return ecm.getHealth();
     }
 
+
+    @Override
+    public UUID createApplication(String organizationName, String name) throws Exception {
+        throw new UnsupportedOperationException("Not supported in v2");
+    }
+
+
+    @Override
+    public UUID createApplication(
+        String organizationName, String name, Map<String, Object> properties) throws Exception {
+        throw new UnsupportedOperationException("Not supported in v2");
+    }
+
+    @Override
+    public UUID initializeApplication(
+        String orgName, UUID appId, String appName, Map<String, Object> props) throws Exception {
+        throw new UnsupportedOperationException("Not supported in v2");
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/60785263/stack/core/src/main/java/org/apache/usergrid/corepersistence/CpSetup.java
----------------------------------------------------------------------
diff --git a/stack/core/src/main/java/org/apache/usergrid/corepersistence/CpSetup.java b/stack/core/src/main/java/org/apache/usergrid/corepersistence/CpSetup.java
index 8dd4a12..c5c792b 100644
--- a/stack/core/src/main/java/org/apache/usergrid/corepersistence/CpSetup.java
+++ b/stack/core/src/main/java/org/apache/usergrid/corepersistence/CpSetup.java
@@ -100,7 +100,7 @@ public class CpSetup implements Setup {
         logger.info( "Setting up management app" );
 
         try {
-            emf.initializeApplication( DEFAULT_ORGANIZATION, emf.getManagementAppId(), MANAGEMENT_APPLICATION, null );
+            emf.initializeApplicationV2( DEFAULT_ORGANIZATION, emf.getManagementAppId(), MANAGEMENT_APPLICATION, null );
         }
         catch ( ApplicationAlreadyExistsException ex ) {
             logger.warn( "Application {}/{} already exists", DEFAULT_ORGANIZATION, MANAGEMENT_APPLICATION );

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/60785263/stack/core/src/main/java/org/apache/usergrid/corepersistence/migration/AppInfoMigrationPlugin.java
----------------------------------------------------------------------
diff --git a/stack/core/src/main/java/org/apache/usergrid/corepersistence/migration/AppInfoMigrationPlugin.java b/stack/core/src/main/java/org/apache/usergrid/corepersistence/migration/AppInfoMigrationPlugin.java
index 1a456c8..1c38615 100644
--- a/stack/core/src/main/java/org/apache/usergrid/corepersistence/migration/AppInfoMigrationPlugin.java
+++ b/stack/core/src/main/java/org/apache/usergrid/corepersistence/migration/AppInfoMigrationPlugin.java
@@ -34,6 +34,7 @@ import java.util.HashMap;
 import java.util.Map;
 import java.util.UUID;
 
+import static org.apache.usergrid.persistence.Schema.PROPERTY_APPLICATION_ID;
 import static org.apache.usergrid.persistence.Schema.PROPERTY_NAME;
 import static org.apache.usergrid.persistence.Schema.PROPERTY_UUID;
 
@@ -49,9 +50,8 @@ public class AppInfoMigrationPlugin implements MigrationPlugin {
 
     public static String PLUGIN_NAME = "appinfo-migration";
 
-    // protected for test purposes only
     @Inject
-    protected EntityManagerFactory emf;
+    protected EntityManagerFactory emf; // protected for test purposes only
 
     @Override
     public String getName() {
@@ -77,13 +77,15 @@ public class AppInfoMigrationPlugin implements MigrationPlugin {
         if ( !results.isEmpty() ) {
 
             // applications still found in old appinfos collection, migrate them.
-            logger.info("Migrating old appinfos");
+
+            String currentAppName = null;
 
             try {
+                logger.info("Migrating old appinfos");
 
                 for (Entity oldAppInfo : results.getEntities()) {
 
-                    final String appName = oldAppInfo.getName();
+                    final String appName = currentAppName = oldAppInfo.getName();
 
                     UUID applicationId;
                     UUID organizationId;
@@ -104,23 +106,37 @@ public class AppInfoMigrationPlugin implements MigrationPlugin {
                     // create and connect new APPLICATION_INFO oldAppInfo to Organization
 
                     final UUID appId = applicationId;
-                    Map<String, Object> appInfoMap = new HashMap<String, Object>() {{
-                        put(PROPERTY_NAME, appName);
-                        put(PROPERTY_UUID, appId);
-                    }};
 
-                    final Entity appInfo;
-                    appInfo = em.create(appId, CpNamingUtils.APPLICATION_INFO, appInfoMap);
-                    em.createConnection(new SimpleEntityRef(Group.ENTITY_TYPE, organizationId), "owns", appInfo);
-                    em.delete(oldAppInfo);
+                    Entity appInfo = getApplicationInfo( emf, appId );
+                    if ( appInfo == null ) {
+                        Map<String, Object> appInfoMap = new HashMap<String, Object>() {{
+                            put(PROPERTY_NAME, appName);
+                            put(PROPERTY_APPLICATION_ID, appId);
+                        }};
+                        appInfo = em.create(appId, CpNamingUtils.APPLICATION_INFO, appInfoMap);
+                        observer.update( getMaxVersion(), "Created application_info for " + appName);
 
-                    observer.update( getMaxVersion(), "Updated application " + appName);
+                    } else {
+                        appInfo.setProperty(PROPERTY_APPLICATION_ID, appId);
+                        em.update(appInfo);
+                        observer.update( getMaxVersion(), "Updated existing application_info for " + appName);
+                    }
+                    em.createConnection(new SimpleEntityRef(Group.ENTITY_TYPE, organizationId), "owns", appInfo);
                 }
 
                 em.refreshIndex();
 
+                // after we've successfully created all of the application_infos, we delete the old appoinfos
+
+                for (Entity oldAppInfo : results.getEntities()) {
+                    em.delete(oldAppInfo);
+                }
+
             } catch (Exception e) {
-                String msg = "Exception writing new application_info collection";
+
+                // stop on any exception and return failure
+
+                String msg = "Exception writing application_info for " + currentAppName;
                 logger.error(msg, e);
                 observer.failed( getMaxVersion(), msg);
             }
@@ -130,7 +146,18 @@ public class AppInfoMigrationPlugin implements MigrationPlugin {
         }
 
         observer.complete();
+    }
+
+    private Entity getApplicationInfo( EntityManagerFactory emf, UUID appId ) throws Exception {
+
+        UUID mgmtAppId = emf.getManagementAppId();
+        EntityManager rootEm = emf.getEntityManager( mgmtAppId );
+
+        final Results applicationInfoResults = rootEm.searchCollection(
+            new SimpleEntityRef("application", mgmtAppId), "application_infos",
+            Query.fromQL("select * where applicationId=" + appId.toString()));
 
+        return applicationInfoResults.getEntity();
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/60785263/stack/core/src/main/java/org/apache/usergrid/exception/ConflictException.java
----------------------------------------------------------------------
diff --git a/stack/core/src/main/java/org/apache/usergrid/exception/ConflictException.java b/stack/core/src/main/java/org/apache/usergrid/exception/ConflictException.java
new file mode 100644
index 0000000..bbebbaa
--- /dev/null
+++ b/stack/core/src/main/java/org/apache/usergrid/exception/ConflictException.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2014 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.usergrid.exception;
+
+public class ConflictException extends Exception {
+
+    public ConflictException() {
+        super();
+    }
+
+    public ConflictException(String arg0, Throwable arg1) {
+        super(arg0, arg1);
+    }
+
+    public ConflictException(String arg0) {
+        super(arg0);
+    }
+
+    public ConflictException(Throwable arg0) {
+        super(arg0);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/60785263/stack/core/src/main/java/org/apache/usergrid/persistence/EntityManagerFactory.java
----------------------------------------------------------------------
diff --git a/stack/core/src/main/java/org/apache/usergrid/persistence/EntityManagerFactory.java b/stack/core/src/main/java/org/apache/usergrid/persistence/EntityManagerFactory.java
index cd71cf9..df1615a 100644
--- a/stack/core/src/main/java/org/apache/usergrid/persistence/EntityManagerFactory.java
+++ b/stack/core/src/main/java/org/apache/usergrid/persistence/EntityManagerFactory.java
@@ -49,10 +49,13 @@ public interface EntityManagerFactory {
      *
      * @param name a unique application name.
      *
-     * @return the newly created application id.
+     * @return Entity of type application_info that represents the newly created Application
      *
      * @throws Exception the exception
      */
+    public abstract Entity createApplicationV2( String organizationName, String name ) throws Exception;
+
+    @Deprecated
     public abstract UUID createApplication( String organizationName, String name ) throws Exception;
 
     /**
@@ -62,12 +65,16 @@ public interface EntityManagerFactory {
      * @param name the name of the application to create.
      * @param properties property values to create in the new entity or null.
      *
-     * @return the newly created application id.
+     * @return Entity of type application_info that represents the newly created Application
      *
      * @throws Exception the exception
      */
+    public abstract Entity createApplicationV2(
+        String organizationName, String name, Map<String, Object> properties ) throws Exception;
+
+    @Deprecated
     public abstract UUID createApplication(
-            String organizationName, String name, Map<String, Object> properties ) throws Exception;
+        String organizationName, String name, Map<String, Object> properties ) throws Exception;
 
     /**
      * Delete Application.
@@ -79,7 +86,7 @@ public interface EntityManagerFactory {
     /**
      * Restore deleted application.
      */
-    public void restoreApplication( UUID applicationId) throws Exception;
+    public Entity restoreApplication( UUID applicationId) throws Exception;
 
     public abstract UUID importApplication( String organization, UUID applicationId, String name,
                                             Map<String, Object> properties ) throws Exception;
@@ -117,6 +124,13 @@ public interface EntityManagerFactory {
 
     public abstract boolean deleteServiceProperty( String name );
 
+    /**
+     * @return Entity of type application_info that represents the newly created application.
+     */
+    public Entity initializeApplicationV2(
+        String orgName, UUID appId, String appName, Map<String, Object> props) throws Exception;
+
+    @Deprecated
     public UUID initializeApplication(
         String orgName, UUID appId, String appName, Map<String, Object> props) throws Exception;
 

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/60785263/stack/core/src/main/java/org/apache/usergrid/persistence/Schema.java
----------------------------------------------------------------------
diff --git a/stack/core/src/main/java/org/apache/usergrid/persistence/Schema.java b/stack/core/src/main/java/org/apache/usergrid/persistence/Schema.java
index f44fffa..1e3826d 100644
--- a/stack/core/src/main/java/org/apache/usergrid/persistence/Schema.java
+++ b/stack/core/src/main/java/org/apache/usergrid/persistence/Schema.java
@@ -108,6 +108,7 @@ public class Schema {
     public static final String TYPE_MEMBER = "member";
 
     public static final String PROPERTY_ACTIVATED = "activated";
+    public static final String PROPERTY_APPLICATION_ID = "applicationId";
     public static final String PROPERTY_COLLECTION_NAME = "collectionName";
     public static final String PROPERTY_CREATED = "created";
     public static final String PROPERTY_CONFIRMED = "confirmed";
@@ -1420,10 +1421,10 @@ public class Schema {
     /*
      * public Entity toEntity(Reader reader) { Entity entity =
      * mapper.convertValue(reader, Entity.class); return entity; }
-     * 
+     *
      * public Entity toEntity(InputStream input) { Entity entity =
      * mapper.convertValue(input, Entity.class); return entity; }
-     * 
+     *
      * public Entity toEntity(String string) { Entity entity =
      * mapper.convertValue(string, Entity.class); return entity; }
      */

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/60785263/stack/core/src/main/java/org/apache/usergrid/persistence/cassandra/EntityManagerFactoryImpl.java
----------------------------------------------------------------------
diff --git a/stack/core/src/main/java/org/apache/usergrid/persistence/cassandra/EntityManagerFactoryImpl.java b/stack/core/src/main/java/org/apache/usergrid/persistence/cassandra/EntityManagerFactoryImpl.java
index 4f3dabc..135424d 100644
--- a/stack/core/src/main/java/org/apache/usergrid/persistence/cassandra/EntityManagerFactoryImpl.java
+++ b/stack/core/src/main/java/org/apache/usergrid/persistence/cassandra/EntityManagerFactoryImpl.java
@@ -22,6 +22,7 @@ import java.util.Map;
 import java.util.TreeMap;
 import java.util.UUID;
 
+import org.apache.usergrid.persistence.Entity;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.BeansException;
@@ -356,6 +357,7 @@ public class EntityManagerFactoryImpl implements EntityManagerFactory, Applicati
     }
 
 
+
     @Override
     public boolean updateServiceProperties( Map<String, String> properties ) {
         try {
@@ -437,7 +439,6 @@ public class EntityManagerFactoryImpl implements EntityManagerFactory, Applicati
         throw new UnsupportedOperationException("Not supported.");
     }
 
-
     @Override
     public void addIndex(UUID appId, String suffix,final int shards,final int replicas,final String consistency) {
         throw new UnsupportedOperationException("Not supported in v1");
@@ -449,7 +450,7 @@ public class EntityManagerFactoryImpl implements EntityManagerFactory, Applicati
     }
 
     @Override
-    public void restoreApplication(UUID applicationId) throws Exception {
+    public Entity restoreApplication(UUID applicationId) throws Exception {
         throw new UnsupportedOperationException("Not supported in v1");
     }
 
@@ -458,4 +459,20 @@ public class EntityManagerFactoryImpl implements EntityManagerFactory, Applicati
         throw new UnsupportedOperationException("Not supported in v1");
     }
 
+    public Entity createApplicationV2( String organizationName, String name ) throws Exception {
+        throw new UnsupportedOperationException("Not supported in v1");
+    }
+
+    @Override
+    public Entity initializeApplicationV2(
+        String orgName, UUID appId, String appName, Map<String, Object> props) throws Exception {
+        throw new UnsupportedOperationException("Not supported in v1");
+    }
+
+    @Override
+    public Entity createApplicationV2(
+        String organizationName, String name, Map<String, Object> properties) throws Exception {
+        throw new UnsupportedOperationException("Not supported in v1");
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/60785263/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/impl/EsEntityIndexImpl.java
----------------------------------------------------------------------
diff --git a/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/impl/EsEntityIndexImpl.java b/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/impl/EsEntityIndexImpl.java
index 18b006d..88f02ab 100644
--- a/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/impl/EsEntityIndexImpl.java
+++ b/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/impl/EsEntityIndexImpl.java
@@ -682,9 +682,8 @@ public class EsEntityIndexImpl implements AliasedEntityIndex {
             @Override
             public void onResponse( DeleteByQueryResponse response) {
                 timeDeleteAllVersions.stop();
-                logger
-                    .debug( "Deleted entity {}:{} from all index scopes with response status = {}", entityId.getType(),
-                        entityId.getUuid(), response.status().toString() );
+                logger.debug( "Deleted entity {}:{} from all index scopes with response status = {}",
+                    entityId.getType(), entityId.getUuid(), response.status().toString() );
 
                 checkDeleteByQueryResponse(tqb, response);
             }
@@ -693,8 +692,8 @@ public class EsEntityIndexImpl implements AliasedEntityIndex {
             @Override
             public void onFailure( Throwable e ) {
                 timeDeleteAllVersions.stop();
-                logger.error( "Deleted entity {}:{} from all index scopes with error {}", entityId.getType(),
-                    entityId.getUuid(), e);
+                logger.error( "Failed to delete entity {}:{} from all index scopes with error {}",
+                    entityId.getType(), entityId.getUuid(), e);
 
 
             }

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/60785263/stack/rest/src/main/java/org/apache/usergrid/rest/applications/ApplicationResource.java
----------------------------------------------------------------------
diff --git a/stack/rest/src/main/java/org/apache/usergrid/rest/applications/ApplicationResource.java b/stack/rest/src/main/java/org/apache/usergrid/rest/applications/ApplicationResource.java
index 5726466..a35532d 100644
--- a/stack/rest/src/main/java/org/apache/usergrid/rest/applications/ApplicationResource.java
+++ b/stack/rest/src/main/java/org/apache/usergrid/rest/applications/ApplicationResource.java
@@ -30,6 +30,7 @@ import javax.ws.rs.core.PathSegment;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriInfo;
 
+import org.apache.commons.lang.StringUtils;
 import org.apache.usergrid.rest.ApiResponse;
 import org.apache.usergrid.rest.security.annotations.RequireOrganizationAccess;
 import org.slf4j.Logger;
@@ -515,7 +516,13 @@ public class ApplicationResource extends ServiceResource {
     @RequireOrganizationAccess
     @Override
     public JSONWithPadding executeDelete(  @Context UriInfo ui,
-        @QueryParam("callback") @DefaultValue("callback") String callback ) throws Exception {
+        @QueryParam("callback") @DefaultValue("callback") String callback,
+        @QueryParam("app_delete_confirm") String confirmDelete) throws Exception {
+
+        if (!"confirm_delete_of_application_and_data".equals( confirmDelete ) ) {
+            throw new IllegalArgumentException(
+                "Cannot delete application without app_delete_confirm parameter");
+        }
 
         Properties props = management.getProperties();
 

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/60785263/stack/rest/src/main/java/org/apache/usergrid/rest/applications/ServiceResource.java
----------------------------------------------------------------------
diff --git a/stack/rest/src/main/java/org/apache/usergrid/rest/applications/ServiceResource.java b/stack/rest/src/main/java/org/apache/usergrid/rest/applications/ServiceResource.java
index bb02f8b..eaa2531 100644
--- a/stack/rest/src/main/java/org/apache/usergrid/rest/applications/ServiceResource.java
+++ b/stack/rest/src/main/java/org/apache/usergrid/rest/applications/ServiceResource.java
@@ -423,9 +423,11 @@ public class ServiceResource extends AbstractContextResource {
 
     @DELETE
     @RequireApplicationAccess
-    public JSONWithPadding executeDelete( @Context UriInfo ui,
-                                          @QueryParam("callback") @DefaultValue("callback") String callback )
-            throws Exception {
+    public JSONWithPadding executeDelete(
+        @Context UriInfo ui,
+        @QueryParam("callback") @DefaultValue("callback") String callback,
+        @QueryParam("app_delete_confirm") String confirmAppDelete )
+        throws Exception {
 
         LOG.debug( "ServiceResource.executeDelete" );
 

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/60785263/stack/rest/src/main/java/org/apache/usergrid/rest/exceptions/ConflictExceptionMapper.java
----------------------------------------------------------------------
diff --git a/stack/rest/src/main/java/org/apache/usergrid/rest/exceptions/ConflictExceptionMapper.java b/stack/rest/src/main/java/org/apache/usergrid/rest/exceptions/ConflictExceptionMapper.java
index 34a813d..51a38e3 100644
--- a/stack/rest/src/main/java/org/apache/usergrid/rest/exceptions/ConflictExceptionMapper.java
+++ b/stack/rest/src/main/java/org/apache/usergrid/rest/exceptions/ConflictExceptionMapper.java
@@ -17,7 +17,7 @@
 package org.apache.usergrid.rest.exceptions;
 
 
-import org.apache.usergrid.management.exceptions.ConflictException;
+import org.apache.usergrid.exception.ConflictException;
 
 import javax.ws.rs.core.Response;
 import javax.ws.rs.ext.Provider;

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/60785263/stack/rest/src/main/java/org/apache/usergrid/rest/organizations/OrganizationResource.java
----------------------------------------------------------------------
diff --git a/stack/rest/src/main/java/org/apache/usergrid/rest/organizations/OrganizationResource.java b/stack/rest/src/main/java/org/apache/usergrid/rest/organizations/OrganizationResource.java
index 695becc..ff26ba2 100644
--- a/stack/rest/src/main/java/org/apache/usergrid/rest/organizations/OrganizationResource.java
+++ b/stack/rest/src/main/java/org/apache/usergrid/rest/organizations/OrganizationResource.java
@@ -20,6 +20,7 @@ package org.apache.usergrid.rest.organizations;
 import com.google.common.collect.BiMap;
 import com.sun.jersey.api.json.JSONWithPadding;
 import java.util.UUID;
+import java.util.regex.Pattern;
 import javax.ws.rs.DELETE;
 import javax.ws.rs.DefaultValue;
 import javax.ws.rs.Path;
@@ -32,6 +33,7 @@ import javax.ws.rs.core.UriInfo;
 import org.apache.shiro.authz.UnauthorizedException;
 import org.apache.usergrid.exception.NotImplementedException;
 import org.apache.usergrid.management.OrganizationInfo;
+import org.apache.usergrid.persistence.index.query.Identifier;
 import org.apache.usergrid.rest.AbstractContextResource;
 import org.apache.usergrid.rest.RootResource;
 import org.apache.usergrid.rest.applications.ApplicationResource;
@@ -40,6 +42,7 @@ import org.apache.usergrid.rest.exceptions.OrganizationApplicationNotFoundExcept
 import org.apache.usergrid.rest.security.annotations.RequireOrganizationAccess;
 import org.apache.usergrid.rest.utils.PathingUtils;
 import org.apache.usergrid.security.shiro.utils.SubjectUtils;
+import org.apache.usergrid.utils.UUIDUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.context.annotation.Scope;
@@ -140,8 +143,15 @@ public class OrganizationResource extends AbstractContextResource {
 
         String orgAppName = PathingUtils.assembleAppName( organizationName, applicationName );
         UUID applicationId = emf.lookupApplication( orgAppName );
+
         if ( applicationId == null ) {
-            throw new OrganizationApplicationNotFoundException( orgAppName, uriInfo, properties );
+
+            // TODO: fix this hacky work-around for apparent Jersey issue
+            applicationId = UUIDUtils.tryExtractUUID( applicationName );
+
+            if ( applicationId == null ) {
+                throw new OrganizationApplicationNotFoundException( orgAppName, uriInfo, properties );
+            }
         }
 
         return appResourceFor( applicationId );

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/60785263/stack/rest/src/test/java/org/apache/usergrid/rest/applications/ApplicationDeleteTest.java
----------------------------------------------------------------------
diff --git a/stack/rest/src/test/java/org/apache/usergrid/rest/applications/ApplicationDeleteTest.java b/stack/rest/src/test/java/org/apache/usergrid/rest/applications/ApplicationDeleteTest.java
index 1826d59..0eaf566 100644
--- a/stack/rest/src/test/java/org/apache/usergrid/rest/applications/ApplicationDeleteTest.java
+++ b/stack/rest/src/test/java/org/apache/usergrid/rest/applications/ApplicationDeleteTest.java
@@ -20,6 +20,9 @@ package org.apache.usergrid.rest.applications;
 
 import com.fasterxml.jackson.databind.JsonNode;
 import com.sun.jersey.api.client.UniformInterfaceException;
+import org.apache.usergrid.corepersistence.ApplicationIdCacheImpl;
+import org.apache.usergrid.corepersistence.util.CpNamingUtils;
+import org.apache.usergrid.persistence.EntityManagerFactory;
 import org.apache.usergrid.rest.test.resource2point0.AbstractRestIT;
 import org.apache.usergrid.rest.test.resource2point0.endpoints.mgmt.ManagementResponse;
 import org.apache.usergrid.rest.test.resource2point0.model.*;
@@ -30,6 +33,9 @@ import org.slf4j.LoggerFactory;
 import javax.ws.rs.core.MediaType;
 import java.io.StringReader;
 import java.util.*;
+import java.util.regex.Pattern;
+
+import static org.junit.Assert.fail;
 
 
 public class ApplicationDeleteTest  extends AbstractRestIT {
@@ -61,9 +67,22 @@ public class ApplicationDeleteTest  extends AbstractRestIT {
 
         // delete the app
 
+        try {
+            clientSetup.getRestClient()
+                .org(orgName).app(appToDeleteId.toString()).getResource()
+                .queryParam("access_token", orgAdminToken.getAccessToken())
+                .delete();
+
+            fail("Delete must fail without app_delete_confirm parameter");
+
+        } catch ( Exception e ) {
+            logger.error("Error", e);
+        }
+
         clientSetup.getRestClient()
             .org(orgName).app(appToDeleteId.toString() ).getResource()
             .queryParam("access_token", orgAdminToken.getAccessToken() )
+            .queryParam("app_delete_confirm", "confirm_delete_of_application_and_data")
             .delete();
 
         // test that we can no longer get the app
@@ -75,7 +94,7 @@ public class ApplicationDeleteTest  extends AbstractRestIT {
                 .type(MediaType.APPLICATION_JSON)
                 .get(ApiResponse.class);
 
-            Assert.fail("Must not be able to get deleted app");
+            fail("Must not be able to get deleted app");
 
         } catch ( UniformInterfaceException expected ) {
             Assert.assertEquals("Error must be 400", 400, expected.getResponse().getStatus() );
@@ -92,7 +111,7 @@ public class ApplicationDeleteTest  extends AbstractRestIT {
                 .type(MediaType.APPLICATION_JSON )
                 .get(ApiResponse.class);
 
-            Assert.fail("Must not be able to get deleted app's collection");
+            fail("Must not be able to get deleted app's collection");
 
         } catch ( UniformInterfaceException expected ) {
             Assert.assertEquals("Error must be 400", 400, expected.getResponse().getStatus() );
@@ -110,7 +129,7 @@ public class ApplicationDeleteTest  extends AbstractRestIT {
                 .type( MediaType.APPLICATION_JSON)
                 .get(ApiResponse.class);
 
-            Assert.fail("Must not be able to get deleted app entity");
+            fail("Must not be able to get deleted app entity");
 
         } catch ( UniformInterfaceException expected ) {
             // TODO: why not a 404?
@@ -129,7 +148,7 @@ public class ApplicationDeleteTest  extends AbstractRestIT {
 
         for ( String appName : orgAppResponse.getData().keySet() ) {
             if ( orgAppResponse.getData().get( appName ).equals( appToDeleteId.toString() )) {
-                Assert.fail("Deleted app must not be included in list of org apps");
+                fail("Deleted app must not be included in list of org apps");
             }
         }
 
@@ -185,21 +204,29 @@ public class ApplicationDeleteTest  extends AbstractRestIT {
 
         // delete the app
 
+        logger.debug("\n\nDeleting app\n");
+
         clientSetup.getRestClient()
-            .org(orgName).app(appToDeleteId.toString() ).getResource()
+            .org(orgName).app( appToDeleteName ).getResource()
             .queryParam("access_token", orgAdminToken.getAccessToken() )
+            .queryParam("app_delete_confirm", "confirm_delete_of_application_and_data")
             .delete();
 
+        Thread.sleep(1000);
+
         // restore the app
 
+        logger.debug("\n\nRestoring app\n");
+
         clientSetup.getRestClient()
-            .org(orgName).app(appToDeleteId.toString() ).getResource()
+            .org(orgName).app( appToDeleteId.toString() ).getResource()
             .queryParam("access_token", orgAdminToken.getAccessToken() )
             .put();
 
-
         // test that we can see the application in the list of applications
 
+        logger.debug("\n\nGetting app list from management end-point\n");
+
         ManagementResponse orgAppResponse = clientSetup.getRestClient()
             .management().orgs().organization( orgName ).apps().getOrganizationApplications();
 
@@ -215,6 +242,8 @@ public class ApplicationDeleteTest  extends AbstractRestIT {
 
         // test that we can get an app entity
 
+        logger.debug("\n\nGetting entities from app\n");
+
         UUID entityId = entities.get(0).getUuid();
         ApiResponse entityResponse = clientSetup.getRestClient()
             .org(orgName).app(appToDeleteName).collection("things").entity( entityId ).getResource()
@@ -255,6 +284,7 @@ public class ApplicationDeleteTest  extends AbstractRestIT {
         clientSetup.getRestClient()
             .org( orgName ).app(appToDeleteId.toString() ).getResource()
             .queryParam( "access_token", orgAdminToken.getAccessToken() )
+            .queryParam("app_delete_confirm", "confirm_delete_of_application_and_data")
             .delete();
 
         // create new app with same name
@@ -270,7 +300,7 @@ public class ApplicationDeleteTest  extends AbstractRestIT {
                 .queryParam("access_token", orgAdminToken.getAccessToken())
                 .put();
 
-            Assert.fail("Must fail to restore app with same name as existing app");
+            fail("Must fail to restore app with same name as existing app");
 
         } catch ( UniformInterfaceException e ) {
             Assert.assertEquals(409, e.getResponse().getStatus());
@@ -300,6 +330,7 @@ public class ApplicationDeleteTest  extends AbstractRestIT {
         clientSetup.getRestClient()
             .org( orgName ).app(appToDeleteId.toString() ).getResource()
             .queryParam( "access_token", orgAdminToken.getAccessToken() )
+            .queryParam("app_delete_confirm", "confirm_delete_of_application_and_data")
             .delete();
 
         // create new app with same name
@@ -313,9 +344,10 @@ public class ApplicationDeleteTest  extends AbstractRestIT {
             clientSetup.getRestClient()
                 .org(orgName).app( newAppId.toString() ).getResource()
                 .queryParam("access_token", orgAdminToken.getAccessToken())
+                .queryParam("app_delete_confirm", "confirm_delete_of_application_and_data")
                 .delete();
 
-            Assert.fail("Must fail to delete app with same name as deleted app");
+            fail("Must fail to delete app with same name as deleted app");
 
         } catch ( UniformInterfaceException e ) {
             Assert.assertEquals( 409, e.getResponse().getStatus() );

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/60785263/stack/rest/src/test/java/org/apache/usergrid/rest/test/resource2point0/endpoints/OrganizationResource.java
----------------------------------------------------------------------
diff --git a/stack/rest/src/test/java/org/apache/usergrid/rest/test/resource2point0/endpoints/OrganizationResource.java b/stack/rest/src/test/java/org/apache/usergrid/rest/test/resource2point0/endpoints/OrganizationResource.java
index 253de6e..cf774d0 100644
--- a/stack/rest/src/test/java/org/apache/usergrid/rest/test/resource2point0/endpoints/OrganizationResource.java
+++ b/stack/rest/src/test/java/org/apache/usergrid/rest/test/resource2point0/endpoints/OrganizationResource.java
@@ -18,6 +18,7 @@ package org.apache.usergrid.rest.test.resource2point0.endpoints;
 
 
 import java.util.Map;
+import java.util.UUID;
 
 import javax.ws.rs.core.MediaType;
 
@@ -38,11 +39,10 @@ public class OrganizationResource extends NamedResource {
         super( name, context, parent );
     }
 
-    public ApplicationsResource app(final String app){
-        return new ApplicationsResource( app, context ,this );
+    public ApplicationsResource app(final String name){
+        return new ApplicationsResource( name, context ,this );
     }
 
-
     public void post(Map<String,String> organization) {
 
         getResource().type( MediaType.APPLICATION_JSON_TYPE ).accept( MediaType.APPLICATION_JSON )

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/60785263/stack/rest/src/test/resources/log4j.properties
----------------------------------------------------------------------
diff --git a/stack/rest/src/test/resources/log4j.properties b/stack/rest/src/test/resources/log4j.properties
index 4c9c709..27e35c8 100644
--- a/stack/rest/src/test/resources/log4j.properties
+++ b/stack/rest/src/test/resources/log4j.properties
@@ -47,7 +47,6 @@ log4j.logger.org.apache.usergrid.rest.filters.MeteringFilter=ERROR
 #log4j.logger.org.apache.usergrid.corepersistence.CpRelationManager=DEBUG
 #log4j.logger.org.apache.usergrid.corepersistence.CpEntityManager=DEBUG
 #log4j.logger.org.apache.usergrid.corepersistence.CpEntityManagerFactory=DEBUG
-#log4j.logger.org.apache.usergrid.corepersistence.CpSetup=INFO
 
 #log4j.logger.org.apache.usergrid.persistence.index=DEBUG
 #log4j.logger.org.apache.usergrid.persistence.index.impl=DEBUG
@@ -67,16 +66,16 @@ log4j.logger.org.apache.usergrid.rest.filters.MeteringFilter=ERROR
 #log4j.logger.org.apache.usergrid.services.notifiers=DEBUG
 #log4j.logger.org.apache.usergrid.services.groups.users.devices=DEBUG
 
+log4j.logger.org.apache.usergrid.rest=INFO
+log4j.logger.org.apache.usergrid.rest.exceptions=DEBUG
 #log4j.logger.org.apache.usergrid.rest.NotificationsIT=DEBUG
 #log4j.logger.org.apache.usergrid.cassandra.CassandraResource=DEBUG
 #log4j.logger.org.apache.usergrid.rest.TomcatResource=INFO
-#log4j.logger.org.apache.usergrid.rest=INFO
-log4j.logger.org.apache.usergrid.rest.management=DEBUG
+#log4j.logger.org.apache.usergrid.rest.management=DEBUG
 #log4j.logger.org.apache.usergrid.rest.management.users=DEBUG
 #log4j.logger.org.apache.usergrid.rest.organizations.users=DEBUG
 #log4j.logger.org.apache.usergrid.rest.applications.users.UsersResource=DEBUG
 #log4j.logger.org.apache.usergrid.rest.applications.ServiceResource=DEBUG
-
 #log4j.logger.org.apache.usergrid.rest.security=DEBUG
 #log4j.logger.org.apache.usergrid.security=DEBUG
 

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/60785263/stack/services/src/main/java/org/apache/usergrid/management/ApplicationInfo.java
----------------------------------------------------------------------
diff --git a/stack/services/src/main/java/org/apache/usergrid/management/ApplicationInfo.java b/stack/services/src/main/java/org/apache/usergrid/management/ApplicationInfo.java
index 30c494f..d11cf9a 100644
--- a/stack/services/src/main/java/org/apache/usergrid/management/ApplicationInfo.java
+++ b/stack/services/src/main/java/org/apache/usergrid/management/ApplicationInfo.java
@@ -34,6 +34,10 @@ public class ApplicationInfo {
     private final String name;
 
 
+    /**
+     * @param id The application ID (not the same as the ID of the application_info).
+     * @param name The application name in orgname/appname format.
+     */
     public ApplicationInfo( UUID id, String name ) {
         this.id = id;
         this.name = name;

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/60785263/stack/services/src/main/java/org/apache/usergrid/management/ManagementService.java
----------------------------------------------------------------------
diff --git a/stack/services/src/main/java/org/apache/usergrid/management/ManagementService.java b/stack/services/src/main/java/org/apache/usergrid/management/ManagementService.java
index 8ed15f2..b83c46b 100644
--- a/stack/services/src/main/java/org/apache/usergrid/management/ManagementService.java
+++ b/stack/services/src/main/java/org/apache/usergrid/management/ManagementService.java
@@ -46,8 +46,6 @@ public interface ManagementService {
     public void addAdminUserToOrganization( UserInfo user, OrganizationInfo organization, boolean email )
             throws Exception;
 
-    public UUID addApplicationToOrganization( UUID organizationId, UUID applicationId, Entity appInfo ) throws Exception;
-
     public AccessInfo authorizeClient( String clientId, String clientSecret, long ttl ) throws Exception;
 
     public ActivationState handleConfirmationTokenForAdminUser( UUID userId, String token ) throws Exception;
@@ -95,6 +93,8 @@ public interface ManagementService {
 
     public void deactivateOrganization( UUID organizationId ) throws Exception;
 
+    public UUID addApplicationToOrganization(UUID organizationId, Entity appInfo) throws Exception;
+
     public void deleteOrganizationApplication( UUID organizationId, UUID applicationId ) throws Exception;
 
     public void disableAdminUser( UUID userId ) throws Exception;

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/60785263/stack/services/src/main/java/org/apache/usergrid/management/cassandra/ManagementServiceImpl.java
----------------------------------------------------------------------
diff --git a/stack/services/src/main/java/org/apache/usergrid/management/cassandra/ManagementServiceImpl.java b/stack/services/src/main/java/org/apache/usergrid/management/cassandra/ManagementServiceImpl.java
index 84f5d13..2874ffc 100644
--- a/stack/services/src/main/java/org/apache/usergrid/management/cassandra/ManagementServiceImpl.java
+++ b/stack/services/src/main/java/org/apache/usergrid/management/cassandra/ManagementServiceImpl.java
@@ -29,7 +29,10 @@ import java.util.Set;
 import java.util.UUID;
 
 import org.apache.usergrid.corepersistence.util.CpNamingUtils;
+import org.apache.usergrid.exception.ConflictException;
 import org.apache.usergrid.management.exceptions.*;
+import org.apache.usergrid.persistence.*;
+import org.apache.usergrid.persistence.index.query.Query;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -45,16 +48,8 @@ import org.apache.usergrid.management.ManagementService;
 import org.apache.usergrid.management.OrganizationInfo;
 import org.apache.usergrid.management.OrganizationOwnerInfo;
 import org.apache.usergrid.management.UserInfo;
-import org.apache.usergrid.persistence.CredentialsInfo;
-import org.apache.usergrid.persistence.Entity;
-import org.apache.usergrid.persistence.EntityManager;
-import org.apache.usergrid.persistence.EntityManagerFactory;
-import org.apache.usergrid.persistence.EntityRef;
 import org.apache.usergrid.persistence.exceptions.ApplicationAlreadyExistsException;
 import org.apache.usergrid.persistence.index.query.Identifier;
-import org.apache.usergrid.persistence.PagingResultsIterator;
-import org.apache.usergrid.persistence.Results;
-import org.apache.usergrid.persistence.SimpleEntityRef;
 import org.apache.usergrid.persistence.entities.Application;
 import org.apache.usergrid.persistence.entities.Group;
 import org.apache.usergrid.persistence.entities.User;
@@ -647,24 +642,8 @@ public class ManagementServiceImpl implements ManagementService {
 
 
     @Override
-    public UUID importApplication( UUID organizationId, Application application ) throws Exception {
-        // TODO organizationName
-        OrganizationInfo organization = getOrganizationByUuid( organizationId );
-        UUID applicationId =
-                emf.importApplication( organization.getName(), application.getUuid(), application.getName(),
-                        application.getProperties() );
-
-        EntityManager em = emf.getEntityManager( smf.getManagementAppId() );
-        properties.setProperty( "name", buildAppName( application.getName(), organization ) );
-        properties.setProperty( PROPERTY_PATH, organization.getName() );
-        Entity appInfo = em.create(
-            applicationId, CpNamingUtils.APPLICATION_INFO, application.getProperties() );
-
-        writeUserToken( smf.getManagementAppId(), appInfo, encryptionService
-                .plainTextCredentials( generateOAuthSecretKey( AuthPrincipalType.APPLICATION ), null, applicationId ) );
-
-        addApplicationToOrganization( organizationId, applicationId, appInfo );
-        return applicationId;
+    public UUID importApplication( UUID organizationId, final Application application ) throws Exception {
+        throw new UnsupportedOperationException("Import application not supported");
     }
 
 
@@ -1550,14 +1529,14 @@ public class ManagementServiceImpl implements ManagementService {
     @Override
     public Map<String, Object> getOrganizationData( OrganizationInfo organization ) throws Exception {
 
-        Map<String, Object> jsonOrganization = new HashMap<String, Object>();
+        Map<String, Object> jsonOrganization = new HashMap<>();
         jsonOrganization.putAll( JsonUtils.toJsonMap( organization ) );
 
         BiMap<UUID, String> applications = getApplicationsForOrganization( organization.getUuid() );
         jsonOrganization.put( "applications", applications.inverse() );
 
         List<UserInfo> users = getAdminUsersForOrganization( organization.getUuid() );
-        Map<String, Object> jsonUsers = new HashMap<String, Object>();
+        Map<String, Object> jsonUsers = new HashMap<>();
         for ( UserInfo u : users ) {
             jsonUsers.put( u.getUsername(), u );
         }
@@ -1631,20 +1610,17 @@ public class ManagementServiceImpl implements ManagementService {
         EntityManager em = emf.getEntityManager( smf.getManagementAppId() );
 
         OrganizationInfo organizationInfo = getOrganizationByUuid( organizationId );
-        UUID applicationId = emf.createApplication(
-            organizationInfo.getName(), applicationName, properties );
+        Entity appInfo = emf.createApplicationV2(
+            organizationInfo.getName(), applicationName, properties);
         em.refreshIndex();
 
-        Entity appInfo = em.get(
-            new SimpleEntityRef( CpNamingUtils.APPLICATION_INFO, applicationId ));
-
         writeUserToken( smf.getManagementAppId(), appInfo,
             encryptionService.plainTextCredentials(
                 generateOAuthSecretKey( AuthPrincipalType.APPLICATION ),
                 null,
                 smf.getManagementAppId() ) );
 
-        addApplicationToOrganization( organizationId, applicationId, appInfo );
+        UUID applicationId = addApplicationToOrganization( organizationId, appInfo );
 
         UserInfo user = null;
         try {
@@ -1668,20 +1644,6 @@ public class ManagementServiceImpl implements ManagementService {
 
     @Override
     public void deleteApplication(UUID applicationId) throws Exception {
-
-        // make sure there is not already a delete app with the same name
-
-        EntityManager em = emf.getEntityManager(CpNamingUtils.MANAGEMENT_APPLICATION_ID);
-        Entity appToDelete = em.get(
-            new SimpleEntityRef( CpNamingUtils.APPLICATION_INFO, applicationId ));
-
-        final EntityRef alias = em.getAlias(
-            CpNamingUtils.DELETED_APPLICATION_INFO, appToDelete.getName() );
-
-        if ( alias != null ) {
-            throw new ConflictException("Cannot delete app with same name as already deleted app");
-        }
-
         emf.deleteApplication( applicationId );
     }
 
@@ -1701,13 +1663,10 @@ public class ManagementServiceImpl implements ManagementService {
         // restore application_info entity
 
         EntityManager em = emf.getEntityManager( CpNamingUtils.MANAGEMENT_APPLICATION_ID );
-        emf.restoreApplication(applicationId);
+        Entity appInfo = emf.restoreApplication(applicationId);
 
         // restore token
 
-        Entity appInfo = em.get(
-            new SimpleEntityRef( CpNamingUtils.APPLICATION_INFO, applicationId ));
-
         writeUserToken( smf.getManagementAppId(), appInfo,
             encryptionService.plainTextCredentials(
                 generateOAuthSecretKey( AuthPrincipalType.APPLICATION ),
@@ -1718,7 +1677,7 @@ public class ManagementServiceImpl implements ManagementService {
         EntityRef alias = em.getAlias( Group.ENTITY_TYPE, orgName );
         Entity orgEntity = em.get( alias );
 
-        addApplicationToOrganization( orgEntity.getUuid(), applicationId, appInfo );
+        addApplicationToOrganization( orgEntity.getUuid(), appInfo );
 
         // create activity
 
@@ -1773,6 +1732,7 @@ public class ManagementServiceImpl implements ManagementService {
         final BiMap<UUID, String> applications = HashBiMap.create();
         final EntityManager em = emf.getEntityManager( smf.getManagementAppId() );
 
+        // query for application_info entities
         final Results results = em.getConnectedEntities(
                 new SimpleEntityRef(Group.ENTITY_TYPE, organizationGroupId),
                 "owns", CpNamingUtils.APPLICATION_INFO, Level.ALL_PROPERTIES );
@@ -1791,7 +1751,11 @@ public class ManagementServiceImpl implements ManagementService {
                 entityName = entityName.toLowerCase();
             }
 
-            applications.put( entity.getUuid(), entityName );
+            // make sure we return applicationId and not the application_info UUID
+            UUID applicationId = UUIDUtils.tryExtractUUID(
+                entity.getProperty( PROPERTY_APPLICATION_ID ).toString() );
+
+            applications.put( applicationId, entityName );
         }
 
 
@@ -1813,8 +1777,14 @@ public class ManagementServiceImpl implements ManagementService {
     }
 
 
+    /**
+     * @return UUID of the application itself (NOT the application_info entity).
+     */
     @Override
-    public UUID addApplicationToOrganization( UUID organizationId, UUID applicationId, Entity appInfo ) throws Exception {
+    public UUID addApplicationToOrganization(UUID organizationId, Entity appInfo) throws Exception {
+
+        UUID applicationId = UUIDUtils.tryExtractUUID(
+            appInfo.getProperty(PROPERTY_APPLICATION_ID).toString());
 
         if ( ( organizationId == null ) || ( applicationId == null ) ) {
             return null;
@@ -1860,7 +1830,12 @@ public class ManagementServiceImpl implements ManagementService {
             return null;
         }
         EntityManager em = emf.getEntityManager( smf.getManagementAppId() );
-        Entity entity = em.get( new SimpleEntityRef( CpNamingUtils.APPLICATION_INFO, applicationId ));
+        EntityRef mgmtAppRef = new SimpleEntityRef( Schema.TYPE_APPLICATION, smf.getManagementAppId() );
+
+        final Results results = em.searchCollection(mgmtAppRef, CpNamingUtils.APPLICATION_INFOS,
+            Query.fromQL("select * where " + PROPERTY_APPLICATION_ID + " = " + applicationId.toString()));
+
+        Entity entity = results.getEntity();
 
         if ( entity != null ) {
             return new ApplicationInfo( applicationId, entity.getName() );
@@ -1875,8 +1850,12 @@ public class ManagementServiceImpl implements ManagementService {
             return null;
         }
         EntityManager em = emf.getEntityManager( smf.getManagementAppId() );
-        Entity entity = em.get( new SimpleEntityRef(
-            CpNamingUtils.DELETED_APPLICATION_INFO, applicationId ));
+        EntityRef mgmtAppRef = new SimpleEntityRef( Schema.TYPE_APPLICATION, smf.getManagementAppId() );
+
+        final Results results = em.searchCollection(mgmtAppRef, CpNamingUtils.DELETED_APPLICATION_INFOS,
+            Query.fromQL("select * where " + PROPERTY_APPLICATION_ID + " = " + applicationId.toString()));
+
+        Entity entity = results.getEntity();
 
         if ( entity != null ) {
             return new ApplicationInfo( applicationId, entity.getName() );

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/60785263/stack/services/src/main/java/org/apache/usergrid/management/exceptions/ConflictException.java
----------------------------------------------------------------------
diff --git a/stack/services/src/main/java/org/apache/usergrid/management/exceptions/ConflictException.java b/stack/services/src/main/java/org/apache/usergrid/management/exceptions/ConflictException.java
deleted file mode 100644
index 2ec14c8..0000000
--- a/stack/services/src/main/java/org/apache/usergrid/management/exceptions/ConflictException.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright 2014 The Apache Software Foundation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.usergrid.management.exceptions;
-
-public class ConflictException extends ManagementException {
-
-    public ConflictException() {
-        super();
-    }
-
-    public ConflictException(String arg0, Throwable arg1) {
-        super(arg0, arg1);
-    }
-
-    public ConflictException(String arg0) {
-        super(arg0);
-    }
-
-    public ConflictException(Throwable arg0) {
-        super(arg0);
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/60785263/stack/services/src/test/java/org/apache/usergrid/corepersistence/migration/AppInfoMigrationPluginTest.java
----------------------------------------------------------------------
diff --git a/stack/services/src/test/java/org/apache/usergrid/corepersistence/migration/AppInfoMigrationPluginTest.java b/stack/services/src/test/java/org/apache/usergrid/corepersistence/migration/AppInfoMigrationPluginTest.java
index c117c49..30b7a3c 100644
--- a/stack/services/src/test/java/org/apache/usergrid/corepersistence/migration/AppInfoMigrationPluginTest.java
+++ b/stack/services/src/test/java/org/apache/usergrid/corepersistence/migration/AppInfoMigrationPluginTest.java
@@ -24,16 +24,16 @@ import org.apache.usergrid.ServiceITSetup;
 import org.apache.usergrid.ServiceITSetupImpl;
 import org.apache.usergrid.cassandra.ClearShiroSubject;
 import org.apache.usergrid.management.OrganizationOwnerInfo;
-import org.apache.usergrid.persistence.Entity;
-import org.apache.usergrid.persistence.EntityManager;
-import org.apache.usergrid.persistence.Results;
-import org.apache.usergrid.persistence.SimpleEntityRef;
+import org.apache.usergrid.persistence.*;
 import org.apache.usergrid.persistence.core.migration.data.ProgressObserver;
+import org.apache.usergrid.persistence.entities.Application;
 import org.apache.usergrid.persistence.index.query.Query;
 import org.junit.ClassRule;
 import org.junit.Rule;
 import org.junit.Test;
 import org.mockito.Mockito;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import java.util.*;
 
@@ -48,6 +48,7 @@ import static org.junit.Assert.*;
  * ManagementService's application and organization logic.
  */
 public class AppInfoMigrationPluginTest {
+    private static final Logger logger = LoggerFactory.getLogger(AppInfoMigrationPluginTest.class);
 
     @Rule
     public ClearShiroSubject clearShiroSubject = new ClearShiroSubject();
@@ -62,9 +63,11 @@ public class AppInfoMigrationPluginTest {
     @Test
     public void testRun() throws Exception {
 
-        // create 10 applications, each with 10 entities
+       // create 10 applications, each with 10 entities
 
-        final String orgName =  uniqueOrg();
+        logger.debug("\n\nCreate 10 apps each with 10 entities");
+
+       final String orgName =  uniqueOrg();
         OrganizationOwnerInfo organization =  orgAppRule.createOwnerAndOrganization(
             orgName, uniqueUsername(), uniqueEmail(),"Ed Anuff", "test" );
 
@@ -85,46 +88,66 @@ public class AppInfoMigrationPluginTest {
             }
         }
 
-        assertNotNull("Should be able to get application",
-            setup.getEmf().lookupApplication(orgName + "/application0"));
+        UUID mgmtAppId = setup.getEmf().getManagementAppId();
+        EntityManager rootEm = setup.getEmf().getEntityManager( mgmtAppId );
+
+        checkApplicationsOk( orgName );
 
         // create corresponding 10 appinfo entities in Management app
         // and delete the application_info entities from the Management app
 
-        UUID mgmtAppId = setup.getEmf().getManagementAppId();
-        EntityManager rootEm = setup.getEmf().getEntityManager( mgmtAppId );
+        logger.debug("\n\nCreate old-style appinfo entities to be migrated\n");
 
+        List<Entity> deletedApps = new ArrayList<>();
+
+        int count = 0;
         for ( UUID appId : appIds ) {
+
+            final Entity applicationInfo = getApplicationInfo( appId );
+
+            final String appName = applicationInfo.getName();
             final String finalOrgId = organization.getOrganization().getUuid().toString();
-            final String finalAppId = appId.toString();
+            final String finalAppId = applicationInfo.getProperty( Schema.PROPERTY_APPLICATION_ID ).toString();
             rootEm.create("appinfo", new HashMap<String, Object>() {{
+                put("name", appName );
                 put("organizationUuid", finalOrgId );
                 put("applicationUuid", finalAppId );
             }});
-            rootEm.delete( new SimpleEntityRef("application_info", appId ));
+
+            // delete some but not all of the application_info entities
+            // so that we cover both create and update cases
+
+            if ( count++ % 2 == 0 ) {
+                rootEm.delete( applicationInfo );
+                deletedApps.add( applicationInfo );
+            }
         }
 
+        setup.getEmf().refreshIndex();
         setup.getEmf().flushEntityManagerCaches();
 
-        // test that applications are now borked
+        Thread.sleep(1000);
+
+        // test that applications are now broken
 
-        assertNull("Should not be able to get application",
-            setup.getEmf().lookupApplication(orgName + "/application0"));
+        checkApplicationsBroken( orgName, deletedApps );
 
         // run the migration, which should restore the application_info entities
 
+        logger.debug("\n\nRun the migration\n");
+
         ProgressObserver po = Mockito.mock(ProgressObserver.class);
         AppInfoMigrationPlugin plugin = new AppInfoMigrationPlugin();
         plugin.emf = setup.getEmf();
         plugin.run( po );
 
+        logger.debug("\n\nVerify migration results\n");
+
         // test that expected calls were made the to progress observer (use mock library)
 
         Mockito.verify( po, Mockito.times(10) ).update( Mockito.anyInt(), Mockito.anyString() );
         setup.getEmf().refreshIndex();
 
-        // test that 10 appinfo entities have been removed
-
         final Results appInfoResults = rootEm.searchCollection(
             new SimpleEntityRef("application", mgmtAppId), "appinfos", Query.fromQL("select *"));
         assertEquals( 0, appInfoResults.size() );
@@ -133,9 +156,57 @@ public class AppInfoMigrationPluginTest {
             new SimpleEntityRef("application", mgmtAppId), "application_infos", Query.fromQL("select *"));
         assertEquals( 10, applicationInfoResults.size() );
 
-        // test that 10 applications are no longer borked
+        // test that 10 applications are no longer broken
+
+        checkApplicationsOk( orgName );
+    }
+
+    private void checkApplicationsBroken( String orgName, List<Entity> deletedApps ) throws Exception {
+
+        logger.debug("\n\nChecking applications broken\n");
+
+
+        for ( Entity applicationInfo : deletedApps ) {
+
+            String appName = applicationInfo.getName();
+            UUID uuid = setup.getEmf().lookupApplication( appName );
+
+            // missing application_info does not completely break applications, but we...
+            assertNull("Should not be able to lookup deleted application by name" + appName, uuid);
+        }
+    }
+
+    private void checkApplicationsOk( String orgName) throws Exception {
+
+        logger.debug("\n\nChecking applications OK\n");
+
+        for (int i=0; i<10; i++) {
+
+            String appName = orgName + "/application" + i;
+
+            UUID uuid = setup.getEmf().lookupApplication( appName );
+            assertNotNull("Should be able to get application", uuid );
+
+            EntityManager em = setup.getEmf().getEntityManager( uuid );
+
+            Application app = em.getApplication();
+            assertEquals( appName, app.getName() );
+
+            Results results = em.searchCollection(
+                em.getApplicationRef(), "things", Query.fromQL("select *"));
+            assertEquals( "Should have 10 entities", 10, results.size() );
+        }
+    }
+
+    private Entity getApplicationInfo( UUID appId ) throws Exception {
+
+        UUID mgmtAppId = setup.getEmf().getManagementAppId();
+        EntityManager rootEm = setup.getEmf().getEntityManager( mgmtAppId );
+
+        final Results applicationInfoResults = rootEm.searchCollection(
+            new SimpleEntityRef("application", mgmtAppId), "application_infos",
+            Query.fromQL("select * where applicationId=" + appId.toString()));
 
-        assertNotNull("Should be able to get application",
-            setup.getEmf().lookupApplication(orgName + "/application0"));
+        return applicationInfoResults.getEntity();
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/60785263/stack/services/src/test/java/org/apache/usergrid/management/cassandra/ApplicationCreatorIT.java
----------------------------------------------------------------------
diff --git a/stack/services/src/test/java/org/apache/usergrid/management/cassandra/ApplicationCreatorIT.java b/stack/services/src/test/java/org/apache/usergrid/management/cassandra/ApplicationCreatorIT.java
index 20b2e17..6e0f37e 100644
--- a/stack/services/src/test/java/org/apache/usergrid/management/cassandra/ApplicationCreatorIT.java
+++ b/stack/services/src/test/java/org/apache/usergrid/management/cassandra/ApplicationCreatorIT.java
@@ -19,6 +19,7 @@ package org.apache.usergrid.management.cassandra;
 
 import java.util.Set;
 
+import org.apache.usergrid.corepersistence.ApplicationIdCacheImpl;
 import org.junit.Rule;
 import org.junit.Test;