From 8ccd001652273e6c3900899ebe173eab08f7255a Mon Sep 17 00:00:00 2001 From: Arpit Mohan Date: Tue, 19 Mar 2019 19:39:05 +0530 Subject: [PATCH] Adding abstractions for CRUD APIs. Now we can easily add controllers for any resource quickly by simply adding a few files. --- .../server/configurations/SecurityConfig.java | 16 ++--- .../com/mobtools/server/constants/Url.java | 1 + .../server/controllers/BaseController.java | 36 +++++++++- .../server/controllers/TenantController.java | 31 +++++++++ .../server/controllers/WidgetController.java | 33 +++------ .../server/repositories/TenantRepository.java | 10 +++ .../server/repositories/UserRepository.java | 8 +++ .../server/repositories/WidgetRepository.java | 2 +- .../mobtools/server/services/BaseService.java | 68 ++++++++++++++++++- .../mobtools/server/services/CrudService.java | 14 ++++ .../server/services/TenantService.java | 9 +++ .../server/services/TenantServiceImpl.java | 30 ++++++++ .../mobtools/server/services/UserService.java | 6 ++ .../server/services/UserServiceImpl.java | 19 ++++++ .../server/services/WidgetService.java | 9 +-- .../server/services/WidgetServiceImpl.java | 61 ++--------------- 16 files changed, 252 insertions(+), 101 deletions(-) create mode 100644 app/server/server/src/main/java/com/mobtools/server/controllers/TenantController.java create mode 100644 app/server/server/src/main/java/com/mobtools/server/repositories/TenantRepository.java create mode 100644 app/server/server/src/main/java/com/mobtools/server/repositories/UserRepository.java create mode 100644 app/server/server/src/main/java/com/mobtools/server/services/CrudService.java create mode 100644 app/server/server/src/main/java/com/mobtools/server/services/TenantService.java create mode 100644 app/server/server/src/main/java/com/mobtools/server/services/TenantServiceImpl.java create mode 100644 app/server/server/src/main/java/com/mobtools/server/services/UserService.java create mode 100644 app/server/server/src/main/java/com/mobtools/server/services/UserServiceImpl.java diff --git a/app/server/server/src/main/java/com/mobtools/server/configurations/SecurityConfig.java b/app/server/server/src/main/java/com/mobtools/server/configurations/SecurityConfig.java index 3fe1409516..202553527a 100644 --- a/app/server/server/src/main/java/com/mobtools/server/configurations/SecurityConfig.java +++ b/app/server/server/src/main/java/com/mobtools/server/configurations/SecurityConfig.java @@ -27,15 +27,15 @@ public class SecurityConfig { @Bean public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) { return http - .csrf().disable() - .formLogin().disable() - .httpBasic().disable() + .csrf().disable() + .formLogin().disable() + .httpBasic().disable() // .authenticationManager(reactiveAuthenticationManager) // .securityContextRepository(securityContextRepository) - .authorizeExchange() - .anyExchange().permitAll() - .and() - .logout().disable() - .build(); + .authorizeExchange() + .anyExchange().permitAll() + .and() + .logout().disable() + .build(); } } diff --git a/app/server/server/src/main/java/com/mobtools/server/constants/Url.java b/app/server/server/src/main/java/com/mobtools/server/constants/Url.java index 3159a870b7..ba05d0f6af 100644 --- a/app/server/server/src/main/java/com/mobtools/server/constants/Url.java +++ b/app/server/server/src/main/java/com/mobtools/server/constants/Url.java @@ -4,4 +4,5 @@ public interface Url { String BASE_URL = "/api"; String VERSION = "/v1"; String WIDGET_URL = BASE_URL + VERSION + "/widgets"; + String TENANT_URL = BASE_URL + VERSION + "/tenants"; } diff --git a/app/server/server/src/main/java/com/mobtools/server/controllers/BaseController.java b/app/server/server/src/main/java/com/mobtools/server/controllers/BaseController.java index cbd5a8ff07..761c7a8c08 100644 --- a/app/server/server/src/main/java/com/mobtools/server/controllers/BaseController.java +++ b/app/server/server/src/main/java/com/mobtools/server/controllers/BaseController.java @@ -1,4 +1,38 @@ package com.mobtools.server.controllers; -public abstract class BaseController { +import com.mobtools.server.domains.BaseDomain; +import com.mobtools.server.dtos.ResponseDto; +import com.mobtools.server.services.CrudService; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.*; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import javax.validation.Valid; + +@RequiredArgsConstructor +public abstract class BaseController { + + private final S service; + + @PostMapping + @ResponseStatus(HttpStatus.CREATED) + public Mono> create(@Valid @RequestBody T resource) { + return service.create(resource) + .map(created -> new ResponseDto<>(HttpStatus.CREATED.value(), created, null)); + } + + @GetMapping("") + public Flux> getAll() { + return service.get() + .map(resources -> new ResponseDto<>(HttpStatus.OK.value(), resources, null)); + } + + @PutMapping("/{id}") + public Mono> update(@PathVariable ID id, @RequestBody T resource) throws Exception { + return service.update(id, resource) + .map(updatedResource -> new ResponseDto<>(HttpStatus.OK.value(), updatedResource, null)); + } + } diff --git a/app/server/server/src/main/java/com/mobtools/server/controllers/TenantController.java b/app/server/server/src/main/java/com/mobtools/server/controllers/TenantController.java new file mode 100644 index 0000000000..edbfb8c7c5 --- /dev/null +++ b/app/server/server/src/main/java/com/mobtools/server/controllers/TenantController.java @@ -0,0 +1,31 @@ +package com.mobtools.server.controllers; + +import com.mobtools.server.constants.Url; +import com.mobtools.server.domains.Tenant; +import com.mobtools.server.dtos.ResponseDto; +import com.mobtools.server.services.TenantService; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import reactor.core.publisher.Mono; + +@RestController +@RequestMapping(Url.TENANT_URL) +public class TenantController extends BaseController { + + private final TenantService tenantService; + + public TenantController(TenantService tenantService) { + super(tenantService); + this.tenantService = tenantService; + } + + @GetMapping("/{name}") + public Mono> getByName(@PathVariable String name) { + return tenantService.getByName(name) + .map(widget -> new ResponseDto<>(HttpStatus.OK.value(), widget, null)); + } + +} diff --git a/app/server/server/src/main/java/com/mobtools/server/controllers/WidgetController.java b/app/server/server/src/main/java/com/mobtools/server/controllers/WidgetController.java index 5ff12f2910..15d025fc37 100644 --- a/app/server/server/src/main/java/com/mobtools/server/controllers/WidgetController.java +++ b/app/server/server/src/main/java/com/mobtools/server/controllers/WidgetController.java @@ -4,32 +4,22 @@ import com.mobtools.server.constants.Url; import com.mobtools.server.domains.Widget; import com.mobtools.server.dtos.ResponseDto; import com.mobtools.server.services.WidgetService; -import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; -import org.springframework.web.bind.annotation.*; -import reactor.core.publisher.Flux; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; import reactor.core.publisher.Mono; -import javax.validation.Valid; - @RestController @RequestMapping(Url.WIDGET_URL) -@RequiredArgsConstructor -public class WidgetController extends BaseController { +public class WidgetController extends BaseController { private final WidgetService widgetService; - @PostMapping - @ResponseStatus(HttpStatus.CREATED) - public Mono> create(@Valid @RequestBody Widget widget) { - return widgetService.create(widget) - .map(createdWidget -> new ResponseDto<>(HttpStatus.CREATED.value(), createdWidget, null)); - } - - @GetMapping("") - public Flux> getAllWidgets() { - return widgetService.get() - .map(widgets -> new ResponseDto<>(HttpStatus.OK.value(), widgets, null)); + public WidgetController(WidgetService service) { + super(service); + this.widgetService = service; } @GetMapping("/{name}") @@ -37,11 +27,4 @@ public class WidgetController extends BaseController { return widgetService.getByName(name) .map(widget -> new ResponseDto<>(HttpStatus.OK.value(), widget, null)); } - - @PutMapping("/{id}") - public Mono> update(@PathVariable String id, @RequestBody Widget widget) throws Exception { - return widgetService.update(id, widget) - .map(updatedWidget -> new ResponseDto<>(HttpStatus.OK.value(), updatedWidget, null)); - } - } diff --git a/app/server/server/src/main/java/com/mobtools/server/repositories/TenantRepository.java b/app/server/server/src/main/java/com/mobtools/server/repositories/TenantRepository.java new file mode 100644 index 0000000000..f11113c0ea --- /dev/null +++ b/app/server/server/src/main/java/com/mobtools/server/repositories/TenantRepository.java @@ -0,0 +1,10 @@ +package com.mobtools.server.repositories; + +import com.mobtools.server.domains.Tenant; +import org.springframework.stereotype.Repository; +import reactor.core.publisher.Mono; + +@Repository +public interface TenantRepository extends BaseRepository { + Mono findByName(String name); +} diff --git a/app/server/server/src/main/java/com/mobtools/server/repositories/UserRepository.java b/app/server/server/src/main/java/com/mobtools/server/repositories/UserRepository.java new file mode 100644 index 0000000000..dd8524b074 --- /dev/null +++ b/app/server/server/src/main/java/com/mobtools/server/repositories/UserRepository.java @@ -0,0 +1,8 @@ +package com.mobtools.server.repositories; + +import com.mobtools.server.domains.User; +import org.springframework.stereotype.Repository; + +@Repository +public interface UserRepository extends BaseRepository { +} diff --git a/app/server/server/src/main/java/com/mobtools/server/repositories/WidgetRepository.java b/app/server/server/src/main/java/com/mobtools/server/repositories/WidgetRepository.java index 9a60d022aa..faa1f8c49d 100644 --- a/app/server/server/src/main/java/com/mobtools/server/repositories/WidgetRepository.java +++ b/app/server/server/src/main/java/com/mobtools/server/repositories/WidgetRepository.java @@ -5,7 +5,7 @@ import org.springframework.stereotype.Repository; import reactor.core.publisher.Mono; @Repository -public interface WidgetRepository extends BaseRepository { +public interface WidgetRepository extends BaseRepository { Mono findByName(String name); } diff --git a/app/server/server/src/main/java/com/mobtools/server/services/BaseService.java b/app/server/server/src/main/java/com/mobtools/server/services/BaseService.java index 044ee0ff98..e7b5df1bd9 100644 --- a/app/server/server/src/main/java/com/mobtools/server/services/BaseService.java +++ b/app/server/server/src/main/java/com/mobtools/server/services/BaseService.java @@ -1,10 +1,72 @@ package com.mobtools.server.services; -import lombok.RequiredArgsConstructor; +import com.mobtools.server.domains.BaseDomain; +import com.mobtools.server.repositories.BaseRepository; +import com.mongodb.BasicDBObject; +import com.mongodb.DBObject; +import org.springframework.data.mongodb.core.ReactiveMongoTemplate; +import org.springframework.data.mongodb.core.convert.MongoConverter; +import org.springframework.data.mongodb.core.query.Criteria; +import org.springframework.data.mongodb.core.query.Query; +import org.springframework.data.mongodb.core.query.Update; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; import reactor.core.scheduler.Scheduler; -@RequiredArgsConstructor -public abstract class BaseService { +import java.util.Map; + +public abstract class BaseService implements CrudService { final Scheduler scheduler; + + private final MongoConverter mongoConverter; + + private final ReactiveMongoTemplate mongoTemplate; + + private final R repository; + + public BaseService(Scheduler scheduler, + MongoConverter mongoConverter, + ReactiveMongoTemplate reactiveMongoTemplate, + R repository) { + this.scheduler = scheduler; + this.mongoConverter = mongoConverter; + this.mongoTemplate = reactiveMongoTemplate; + this.repository = repository; + } + + @Override + public Mono update(ID id, T resource) throws Exception { + if (id == null) { + throw new Exception("Invalid id provided"); + } + + Query query = new Query(Criteria.where("id").is(id)); + + DBObject update = getDbObject(resource); + + Update updateObj = new Update(); + Map updateMap = update.toMap(); + updateMap.entrySet().stream().forEach(entry -> updateObj.set(entry.getKey(), entry.getValue())); + + return mongoTemplate.updateFirst(query, updateObj, resource.getClass()) + .flatMap(obj -> repository.findById(id)) + .subscribeOn(scheduler); + } + + @Override + public Flux get() { + return repository.findAll(); + } + + @Override + public Mono create(T widget) { + return repository.save(widget); + } + + private DBObject getDbObject(Object o) { + BasicDBObject basicDBObject = new BasicDBObject(); + mongoConverter.write(o, basicDBObject); + return basicDBObject; + } } \ No newline at end of file diff --git a/app/server/server/src/main/java/com/mobtools/server/services/CrudService.java b/app/server/server/src/main/java/com/mobtools/server/services/CrudService.java new file mode 100644 index 0000000000..19302a89c2 --- /dev/null +++ b/app/server/server/src/main/java/com/mobtools/server/services/CrudService.java @@ -0,0 +1,14 @@ +package com.mobtools.server.services; + +import com.mobtools.server.domains.BaseDomain; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +public interface CrudService { + + Flux get(); + + Mono create(T resource); + + Mono update(ID id, T resource) throws Exception; +} diff --git a/app/server/server/src/main/java/com/mobtools/server/services/TenantService.java b/app/server/server/src/main/java/com/mobtools/server/services/TenantService.java new file mode 100644 index 0000000000..ebeeb80d04 --- /dev/null +++ b/app/server/server/src/main/java/com/mobtools/server/services/TenantService.java @@ -0,0 +1,9 @@ +package com.mobtools.server.services; + +import com.mobtools.server.domains.Tenant; +import reactor.core.publisher.Mono; + +public interface TenantService extends CrudService { + + Mono getByName(String name); +} diff --git a/app/server/server/src/main/java/com/mobtools/server/services/TenantServiceImpl.java b/app/server/server/src/main/java/com/mobtools/server/services/TenantServiceImpl.java new file mode 100644 index 0000000000..5978e85eef --- /dev/null +++ b/app/server/server/src/main/java/com/mobtools/server/services/TenantServiceImpl.java @@ -0,0 +1,30 @@ +package com.mobtools.server.services; + +import com.mobtools.server.domains.Tenant; +import com.mobtools.server.repositories.TenantRepository; +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 TenantServiceImpl extends BaseService implements TenantService { + + private final TenantRepository repository; + + @Autowired + public TenantServiceImpl(Scheduler scheduler, + MongoConverter mongoConverter, + ReactiveMongoTemplate reactiveMongoTemplate, + TenantRepository repository) { + super(scheduler, mongoConverter, reactiveMongoTemplate, repository); + this.repository = repository; + } + + @Override + public Mono getByName(String name) { + return repository.findByName(name); + } +} diff --git a/app/server/server/src/main/java/com/mobtools/server/services/UserService.java b/app/server/server/src/main/java/com/mobtools/server/services/UserService.java new file mode 100644 index 0000000000..2b28760661 --- /dev/null +++ b/app/server/server/src/main/java/com/mobtools/server/services/UserService.java @@ -0,0 +1,6 @@ +package com.mobtools.server.services; + +import com.mobtools.server.domains.User; + +public interface UserService extends CrudService { +} diff --git a/app/server/server/src/main/java/com/mobtools/server/services/UserServiceImpl.java b/app/server/server/src/main/java/com/mobtools/server/services/UserServiceImpl.java new file mode 100644 index 0000000000..d28cd3f51d --- /dev/null +++ b/app/server/server/src/main/java/com/mobtools/server/services/UserServiceImpl.java @@ -0,0 +1,19 @@ +package com.mobtools.server.services; + +import com.mobtools.server.domains.User; +import com.mobtools.server.repositories.UserRepository; +import org.springframework.data.mongodb.core.ReactiveMongoTemplate; +import org.springframework.data.mongodb.core.convert.MongoConverter; +import org.springframework.stereotype.Service; +import reactor.core.scheduler.Scheduler; + +@Service +public class UserServiceImpl extends BaseService implements UserService { + + public UserServiceImpl(Scheduler scheduler, + MongoConverter mongoConverter, + ReactiveMongoTemplate reactiveMongoTemplate, + UserRepository repository) { + super(scheduler, mongoConverter, reactiveMongoTemplate, repository); + } +} diff --git a/app/server/server/src/main/java/com/mobtools/server/services/WidgetService.java b/app/server/server/src/main/java/com/mobtools/server/services/WidgetService.java index 484c73dd61..ff8a0a28db 100644 --- a/app/server/server/src/main/java/com/mobtools/server/services/WidgetService.java +++ b/app/server/server/src/main/java/com/mobtools/server/services/WidgetService.java @@ -1,16 +1,9 @@ package com.mobtools.server.services; import com.mobtools.server.domains.Widget; -import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; -public interface WidgetService { +public interface WidgetService extends CrudService { Mono getByName(String name); - - Flux get(); - - Mono create(Widget widget); - - Mono update(String id, Widget widget) throws Exception; } diff --git a/app/server/server/src/main/java/com/mobtools/server/services/WidgetServiceImpl.java b/app/server/server/src/main/java/com/mobtools/server/services/WidgetServiceImpl.java index a9d1ecd40b..730c1406d1 100644 --- a/app/server/server/src/main/java/com/mobtools/server/services/WidgetServiceImpl.java +++ b/app/server/server/src/main/java/com/mobtools/server/services/WidgetServiceImpl.java @@ -2,81 +2,32 @@ package com.mobtools.server.services; import com.mobtools.server.domains.Widget; import com.mobtools.server.repositories.WidgetRepository; -import com.mongodb.BasicDBObject; -import com.mongodb.DBObject; 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.data.mongodb.core.query.Criteria; -import org.springframework.data.mongodb.core.query.Query; -import org.springframework.data.mongodb.core.query.Update; import org.springframework.stereotype.Service; -import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.core.scheduler.Scheduler; @Service @Slf4j -public class WidgetServiceImpl extends BaseService implements WidgetService { +public class WidgetServiceImpl extends BaseService implements WidgetService { private WidgetRepository widgetRepository; - private final MongoConverter mongoConverter; - - private final ReactiveMongoTemplate mongoTemplate; - @Autowired - public WidgetServiceImpl(Scheduler scheduler, WidgetRepository widgetRepository, MongoConverter mongoConverter, ReactiveMongoTemplate mongoTemplate) { - super(scheduler); + public WidgetServiceImpl(Scheduler scheduler, + MongoConverter mongoConverter, + ReactiveMongoTemplate mongoTemplate, + WidgetRepository widgetRepository) { + super(scheduler, mongoConverter, mongoTemplate, widgetRepository); this.widgetRepository = widgetRepository; - this.mongoConverter = mongoConverter; - this.mongoTemplate = mongoTemplate; } @Override public Mono getByName(String name) { return widgetRepository.findByName(name); - } - @Override - public Flux get() { - return widgetRepository.findAll(); - } - - @Override - public Mono create(Widget widget) { - - return widgetRepository.save(widget); - - } - - @Override - public Mono update(String id, Widget widget) throws Exception { - if (id == null) { - throw new Exception("Invalid id provided"); - } - - Query query = new Query(); - query.addCriteria(Criteria.where("id").is(id)); - - Update updateObj = new Update(); - -// DBObject update = getDbObject(widget); -// Map updateMap = update.toMap(); -// updateMap.entrySet().stream().forEach(entry -> { -// updateObj.set(entry.getKey(), entry.getValue()); -// }); - updateObj.set("name", "testName"); - mongoTemplate.updateFirst(query,updateObj, Widget.class); - return widgetRepository.save(widget); - - } - - private DBObject getDbObject(Object o) { - BasicDBObject basicDBObject = new BasicDBObject(); - mongoConverter.write(o, basicDBObject); - return basicDBObject; - } }