Refactoring the code to add page archival for a given application

The code for archiving an application has been moved to ApplicationPageService so that both the PageService and ApplicationService can access it.
This commit is contained in:
Arpit Mohan 2020-02-05 08:37:37 +05:30
parent 3838338099
commit 440de34857
10 changed files with 111 additions and 47 deletions

View File

@ -9,6 +9,7 @@ import com.appsmith.server.services.ApplicationService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
@ -52,4 +53,11 @@ public class ApplicationController extends BaseController<ApplicationService, Ap
.map(updatedApplication -> new ResponseDTO<>(HttpStatus.OK.value(), updatedApplication, null));
}
@DeleteMapping("/{id}")
public Mono<ResponseDTO<Application>> delete(@PathVariable String id) {
log.debug("Going to delete application with id: {}", id);
return applicationPageService.deleteApplication(id)
.map(deletedResource -> new ResponseDTO<>(HttpStatus.OK.value(), deletedResource, null));
}
}

View File

@ -10,6 +10,7 @@ import com.appsmith.server.services.PageService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
@ -68,4 +69,11 @@ public class PageController extends BaseController<PageService, Page, String> {
return applicationPageService.getPageByName(applicationName, pageName, true)
.map(page -> new ResponseDTO<>(HttpStatus.OK.value(), page, null));
}
@DeleteMapping("/{id}")
public Mono<ResponseDTO<Page>> delete(@PathVariable String id) {
log.debug("Going to delete page with id: {}", id);
return service.delete(id)
.map(deletedResource -> new ResponseDTO<>(HttpStatus.OK.value(), deletedResource, null));
}
}

View File

@ -16,7 +16,7 @@ public interface BaseRepository<T, ID extends Serializable> extends ReactiveMong
* @param T The entity which needs to be archived
* @return Mono<T>
*/
Mono<T> archiveById(T entity);
Mono<T> archive(T entity);
/**
* This function directly updates the document by setting the deleted flag to true for the entity with the given id

View File

@ -76,7 +76,7 @@ public class BaseRepositoryImpl<T extends BaseDomain, ID extends Serializable> e
}
@Override
public Mono<T> archiveById(T entity) {
public Mono<T> archive(T entity) {
Assert.notNull(entity, "The given entity must not be null!");
Assert.notNull(entity.getId(), "The given entity's id must not be null!");
Assert.isTrue(!entity.getDeleted(), "The given entity is already deleted");

View File

@ -18,4 +18,6 @@ public interface ApplicationPageService {
Mono<Page> getPageByName(String applicationName, String pageName, Boolean viewMode);
Mono<Application> makePageDefault(String applicationId, String pageId);
Mono<Application> deleteApplication(String id);
}

View File

@ -1,5 +1,6 @@
package com.appsmith.server.services;
import com.appsmith.server.constants.AnalyticsEvents;
import com.appsmith.server.constants.FieldName;
import com.appsmith.server.domains.Application;
import com.appsmith.server.domains.ApplicationPage;
@ -8,23 +9,30 @@ import com.appsmith.server.domains.Page;
import com.appsmith.server.domains.User;
import com.appsmith.server.exceptions.AppsmithError;
import com.appsmith.server.exceptions.AppsmithException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;
import java.util.ArrayList;
import java.util.List;
@Slf4j
@Service
public class ApplicationPageServiceImpl implements ApplicationPageService {
private final ApplicationService applicationService;
private final PageService pageService;
private final SessionUserService sessionUserService;
private final AnalyticsService analyticsService;
public ApplicationPageServiceImpl(ApplicationService applicationService,
PageService pageService, SessionUserService sessionUserService) {
PageService pageService,
SessionUserService sessionUserService,
AnalyticsService analyticsService) {
this.applicationService = applicationService;
this.pageService = pageService;
this.sessionUserService = sessionUserService;
this.analyticsService = analyticsService;
}
public Mono<Page> createPage(Page page) {
@ -188,4 +196,33 @@ public class ApplicationPageServiceImpl implements ApplicationPageService {
.flatMap(savedPage -> addPageToApplication(Mono.just(savedApplication), savedPage, true));
});
}
/**
* This function performs a soft delete for the application along with it's associated pages and actions.
*
* @param id The application id to delete
* @return The modified application object with the deleted flag set
*/
@Override
public Mono<Application> deleteApplication(String id) {
log.debug("Archiving application with id: {}", id);
Mono<Application> applicationMono = applicationService.findById(id)
.switchIfEmpty(Mono.error(new AppsmithException(AppsmithError.NO_RESOURCE_FOUND, "application", id)))
.flatMap(application -> {
log.debug("Archiving pages for applicationId: {}", id);
return pageService.findByApplicationId(id)
.flatMap(page -> pageService.delete(page.getId()))
.collectList()
.thenReturn(application);
})
.flatMap(application -> applicationService.archive(application));
return applicationMono
.map(deletedObj -> {
analyticsService.sendEvent(AnalyticsEvents.DELETE + "_" + deletedObj.getClass().getSimpleName().toUpperCase(), (Application) deletedObj);
return (Application) deletedObj;
});
}
}

