code: public void deleteApplication(ApplicationDefinition appDef, String key) {
          checkServiceState();
          String appKey = appDef.getKey();
          if (Utils.isEmpty(appKey)) {
              Utils.require(Utils.isEmpty(key), "Application key does not match: %s", key);
          } else {
              Utils.require(appKey.equals(key), "Application key does not match: %s", key);
          }
          assert Tenant.getTenant(appDef) != null;
          
          // Delete storage service-specific data first.
          m_logger.info("Deleting application: {}", appDef.getAppName());
          StorageService storageService = getStorageService(appDef);
          storageService.deleteApplication(appDef);
          TaskManagerService.instance().deleteApplicationTasks(appDef);
          deleteAppProperties(appDef);
      }
docs: Delete the application with the given definition, including all of its data. The
  given {@link ApplicationDefinition} must define the tenant in which the application
  resides. If the given application doesn't exist, the call is a no-op. If the
  application exists, the given key must match the current key, if one is defined, or
  be null/empty if no key is defined.
  
  @param appDef    {@link ApplicationDefinition} of application to delete.
  @param key       Application key of existing application, if any.