diff --git a/monolithic-architecture/README.md b/monolithic-architecture/README.md new file mode 100644 index 000000000000..2be0ad399dd2 --- /dev/null +++ b/monolithic-architecture/README.md @@ -0,0 +1,150 @@ +--- +title: "Monolithic Ecommerce App: A Cohesive Application Model" +shortTitle: Monolithic Ecommerce +description: "Explore the Monolithic Ecommerce application structure, its design intent, benefits, limitations, and real-world applications. Understand its simplicity and practical use cases." +category: Architectural +language: en +tag: + - Cohesion + - Simplicity + - Scalability + - Deployment + - Maintainability +--- + +## Monolithic-Ecommerce App +* A Monolithic Ecommerce example to showcase Monolithic Architecture + +## The Intent of Monolithic Design pattern +> the Monolithic Design Pattern structures an application as a single, cohesive unit where all components—such as business logic, user interface, and data access are tightly integrated and operate as part of a single executable. + +## Detailed Explanation of the Monolithic Architecture +Real-world Example +> A traditional E-commerce website is the most straightforward example for a monolithic application as it is comprised of a catalogue of products, orders to be made, shopping carts, and payment processes that are all inseperable of each other. + +In Plain words +>The monolithic design pattern structures an application as a single unified unit, where all components are tightly coupled and run within a single process. + +GeeksforGeeks states +> Monolithic architecture, a traditional approach in system design, which contains all application components into a single codebase. This unified structure simplifies development and deployment processes, offering ease of management and tight integration. However, because of its rigidity, it is difficult to scale and maintain, which makes it difficult to adjust to changing needs. + +Why use MVC for a Monolithic Application ? +>The Model-View-Controller (MVC) pattern is not inherently tied to microservices or distributed systems. It's a software design pattern that organizes the codebase by separating concerns into three distinct layers: +>* Model +>* View +>* Controller +> +> this also helps maintain the principles of a Monolithic Architecture which are: +> +> Simple to +>* Develop +>* Test +>* Deploy +>* Scale +> +## We can clearly see that this is a Monolithic application through the main class +This is a simplified version of the main application that shows the main interaction point with the CLI and how a user is registered +```java +@SpringBootApplication +public class EcommerceApp implements CommandLineRunner { + + private static final Logger log = LogManager.getLogger(EcommerceApp.class); + private final UserCon userService; + private final ProductCon productService; + private final OrderCon orderService; + public EcommerceApp(UserCon userService, ProductCon productService, OrderCon orderService) { + this.userService = userService; + this.productService = productService; + this.orderService = orderService; + } + public static void main(String... args) { + SpringApplication.run(EcommerceApp.class, args); + } + @Override + public void run(String... args) { + Scanner scanner = new Scanner(System.in, StandardCharsets.UTF_8); + + log.info("Welcome to the Monolithic E-commerce CLI!"); + while (true) { + log.info("\nChoose an option:"); + log.info("1. Register User"); + log.info("2. Add Product"); + log.info("3. Place Order"); + log.info("4. Exit"); + log.info("Enter your choice: "); + + int userInput = scanner.nextInt(); + scanner.nextLine(); + + switch (userInput) { + case 1 -> registerUser(scanner); + case 2 -> addProduct(scanner); + case 3 -> placeOrder(scanner); + case 4 -> { + log.info("Exiting the application. Goodbye!"); + return; + } + default -> log.info("Invalid choice! Please try again."); + } + } + } + protected void registerUser(Scanner scanner) { + log.info("Enter user details:"); + log.info("Name: "); + String name = scanner.nextLine(); + log.info("Email: "); + String email = scanner.nextLine(); + log.info("Password: "); + String password = scanner.nextLine(); + + User user = new User(null, name, email, password); + userService.registerUser(user); + log.info("User registered successfully!"); + } + +} +``` +### We can clearly reach the conclusion that all of these classes reside under the same module and are essential for each other's functionality, this is supported by the presence of all relevant classes as parts of the main application class. + +## When should you resort to a Monolithic Architecture ? +>* An enterprise Starting off with a relatively small team +>* Simplicity is the most important factor of the project +>* Maintaining less entry points to the system is cruical +>* Prototyping ideas +> +## Pros & Cons of using Monolithic Architecture +>### Pros: +>* Simple Development: Easy to develop and deploy. +>* Unified Codebase: All code in one place, simplifying debugging. +>* Better Performance: No inter-service communication overhead. +>* Lower Costs: Minimal infrastructure and tooling requirements. +>* Ease of Testing: Single application makes end-to-end testing straightforward. +> * This is also assisted by the MVC structure employed in this example. +>### Cons: +>* Scalability Issues: Cannot scale individual components. +>* Tight Coupling: Changes in one area may impact the whole system. +>* Deployment Risks: A single failure can crash the entire application. +>* Complex Maintenance: Harder to manage as the codebase grows. +>* Limited Flexibility: Difficult to adopt new technologies for specific parts. + +## Real-World Applications of Monolithic architecture Pattern in Java +>* E-Commerce Platforms +>* Content Management Systems (CMS) +>* Banking and Financial Systems +>* Enterprise Resource Planning (ERP) Systems +>* Retail Point of Sale (POS) Systems + +## References +>* [GeeksforGeeks](https://www.geeksforgeeks.org/monolithic-architecture-system-design/) +>* [Wikipedia](https://en.wikipedia.org/wiki/Monolithic_application) +>* [vFunction](https://vfunction.com/blog/what-is-monolithic-application/#:~:text=A%20traditional%20e%2Dcommerce%20platform,inseparable%20components%20of%20the%20system.) Blog post +>* [Microservices.io](https://microservices.io/patterns/monolithic.html) +>* [IBM](https://www.ibm.com/think/topics/monolithic-architecture) +>#### References used to create the code +>* [Mockito](https://site.mockito.org/) -Testing +>* [Junit](https://junit.org/junit5/docs/current/user-guide/) -Testing +>* [Springboot](https://docs.spring.io/spring-boot/index.html) -Web Application Initiation (implemented but not utilized in this example) +>* [Sprint Data Jpa](https://docs.spring.io/spring-data/jpa/reference/index.html) -Database connection +>* [Lombok](https://projectlombok.org/) -Simplifying Classes +>* [Log4j](https://logging.apache.org/log4j/2.x/index.html) -Capturing Logs +>* [H2 Databse](https://www.h2database.com/html/tutorial.html) -Efficient, Simple, Dynamic Databse \ No newline at end of file diff --git a/monolithic-architecture/etc/Monolithic-Ecommerce.urm.puml b/monolithic-architecture/etc/Monolithic-Ecommerce.urm.puml new file mode 100644 index 000000000000..0f1c6d96e735 --- /dev/null +++ b/monolithic-architecture/etc/Monolithic-Ecommerce.urm.puml @@ -0,0 +1,123 @@ +@startuml +package com.iluwatar.monolithic.model { + class Orders { + - id : Long + - product : Products + - quantity : Integer + - totalPrice : Double + - user : User + + Orders() + + Orders(id : Long, user : User, product : Products, quantity : Integer, totalPrice : Double) + # canEqual(other : Object) : boolean + + equals(o : Object) : boolean + + getId() : Long + + getProduct() : Products + + getQuantity() : Integer + + getTotalPrice() : Double + + getUser() : User + + hashCode() : int + + setId(id : Long) + + setProduct(product : Products) + + setQuantity(quantity : Integer) + + setTotalPrice(totalPrice : Double) + + setUser(user : User) + + toString() : String + } + class Products { + - description : String + - id : Long + - name : String + - price : Double + - stock : Integer + + Products() + + Products(id : Long, name : String, description : String, price : Double, stock : Integer) + # canEqual(other : Object) : boolean + + equals(o : Object) : boolean + + getDescription() : String + + getId() : Long + + getName() : String + + getPrice() : Double + + getStock() : Integer + + hashCode() : int + + setDescription(description : String) + + setId(id : Long) + + setName(name : String) + + setPrice(price : Double) + + setStock(stock : Integer) + + toString() : String + } + class User { + - email : String + - id : Long + - name : String + - password : String + + User() + + User(id : Long, name : String, email : String, password : String) + # canEqual(other : Object) : boolean + + equals(o : Object) : boolean + + getEmail() : String + + getId() : Long + + getName() : String + + getPassword() : String + + hashCode() : int + + setEmail(email : String) + + setId(id : Long) + + setName(name : String) + + setPassword(password : String) + + toString() : String + } +} +package com.iluwatar.monolithic.repository { + interface OrderRepo { + } + interface ProductRepo { + } + interface UserRepo { + + findByEmail(String) : User {abstract} + } +} +package com.iluwatar.monolithic.controller { + class OrderCon { + - orderRepository : OrderRepo + - productRepository : ProductRepo + - userRepository : UserRepo + + OrderCon(orderRepository : OrderRepo, userRepository : UserRepo, productRepository : ProductRepo) + + placeOrder(userId : Long, productId : Long, quantity : Integer) : Orders + } + class ProductCon { + - productRepository : ProductRepo + + ProductCon(productRepository : ProductRepo) + + addProduct(product : Products) : Products + + getAllProducts() : List + } + class UserCon { + - userRepository : UserRepo + + UserCon(userRepository : UserRepo) + + registerUser(user : User) : User + } +} +package com.iluwatar.monolithic { + class EcommerceApp { + - log : Logger {static} + - orderService : OrderCon + - productService : ProductCon + - userService : UserCon + + EcommerceApp(userService : UserCon, productService : ProductCon, orderService : OrderCon) + # addProduct(scanner : Scanner) + + main(args : String[]) {static} + # placeOrder(scanner : Scanner) + # registerUser(scanner : Scanner) + + run(args : String[]) + } +} +UserCon --> "-userRepository" UserRepo +Orders --> "-user" User +OrderCon --> "-productRepository" ProductRepo +OrderCon --> "-userRepository" UserRepo +OrderCon --> "-orderRepository" OrderRepo +EcommerceApp --> "-userService" UserCon +EcommerceApp --> "-productService" ProductCon +ProductCon --> "-productRepository" ProductRepo +Orders --> "-product" Products +EcommerceApp --> "-orderService" OrderCon +@enduml \ No newline at end of file diff --git a/monolithic-architecture/etc/monolithic-architecture.urm.puml b/monolithic-architecture/etc/monolithic-architecture.urm.puml new file mode 100644 index 000000000000..73e7506373b3 --- /dev/null +++ b/monolithic-architecture/etc/monolithic-architecture.urm.puml @@ -0,0 +1,123 @@ +@startuml +package com.iluwatar.monolithic.model { + class Orders { + - id : Long + - product : Products + - quantity : Integer + - totalPrice : Double + - user : User + + Orders() + + Orders(id : Long, user : User, product : Products, quantity : Integer, totalPrice : Double) + # canEqual(other : Object) : boolean + + equals(o : Object) : boolean + + getId() : Long + + getProduct() : Products + + getQuantity() : Integer + + getTotalPrice() : Double + + getUser() : User + + hashCode() : int + + setId(id : Long) + + setProduct(product : Products) + + setQuantity(quantity : Integer) + + setTotalPrice(totalPrice : Double) + + setUser(user : User) + + toString() : String + } + class Products { + - description : String + - id : Long + - name : String + - price : Double + - stock : Integer + + Products() + + Products(id : Long, name : String, description : String, price : Double, stock : Integer) + # canEqual(other : Object) : boolean + + equals(o : Object) : boolean + + getDescription() : String + + getId() : Long + + getName() : String + + getPrice() : Double + + getStock() : Integer + + hashCode() : int + + setDescription(description : String) + + setId(id : Long) + + setName(name : String) + + setPrice(price : Double) + + setStock(stock : Integer) + + toString() : String + } + class User { + - email : String + - id : Long + - name : String + - password : String + + User() + + User(id : Long, name : String, email : String, password : String) + # canEqual(other : Object) : boolean + + equals(o : Object) : boolean + + getEmail() : String + + getId() : Long + + getName() : String + + getPassword() : String + + hashCode() : int + + setEmail(email : String) + + setId(id : Long) + + setName(name : String) + + setPassword(password : String) + + toString() : String + } +} +package com.iluwatar.monolithic.repository { + interface OrderRepo { + } + interface ProductRepo { + } + interface UserRepo { + + findByEmail(String) : User {abstract} + } +} +package com.iluwatar.monolithic.controller { + class OrderCon { + - orderRepository : OrderRepo + - productRepository : ProductRepo + - userRepository : UserRepo + + OrderCon(orderRepository : OrderRepo, userRepository : UserRepo, productRepository : ProductRepo) + + placeOrder(userId : Long, productId : Long, quantity : Integer) : Orders + } + class ProductCon { + - productRepository : ProductRepo + + ProductCon(productRepository : ProductRepo) + + addProduct(product : Products) : Products + + getAllProducts() : List + } + class UserCon { + - userRepository : UserRepo + + UserCon(userRepository : UserRepo) + + registerUser(user : User) : User + } +} +package com.iluwatar.monolithic { + class EcommerceApp { + - log : Logger {static} + - orderService : OrderCon + - productService : ProductCon + - userService : UserCon + + EcommerceApp(userService : UserCon, productService : ProductCon, orderService : OrderCon) + # addProduct(scanner : Scanner) + + main(args : String[]) {static} + # placeOrder(scanner : Scanner) + # registerUser(scanner : Scanner) + + run(args : String[]) + } +} +UserCon --> "-userRepository" UserRepo +Orders --> "-user" User +OrderCon --> "-productRepository" ProductRepo +OrderCon --> "-userRepository" UserRepo +OrderCon --> "-orderRepository" OrderRepo +EcommerceApp --> "-userService" UserCon +Orders --> "-product" Products +ProductCon --> "-productRepository" ProductRepo +EcommerceApp --> "-productService" ProductCon +EcommerceApp --> "-orderService" OrderCon +@enduml \ No newline at end of file diff --git a/monolithic-architecture/pom.xml b/monolithic-architecture/pom.xml new file mode 100644 index 000000000000..3fa8c5f0a274 --- /dev/null +++ b/monolithic-architecture/pom.xml @@ -0,0 +1,107 @@ + + + + 4.0.0 + + + com.iluwatar + java-design-patterns + 1.26.0-SNAPSHOT + + + monolithic-architecture + + + + + org.springframework.boot + spring-boot-starter-web + + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + + + com.h2database + h2 + runtime + + + + + jakarta.persistence + jakarta.persistence-api + 3.1.0 + + + + + org.junit.jupiter + junit-jupiter-engine + test + + + + + org.mockito + mockito-core + test + + + + + + + org.apache.maven.plugins + maven-assembly-plugin + + + + + + com.iluwatar.monolithic.EcommerceApp + + + + jar-with-dependencies + + + + + + + + + + diff --git a/monolithic-architecture/src/main/java/com/iluwatar/monolithic/EcommerceApp.java b/monolithic-architecture/src/main/java/com/iluwatar/monolithic/EcommerceApp.java new file mode 100644 index 000000000000..9eed3705a4e7 --- /dev/null +++ b/monolithic-architecture/src/main/java/com/iluwatar/monolithic/EcommerceApp.java @@ -0,0 +1,157 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.monolithic; + +import com.iluwatar.monolithic.controller.OrderController; +import com.iluwatar.monolithic.controller.ProductController; +import com.iluwatar.monolithic.controller.UserController; +import com.iluwatar.monolithic.model.Product; +import com.iluwatar.monolithic.model.User; +import java.nio.charset.StandardCharsets; +import java.util.Scanner; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.springframework.boot.CommandLineRunner; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * Main entry point for the Monolithic E-commerce application. + * ------------------------------------------------------------------------ + * Monolithic architecture is a software design pattern where all components + * of the application (presentation, business logic, and data access layers) + * are part of a single unified codebase and deployable unit. + * ------------------------------------------------------------------------ + * This example implements a monolithic architecture by integrating + * user management, product management, and order placement within + * the same application, sharing common resources and a single database. + */ + +@SpringBootApplication +public class EcommerceApp implements CommandLineRunner { + + private static final Logger log = LogManager.getLogger(EcommerceApp.class); + private final UserController userService; + private final ProductController productService; + private final OrderController orderService; + /** + * Initilizing controllers as services. + * */ + public EcommerceApp(UserController userService, ProductController productService, OrderController orderService) { + this.userService = userService; + this.productService = productService; + this.orderService = orderService; + } + /** + * The main entry point for the Monolithic E-commerce application. + * Initializes the Spring Boot application and starts the embedded server. + */ + public static void main(String... args) { + SpringApplication.run(EcommerceApp.class, args); + } + + @Override + public void run(String... args) { + Scanner scanner = new Scanner(System.in, StandardCharsets.UTF_8); + + log.info("Welcome to the Monolithic E-commerce CLI!"); + while (true) { + log.info("\nChoose an option:"); + log.info("1. Register User"); + log.info("2. Add Product"); + log.info("3. Place Order"); + log.info("4. Exit"); + log.info("Enter your choice: "); + + int userInput = scanner.nextInt(); + scanner.nextLine(); + + switch (userInput) { + case 1 -> registerUser(scanner); + case 2 -> addProduct(scanner); + case 3 -> placeOrder(scanner); + case 4 -> { + log.info("Exiting the application. Goodbye!"); + return; + } + default -> log.info("Invalid choice! Please try again."); + } + } + } + /** + * Handles User Registration through user CLI inputs. + * */ + protected void registerUser(Scanner scanner) { + log.info("Enter user details:"); + log.info("Name: "); + String name = scanner.nextLine(); + log.info("Email: "); + String email = scanner.nextLine(); + log.info("Password: "); + String password = scanner.nextLine(); + + User user = new User(null, name, email, password); + userService.registerUser(user); + log.info("User registered successfully!"); + } + /** + * Handles the addition of products. + * */ + protected void addProduct(Scanner scanner) { + log.info("Enter product details:"); + log.info("Name: "); + String name = scanner.nextLine(); + log.info("Description: "); + String description = scanner.nextLine(); + log.info("Price: "); + double price = scanner.nextDouble(); + log.info("Stock: "); + int stock = scanner.nextInt(); + Product product = new Product(null, name, description, price, stock); + scanner.nextLine(); + productService.addProduct(product); + log.info("Product added successfully!"); + } + /** + * Handles Order Placement through user CLI inputs. + */ + protected void placeOrder(Scanner scanner) { + log.info("Enter order details:"); + log.info("User ID: "); + long userId = scanner.nextLong(); + log.info("Product ID: "); + long productId = scanner.nextLong(); + log.info("Quantity: "); + int quantity = scanner.nextInt(); + scanner.nextLine(); + + try { + orderService.placeOrder(userId, productId, quantity); + log.info("Order placed successfully!"); + } catch (Exception e) { + log.info("Error placing order: {}", e.getMessage()); + } + } +} diff --git a/monolithic-architecture/src/main/java/com/iluwatar/monolithic/controller/OrderController.java b/monolithic-architecture/src/main/java/com/iluwatar/monolithic/controller/OrderController.java new file mode 100644 index 000000000000..897c10b0ef2f --- /dev/null +++ b/monolithic-architecture/src/main/java/com/iluwatar/monolithic/controller/OrderController.java @@ -0,0 +1,70 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.monolithic.controller; +import com.iluwatar.monolithic.exceptions.InsufficientStockException; +import com.iluwatar.monolithic.exceptions.NonExistentProductException; +import com.iluwatar.monolithic.exceptions.NonExistentUserException; +import com.iluwatar.monolithic.model.Order; +import com.iluwatar.monolithic.model.Product; +import com.iluwatar.monolithic.model.User; +import com.iluwatar.monolithic.repository.OrderRepository; +import com.iluwatar.monolithic.repository.ProductRepository; +import com.iluwatar.monolithic.repository.UserRepository; +import org.springframework.stereotype.Service; +/** + * OrderController is a controller class for managing Order operations. + * */ +@Service +public class OrderController { + private final OrderRepository orderRepository; + private final UserRepository userRepository; + private final ProductRepository productRepository; + /** + * This function handles the initializing of the controller. + * */ + public OrderController(OrderRepository orderRepository, UserRepository userRepository, ProductRepository productRepository) { + this.orderRepository = orderRepository; + this.userRepository = userRepository; + this.productRepository = productRepository; + } + /** + * This function handles placing orders with all of its cases. + * */ + public Order placeOrder(Long userId, Long productId, Integer quantity) { + final User user = userRepository.findById(userId).orElseThrow(() -> new NonExistentUserException("User with ID " + userId + " not found")); + + final Product product = productRepository.findById(productId).orElseThrow(() -> new NonExistentProductException("Product with ID " + productId + " not found")); + + if (product.getStock() < quantity) { + throw new InsufficientStockException("Not enough stock for product " + productId); + } + + product.setStock(product.getStock() - quantity); + productRepository.save(product); + + final Order order = new Order(null, user, product, quantity, product.getPrice() * quantity); + return orderRepository.save(order); + } +} diff --git a/monolithic-architecture/src/main/java/com/iluwatar/monolithic/controller/ProductController.java b/monolithic-architecture/src/main/java/com/iluwatar/monolithic/controller/ProductController.java new file mode 100644 index 000000000000..c2f90276aeab --- /dev/null +++ b/monolithic-architecture/src/main/java/com/iluwatar/monolithic/controller/ProductController.java @@ -0,0 +1,58 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.monolithic.controller; + +import com.iluwatar.monolithic.model.Product; +import com.iluwatar.monolithic.repository.ProductRepository; +import java.util.List; +import org.springframework.stereotype.Service; + +/** + * ProductCon is a controller class for managing Product operations. + * */ + + +@Service +public class ProductController { + private final ProductRepository productRepository; + /** + * Linking Controller to DB. + * */ + public ProductController(ProductRepository productRepository) { + this.productRepository = productRepository; + } + /** + * Adds a product to the DB. + * */ + public Product addProduct(Product product) { + return productRepository.save(product); + } + /** + * Returns all relevant Product. + * */ + public List getAllProducts() { + return productRepository.findAll(); + } +} diff --git a/monolithic-architecture/src/main/java/com/iluwatar/monolithic/controller/UserController.java b/monolithic-architecture/src/main/java/com/iluwatar/monolithic/controller/UserController.java new file mode 100644 index 000000000000..cec2c6121c0b --- /dev/null +++ b/monolithic-architecture/src/main/java/com/iluwatar/monolithic/controller/UserController.java @@ -0,0 +1,48 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.monolithic.controller; + +import com.iluwatar.monolithic.model.User; +import com.iluwatar.monolithic.repository.UserRepository; +import org.springframework.stereotype.Service; +/** + * UserController is a controller class for managing user operations. + */ +@Service +public class UserController { + private final UserRepository userRepository; + /** + * Linking Controller to DB. + */ + public UserController(UserRepository userRepository) { + this.userRepository = userRepository; + } + /** + * Adds a user to the DB. + */ + public User registerUser(User user) { + return userRepository.save(user); + } +} diff --git a/monolithic-architecture/src/main/java/com/iluwatar/monolithic/exceptions/InsufficientStockException.java b/monolithic-architecture/src/main/java/com/iluwatar/monolithic/exceptions/InsufficientStockException.java new file mode 100644 index 000000000000..9e476c714d55 --- /dev/null +++ b/monolithic-architecture/src/main/java/com/iluwatar/monolithic/exceptions/InsufficientStockException.java @@ -0,0 +1,40 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.monolithic.exceptions; + +import java.io.Serial; +/** + * Custom Exception class for enhanced readability. + * */ +public class InsufficientStockException extends RuntimeException { + @Serial + private static final long serialVersionUID = 1005208208127745099L; + /** + * Exception Constructor that is readable through code and provides the message inputted into it. + * */ + public InsufficientStockException(String message) { + super(message); + } +} diff --git a/monolithic-architecture/src/main/java/com/iluwatar/monolithic/exceptions/NonExistentProductException.java b/monolithic-architecture/src/main/java/com/iluwatar/monolithic/exceptions/NonExistentProductException.java new file mode 100644 index 000000000000..2615f3a8e1af --- /dev/null +++ b/monolithic-architecture/src/main/java/com/iluwatar/monolithic/exceptions/NonExistentProductException.java @@ -0,0 +1,40 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.monolithic.exceptions; + +import java.io.Serial; +/** + * Custom Exception class for enhanced readability. + * */ +public class NonExistentProductException extends RuntimeException { + @Serial + private static final long serialVersionUID = -593425162052345565L; + /** + * Exception Constructor that is readable through code and provides the message inputted into it. + * */ + public NonExistentProductException(String msg) { + super(msg); + } +} diff --git a/monolithic-architecture/src/main/java/com/iluwatar/monolithic/exceptions/NonExistentUserException.java b/monolithic-architecture/src/main/java/com/iluwatar/monolithic/exceptions/NonExistentUserException.java new file mode 100644 index 000000000000..23df21092b81 --- /dev/null +++ b/monolithic-architecture/src/main/java/com/iluwatar/monolithic/exceptions/NonExistentUserException.java @@ -0,0 +1,40 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.monolithic.exceptions; + +import java.io.Serial; +/** + * Custom Exception class for enhanced readability. + * */ +public class NonExistentUserException extends RuntimeException { + @Serial + private static final long serialVersionUID = -7660909426227843633L; + /** + * Exception Constructor that is readable through code and provides the message inputted into it. + * */ + public NonExistentUserException(String msg) { + super(msg); + } +} diff --git a/monolithic-architecture/src/main/java/com/iluwatar/monolithic/model/Order.java b/monolithic-architecture/src/main/java/com/iluwatar/monolithic/model/Order.java new file mode 100644 index 000000000000..09a3c8de8dc3 --- /dev/null +++ b/monolithic-architecture/src/main/java/com/iluwatar/monolithic/model/Order.java @@ -0,0 +1,57 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.monolithic.model; + +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.ManyToOne; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * Represents a Database in which Order are stored. + */ +@Entity +@Data +@NoArgsConstructor +@AllArgsConstructor +public class Order { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne + private User user; + + @ManyToOne + private Product product; + + private Integer quantity; + + private Double totalPrice; +} diff --git a/monolithic-architecture/src/main/java/com/iluwatar/monolithic/model/Product.java b/monolithic-architecture/src/main/java/com/iluwatar/monolithic/model/Product.java new file mode 100644 index 000000000000..8c4e442b1238 --- /dev/null +++ b/monolithic-architecture/src/main/java/com/iluwatar/monolithic/model/Product.java @@ -0,0 +1,55 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.monolithic.model; + +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * Represents a database of products. + */ +@Entity +@Data +@NoArgsConstructor +@AllArgsConstructor +public class Product { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private String name; + + private String description; + + private Double price; + + private Integer stock; +} + diff --git a/monolithic-architecture/src/main/java/com/iluwatar/monolithic/model/User.java b/monolithic-architecture/src/main/java/com/iluwatar/monolithic/model/User.java new file mode 100644 index 000000000000..c3c278dbd519 --- /dev/null +++ b/monolithic-architecture/src/main/java/com/iluwatar/monolithic/model/User.java @@ -0,0 +1,54 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.monolithic.model; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * Represents a Product entity for the database. + */ +@Entity +@Data +@NoArgsConstructor +@AllArgsConstructor +public class User { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private String name; + + @Column(unique = true) + private String email; + + private String password; +} diff --git a/monolithic-architecture/src/main/java/com/iluwatar/monolithic/repository/OrderRepository.java b/monolithic-architecture/src/main/java/com/iluwatar/monolithic/repository/OrderRepository.java new file mode 100644 index 000000000000..366fa1c7b4d7 --- /dev/null +++ b/monolithic-architecture/src/main/java/com/iluwatar/monolithic/repository/OrderRepository.java @@ -0,0 +1,33 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.monolithic.repository; + +import com.iluwatar.monolithic.model.Order; +import org.springframework.data.jpa.repository.JpaRepository; +/** + * This interface allows JpaRepository to generate queries for the required tables. + */ +public interface OrderRepository extends JpaRepository { +} diff --git a/monolithic-architecture/src/main/java/com/iluwatar/monolithic/repository/ProductRepository.java b/monolithic-architecture/src/main/java/com/iluwatar/monolithic/repository/ProductRepository.java new file mode 100644 index 000000000000..4d4c17521fcd --- /dev/null +++ b/monolithic-architecture/src/main/java/com/iluwatar/monolithic/repository/ProductRepository.java @@ -0,0 +1,33 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.monolithic.repository; + +import com.iluwatar.monolithic.model.Product; +import org.springframework.data.jpa.repository.JpaRepository; +/** + * This interface allows JpaRepository to generate queries for the required tables. + */ +public interface ProductRepository extends JpaRepository { +} diff --git a/monolithic-architecture/src/main/java/com/iluwatar/monolithic/repository/UserRepository.java b/monolithic-architecture/src/main/java/com/iluwatar/monolithic/repository/UserRepository.java new file mode 100644 index 000000000000..2a96a1b51cb7 --- /dev/null +++ b/monolithic-architecture/src/main/java/com/iluwatar/monolithic/repository/UserRepository.java @@ -0,0 +1,37 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.monolithic.repository; + +import com.iluwatar.monolithic.model.User; +import org.springframework.data.jpa.repository.JpaRepository; +/** + * This interface allows JpaRepository to generate queries for the required tables. + */ +public interface UserRepository extends JpaRepository { + /** + * Utilizes JpaRepository functionalities to generate a function which looks up in the User table using emails. + * */ + User findByEmail(String email); +} \ No newline at end of file diff --git a/monolithic-architecture/src/main/resources/application.properties b/monolithic-architecture/src/main/resources/application.properties new file mode 100644 index 000000000000..166f3dafd7ac --- /dev/null +++ b/monolithic-architecture/src/main/resources/application.properties @@ -0,0 +1,7 @@ +spring.datasource.driver-class-name=org.h2.Driver +spring.datasource.password=password +spring.datasource.url=jdbc:h2:mem:testdb +spring.datasource.username=admin +spring.h2.console.enabled=true +spring.jpa.hibernate.ddl-auto=update +spring.jpa.show-sql=true diff --git a/monolithic-architecture/src/test/java/com/iluwatar/monolithic/MonolithicAppTest.java b/monolithic-architecture/src/test/java/com/iluwatar/monolithic/MonolithicAppTest.java new file mode 100644 index 000000000000..c9731692f7b4 --- /dev/null +++ b/monolithic-architecture/src/test/java/com/iluwatar/monolithic/MonolithicAppTest.java @@ -0,0 +1,261 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.monolithic; + +import com.iluwatar.monolithic.controller.OrderController; +import com.iluwatar.monolithic.controller.ProductController; +import com.iluwatar.monolithic.controller.UserController; +import com.iluwatar.monolithic.exceptions.InsufficientStockException; +import com.iluwatar.monolithic.exceptions.NonExistentProductException; +import com.iluwatar.monolithic.exceptions.NonExistentUserException; +import com.iluwatar.monolithic.model.Order; +import com.iluwatar.monolithic.model.Product; +import com.iluwatar.monolithic.model.User; +import com.iluwatar.monolithic.repository.OrderRepository; +import com.iluwatar.monolithic.repository.ProductRepository; +import com.iluwatar.monolithic.repository.UserRepository; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.nio.charset.StandardCharsets; +import java.util.Optional; +import java.util.Scanner; +import static org.junit.jupiter.api.Assertions.*; + + +import static org.mockito.Mockito.*; + +class MonolithicAppTest { + + @Mock + private UserController userService; + + @Mock + private ProductController productService; + + @Mock + private OrderController orderService; + + private EcommerceApp ecommerceApp; + + private ByteArrayOutputStream outputStream; + + @BeforeEach + void setUp() { + MockitoAnnotations.openMocks(this); + ecommerceApp = new EcommerceApp(userService, productService, orderService); + outputStream = new ByteArrayOutputStream(); + System.setOut(new PrintStream(outputStream, true, StandardCharsets.UTF_8)); + } + + @Test + void testRegisterUser() { + String simulatedInput = "John Doe\njohn@example.com\npassword123\n"; + System.setIn(new ByteArrayInputStream(simulatedInput.getBytes(StandardCharsets.UTF_8))); + + ecommerceApp.registerUser(new Scanner(System.in, StandardCharsets.UTF_8)); + + verify(userService, times(1)).registerUser(any(User.class)); + assertTrue(outputStream.toString().contains("User registered successfully!")); + } + + @Test + void testPlaceOrderUserNotFound() { + UserRepository mockUserRepository = mock(UserRepository.class); + ProductRepository mockProductRepository = mock(ProductRepository.class); + OrderRepository mockOrderRepo = mock(OrderRepository.class); + + when(mockUserRepository.findById(1L)).thenReturn(Optional.empty()); + + OrderController orderCon = new OrderController(mockOrderRepo, mockUserRepository, mockProductRepository); + + Exception exception = assertThrows(NonExistentUserException.class, () -> { + orderCon.placeOrder(1L, 1L, 5); + }); + + assertEquals("User with ID 1 not found", exception.getMessage()); + } + + @Test + void testPlaceOrderProductNotFound() { + UserRepository mockUserRepository = mock(UserRepository.class); + ProductRepository mockProductRepository = mock(ProductRepository.class); + OrderRepository mockOrderRepository = mock(OrderRepository.class); + + User mockUser = new User(1L, "John Doe", "john@example.com", "password123"); + when(mockUserRepository.findById(1L)).thenReturn(Optional.of(mockUser)); + + when(mockProductRepository.findById(1L)).thenReturn(Optional.empty()); + + OrderController orderCon = new OrderController(mockOrderRepository, mockUserRepository, mockProductRepository); + + Exception exception = assertThrows(NonExistentProductException.class, () -> { + orderCon.placeOrder(1L, 1L, 5); + }); + + assertEquals("Product with ID 1 not found", exception.getMessage()); + } + + + + @Test + void testOrderConstructor(){ + OrderRepository mockOrderRepository = mock(OrderRepository.class); + UserRepository mockUserRepository = mock(UserRepository.class); + ProductRepository mockProductRepository = mock(ProductRepository.class); + + OrderController orderCon = new OrderController(mockOrderRepository, mockUserRepository, mockProductRepository); + + assertNotNull(orderCon); + } + + @Test + void testAddProduct() { + String simulatedInput = "Laptop\nGaming Laptop\n1200.50\n10\n"; + System.setIn(new ByteArrayInputStream(simulatedInput.getBytes(StandardCharsets.UTF_8))); + + ecommerceApp.addProduct(new Scanner(System.in, StandardCharsets.UTF_8)); + + verify(productService, times(1)).addProduct(any(Product.class)); + assertTrue(outputStream.toString().contains("Product added successfully!")); + } + + @Test + void testPlaceOrderSuccess() { + String simulatedInput = "1\n2\n3\n"; + System.setIn(new ByteArrayInputStream(simulatedInput.getBytes(StandardCharsets.UTF_8))); + + Order mockOrder = new Order(); + doReturn(mockOrder).when(orderService).placeOrder(anyLong(), anyLong(), anyInt()); + + ecommerceApp.placeOrder(new Scanner(System.in, StandardCharsets.UTF_8)); + + verify(orderService, times(1)).placeOrder(anyLong(), anyLong(), anyInt()); + assertTrue(outputStream.toString().contains("Order placed successfully!")); + } + + @Test + void testPlaceOrderFailure() { + String simulatedInput = "1\n2\n3\n"; + System.setIn(new ByteArrayInputStream(simulatedInput.getBytes(StandardCharsets.UTF_8))); + + doThrow(new RuntimeException("Product out of stock")) + .when(orderService).placeOrder(anyLong(), anyLong(), anyInt()); + + ecommerceApp.placeOrder(new Scanner(System.in, StandardCharsets.UTF_8)); + + verify(orderService, times(1)).placeOrder(anyLong(), anyLong(), anyInt()); + assertTrue(outputStream.toString().contains("Error placing order: Product out of stock")); + } + @Test + void testPlaceOrderInsufficientStock() { + UserRepository mockUserRepository = mock(UserRepository.class); + ProductRepository mockProductRepository = mock(ProductRepository.class); + OrderRepository mockOrderRepository = mock(OrderRepository.class); + + User mockUser = new User(1L, "John Doe", "john@example.com", "password123"); + when(mockUserRepository.findById(1L)).thenReturn(Optional.of(mockUser)); + Product mockProduct = new Product(1L, "Laptop", "High-end gaming laptop", 1500.00, 2); // Only 2 in stock + when(mockProductRepository.findById(1L)).thenReturn(Optional.of(mockProduct)); + + OrderController orderCon = new OrderController(mockOrderRepository, mockUserRepository, mockProductRepository); + + Exception exception = assertThrows(InsufficientStockException.class, () -> { + orderCon.placeOrder(1L, 1L, 5); + }); + assertEquals("Not enough stock for product 1", exception.getMessage()); +} + @Test + void testProductConAddProduct() { + ProductRepository mockProductRepository = mock(ProductRepository.class); + + Product mockProduct = new Product(1L, "Smartphone", "High-end smartphone", 1000.00, 20); + + when(mockProductRepository.save(any(Product.class))).thenReturn(mockProduct); + + ProductController productController = new ProductController(mockProductRepository); + + Product savedProduct = productController.addProduct(mockProduct); + + verify(mockProductRepository, times(1)).save(any(Product.class)); + + assertNotNull(savedProduct); + assertEquals("Smartphone", savedProduct.getName()); + assertEquals("High-end smartphone", savedProduct.getDescription()); + assertEquals(1000.00, savedProduct.getPrice()); + assertEquals(20, savedProduct.getStock()); + } + + @Test + void testRun() { + String simulatedInput = """ + 1 + John Doe + john@example.com + password123 + 2 + Laptop + Gaming Laptop + 1200.50 + 10 + 3 + 1 + 1 + 2 + 4 + """; // Exit + System.setIn(new ByteArrayInputStream(simulatedInput.getBytes(StandardCharsets.UTF_8))); + + ByteArrayOutputStream outputTest = new ByteArrayOutputStream(); + System.setOut(new PrintStream(outputTest, true, StandardCharsets.UTF_8)); + + when(userService.registerUser(any(User.class))).thenReturn(new User(1L, "John Doe", "john@example.com", "password123")); + when(productService.addProduct(any(Product.class))).thenReturn(new Product(1L, "Laptop", "Gaming Laptop", 1200.50, 10)); + when(orderService.placeOrder(anyLong(), anyLong(), anyInt())).thenReturn(new Order(1L, new User(1L, "John Doe", "john@example.com","password123" ), new Product(1L, "Laptop", "Gaming Laptop", 1200.50, 10), 5, 6002.50)); + + ecommerceApp.run(); + + verify(userService, times(1)).registerUser(any(User.class)); + verify(productService, times(1)).addProduct(any(Product.class)); + verify(orderService, times(1)).placeOrder(anyLong(), anyLong(), anyInt()); + + String output = outputTest.toString(StandardCharsets.UTF_8); + assertTrue(output.contains("Welcome to the Monolithic E-commerce CLI!")); + assertTrue(output.contains("Choose an option:")); + assertTrue(output.contains("Register User")); + assertTrue(output.contains("Add Product")); + assertTrue(output.contains("Place Order")); + assertTrue(output.contains("Exiting the application. Goodbye!")); +} + + + + +} \ No newline at end of file diff --git a/pom.xml b/pom.xml index 5f0d579cf78f..dd46bdeb31c3 100644 --- a/pom.xml +++ b/pom.xml @@ -219,11 +219,12 @@ microservices-distributed-tracing microservices-client-side-ui-composition microservices-idempotent-consumer + monolithic-architecture session-facade templateview money table-inheritance - bloc + bloc