View File

@ -14,4 +14,5 @@ public interface ApplicationService extends CrudService<Application, String> {
Mono<Application> save(Application application);
Mono<Application> archive(Application application);
}

View File

@ -1,12 +1,9 @@
package com.appsmith.server.services;
import com.appsmith.server.constants.AnalyticsEvents;
import com.appsmith.server.constants.FieldName;
import com.appsmith.server.domains.Action;
import com.appsmith.server.domains.Application;
import com.appsmith.server.domains.ApplicationPage;
import com.appsmith.server.domains.Layout;
import com.appsmith.server.domains.Page;
import com.appsmith.server.domains.User;
import com.appsmith.server.exceptions.AppsmithError;
import com.appsmith.server.exceptions.AppsmithException;
@ -103,6 +100,11 @@ public class ApplicationServiceImpl extends BaseService<ApplicationRepository, A
return repository.save(application);
}
@Override
public Mono<Application> archive(Application application) {
return repository.archive(application);
}
/**
* This function walks through all the pages in the application. In each page, it walks through all the layouts.
* In a layout, dsl and publishedDsl JSONObjects exist. Publish function is responsible for copying the dsl into
@ -144,44 +146,4 @@ public class ApplicationServiceImpl extends BaseService<ApplicationRepository, A
.collectList()
.map(pages -> true);
}
/**
* This function performs a soft delete for the application along with it's associated pages and actions.
*
* @param id The application id to delete
* @return The modified application object with the deleted flag set
*/
@Override
public Mono<Application> delete(String id) {
log.debug("Archiving application with id: {}", id);
Mono<Application> applicationMono = repository.findById(id)
.switchIfEmpty(Mono.error(new AppsmithException(AppsmithError.NO_RESOURCE_FOUND, "application", id)))
.flatMap(application -> pageRepository.findByApplicationId(id)
.flatMap(page -> {
log.debug("Going to archive pageId: {} for applicationId: {}", page.getId(), id);
Mono<Page> archivedPageMono = pageRepository.archiveById(page);
Mono<List<Action>> archivedActionsMono = actionRepository.findByPageId(page.getId())
.flatMap(action -> {
log.debug("Going to archive actionId: {} for applicationId: {}", action.getId(), id);
return actionRepository.archiveById(action);
})
.collectList();
return Mono.zip(archivedPageMono, archivedActionsMono)
.map(tuple -> {
Page page1 = tuple.getT1();
List<Action> actions = tuple.getT2();
log.debug("Archived pageId: {} and {} actions for applicationId: {}", page1.getId(), actions.size(), id);
return page1;
});
})
.collectList()
.flatMap(pages -> repository.archiveById(application)));
return applicationMono
.map(deletedObj -> {
analyticsService.sendEvent(AnalyticsEvents.DELETE + "_" + deletedObj.getClass().getSimpleName().toUpperCase(), (Application) deletedObj);
return (Application) deletedObj;
});
}
}

