Skip to content

Commit

Permalink
Issue 62: Store LSSS requests in an internal queue
Browse files Browse the repository at this point in the history
Maintain existing end-point for submitting FeatureRequest, unchanged.
The FeatureRequest is then converted into an InternalRequest and stored in the database.
The product end-point no longer performs push and instead new end-points are created under `/internal/request/` to perform the push.
This new end-point `/internal/request/` includes CRUD operations.

The new push end-point `/internal/request/push` will convert the InternalRequest to a FeatureRequest before pushing.
This ensures that any service outside of Product Management System will only know about FeatureRequest and do not need to be aware of InternalRequest in any manner.
From the point of view of services outside of Product Management System, Product Management System receives a FeatureRequest and pushes a FeatureRequest.
  • Loading branch information
kaladay committed Apr 30, 2020
1 parent 50394bc commit 5e9ca16
Show file tree
Hide file tree
Showing 10 changed files with 496 additions and 67 deletions.
121 changes: 121 additions & 0 deletions src/main/java/edu/tamu/app/controller/InternalRequestController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package edu.tamu.app.controller;

import static edu.tamu.weaver.response.ApiStatus.SUCCESS;
import static edu.tamu.weaver.response.ApiStatus.ERROR;
import static edu.tamu.weaver.validation.model.BusinessValidationType.CREATE;
import static edu.tamu.weaver.validation.model.BusinessValidationType.DELETE;
import static edu.tamu.weaver.validation.model.BusinessValidationType.UPDATE;

import java.util.Optional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
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;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import edu.tamu.app.model.InternalRequest;
import edu.tamu.app.model.Product;
import edu.tamu.app.model.RemoteProductManager;
import edu.tamu.app.model.repo.InternalRequestRepo;
import edu.tamu.app.model.repo.ProductRepo;
import edu.tamu.app.model.request.FeatureRequest;
import edu.tamu.app.service.manager.RemoteProductManagerBean;
import edu.tamu.app.service.registry.ManagementBeanRegistry;
import edu.tamu.weaver.response.ApiResponse;
import edu.tamu.weaver.validation.aspect.annotation.WeaverValidatedModel;
import edu.tamu.weaver.validation.aspect.annotation.WeaverValidation;

@RestController
@RequestMapping("/internal/request")
public class InternalRequestController {

@Autowired
private InternalRequestRepo internalRequestRepo;

@Autowired
private ProductRepo productRepo;

@Autowired
private ManagementBeanRegistry managementBeanRegistry;

@GetMapping
@PreAuthorize("hasRole('MANAGER')")
public ApiResponse read() {
return new ApiResponse(SUCCESS, internalRequestRepo.findAll());
}

@GetMapping("/{id}")
@PreAuthorize("hasRole('MANAGER')")
public ApiResponse read(@PathVariable Long id) {
return new ApiResponse(SUCCESS, internalRequestRepo.findOne(id));
}

@PostMapping
@PreAuthorize("hasRole('MANAGER')")
@WeaverValidation(business = { @WeaverValidation.Business(value = CREATE) })
public ApiResponse create(@WeaverValidatedModel InternalRequest internalRequest) {
return new ApiResponse(SUCCESS, internalRequestRepo.create(internalRequest));
}

@PutMapping
@PreAuthorize("hasRole('MANAGER')")
@WeaverValidation(business = { @WeaverValidation.Business(value = UPDATE) })
public ApiResponse update(@WeaverValidatedModel InternalRequest internalRequest) {
return new ApiResponse(SUCCESS, internalRequestRepo.update(internalRequest));
}

@DeleteMapping
@PreAuthorize("hasRole('MANAGER')")
@WeaverValidation(business = { @WeaverValidation.Business(value = DELETE) })
public ApiResponse delete(@WeaverValidatedModel InternalRequest internalRequest) {
internalRequestRepo.delete(internalRequest);
return new ApiResponse(SUCCESS);
}

@PostMapping("/push")
@PreAuthorize("hasRole('MANAGER')")
public ApiResponse push(@RequestParam Long requestId, @RequestParam Long productId, @RequestParam String scopeId) {
Optional<InternalRequest> internalRequest = Optional.ofNullable(internalRequestRepo.findOne(requestId));
Optional<Product> product = Optional.ofNullable(productRepo.findOne(productId));
ApiResponse response;

if (internalRequest.isPresent() && product.isPresent()) {
Optional<RemoteProductManager> remoteProductManager = Optional
.ofNullable(product.get().getRemoteProductManager());

if (remoteProductManager.isPresent()) {
FeatureRequest featureRequest = new FeatureRequest(
internalRequest.get().getTitle(), internalRequest.get().getDescription(), productId, scopeId);

RemoteProductManagerBean remoteProductManagerBean =
(RemoteProductManagerBean) managementBeanRegistry.getService(remoteProductManager.get().getName());

featureRequest.setScopeId(product.get().getScopeId());
try {
response = new ApiResponse(SUCCESS, remoteProductManagerBean.push(featureRequest));
internalRequestRepo.delete(internalRequest.get());
} catch (Exception e) {
response = new ApiResponse(ERROR, "Error pushing request to " + remoteProductManager.get().getName()
+ " for product " + product.get().getName() + "!");
}
} else {
response = new ApiResponse(ERROR,
product.get().getName() + " product does not have a Remote Product Manager!");
}
} else if (internalRequest.isPresent()) {
response = new ApiResponse(ERROR, "Product with id " + productId + " not found!");

} else {
response = new ApiResponse(ERROR, "Internal Request with id " + requestId + " not found!");
}

return response;
}

}
29 changes: 7 additions & 22 deletions src/main/java/edu/tamu/app/controller/ProductController.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@
import com.fasterxml.jackson.annotation.JsonView;

