Δημιουργία controller,repository, service για την εισαγωγή προϊόντων

Θα δημιουργήσουμε τα 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

Θα δημιουργήσουμε έναν 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);
                        }