From 68e1bef0f6f2203537511c3e861b6ecdc36bc366 Mon Sep 17 00:00:00 2001 From: Trisha Anand Date: Thu, 25 Jul 2019 07:11:05 +0000 Subject: [PATCH] Introduced TenantSetting to store the real setting value. Setting would exist as set of settings that can be configured for a given tenant. The TenantSetting document stores the configured values for each setting. Also, introduced the util cascadeSave. This is done with the aim of storing the lower order documents first before storing the higher order composite documents (which contain DBRef). --- .../com/mobtools/server/constants/Url.java | 1 + .../server/controllers/LayoutController.java | 2 +- .../server/controllers/SettingController.java | 18 +++++++++ .../com/mobtools/server/domains/Setting.java | 24 ++++++++++++ .../com/mobtools/server/domains/Tenant.java | 4 ++ .../server/domains/TenantSetting.java | 25 ++++++++++++ .../plugins/PostgresDBPluginExecutor.java | 8 ++-- .../plugins/RestTemplatePluginExecutor.java | 10 ++--- .../server/repositories/LayoutRepository.java | 2 +- .../repositories/SettingRepository.java | 11 ++++++ .../mobtools/server/services/BaseService.java | 4 +- .../server/services/PluginExecutor.java | 6 +-- .../server/services/PluginService.java | 1 + .../server/services/SettingService.java | 9 +++++ .../server/services/SettingServiceImpl.java | 30 ++++++++++++++ .../server/services/TenantService.java | 2 + .../server/services/TenantServiceImpl.java | 39 ++++++++++++++++++- 17 files changed, 179 insertions(+), 17 deletions(-) create mode 100644 app/server/src/main/java/com/mobtools/server/controllers/SettingController.java create mode 100644 app/server/src/main/java/com/mobtools/server/domains/Setting.java create mode 100644 app/server/src/main/java/com/mobtools/server/domains/TenantSetting.java create mode 100644 app/server/src/main/java/com/mobtools/server/repositories/SettingRepository.java create mode 100644 app/server/src/main/java/com/mobtools/server/services/SettingService.java create mode 100644 app/server/src/main/java/com/mobtools/server/services/SettingServiceImpl.java diff --git a/app/server/src/main/java/com/mobtools/server/constants/Url.java b/app/server/src/main/java/com/mobtools/server/constants/Url.java index ca718f898c..88c6af6116 100644 --- a/app/server/src/main/java/com/mobtools/server/constants/Url.java +++ b/app/server/src/main/java/com/mobtools/server/constants/Url.java @@ -8,4 +8,5 @@ public interface Url { String LAYOUT_URL = BASE_URL + VERSION + "/layouts"; String PLUGIN_URL = BASE_URL + VERSION + "/plugins"; String QUERY_URL = BASE_URL + VERSION + "/queries"; + String SETTING_URL = BASE_URL + VERSION + "/settings"; } diff --git a/app/server/src/main/java/com/mobtools/server/controllers/LayoutController.java b/app/server/src/main/java/com/mobtools/server/controllers/LayoutController.java index 8c25ede547..3f76d6eb33 100644 --- a/app/server/src/main/java/com/mobtools/server/controllers/LayoutController.java +++ b/app/server/src/main/java/com/mobtools/server/controllers/LayoutController.java @@ -9,7 +9,7 @@ import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping(Url.LAYOUT_URL) -public class LayoutController extends BaseController { +public class LayoutController extends BaseController { @Autowired public LayoutController(LayoutService service) { diff --git a/app/server/src/main/java/com/mobtools/server/controllers/SettingController.java b/app/server/src/main/java/com/mobtools/server/controllers/SettingController.java new file mode 100644 index 0000000000..0a86e280d5 --- /dev/null +++ b/app/server/src/main/java/com/mobtools/server/controllers/SettingController.java @@ -0,0 +1,18 @@ +package com.mobtools.server.controllers; + +import com.mobtools.server.constants.Url; +import com.mobtools.server.domains.Setting; +import com.mobtools.server.services.SettingService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping(Url.SETTING_URL) +public class SettingController extends BaseController { + + @Autowired + public SettingController(SettingService settingService) { + super(settingService); + } +} diff --git a/app/server/src/main/java/com/mobtools/server/domains/Setting.java b/app/server/src/main/java/com/mobtools/server/domains/Setting.java new file mode 100644 index 0000000000..af3ff34d22 --- /dev/null +++ b/app/server/src/main/java/com/mobtools/server/domains/Setting.java @@ -0,0 +1,24 @@ +package com.mobtools.server.domains; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; +import org.springframework.data.mongodb.core.index.Indexed; +import org.springframework.data.mongodb.core.mapping.Document; + +@Getter +@Setter +@ToString +@NoArgsConstructor +@Document +public class Setting extends BaseDomain { + + @Indexed(unique = true) + private String key; + + private String defaultValue; + + private Boolean isTenantSetting; + +} diff --git a/app/server/src/main/java/com/mobtools/server/domains/Tenant.java b/app/server/src/main/java/com/mobtools/server/domains/Tenant.java index 180b568ab0..af9cf54c13 100644 --- a/app/server/src/main/java/com/mobtools/server/domains/Tenant.java +++ b/app/server/src/main/java/com/mobtools/server/domains/Tenant.java @@ -6,6 +6,8 @@ import lombok.Setter; import lombok.ToString; import org.springframework.data.mongodb.core.mapping.Document; +import java.util.List; + @Getter @Setter @@ -20,4 +22,6 @@ public class Tenant extends BaseDomain { private String website; + private List tenantSettings; + } diff --git a/app/server/src/main/java/com/mobtools/server/domains/TenantSetting.java b/app/server/src/main/java/com/mobtools/server/domains/TenantSetting.java new file mode 100644 index 0000000000..12c45dcc65 --- /dev/null +++ b/app/server/src/main/java/com/mobtools/server/domains/TenantSetting.java @@ -0,0 +1,25 @@ +package com.mobtools.server.domains; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; +import org.springframework.data.mongodb.core.mapping.DBRef; + + +/* + * Only used to store the settings that are different from the default values already set in setting collection + */ + +@Getter +@Setter +@ToString +@NoArgsConstructor +public class TenantSetting extends BaseDomain { + + @DBRef + private Setting setting; + + private String settingValue; + +} diff --git a/app/server/src/main/java/com/mobtools/server/plugins/PostgresDBPluginExecutor.java b/app/server/src/main/java/com/mobtools/server/plugins/PostgresDBPluginExecutor.java index c37eed775e..365b54f1c3 100644 --- a/app/server/src/main/java/com/mobtools/server/plugins/PostgresDBPluginExecutor.java +++ b/app/server/src/main/java/com/mobtools/server/plugins/PostgresDBPluginExecutor.java @@ -34,8 +34,8 @@ public class PostgresDBPluginExecutor extends PluginExecutor { @Override public Flux execute(Query queryObj, CommandQueryParams params) { - if(conn == null) { - init(); + if (conn == null) { + init(); } ArrayList list = new ArrayList(50); try { @@ -45,9 +45,9 @@ public class PostgresDBPluginExecutor extends PluginExecutor { ResultSet resultSet = statement.executeQuery(queryTemplate); ResultSetMetaData metaData = resultSet.getMetaData(); Integer colCount = metaData.getColumnCount(); - while(resultSet.next()) { + while (resultSet.next()) { HashMap row = new HashMap(colCount); - for(int i = 1; i<=colCount; i++) { + for (int i = 1; i <= colCount; i++) { row.put(metaData.getColumnName(i), resultSet.getObject(i)); } list.add(row); diff --git a/app/server/src/main/java/com/mobtools/server/plugins/RestTemplatePluginExecutor.java b/app/server/src/main/java/com/mobtools/server/plugins/RestTemplatePluginExecutor.java index e31d4b8198..fc3126c900 100644 --- a/app/server/src/main/java/com/mobtools/server/plugins/RestTemplatePluginExecutor.java +++ b/app/server/src/main/java/com/mobtools/server/plugins/RestTemplatePluginExecutor.java @@ -31,8 +31,8 @@ public class RestTemplatePluginExecutor extends PluginExecutor { protected Flux execute(Query query, CommandQueryParams params) { String requestBody = query.getCommandTemplate(); Map propertyMap = query.getProperties() - .stream() - .collect(Collectors.toMap(Property::getKey, prop -> prop)); + .stream() + .collect(Collectors.toMap(Property::getKey, prop -> prop)); String url = propertyMap.get(PROP_URL).getValue(); String httpMethod = propertyMap.get(PROP_HTTP_METHOD).getValue(); @@ -43,7 +43,7 @@ public class RestTemplatePluginExecutor extends PluginExecutor { .build(); WebClient.RequestHeadersSpec request = webClient.method(HttpMethod.resolve(httpMethod)) - .body(BodyInserters.fromObject(requestBody)); + .body(BodyInserters.fromObject(requestBody)); Mono responseMono = request.exchange(); ClientResponse clientResponse = responseMono.block(); @@ -51,14 +51,14 @@ public class RestTemplatePluginExecutor extends PluginExecutor { List contentTypes = clientResponse.headers().header(HttpHeaders.CONTENT_TYPE); Class clazz = String.class; - if(contentTypes != null && contentTypes.size() > 0) { + if (contentTypes != null && contentTypes.size() > 0) { String contentType = contentTypes.get(0); boolean isJson = MediaType.APPLICATION_JSON_UTF8_VALUE.toLowerCase() .equals(contentType.toLowerCase() .replaceAll("\\s", "")) || MediaType.APPLICATION_JSON_VALUE.equals(contentType.toLowerCase()); - if(isJson) { + if (isJson) { clazz = JSONObject.class; } } diff --git a/app/server/src/main/java/com/mobtools/server/repositories/LayoutRepository.java b/app/server/src/main/java/com/mobtools/server/repositories/LayoutRepository.java index 5aa415b3e4..a20e37ef3a 100644 --- a/app/server/src/main/java/com/mobtools/server/repositories/LayoutRepository.java +++ b/app/server/src/main/java/com/mobtools/server/repositories/LayoutRepository.java @@ -4,5 +4,5 @@ import com.mobtools.server.domains.Layout; import org.springframework.stereotype.Repository; @Repository -public interface LayoutRepository extends BaseRepository{ +public interface LayoutRepository extends BaseRepository { } diff --git a/app/server/src/main/java/com/mobtools/server/repositories/SettingRepository.java b/app/server/src/main/java/com/mobtools/server/repositories/SettingRepository.java new file mode 100644 index 0000000000..bedc261d57 --- /dev/null +++ b/app/server/src/main/java/com/mobtools/server/repositories/SettingRepository.java @@ -0,0 +1,11 @@ +package com.mobtools.server.repositories; + +import com.mobtools.server.domains.Setting; +import org.springframework.stereotype.Repository; +import reactor.core.publisher.Mono; + +@Repository +public interface SettingRepository extends BaseRepository { + + Mono findByKey(String key); +} diff --git a/app/server/src/main/java/com/mobtools/server/services/BaseService.java b/app/server/src/main/java/com/mobtools/server/services/BaseService.java index 0ccb36e621..0604c1ad0f 100644 --- a/app/server/src/main/java/com/mobtools/server/services/BaseService.java +++ b/app/server/src/main/java/com/mobtools/server/services/BaseService.java @@ -65,8 +65,8 @@ public abstract class BaseService create(T widget) { - return repository.save(widget); + public Mono create(T object) { + return repository.save(object); } private DBObject getDbObject(Object o) { diff --git a/app/server/src/main/java/com/mobtools/server/services/PluginExecutor.java b/app/server/src/main/java/com/mobtools/server/services/PluginExecutor.java index 45e09fd913..ef5efd0219 100644 --- a/app/server/src/main/java/com/mobtools/server/services/PluginExecutor.java +++ b/app/server/src/main/java/com/mobtools/server/services/PluginExecutor.java @@ -42,7 +42,7 @@ public abstract class PluginExecutor { * This function replaces the variables in the query commandTemplate with the actual params * Executors can override this function to provide their own implementation if they wish to do something custom * - * @param query Query + * @param query Query * @param params CommandQueryParams */ protected Query replaceTemplate(Query query, CommandQueryParams params) { @@ -52,7 +52,7 @@ public abstract class PluginExecutor { Map queryMap = new HashMap<>(); Map headerMap = new HashMap<>(); - if(params.getQueryParams() != null) { + if (params.getQueryParams() != null) { queryMap = params .getQueryParams() .stream() @@ -61,7 +61,7 @@ public abstract class PluginExecutor { // Incase there's a conflict, we pick the older value (oldValue, newValue) -> oldValue)); } - if(params.getHeaderParams() != null) { + if (params.getHeaderParams() != null) { headerMap = params .getHeaderParams() .stream() diff --git a/app/server/src/main/java/com/mobtools/server/services/PluginService.java b/app/server/src/main/java/com/mobtools/server/services/PluginService.java index 630322c88f..2f4b12ae55 100644 --- a/app/server/src/main/java/com/mobtools/server/services/PluginService.java +++ b/app/server/src/main/java/com/mobtools/server/services/PluginService.java @@ -8,6 +8,7 @@ public interface PluginService extends CrudService { /** * Return an instance of PluginExecutor based on the classname available. * If the classname is not available, null is returned. + * * @param pluginType * @param className * @return PluginExecutor diff --git a/app/server/src/main/java/com/mobtools/server/services/SettingService.java b/app/server/src/main/java/com/mobtools/server/services/SettingService.java new file mode 100644 index 0000000000..b7575e9b60 --- /dev/null +++ b/app/server/src/main/java/com/mobtools/server/services/SettingService.java @@ -0,0 +1,9 @@ +package com.mobtools.server.services; + +import com.mobtools.server.domains.Setting; +import reactor.core.publisher.Mono; + +public interface SettingService extends CrudService { + + Mono getByKey(String key); +} diff --git a/app/server/src/main/java/com/mobtools/server/services/SettingServiceImpl.java b/app/server/src/main/java/com/mobtools/server/services/SettingServiceImpl.java new file mode 100644 index 0000000000..a06e2f27e3 --- /dev/null +++ b/app/server/src/main/java/com/mobtools/server/services/SettingServiceImpl.java @@ -0,0 +1,30 @@ +package com.mobtools.server.services; + +import com.mobtools.server.domains.Setting; +import com.mobtools.server.repositories.SettingRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.mongodb.core.ReactiveMongoTemplate; +import org.springframework.data.mongodb.core.convert.MongoConverter; +import org.springframework.stereotype.Service; +import reactor.core.publisher.Mono; +import reactor.core.scheduler.Scheduler; + +@Service +public class SettingServiceImpl extends BaseService implements SettingService { + + private final SettingRepository repository; + + @Autowired + public SettingServiceImpl(Scheduler scheduler, + MongoConverter mongoConverter, + ReactiveMongoTemplate reactiveMongoTemplate, + SettingRepository repository) { + super(scheduler, mongoConverter, reactiveMongoTemplate, repository); + this.repository = repository; + } + + @Override + public Mono getByKey(String key) { + return repository.findByKey(key); + } +} diff --git a/app/server/src/main/java/com/mobtools/server/services/TenantService.java b/app/server/src/main/java/com/mobtools/server/services/TenantService.java index ebeeb80d04..e902941cc1 100644 --- a/app/server/src/main/java/com/mobtools/server/services/TenantService.java +++ b/app/server/src/main/java/com/mobtools/server/services/TenantService.java @@ -6,4 +6,6 @@ import reactor.core.publisher.Mono; public interface TenantService extends CrudService { Mono getByName(String name); + + Mono create(Tenant object); } diff --git a/app/server/src/main/java/com/mobtools/server/services/TenantServiceImpl.java b/app/server/src/main/java/com/mobtools/server/services/TenantServiceImpl.java index 5978e85eef..17589e91cd 100644 --- a/app/server/src/main/java/com/mobtools/server/services/TenantServiceImpl.java +++ b/app/server/src/main/java/com/mobtools/server/services/TenantServiceImpl.java @@ -1,30 +1,67 @@ package com.mobtools.server.services; +import com.mobtools.server.domains.Setting; import com.mobtools.server.domains.Tenant; +import com.mobtools.server.domains.TenantSetting; import com.mobtools.server.repositories.TenantRepository; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.mongodb.core.ReactiveMongoTemplate; import org.springframework.data.mongodb.core.convert.MongoConverter; import org.springframework.stereotype.Service; +import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.core.scheduler.Scheduler; +import javax.validation.constraints.NotNull; +import java.util.stream.Stream; + +@Slf4j @Service public class TenantServiceImpl extends BaseService implements TenantService { private final TenantRepository repository; + private final SettingService settingService; @Autowired public TenantServiceImpl(Scheduler scheduler, MongoConverter mongoConverter, ReactiveMongoTemplate reactiveMongoTemplate, - TenantRepository repository) { + TenantRepository repository, + SettingService settingService) { super(scheduler, mongoConverter, reactiveMongoTemplate, repository); this.repository = repository; + this.settingService = settingService; } @Override public Mono getByName(String name) { return repository.findByName(name); } + + @Override + public Mono create(@NotNull Tenant tenant) { + + //Embed the setting object into tenantSetting. This is done only for settings for which the values deviate from the default. + //It is assumed that the tenant create API body would only contain the settings for which the default value and + //true value are different. + if (tenant.getTenantSettings() != null) { + + try (Stream stream = tenant.getTenantSettings().stream()) { + Flux tenantSettingFlux = Flux.fromStream(stream); + tenantSettingFlux.map(this::getAndStoreSettingObjectInTenantSetting).subscribe(); + } + } + + return repository.save(tenant); + + } + + private Object getAndStoreSettingObjectInTenantSetting(TenantSetting tenantSetting) { + String key = tenantSetting.getSetting().getKey(); + Mono setting = settingService.getByKey(key); + return setting.doOnNext(set -> tenantSetting.setSetting(set)) + .thenReturn(tenantSetting) + .subscribe(); + } }