import edu.tamu.app.cache.service.ProductScheduledCache;
import edu.tamu.app.model.InternalRequest;
import edu.tamu.app.model.Product;
import edu.tamu.app.model.RemoteProductManager;
import edu.tamu.app.model.repo.InternalRequestRepo;
import edu.tamu.app.model.repo.ProductRepo;
import edu.tamu.app.model.repo.RemoteProductManagerRepo;
import edu.tamu.app.model.request.FeatureRequest;
Expand Down Expand Up @@ -58,6 +60,9 @@ public class ProductController {
@Autowired
private List<ProductScheduledCache<?, ?>> productSceduledCaches;

@Autowired
private InternalRequestRepo internalRequestRepo;

private Logger logger = LoggerFactory.getLogger(this.getClass());

@GetMapping
Expand Down Expand Up @@ -122,28 +127,8 @@ public ApiResponse submitIssueRequest(@RequestBody TicketRequest request) {
@PostMapping("/feature")
@PreAuthorize("hasRole('MANAGER') or @whitelist.isAllowed()")
public ApiResponse pushRequest(@RequestBody FeatureRequest request) {
Optional<Product> product = Optional.ofNullable(productRepo.findOne(request.getProductId()));
ApiResponse response;
if (product.isPresent()) {
Optional<RemoteProductManager> remoteProductManager = Optional
.ofNullable(product.get().getRemoteProductManager());
if (remoteProductManager.isPresent()) {
RemoteProductManagerBean remoteProductManagerBean = (RemoteProductManagerBean) managementBeanRegistry.getService(remoteProductManager.get().getName());
request.setScopeId(product.get().getScopeId());
try {
response = new ApiResponse(SUCCESS, remoteProductManagerBean.push(request));
} catch (Exception e) {
response = new ApiResponse(ERROR, "Error pushing request to " + remoteProductManager.get().getName()
+ " for product " + product.get().getName() + "!");
}
} else {
response = new ApiResponse(ERROR,
product.get().getName() + " product does not have a Remote Product Manager!");
}
} else {
response = new ApiResponse(ERROR, "Product with id " + request.getProductId() + " not found!");
}
return response;
internalRequestRepo.create(new InternalRequest(request.getTitle(), request.getDescription()));
return new ApiResponse(SUCCESS, request);
}

@GetMapping("/{remoteProductManagerId}/remote-products")
Expand Down
76 changes: 76 additions & 0 deletions src/main/java/edu/tamu/app/model/InternalRequest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package edu.tamu.app.model;

import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.validation.constraints.NotNull;

import org.hibernate.annotations.CreationTimestamp;

import com.fasterxml.jackson.annotation.JsonView;

import edu.tamu.app.model.validation.InternalRequestValidator;
import edu.tamu.weaver.response.ApiView;
import edu.tamu.weaver.validation.model.ValidatingBaseEntity;

@Entity
public class InternalRequest extends ValidatingBaseEntity {

@NotNull
@Column(nullable = false)
@JsonView(ApiView.Partial.class)
private String title;

@NotNull
@Column(nullable = false)
@JsonView(ApiView.Partial.class)
private String description;

@NotNull
@Column(nullable = false, updatable = false)
@CreationTimestamp
private Date createdOn;

public InternalRequest() {
super();
this.modelValidator = new InternalRequestValidator();
}

public InternalRequest(String title, String description) {
this.title = title;
this.description = description;
this.createdOn = new Date();
}

public InternalRequest(String title, String description, Date createdOn) {
this.title = title;
this.description = description;
this.createdOn = createdOn;
}

public String getTitle() {
return title;
}

public void setTitle(String title) {
this.title = title;
}

public String getDescription() {
return description;
}

public void setDescription(String description) {
this.description = description;
}

public Date getCreatedOn() {
return createdOn;
}

public void setCreatedOn(Date created) {
this.createdOn = created;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package edu.tamu.app.model.repo;

import edu.tamu.app.model.InternalRequest;
import edu.tamu.app.model.repo.custom.InternalRequestRepoCustom;
import edu.tamu.weaver.data.model.repo.WeaverRepo;

public interface InternalRequestRepo extends WeaverRepo<InternalRequest>, InternalRequestRepoCustom {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package edu.tamu.app.model.repo.custom;

public interface InternalRequestRepoCustom {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package edu.tamu.app.model.repo.impl;

import edu.tamu.app.model.InternalRequest;
import edu.tamu.app.model.repo.InternalRequestRepo;
import edu.tamu.app.model.repo.custom.InternalRequestRepoCustom;
import edu.tamu.weaver.data.model.repo.impl.AbstractWeaverRepoImpl;

public class InternalRequestRepoImpl extends AbstractWeaverRepoImpl<InternalRequest, InternalRequestRepo> implements InternalRequestRepoCustom {

@Override
protected String getChannel() {
return "/channel/internal/request";
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package edu.tamu.app.model.validation;

import edu.tamu.weaver.validation.model.InputValidationType;
import edu.tamu.weaver.validation.validators.BaseModelValidator;
import edu.tamu.weaver.validation.validators.InputValidator;

public class InternalRequestValidator extends BaseModelValidator {

public InternalRequestValidator() {
String titleProperty = "title";
this.addInputValidator(new InputValidator(InputValidationType.required, "An Internal Request requires a title", titleProperty, true));

String descriptionProperty = "description";
this.addInputValidator(new InputValidator(InputValidationType.required, "An Internal Request requires a description", descriptionProperty, true));
}
}
Loading

0 comments on commit 5e9ca16

Please sign in to comment.