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).
This commit is contained in:
Trisha Anand 2019-07-25 07:11:05 +00:00
parent 2a5656afbb
commit 68e1bef0f6
17 changed files with 179 additions and 17 deletions

View File

@ -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";
}

View File

@ -9,7 +9,7 @@ import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping(Url.LAYOUT_URL)
public class LayoutController extends BaseController<LayoutService, Layout, String> {
public class LayoutController extends BaseController<LayoutService, Layout, String> {
@Autowired
public LayoutController(LayoutService service) {

View File

@ -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<SettingService, Setting, String> {
@Autowired
public SettingController(SettingService settingService) {
super(settingService);
}
}

View File

@ -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;
}

View File

@ -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<TenantSetting> tenantSettings;
}

View File

@ -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;
}

View File

@ -34,8 +34,8 @@ public class PostgresDBPluginExecutor extends PluginExecutor {
@Override
public Flux<Object> 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);

View File

@ -31,8 +31,8 @@ public class RestTemplatePluginExecutor extends PluginExecutor {
protected Flux<Object> execute(Query query, CommandQueryParams params) {
String requestBody = query.getCommandTemplate();
Map<String, Property> 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<ClientResponse> responseMono = request.exchange();
ClientResponse clientResponse = responseMono.block();
@ -51,14 +51,14 @@ public class RestTemplatePluginExecutor extends PluginExecutor {
List<String> 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;
}
}

View File

@ -4,5 +4,5 @@ import com.mobtools.server.domains.Layout;
import org.springframework.stereotype.Repository;
@Repository
public interface LayoutRepository extends BaseRepository<Layout, String>{
public interface LayoutRepository extends BaseRepository<Layout, String> {
}

View File

@ -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<Setting, String> {
Mono<Setting> findByKey(String key);
}

View File

@ -65,8 +65,8 @@ public abstract class BaseService<R extends BaseRepository, T extends BaseDomain
}
@Override
public Mono<T> create(T widget) {
return repository.save(widget);
public Mono<T> create(T object) {
return repository.save(object);
}
private DBObject getDbObject(Object o) {

View File

@ -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<String, String> queryMap = new HashMap<>();
Map<String, String> 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()

View File

@ -8,6 +8,7 @@ public interface PluginService extends CrudService<Plugin, String> {
/**
* 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

View File

@ -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<Setting, String> {
Mono<Setting> getByKey(String key);
}

View File

@ -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<SettingRepository, Setting, String> 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<Setting> getByKey(String key) {
return repository.findByKey(key);
}
}

View File

@ -6,4 +6,6 @@ import reactor.core.publisher.Mono;
public interface TenantService extends CrudService<Tenant, String> {
Mono<Tenant> getByName(String name);
Mono<Tenant> create(Tenant object);
}

View File

@ -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<TenantRepository, Tenant, String> 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<Tenant> getByName(String name) {
return repository.findByName(name);
}
@Override
public Mono<Tenant> 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<TenantSetting> stream = tenant.getTenantSettings().stream()) {
Flux<TenantSetting> 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> setting = settingService.getByKey(key);
return setting.doOnNext(set -> tenantSetting.setSetting(set))
.thenReturn(tenantSetting)
.subscribe();
}
}