Θα δημιουργήσουμε τα components, που χρειάζονται, ώστε να προσθέτουμε προϊόντα στον πίνακα products.
Δημιουργούμε ένα repository ProductRepository.
package springeshop.repositories;
@Repository
public interface ProductRepository extends JpaRepository<Product, Integer> {
Product findByid(int id);
Product findByName(String name);
}
Δημιουργούμε το interface ProductService στο springeshop.service.
package springeshop.service;
public interface ProductService{
Product findById(int id);
Product findByName(String name);
void saveProduct(Product product);
void updateProduct(Product product);
void deleteProductById(int id);
boolean doesProductExist(Product product);
}
Δημιουργούμε την υλοποίηση του, ProductServiceImpl
package springeshop.service;
@Service("productService")
@Transactional
public class ProductServiceImpl implements ProductService{
@Autowired
private ProductRepository productRepository;
@Override
public Product findById(int id) {
return productRepository.findById(id);
}
@Override
public Product findByName(String name) {
return productRepository.findByName(name);
}
@Override
public void saveProduct(Product product) {
productRepository.save(product);
}
@Override
public void updateProduct(Product product) {
saveProduct(product);
}
@Override
public void deleteProductById(int id) {
productRepository.deleteById(id);
}
@Override
public boolean doesProductExist(Product product) {
return findByName(product.getName()) != null;
}
}
Θα δημιουργήσουμε έναν controller ProductApiController στο πακέτο springeshop.controller . Όταν ο client πραγματοποιεί ένα HTTP POST αίτημα στο localhost:8080/api/products, στέλνοντας το προιόν και τις 3 εικόνες (μια για κάθε μέγεθος), η μέθοδος createProduct θα δημιουργεί ένα προιόν στη βάση, αφού πρώτα ανεβάσει τις φωτογραφίες στο AmazonS3.
package springeshop.controller;
@RestController
@RequestMapping("/api")
public class ProductApiController{
public static final Logger logger = LoggerFactory.getLogger(ProductApiController.class);
@Autowired
private ProductService productService;
@Autowired
private CategoryService categoryService;
@Autowired
private InventoryService inventoryService;
@Autowired
private ProductImageService productImageService;
@Autowired
private AmazonS3ClientService amazonS3ClientService;
@RequestMapping(value = "/products", method = RequestMethod.POST, consumes = {"multipart/form-data"})
public ResponseEntity<?> createProduct(@Valid @RequestPart((@value( = "product") Product product,
@RequestPart( (@value( = "smallImage") MultipartFile smallImage,
@RequestPart((@value( = "largeImage") MultipartFile largeImage,
@RequestPart( (@value( = "verySmallImage") MultipartFile verySmallImage) throws InterruptedException, ExecutionException){
...
Εάν υπάρχει το προϊόν ήδη, επιστρέφουμε status 409 Conflict. Επίσης, εάν δεν υπάρχει η κατηγορία ή η μάρκα του προϊόντος επιστρέφουμε 404 Bad Request.
if(productService.doesProductExist(product)){
return new ResponseEntity<>(new ErrorMessage("Unable to create. A Product with name " + product.getName() + " already exist."), HttpStatus.CONFLICT);
}
if(!categoryService.doesCategoryExist(product.getCategory()))){
return new ResponseEntity<>(new ErrorMessage("Unable to create. Category with name {} does not exist"), HttpStatus.BAD_REQUEST);
}
if(!brandService.doesBrandExist(product.getBrand())){
return new ResponseEntity<>(new ErrorMessage("Unable to create. Brand with name {} does not exist"), HttpStatus.BAD_REQUEST);
}
Αποθηκεύουμε το προϊόν στη βάση. Εάν δεν αποθηκευτεί, επιστρέφουμε status 500 Internal Server Error
product.getBrand().setId(brandService.findByName(product.getBrand().getName()).getId());
product.getCategory().setId(categoryService.findByName(product.getCategory().getName()).getId());
productService.saveProduct(product);
if(product.getId() == 0) return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
Ανεβάζουμε τις τρεις εικόνες στο AmazonS3 σε διαφορετικά threads. Αν κάποια δεν ανεβεί σωστά, επιστρέφουμ status 500 Internal Server Error.
CompletableFuture<Boolean> smallImageUploadFuture = this.amazonS3ClientService
.uploadImage(smallImage, getCorrectCategoryName(product.getCategory().getName()), ImageType.SMALL);
CompletableFuture<Boolean> largeImageUploadFuture = this.amazonS3ClientService
.uploadImage(largeImage, getCorrectCategoryName(product.getCategory().getName()), ImageType.LARGE);
CompletableFuture<Boolean> verySmallImageUploadFuture = this.amazonS3ClientService
.uploadImage(verySmallImage, getCorrectCategoryName(product.getCategory().getName()), ImageType.VERY_SMALL);
boolean isSmallImageUploadSuccess = smallImageUploadFuture.get().booleanValue();
boolean isLargeImageUploadSuccess = largeImageUploadFuture.get().booleanValue();
boolean isVerySmallImageUploadSuccess = verySmallImageUploadFuture.get().booleanValue();
if(!(isSmallImageUploadSuccess && isLargeImageUploadSuccess && isVerySmallImageUploadSuccess)){
productService.deleteProductById(product.getId())
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
Αποθηκεύουμε την ποσότητα του προϊόντος στον πίνακα inventory
Inventory productInventory = new Inventory();
productInventory.setProduct(product);
productInventory.setQuantity(product.getQuantity());
inventoryService.saveProductQuantity(productInventory);
Αποθηκεύουμε στον πίνακα product_images, τα URLS των εικόνων στο AmazonS3 και επιστρέφουμε status 201 Created.
ProductImage productImage = new ProductImage();
productImage.setProduct(product);
productInventory.setQuantity(product.getQuantity());
productImage.setSmallImageurl(Constants.AMAZON_S3_URL + Constants.SMALL_PRODUCTS_PATH
+ getCorrectCategoryName(product.getCategory().getName()) + "/"
+ smallImage.getOriginalFilename());
productImage.setLargeImageurl(Constants.AMAZON_S3_URL + Constants.LARGE_PRODUCTS_PATH
+ getCorrectCategoryName(product.getCategory().getName()) + "/"
+ largeImage.getOriginalFilename());
productImage.setVerySmallImageurl(Constants.AMAZON_S3_URL + Constants.VERY_SMALL_PRODUCTS_PATH
+ getCorrectCategoryName(product.getCategory().getName()) + "/"
+ verySmallImage.getOriginalFilename());
productImageService.saveImage(productImage);
return new ResponseEntity<>(HttpStatus.CREATED);
}