View File

@ -10,6 +10,8 @@ public interface PageService extends CrudService<Page, String> {
Mono<Page> findById(String pageId);
Flux<Page> findByApplicationId(String applicationId);
Mono<Page> save(Page page);
Mono<Page> findByIdAndLayoutsId(String pageId, String layoutId);

View File

@ -1,6 +1,8 @@
package com.appsmith.server.services;
import com.appsmith.server.constants.AnalyticsEvents;
import com.appsmith.server.constants.FieldName;
import com.appsmith.server.domains.Action;
import com.appsmith.server.domains.Application;
import com.appsmith.server.domains.ApplicationPage;
import com.appsmith.server.domains.Layout;
@ -8,6 +10,7 @@ import com.appsmith.server.domains.Page;
import com.appsmith.server.dtos.PageNameIdDTO;
import com.appsmith.server.exceptions.AppsmithError;
import com.appsmith.server.exceptions.AppsmithException;
import com.appsmith.server.repositories.ActionRepository;
import com.appsmith.server.repositories.PageRepository;
import lombok.extern.slf4j.Slf4j;
import org.bson.types.ObjectId;
@ -27,6 +30,7 @@ import java.util.List;
public class PageServiceImpl extends BaseService<PageRepository, Page, String> implements PageService {
private final ApplicationService applicationService;
private final ActionRepository actionRepository;
@Autowired
public PageServiceImpl(Scheduler scheduler,
@ -35,9 +39,11 @@ public class PageServiceImpl extends BaseService<PageRepository, Page, String> i
ReactiveMongoTemplate reactiveMongoTemplate,
PageRepository repository,
ApplicationService applicationService,
AnalyticsService analyticsService) {
AnalyticsService analyticsService,
ActionRepository actionRepository) {
super(scheduler, validator, mongoConverter, reactiveMongoTemplate, repository, analyticsService);
this.applicationService = applicationService;
this.actionRepository = actionRepository;
}
@Override
@ -45,6 +51,11 @@ public class PageServiceImpl extends BaseService<PageRepository, Page, String> i
return repository.findById(pageId);
}
@Override
public Flux<Page> findByApplicationId(String applicationId) {
return repository.findByApplicationId(applicationId);
}
@Override
public Mono<Page> save(Page page) {
return repository.save(page);
@ -72,6 +83,39 @@ public class PageServiceImpl extends BaseService<PageRepository, Page, String> i
return repository.deleteAll();
}
/**
* This function archives the page and all the actions associated with that page.
*
* @param id The pageId which needs to be archived.
* @return
*/
@Override
public Mono<Page> delete(String id) {
Mono<Page> pageMono = repository.findById(id)
.switchIfEmpty(Mono.error(new AppsmithException(AppsmithError.NO_RESOURCE_FOUND, FieldName.PAGE_ID, id)))
.flatMap(page -> {
log.debug("Going to archive pageId: {} for applicationId: {}", page.getId(), page.getApplicationId());
Mono<Page> archivedPageMono = repository.archive(page);
Mono<List<Action>> archivedActionsMono = actionRepository.findByPageId(page.getId())
.flatMap(action -> {
log.debug("Going to archive actionId: {} for applicationId: {}", action.getId(), id);
return actionRepository.archive(action);
}).collectList();
return Mono.zip(archivedPageMono, archivedActionsMono)
.map(tuple -> {
Page page1 = tuple.getT1();
List<Action> actions = tuple.getT2();
log.debug("Archived pageId: {} and {} actions for applicationId: {}", page1.getId(), actions.size(), id);
return page1;
});
});
return pageMono.map(deletedObj -> {
analyticsService.sendEvent(AnalyticsEvents.DELETE + "_" + deletedObj.getClass().getSimpleName().toUpperCase(), (Page) deletedObj);
return (Page) deletedObj;
});
}
@Override
public Flux<PageNameIdDTO> findNamesByApplicationId(String applicationId) {
return applicationService