From cdf3f973b3de6c2eab0dab4bbfddf29f1a7d920b Mon Sep 17 00:00:00 2001 From: Andre Velkov Janusev Date: Mon, 25 Aug 2025 11:23:13 +0200 Subject: [PATCH 1/3] Core completed. --- .../java/com/booleanuk/api/CorsConfig.java | 23 +++++++ src/main/java/com/booleanuk/api/Main.java | 11 +++ .../com/booleanuk/api/products/Product.java | 49 +++++++++++++ .../api/products/ProductController.java | 68 +++++++++++++++++++ .../api/products/ProductRepository.java | 49 +++++++++++++ 5 files changed, 200 insertions(+) create mode 100644 src/main/java/com/booleanuk/api/CorsConfig.java create mode 100644 src/main/java/com/booleanuk/api/Main.java create mode 100644 src/main/java/com/booleanuk/api/products/Product.java create mode 100644 src/main/java/com/booleanuk/api/products/ProductController.java create mode 100644 src/main/java/com/booleanuk/api/products/ProductRepository.java diff --git a/src/main/java/com/booleanuk/api/CorsConfig.java b/src/main/java/com/booleanuk/api/CorsConfig.java new file mode 100644 index 0000000..b6dde7d --- /dev/null +++ b/src/main/java/com/booleanuk/api/CorsConfig.java @@ -0,0 +1,23 @@ +package com.booleanuk.api; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +public class CorsConfig { + + @Bean + public WebMvcConfigurer corsConfigurer() { + return new WebMvcConfigurer() { + @Override + public void addCorsMappings(CorsRegistry registry) { + registry.addMapping("/**") // allow all paths + .allowedOrigins("*") // http://localhost:3000 + .allowedMethods("GET", "POST", "PUT", "DELETE") + .allowedHeaders("*"); + } + }; + } +} diff --git a/src/main/java/com/booleanuk/api/Main.java b/src/main/java/com/booleanuk/api/Main.java new file mode 100644 index 0000000..8e749e0 --- /dev/null +++ b/src/main/java/com/booleanuk/api/Main.java @@ -0,0 +1,11 @@ +package com.booleanuk.api; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Main { + public static void main(String[] args) { + SpringApplication.run(Main.class, args); + } +} diff --git a/src/main/java/com/booleanuk/api/products/Product.java b/src/main/java/com/booleanuk/api/products/Product.java new file mode 100644 index 0000000..3c90bb8 --- /dev/null +++ b/src/main/java/com/booleanuk/api/products/Product.java @@ -0,0 +1,49 @@ +package com.booleanuk.api.products; + +public class Product { + private int id; + private String name; + private String category; + private int price; + + public Product() { + } + + public Product(String name, String category, int price) { + this.name = name; + this.category = category; + this.price = price; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getCategory() { + return category; + } + + public void setCategory(String category) { + this.category = category; + } + + public int getPrice() { + return price; + } + + public void setPrice(int price) { + this.price = price; + } +} diff --git a/src/main/java/com/booleanuk/api/products/ProductController.java b/src/main/java/com/booleanuk/api/products/ProductController.java new file mode 100644 index 0000000..079f161 --- /dev/null +++ b/src/main/java/com/booleanuk/api/products/ProductController.java @@ -0,0 +1,68 @@ +package com.booleanuk.api.products; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/products") +public class ProductController { + ProductRepository repository; + + public ProductController(ProductRepository repository) { + this.repository = repository; + } + + @PostMapping + public ResponseEntity createProduct(@RequestBody Product product) { + try { + Product p = this.repository.createProduct(product); + return ResponseEntity.status(HttpStatus.CREATED).body(p); + } catch (Exception e) { + return ResponseEntity.badRequest().body("Error creating product: " + e.getMessage()); + } + } + + @GetMapping + public ResponseEntity getAllProducts() { + try { + return ResponseEntity.ok(this.repository.getAllProducts()); + } catch (Exception e) { + return ResponseEntity.badRequest().body("Could not fetch all products.. " + e.getMessage()); + } + } + + @GetMapping("/{id}") + public ResponseEntity getSingleProduct(@PathVariable int id) { + try { + return ResponseEntity.ok(this.repository.getSingleProduct(id)); + } catch (Exception e) { + return ResponseEntity.status(HttpStatus.NOT_FOUND).body("Error.. " + e.getMessage()); + } + } + + @PutMapping("/{id}") + public ResponseEntity updateProduct(@PathVariable int id) { + try { + return ResponseEntity.status(HttpStatus.CREATED).body(this.repository.updateProduct(id)); + } catch (Exception e) { + return ResponseEntity.status(HttpStatus.NOT_FOUND).body("Could not find product to update " + e.getMessage()); + } + } + + + @DeleteMapping("/{id}") + public ResponseEntity deleteProduct(@PathVariable int id) { + try { + if (this.repository.deleteProduct(id)) { + return ResponseEntity.status(HttpStatus.OK).body("Product removed."); + } + } catch (Exception e) { + return ResponseEntity.status(HttpStatus.NOT_FOUND).body("Could not find product to delete, " + e.getMessage()); + } + return ResponseEntity.badRequest().body("Error"); + } + +} diff --git a/src/main/java/com/booleanuk/api/products/ProductRepository.java b/src/main/java/com/booleanuk/api/products/ProductRepository.java new file mode 100644 index 0000000..7c55346 --- /dev/null +++ b/src/main/java/com/booleanuk/api/products/ProductRepository.java @@ -0,0 +1,49 @@ +package com.booleanuk.api.products; + +import org.springframework.stereotype.Repository; + +import java.util.ArrayList; +import java.util.List; +import java.util.NoSuchElementException; + +@Repository +public class ProductRepository { + private int idCounter = 1; + private List productList = new ArrayList<>(); + + public ProductRepository() {} + + public Product createProduct(Product product) { + product.setId(idCounter++); + this.productList.add(product); + return product; + } + + public List getAllProducts() { + return this.productList; + } + + public Product getSingleProduct(int id) { + return productList.stream() + .filter(product -> product.getId() == id) + .findFirst().orElseThrow(() -> new NoSuchElementException("Product not found with id: " + id)); + } + + public Product updateProduct(int id) { + Product product = productList.stream() + .filter(p -> p.getId() == id) + .findFirst().orElseThrow(() -> new NoSuchElementException("Product not found with id: " + id)); + + // UPDATE PRODUCT info and then return product wowoww + // product.setName(); + return product; + } + + public boolean deleteProduct(int id) { + Product product = productList.stream() + .filter(p -> p.getId() == id) + .findFirst().orElseThrow(() -> new NoSuchElementException("Product not found with id: " + id)); + + return productList.remove(product); + } +} From d934b18560fb6d452f4d4f157efaa3ba129c9559 Mon Sep 17 00:00:00 2001 From: Andre Velkov Janusev Date: Mon, 25 Aug 2025 11:28:56 +0200 Subject: [PATCH 2/3] *Fix on PUT req, Core completed. --- .../java/com/booleanuk/api/products/ProductController.java | 4 ++-- .../java/com/booleanuk/api/products/ProductRepository.java | 7 +++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/booleanuk/api/products/ProductController.java b/src/main/java/com/booleanuk/api/products/ProductController.java index 079f161..d87b667 100644 --- a/src/main/java/com/booleanuk/api/products/ProductController.java +++ b/src/main/java/com/booleanuk/api/products/ProductController.java @@ -44,9 +44,9 @@ public ResponseEntity getSingleProduct(@PathVariable int id) { } @PutMapping("/{id}") - public ResponseEntity updateProduct(@PathVariable int id) { + public ResponseEntity updateProduct(@PathVariable int id, @RequestBody Product body) { try { - return ResponseEntity.status(HttpStatus.CREATED).body(this.repository.updateProduct(id)); + return ResponseEntity.status(HttpStatus.CREATED).body(this.repository.updateProduct(id, body)); } catch (Exception e) { return ResponseEntity.status(HttpStatus.NOT_FOUND).body("Could not find product to update " + e.getMessage()); } diff --git a/src/main/java/com/booleanuk/api/products/ProductRepository.java b/src/main/java/com/booleanuk/api/products/ProductRepository.java index 7c55346..9bb0334 100644 --- a/src/main/java/com/booleanuk/api/products/ProductRepository.java +++ b/src/main/java/com/booleanuk/api/products/ProductRepository.java @@ -29,13 +29,16 @@ public Product getSingleProduct(int id) { .findFirst().orElseThrow(() -> new NoSuchElementException("Product not found with id: " + id)); } - public Product updateProduct(int id) { + public Product updateProduct(int id, Product body) { Product product = productList.stream() .filter(p -> p.getId() == id) .findFirst().orElseThrow(() -> new NoSuchElementException("Product not found with id: " + id)); // UPDATE PRODUCT info and then return product wowoww - // product.setName(); + product.setName(body.getName()); + product.setCategory(body.getCategory()); + product.setPrice(body.getPrice()); + return product; } From c5ef5820fdd7fc46e56274fb37a484e63c029b1c Mon Sep 17 00:00:00 2001 From: Andre Velkov Janusev Date: Mon, 25 Aug 2025 12:04:08 +0200 Subject: [PATCH 3/3] Extensions completed. --- .../api/products/ProductController.java | 24 ++++++------- .../api/products/ProductRepository.java | 34 ++++++++++++++----- 2 files changed, 37 insertions(+), 21 deletions(-) diff --git a/src/main/java/com/booleanuk/api/products/ProductController.java b/src/main/java/com/booleanuk/api/products/ProductController.java index d87b667..b707589 100644 --- a/src/main/java/com/booleanuk/api/products/ProductController.java +++ b/src/main/java/com/booleanuk/api/products/ProductController.java @@ -5,6 +5,7 @@ import org.springframework.web.bind.annotation.*; import java.util.List; +import java.util.NoSuchElementException; @RestController @RequestMapping("/products") @@ -26,11 +27,11 @@ public ResponseEntity createProduct(@RequestBody Product product) { } @GetMapping - public ResponseEntity getAllProducts() { + public ResponseEntity getAllProducts(@RequestParam String category ) { try { - return ResponseEntity.ok(this.repository.getAllProducts()); + return ResponseEntity.ok(this.repository.getAllProducts(category)); } catch (Exception e) { - return ResponseEntity.badRequest().body("Could not fetch all products.. " + e.getMessage()); + return ResponseEntity.status(HttpStatus.NOT_FOUND).body("Error: " + e.getMessage()); } } @@ -47,22 +48,21 @@ public ResponseEntity getSingleProduct(@PathVariable int id) { public ResponseEntity updateProduct(@PathVariable int id, @RequestBody Product body) { try { return ResponseEntity.status(HttpStatus.CREATED).body(this.repository.updateProduct(id, body)); - } catch (Exception e) { - return ResponseEntity.status(HttpStatus.NOT_FOUND).body("Could not find product to update " + e.getMessage()); + } catch (IllegalArgumentException e) { + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("Error: " + e.getMessage()); + } catch (NoSuchElementException e) { + return ResponseEntity.status(HttpStatus.NOT_FOUND).body("Error: " + e.getMessage()); } } - @DeleteMapping("/{id}") public ResponseEntity deleteProduct(@PathVariable int id) { try { - if (this.repository.deleteProduct(id)) { - return ResponseEntity.status(HttpStatus.OK).body("Product removed."); - } - } catch (Exception e) { - return ResponseEntity.status(HttpStatus.NOT_FOUND).body("Could not find product to delete, " + e.getMessage()); + this.repository.deleteProduct(id); + return ResponseEntity.status(HttpStatus.OK).body("Product removed."); + } catch (NoSuchElementException e) { + return ResponseEntity.status(HttpStatus.NOT_FOUND).body("Error: " + e.getMessage()); } - return ResponseEntity.badRequest().body("Error"); } } diff --git a/src/main/java/com/booleanuk/api/products/ProductRepository.java b/src/main/java/com/booleanuk/api/products/ProductRepository.java index 9bb0334..bee6b77 100644 --- a/src/main/java/com/booleanuk/api/products/ProductRepository.java +++ b/src/main/java/com/booleanuk/api/products/ProductRepository.java @@ -13,14 +13,27 @@ public class ProductRepository { public ProductRepository() {} - public Product createProduct(Product product) { + public Product createProduct(Product product) throws Exception { + for (Product p : productList) { + if (p.getName().equalsIgnoreCase(product.getName())) { + throw new Exception("Product with provided name already exists."); + } + } + product.setId(idCounter++); this.productList.add(product); return product; } - public List getAllProducts() { - return this.productList; + public List getAllProducts(String category) throws Exception { + List list = productList.stream() + .filter(product -> product.getCategory().equalsIgnoreCase(category)) + .toList(); + if (!list.isEmpty()) { + return list; + } else { + throw new Exception("No products of the provided category were found."); + } } public Product getSingleProduct(int id) { @@ -34,19 +47,22 @@ public Product updateProduct(int id, Product body) { .filter(p -> p.getId() == id) .findFirst().orElseThrow(() -> new NoSuchElementException("Product not found with id: " + id)); - // UPDATE PRODUCT info and then return product wowoww - product.setName(body.getName()); - product.setCategory(body.getCategory()); - product.setPrice(body.getPrice()); + for (Product p : productList) { + if (p.getName().equalsIgnoreCase(body.getName())) + throw new IllegalArgumentException("Product with provided name already exists."); + } + product.setName(body.getName()); + product.setCategory(body.getCategory()); + product.setPrice(body.getPrice()); return product; } - public boolean deleteProduct(int id) { + public void deleteProduct(int id) { Product product = productList.stream() .filter(p -> p.getId() == id) .findFirst().orElseThrow(() -> new NoSuchElementException("Product not found with id: " + id)); - return productList.remove(product); + productList.remove(product); } }