From 3ba2560e094164bb162168192d49805e29cfb7ed Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 8 Feb 2026 20:37:15 +0200 Subject: [PATCH 1/8] build(deps-dev): bump org.htmlunit:htmlunit from 4.7.0 to 4.17.0 (#3334) Bumps [org.htmlunit:htmlunit](https://github.com/HtmlUnit/htmlunit) from 4.7.0 to 4.17.0. - [Release notes](https://github.com/HtmlUnit/htmlunit/releases) - [Commits](https://github.com/HtmlUnit/htmlunit/compare/4.7.0...4.17.0) --- updated-dependencies: - dependency-name: org.htmlunit:htmlunit dependency-version: 4.17.0 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index e91832d03358..661abe365a18 100644 --- a/pom.xml +++ b/pom.xml @@ -48,7 +48,7 @@ 0.8.13 1.4 - 4.7.0 + 4.17.0 2.11.0 6.0.0 1.1.0 From 812e4cd6a246b69941a6a763d89e1e1b4aa8d2b8 Mon Sep 17 00:00:00 2001 From: Naman Srivastava <82610773+naman-sriv@users.noreply.github.com> Date: Mon, 9 Feb 2026 00:10:07 +0530 Subject: [PATCH 2/8] feat: Microservices pattern : Self-Registration (#3245) * Services and information * README.md updated * unit tests added for controllers * pom.xml, clean up, java version update and slf4j logging added * pom files updated * Removed children maven wrappers * Microservice-self-registration added to pom file * POM file updated for self-registration * pom file updated * Update pom.xml correction to mudule name * SonarQube comments addressed * sonarqube comments on coverage addressed * Code coverage for custom health checks * changes for unit tests * changes for unit tests * changes to for code coverage improvement --- microservices-self-registration/README.md | 236 ++++++++++++++++++ .../application.log.2025-04-09.0.gz | Bin 0 -> 5525 bytes .../contextservice/.gitattributes | 2 + .../contextservice/.gitignore | 33 +++ .../application.log.2025-04-05.0.gz | Bin 0 -> 1977 bytes .../application.log.2025-04-07.0.gz | Bin 0 -> 27133 bytes .../application.log.2025-04-09.0.gz | Bin 0 -> 37553 bytes .../contextservice/pom.xml | 73 ++++++ .../ContextserviceApplication.java | 17 ++ .../contextservice/MyCustomHealthCheck.java | 42 ++++ .../client/GreetingServiceClient.java | 11 + .../controller/ContextController.java | 26 ++ .../src/main/resources/application.yml | 25 ++ .../contextservice/ContextControllerTest.java | 49 ++++ .../ContextserviceApplicationTests.java | 17 ++ .../learning/contextservice/TestConfig.java | 17 ++ .../myCustomHealthCheckTest.java | 33 +++ .../eurekaserver/.gitattributes | 2 + .../eurekaserver/.gitignore | 33 +++ .../eurekaserver/pom.xml | 55 ++++ .../eurekaserver/EurekaserverApplication.java | 15 ++ .../src/main/resources/application.yml | 10 + .../EurekaserverApplicationTests.java | 17 ++ .../greetingservice/.gitattributes | 2 + .../greetingservice/.gitignore | 33 +++ .../application.log.2025-04-05.0.gz | Bin 0 -> 1893 bytes .../application.log.2025-04-07.0.gz | Bin 0 -> 6769 bytes .../application.log.2025-04-09.0.gz | Bin 0 -> 18884 bytes .../application.log.2025-04-11.0.gz | Bin 0 -> 121657 bytes .../greetingservice/pom.xml | 69 +++++ .../GreetingserviceApplication.java | 17 ++ .../greetingservice/MyCustomHealthCheck.java | 41 +++ .../controller/GreetingsController.java | 13 + .../src/main/resources/application.yml | 22 ++ .../GreetingserviceApplicationTests.java | 17 ++ .../MyCustomHealthCheckTest.java | 22 ++ .../controller/GreetingControllerTest.java | 36 +++ microservices-self-registration/pom.xml | 63 +++++ pom.xml | 1 + 39 files changed, 1049 insertions(+) create mode 100644 microservices-self-registration/README.md create mode 100644 microservices-self-registration/application.log.2025-04-09.0.gz create mode 100644 microservices-self-registration/contextservice/.gitattributes create mode 100644 microservices-self-registration/contextservice/.gitignore create mode 100644 microservices-self-registration/contextservice/application.log.2025-04-05.0.gz create mode 100644 microservices-self-registration/contextservice/application.log.2025-04-07.0.gz create mode 100644 microservices-self-registration/contextservice/application.log.2025-04-09.0.gz create mode 100644 microservices-self-registration/contextservice/pom.xml create mode 100644 microservices-self-registration/contextservice/src/main/java/com/learning/contextservice/ContextserviceApplication.java create mode 100644 microservices-self-registration/contextservice/src/main/java/com/learning/contextservice/MyCustomHealthCheck.java create mode 100644 microservices-self-registration/contextservice/src/main/java/com/learning/contextservice/client/GreetingServiceClient.java create mode 100644 microservices-self-registration/contextservice/src/main/java/com/learning/contextservice/controller/ContextController.java create mode 100644 microservices-self-registration/contextservice/src/main/resources/application.yml create mode 100644 microservices-self-registration/contextservice/src/test/java/com/learning/contextservice/ContextControllerTest.java create mode 100644 microservices-self-registration/contextservice/src/test/java/com/learning/contextservice/ContextserviceApplicationTests.java create mode 100644 microservices-self-registration/contextservice/src/test/java/com/learning/contextservice/TestConfig.java create mode 100644 microservices-self-registration/contextservice/src/test/java/com/learning/contextservice/myCustomHealthCheckTest.java create mode 100644 microservices-self-registration/eurekaserver/.gitattributes create mode 100644 microservices-self-registration/eurekaserver/.gitignore create mode 100644 microservices-self-registration/eurekaserver/pom.xml create mode 100644 microservices-self-registration/eurekaserver/src/main/java/com/learning/eurekaserver/EurekaserverApplication.java create mode 100644 microservices-self-registration/eurekaserver/src/main/resources/application.yml create mode 100644 microservices-self-registration/eurekaserver/src/test/java/com/learning/eurekaserver/EurekaserverApplicationTests.java create mode 100644 microservices-self-registration/greetingservice/.gitattributes create mode 100644 microservices-self-registration/greetingservice/.gitignore create mode 100644 microservices-self-registration/greetingservice/application.log.2025-04-05.0.gz create mode 100644 microservices-self-registration/greetingservice/application.log.2025-04-07.0.gz create mode 100644 microservices-self-registration/greetingservice/application.log.2025-04-09.0.gz create mode 100644 microservices-self-registration/greetingservice/application.log.2025-04-11.0.gz create mode 100644 microservices-self-registration/greetingservice/pom.xml create mode 100644 microservices-self-registration/greetingservice/src/main/java/com/learning/greetingservice/GreetingserviceApplication.java create mode 100644 microservices-self-registration/greetingservice/src/main/java/com/learning/greetingservice/MyCustomHealthCheck.java create mode 100644 microservices-self-registration/greetingservice/src/main/java/com/learning/greetingservice/controller/GreetingsController.java create mode 100644 microservices-self-registration/greetingservice/src/main/resources/application.yml create mode 100644 microservices-self-registration/greetingservice/src/test/java/com/learning/greetingservice/GreetingserviceApplicationTests.java create mode 100644 microservices-self-registration/greetingservice/src/test/java/com/learning/greetingservice/MyCustomHealthCheckTest.java create mode 100644 microservices-self-registration/greetingservice/src/test/java/com/learning/greetingservice/controller/GreetingControllerTest.java create mode 100644 microservices-self-registration/pom.xml diff --git a/microservices-self-registration/README.md b/microservices-self-registration/README.md new file mode 100644 index 000000000000..bfc837817c57 --- /dev/null +++ b/microservices-self-registration/README.md @@ -0,0 +1,236 @@ +--- +title: "Microservices Self-Registration Pattern in Java with Spring Boot and Eureka" +shortTitle: Microservices Pattern - Self-Registration +description: "Dynamically register and discover Java microservices using Spring Boot and Eureka for resilient, scalable communication." +category: Service Discovery +language: en +tag: + - Microservices + - Self-Registration + - Service Discovery + - Eureka + - Spring Boot + - Spring Cloud + - Java + - Dynamic Configuration + - Resilience +--- + +## Intent of Microservices Self-Registration Pattern + +The intent of the Self-Registration pattern is to enable microservices to automatically announce their presence and location to a central registry (like Eureka) upon startup, simplifying service discovery and allowing other services to find and communicate with them without manual configuration or hardcoded addresses. This promotes dynamic and resilient microservices architectures. + +## What's in the Project + +This project demonstrates the Microservices Self-Registration pattern using Java, Spring Boot (version 3.4.4), and Eureka for service discovery. It consists of three main components: a Eureka Server and two simple microservices, a Greeting Service and a Context Service, which discover and communicate with each other. + +### Project Structure +* **`eureka-server`:** The central service registry where microservices register themselves. +* **`greeting-service`:** A simple microservice that provides a greeting. +* **`context-service`:** A microservice that consumes the greeting from the Greeting Service and adds context. + + The **Eureka Server** acts as the discovery service. Microservices register themselves with the Eureka Server, providing their network location. + + package com.example.eurekaserver; + + import org.springframework.boot.SpringApplication; + import org.springframework.boot.autoconfigure.SpringBootApplication; + import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; + + @SpringBootApplication + @EnableEurekaServer + public class EurekaServerApplication { + + public static void main(String[] args) { + SpringApplication.run(EurekaServerApplication.class, args); + } + } + + The **Greeting Service** is a simple microservice that exposes an endpoint to retrieve a greeting. + + package com.example.greetingservice; + + import org.springframework.boot.SpringApplication; + import org.springframework.boot.autoconfigure.SpringBootApplication; + import org.springframework.cloud.client.discovery.EnableDiscoveryClient; + + @SpringBootApplication + @EnableDiscoveryClient + public class GreetingServiceApplication { + + public static void main(String[] args) { + SpringApplication.run(GreetingServiceApplication.class, args); + } + } + + Greeting Controller + + package com.example.greetingservice.controller; + + import org.springframework.web.bind.annotation.GetMapping; + import org.springframework.web.bind.annotation.RestController; + + @RestController + public class GreetingController { + + @GetMapping("/greeting") + public String getGreeting() { + return "Hello"; + } + } + +The **Context Service** consumes the greeting from the Greeting Service using OpenFeign and adds contextual information. + + package com.example.contextservice; + + import org.springframework.boot.SpringApplication; + import org.springframework.boot.autoconfigure.SpringBootApplication; + import org.springframework.cloud.client.discovery.EnableDiscoveryClient; + import org.springframework.cloud.openfeign.EnableFeignClients; + + @SpringBootApplication + @EnableDiscoveryClient + @EnableFeignClients + public class ContextServiceApplication { + + public static void main(String[] args) { + SpringApplication.run(ContextServiceApplication.class, args); + } + } + + Feign Client : Spring Cloud OpenFeign is a declarative HTTP client that makes it easier to consume RESTful web services in your Spring Cloud applications. Instead of writing the boilerplate code for making HTTP requests, you simply declare interface with annotations that describe the web service you want to consume. + + package com.example.contextservice.client; + + import org.springframework.cloud.openfeign.FeignClient; + import org.springframework.web.bind.annotation.GetMapping; + + @FeignClient(name = "greeting-service") + public interface GreetingServiceClient { + + @GetMapping("/greeting") + String getGreeting(); + } + + Context Controller + + package com.example.contextservice.controller; + + import com.example.contextservice.client.GreetingServiceClient; + import org.springframework.beans.factory.annotation.Autowired; + import org.springframework.beans.factory.annotation.Value; + import org.springframework.web.bind.annotation.GetMapping; + import org.springframework.web.bind.annotation.RestController; + + @RestController + public class ContextController { + + @Autowired + private GreetingServiceClient greetingServiceClient; + + @Value("${user.region}") + private String userRegion; + + @GetMapping("/context") + public String getContext() { + String greeting = greetingServiceClient.getGreeting(); + return "The Greeting Service says: " + greeting + " from " + userRegion + "!"; + } + } + + 1. Both the Greeting Service and the Context Service register themselves with the Eureka Server upon startup using the _@EnableDiscoveryClient_ annotation. + 2. The Context Service, annotated with _@EnableFeignClients_, uses the GreetingServiceClient interface with _@FeignClient(name = "greeting-service")_ to declare its intent to communicate with the service named "greeting-service" in Eureka. + 3. When the /context endpoint of the Context Service is accessed, it calls the _getGreeting()_ method of the GreetingServiceClient. + 4. OpenFeign, leveraging the service discovery information from Eureka, resolves the network location of an available instance of the Greeting Service and makes an HTTP GET request to its /greeting endpoint. + 5. The Greeting Service responds with "Hello", and the Context Service then adds the configured user.region to the response. + + This project utilizes Spring Boot Actuator, which is included as a dependency, to provide health check endpoints for each microservice. These endpoints (e.g., /actuator/health) can be used by Eureka Server to monitor the health of the registered instances. + +## Steps to use for this Project + +Prerequisites: + - Java Development Kit (JDK): Make sure you have a compatible JDK installed (ideally Java 17 or later, as Spring Boot 3.x requires it). + - Maven or Gradle: You'll need either Maven (if you chose Maven during Spring Initializr setup) or Gradle (if you chose Gradle) installed on your system. + - An IDE (Optional but Recommended): IntelliJ IDEA, Eclipse, or Spring Tool Suite (STS) can make it easier to work with the project. + - Web Browser: You'll need a web browser to access the Eureka dashboard and the microservice endpoints. + +Step : + - You'll need to build each microservice individually. Navigate to the root directory of each project in your terminal or command prompt and run the appropriate build command: + _cd eurekaserver + mvn clean install + cd ../greetingservice + mvn clean install + cd ../contextservice + mvn clean install_ +Step : + - Navigate to the root directory of your eurekaserver project in your terminal or command prompt + _mvn spring-boot:run_ + - Wait for the Eureka Server application to start. You should see logs in the console indicating that it has started on port 8761 (as configured). + - Open your web browser and go to http://localhost:8761/. You should see the Eureka Server dashboard. Initially, the list of registered instances will be empty. +Step : + - Run the Greeting Service + - Open a new terminal or command prompt. + - Navigate to the root directory of your greetingservice project. + - Run the Spring Boot application: _mvn spring-boot:run_ + - Wait for the Greeting Service to start. You should see logs indicating that it has registered with the Eureka Server. + - Go back to your Eureka Server dashboard in the browser (http://localhost:8761/). You should now see GREETINGSERVICE listed under the "Instances currently registered with Eureka". Its status should be "UP". +Step : + - Run the Context Service + - Open a new terminal or command prompt. + - Navigate to the root directory of your contextservice project. + - Run the Spring Boot application: _mvn spring-boot:run_ + - Wait for the Context Service to start. You should see logs indicating that it has registered with the Eureka Server. + - Go back to your Eureka Server dashboard in the browser (http://localhost:8761/). You should now see CONTEXTSERVICE listed under the "Instances currently registered with Eureka". Its status should be "UP". +STEP : + - Test the Greeting Service Directly: Open your web browser and go to http://localhost:8081/greeting. You should see the output: Hello. + - Test the Context Service (which calls the Greeting Service): Open your web browser and go to http://localhost:8082/context. You should see the output: The Greeting Service says: Hello from Chennai, Tamil Nadu, India!. This confirms that the Context Service successfully discovered and called the Greeting Service through Eureka. + +Optional: Check Health Endpoints + +You can also verify the health status of each service using Spring Boot Actuator: + - Greeting Service Health: http://localhost:8081/actuator/health (should return {"status":"UP"}) + - Context Service Health: http://localhost:8082/actuator/health (should return {"status":"UP"}) + - Eureka Server Health: http://localhost:8761/actuator/health (should return {"status":"UP"}) + +## When to use Microservices Self-Registration Pattern + + - **Dynamic Environments:** When your microservices are frequently deployed, scaled up or down, or their network locations (IP addresses and ports) change often. This is common in cloud-based or containerized environments (like Docker and Kubernetes). + - **Large Number of Services:** As the number of microservices in your system grows, manually managing their configurations and dependencies becomes complex and error-prone. Self-registration automates this process. + - **Need for Automatic Service** Discovery: When services need to find and communicate with each other without hardcoding network locations. This allows for greater flexibility and reduces coupling. + - **Implementing Load Balancing:** Service registries like Eureka often integrate with load balancers, enabling them to automatically distribute traffic across available instances of a service that have registered themselves. + - **Improving System Resilience:** If a service instance fails, the registry will eventually be updated (through heartbeats or health checks), and other services can discover and communicate with the remaining healthy instances. + - **DevOps Automation:** This pattern aligns well with DevOps practices, allowing for more automated deployment and management of microservices. + +## Real-World Applications of Self-Registration pattern + + - E-Commerce platforms have numerous independent services for product catalogs, order processing, payments, shipping, etc. Self-registration allows these services to dynamically discover and communicate with each other as the system scales during peak loads or as new features are deployed. + - Streaming services rely on many microservices for user authentication, content delivery networks (CDNs), recommendation engines, billing systems, etc. Self-registration helps these services adapt to varying user demands and infrastructure changes. + - Social media These platforms use microservices for managing user profiles, timelines, messaging, advertising, and more. Self-registration enables these services to scale independently and handle the massive traffic they experience. + +## Advantages + + - Microservices can dynamically locate and communicate with each other without needing to know their specific network addresses beforehand. This is crucial in dynamic environments where IP addresses and ports can change frequently. + - Reduces the need for manual configuration of service locations in each microservice. Services don't need to be updated every time another service's location changes. + - Scaling microservices up or down becomes easier. New instances automatically register themselves with the service registry, making them immediately discoverable by other services without manual intervention. + - If a service instance fails, it will eventually stop sending heartbeats to the registry and will be removed. Consumers can then discover and connect to other healthy instances, improving the system's overall resilience. + - Services are less tightly coupled as they don't have direct dependencies on the physical locations of other services. This makes deployments and updates more flexible. + - Service registries often integrate with load balancers. When a new service instance registers, the load balancer can automatically include it in the pool of available instances, distributing traffic effectively. + - Microservices can be deployed across different environments (development, testing, production) without significant changes to their discovery mechanism, as long as they are configured to connect to the appropriate service registry for that environment. + +## Trade-offs + + - Introducing a service registry adds another component to your system that needs to be set up, managed, and monitored. This increases the overall complexity of the infrastructure. + - The service registry itself becomes a critical component. If the service registry becomes unavailable, it can disrupt communication between microservices. High availability for the service registry is therefore essential. + - Microservices need to communicate with the service registry for registration, sending heartbeats, and querying for other services. This can lead to increased network traffic. + - There might be a slight delay between when a microservice instance starts and when it becomes fully registered and discoverable in the service registry. This needs to be considered, especially during scaling events. + - You need to consider how your microservices will behave if they fail to register with the service registry upon startup. Robust error handling and retry mechanisms are often necessary. + - Microservices need to include and configure client libraries (like the Eureka Discovery Client) to interact with the service registry. This adds a dependency to your application code. + - In distributed service registries, ensuring consistency of the registry data across all nodes can be a challenge. Different registries might have different consistency models (e.g., eventual consistency). + +## References + + - Microservices Patterns: https://microservices.io/ + - Eureka Documentation: https://github.com/Netflix/eureka | https://spring.io/projects/spring-cloud-netflix + - Spring Boot Documentation: https://spring.io/projects/spring-boot + - Spring Cloud OpenFeignDocumentation: https://spring.io/projects/spring-cloud-openfeign + - Spring Boot Actuator Documentation: https://www.baeldung.com/spring-boot-actuators \ No newline at end of file diff --git a/microservices-self-registration/application.log.2025-04-09.0.gz b/microservices-self-registration/application.log.2025-04-09.0.gz new file mode 100644 index 0000000000000000000000000000000000000000..d51965d73d7a6d06bba18c80c7aeedb468916013 GIT binary patch literal 5525 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 literal 0 HcmV?d00001 diff --git a/microservices-self-registration/contextservice/.gitattributes b/microservices-self-registration/contextservice/.gitattributes new file mode 100644 index 000000000000..3b41682ac579 --- /dev/null +++ b/microservices-self-registration/contextservice/.gitattributes @@ -0,0 +1,2 @@ +/mvnw text eol=lf +*.cmd text eol=crlf diff --git a/microservices-self-registration/contextservice/.gitignore b/microservices-self-registration/contextservice/.gitignore new file mode 100644 index 000000000000..549e00a2a96f --- /dev/null +++ b/microservices-self-registration/contextservice/.gitignore @@ -0,0 +1,33 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ diff --git a/microservices-self-registration/contextservice/application.log.2025-04-05.0.gz b/microservices-self-registration/contextservice/application.log.2025-04-05.0.gz new file mode 100644 index 0000000000000000000000000000000000000000..6ceb03b833a731820dda00c3b027f16241335466 GIT binary patch literal 1977 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 BD#8E& literal 0 HcmV?d00001 diff --git a/microservices-self-registration/contextservice/application.log.2025-04-09.0.gz b/microservices-self-registration/contextservice/application.log.2025-04-09.0.gz new file mode 100644 index 0000000000000000000000000000000000000000..bd773dc8ba59d123795a9ea1518f8adf1e9e6e2e GIT binary patch literal 37553 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 + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 3.4.4 + + com.learning + contextservice + 0.0.1-SNAPSHOT + contextservice + contextservice + + + 2024.0.1 + + + + org.springframework.boot + spring-boot-starter-web + + + org.projectlombok + lombok + 1.18.38 + provided + + + org.springframework.cloud + spring-cloud-starter-netflix-eureka-client + + + org.springframework.boot + spring-boot-starter-actuator + + + org.springframework.cloud + spring-cloud-starter-openfeign + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + org.springframework.cloud + spring-cloud-dependencies + ${spring-cloud.version} + pom + import + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + org.apache.maven.plugins + maven-compiler-plugin + + + + + \ No newline at end of file diff --git a/microservices-self-registration/contextservice/src/main/java/com/learning/contextservice/ContextserviceApplication.java b/microservices-self-registration/contextservice/src/main/java/com/learning/contextservice/ContextserviceApplication.java new file mode 100644 index 000000000000..eb22d094ffce --- /dev/null +++ b/microservices-self-registration/contextservice/src/main/java/com/learning/contextservice/ContextserviceApplication.java @@ -0,0 +1,17 @@ +package com.learning.contextservice; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.client.discovery.EnableDiscoveryClient; +import org.springframework.cloud.openfeign.EnableFeignClients; + +@SpringBootApplication +@EnableDiscoveryClient +@EnableFeignClients +public class ContextserviceApplication { + + public static void main(String[] args) { + SpringApplication.run(ContextserviceApplication.class, args); + } + +} diff --git a/microservices-self-registration/contextservice/src/main/java/com/learning/contextservice/MyCustomHealthCheck.java b/microservices-self-registration/contextservice/src/main/java/com/learning/contextservice/MyCustomHealthCheck.java new file mode 100644 index 000000000000..0226fc50e803 --- /dev/null +++ b/microservices-self-registration/contextservice/src/main/java/com/learning/contextservice/MyCustomHealthCheck.java @@ -0,0 +1,42 @@ +package com.learning.contextservice; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.actuate.health.Health; +import org.springframework.boot.actuate.health.HealthIndicator; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + + +@Component("myCustomHealthCheck") +public class MyCustomHealthCheck implements HealthIndicator { + + private static final Logger log = LoggerFactory.getLogger(MyCustomHealthCheck.class); + + private volatile boolean isHealthy = true; + + @Scheduled(fixedRate = 5000) // Run every 5 seconds + public void updateHealthStatus() { + // Perform checks here to determine the current health + // For example, check database connectivity, external service availability, etc. + isHealthy = performHealthCheck(); + log.info("Update health status : {}", isHealthy); + } + + boolean performHealthCheck() { + boolean current = System.currentTimeMillis() % 10000 < 5000; // Simulate fluctuating health + log.debug("Performing health check, current status: {}", current); + return current; // Simulate fluctuating health + } + + @Override + public Health health() { + if (isHealthy) { + log.info("Health check successful, service is UP"); + return Health.up().withDetail("message", "Service is running and scheduled checks are OK").build(); + } else { + log.warn("Health check failed, service is DOWN"); + return Health.down().withDetail("error", "Scheduled health checks failed").build(); + } + } +} diff --git a/microservices-self-registration/contextservice/src/main/java/com/learning/contextservice/client/GreetingServiceClient.java b/microservices-self-registration/contextservice/src/main/java/com/learning/contextservice/client/GreetingServiceClient.java new file mode 100644 index 000000000000..367a3bdd496c --- /dev/null +++ b/microservices-self-registration/contextservice/src/main/java/com/learning/contextservice/client/GreetingServiceClient.java @@ -0,0 +1,11 @@ +package com.learning.contextservice.client; + +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.GetMapping; + +@FeignClient(name = "greetingservice") +public interface GreetingServiceClient { + + @GetMapping("/greeting") + String getGreeting(); +} diff --git a/microservices-self-registration/contextservice/src/main/java/com/learning/contextservice/controller/ContextController.java b/microservices-self-registration/contextservice/src/main/java/com/learning/contextservice/controller/ContextController.java new file mode 100644 index 000000000000..5ad8969e0871 --- /dev/null +++ b/microservices-self-registration/contextservice/src/main/java/com/learning/contextservice/controller/ContextController.java @@ -0,0 +1,26 @@ +package com.learning.contextservice.controller; + +import com.learning.contextservice.client.GreetingServiceClient; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class ContextController { + + private final GreetingServiceClient greetingServiceClient; + private final String userRegion; + + @Autowired + public ContextController(GreetingServiceClient greetingServiceClient, @Value("${user.region}") String userRegion) { + this.greetingServiceClient = greetingServiceClient; + this.userRegion = userRegion; + } + + @GetMapping("/context") + public String getContext() { + String greeting = greetingServiceClient.getGreeting(); + return "The Greeting Service says: "+greeting+" from "+userRegion; + } +} diff --git a/microservices-self-registration/contextservice/src/main/resources/application.yml b/microservices-self-registration/contextservice/src/main/resources/application.yml new file mode 100644 index 000000000000..dfef73bbbeec --- /dev/null +++ b/microservices-self-registration/contextservice/src/main/resources/application.yml @@ -0,0 +1,25 @@ +server: + port: 8082 + +spring: + application: + name: contextservice + +eureka: + client: + service-url.defaultZone: http://localhost:8761/eureka + +user: + region: Chennai, Tamil Nadu, India + +management: + endpoint: + health: + show-details: always + web: + exposure: + include: health + +logging: + file: + name: application.log diff --git a/microservices-self-registration/contextservice/src/test/java/com/learning/contextservice/ContextControllerTest.java b/microservices-self-registration/contextservice/src/test/java/com/learning/contextservice/ContextControllerTest.java new file mode 100644 index 000000000000..f11da867cda0 --- /dev/null +++ b/microservices-self-registration/contextservice/src/test/java/com/learning/contextservice/ContextControllerTest.java @@ -0,0 +1,49 @@ +package com.learning.contextservice; + +import com.learning.contextservice.client.GreetingServiceClient; +import org.hamcrest.Matchers; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; + +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Import; +import org.springframework.http.MediaType; +import org.springframework.test.context.bean.override.mockito.MockitoBean; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +@SpringBootTest(classes = ContextserviceApplication.class) +@AutoConfigureMockMvc +@Import(TestConfig.class) +class ContextControllerTest { + + @Autowired + private MockMvc mockMvc; + + @MockitoBean + private GreetingServiceClient greetingServiceClient; + + @Value("${user.region}") + private String userRegion; + + @Test + void shouldReturnContextGreeting() throws Exception{ + Mockito.when(greetingServiceClient.getGreeting()).thenReturn("Mocked Hello"); + + mockMvc.perform(MockMvcRequestBuilders.get("/context") + .accept(MediaType.TEXT_PLAIN)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.content().string("The Greeting Service says: Mocked Hello from Chennai, Tamil Nadu, India")); + } + + @Test + void shouldReturnContextServiceHealthStatusUp() throws Exception { + mockMvc.perform(MockMvcRequestBuilders.get("/actuator/health")) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.content().string(Matchers.containsString("\"status\":\"UP\""))); + } +} diff --git a/microservices-self-registration/contextservice/src/test/java/com/learning/contextservice/ContextserviceApplicationTests.java b/microservices-self-registration/contextservice/src/test/java/com/learning/contextservice/ContextserviceApplicationTests.java new file mode 100644 index 000000000000..a5d5c869c664 --- /dev/null +++ b/microservices-self-registration/contextservice/src/test/java/com/learning/contextservice/ContextserviceApplicationTests.java @@ -0,0 +1,17 @@ +package com.learning.contextservice; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class ContextserviceApplicationTests { + + @Test + void contextLoads() { + // This is a basic integration test that checks if the Spring Application Context loads successfully. + // If the context loads without any exceptions, the test is considered passing. + // It is often left empty as the act of loading the context is the primary verification. + // You can add specific assertions here if you want to verify the presence or state of certain beans. + } + +} diff --git a/microservices-self-registration/contextservice/src/test/java/com/learning/contextservice/TestConfig.java b/microservices-self-registration/contextservice/src/test/java/com/learning/contextservice/TestConfig.java new file mode 100644 index 000000000000..f378f46f59df --- /dev/null +++ b/microservices-self-registration/contextservice/src/test/java/com/learning/contextservice/TestConfig.java @@ -0,0 +1,17 @@ +package com.learning.contextservice; + +import com.learning.contextservice.client.GreetingServiceClient; +import org.mockito.Mockito; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class TestConfig { + + @Bean + public GreetingServiceClient greetingServiceClient() { + GreetingServiceClient mockClient = Mockito.mock(GreetingServiceClient.class); + Mockito.when(mockClient.getGreeting()).thenReturn("Mocked Hello"); + return mockClient; + } +} diff --git a/microservices-self-registration/contextservice/src/test/java/com/learning/contextservice/myCustomHealthCheckTest.java b/microservices-self-registration/contextservice/src/test/java/com/learning/contextservice/myCustomHealthCheckTest.java new file mode 100644 index 000000000000..129209469827 --- /dev/null +++ b/microservices-self-registration/contextservice/src/test/java/com/learning/contextservice/myCustomHealthCheckTest.java @@ -0,0 +1,33 @@ +package com.learning.contextservice; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.actuate.health.Health; +import org.springframework.test.util.ReflectionTestUtils; +import org.springframework.boot.actuate.health.Status; +import static org.junit.jupiter.api.Assertions.*; + +class MyCustomHealthCheckTest { + + @Test + void testHealthUp() { + MyCustomHealthCheck healthCheck = new MyCustomHealthCheck(); + // Simulate a healthy state + ReflectionTestUtils.setField(healthCheck, "isHealthy", true); + Health health = healthCheck.health(); + assertEquals(Status.UP, health.getStatus()); + assertTrue(health.getDetails().containsKey("message")); + assertEquals("Service is running and scheduled checks are OK", health.getDetails().get("message")); + } + + @Test + void testHealthDown() { + MyCustomHealthCheck healthCheck = new MyCustomHealthCheck(); + // Simulate an unhealthy state + ReflectionTestUtils.setField(healthCheck, "isHealthy", false); + Health health = healthCheck.health(); + assertEquals(Status.DOWN, health.getStatus()); + assertTrue(health.getDetails().containsKey("error")); + assertEquals("Scheduled health checks failed", health.getDetails().get("error")); + } + +} \ No newline at end of file diff --git a/microservices-self-registration/eurekaserver/.gitattributes b/microservices-self-registration/eurekaserver/.gitattributes new file mode 100644 index 000000000000..3b41682ac579 --- /dev/null +++ b/microservices-self-registration/eurekaserver/.gitattributes @@ -0,0 +1,2 @@ +/mvnw text eol=lf +*.cmd text eol=crlf diff --git a/microservices-self-registration/eurekaserver/.gitignore b/microservices-self-registration/eurekaserver/.gitignore new file mode 100644 index 000000000000..549e00a2a96f --- /dev/null +++ b/microservices-self-registration/eurekaserver/.gitignore @@ -0,0 +1,33 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ diff --git a/microservices-self-registration/eurekaserver/pom.xml b/microservices-self-registration/eurekaserver/pom.xml new file mode 100644 index 000000000000..b1a4b26cf4f4 --- /dev/null +++ b/microservices-self-registration/eurekaserver/pom.xml @@ -0,0 +1,55 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 3.4.4 + + com.learning + eurekaserver + 0.0.1-SNAPSHOT + eurekaserver + eurekaserver + + + 2024.0.1 + + + + org.springframework.cloud + spring-cloud-starter-netflix-eureka-server + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + org.springframework.cloud + spring-cloud-dependencies + ${spring-cloud.version} + pom + import + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + org.apache.maven.plugins + maven-compiler-plugin + + + + + \ No newline at end of file diff --git a/microservices-self-registration/eurekaserver/src/main/java/com/learning/eurekaserver/EurekaserverApplication.java b/microservices-self-registration/eurekaserver/src/main/java/com/learning/eurekaserver/EurekaserverApplication.java new file mode 100644 index 000000000000..80b3d904ff4c --- /dev/null +++ b/microservices-self-registration/eurekaserver/src/main/java/com/learning/eurekaserver/EurekaserverApplication.java @@ -0,0 +1,15 @@ +package com.learning.eurekaserver; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; + +@SpringBootApplication +@EnableEurekaServer +public class EurekaserverApplication { + + public static void main(String[] args) { + SpringApplication.run(EurekaserverApplication.class, args); + } + +} diff --git a/microservices-self-registration/eurekaserver/src/main/resources/application.yml b/microservices-self-registration/eurekaserver/src/main/resources/application.yml new file mode 100644 index 000000000000..51f8a815d251 --- /dev/null +++ b/microservices-self-registration/eurekaserver/src/main/resources/application.yml @@ -0,0 +1,10 @@ +server: + port: 8761 + +eureka: + client: + register-with-eureka: false + fetch-registry: false + server: + enable-self-preservation: true + diff --git a/microservices-self-registration/eurekaserver/src/test/java/com/learning/eurekaserver/EurekaserverApplicationTests.java b/microservices-self-registration/eurekaserver/src/test/java/com/learning/eurekaserver/EurekaserverApplicationTests.java new file mode 100644 index 000000000000..b5150fefa940 --- /dev/null +++ b/microservices-self-registration/eurekaserver/src/test/java/com/learning/eurekaserver/EurekaserverApplicationTests.java @@ -0,0 +1,17 @@ +package com.learning.eurekaserver; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class EurekaserverApplicationTests { + + @Test + void contextLoads() { + // This is a basic integration test that checks if the Spring Application Context loads successfully. + // If the context loads without any exceptions, the test is considered passing. + // It is often left empty as the act of loading the context is the primary verification. + // You can add specific assertions here if you want to verify the presence or state of certain beans. + } + +} diff --git a/microservices-self-registration/greetingservice/.gitattributes b/microservices-self-registration/greetingservice/.gitattributes new file mode 100644 index 000000000000..3b41682ac579 --- /dev/null +++ b/microservices-self-registration/greetingservice/.gitattributes @@ -0,0 +1,2 @@ +/mvnw text eol=lf +*.cmd text eol=crlf diff --git a/microservices-self-registration/greetingservice/.gitignore b/microservices-self-registration/greetingservice/.gitignore new file mode 100644 index 000000000000..549e00a2a96f --- /dev/null +++ b/microservices-self-registration/greetingservice/.gitignore @@ -0,0 +1,33 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ diff --git a/microservices-self-registration/greetingservice/application.log.2025-04-05.0.gz b/microservices-self-registration/greetingservice/application.log.2025-04-05.0.gz new file mode 100644 index 0000000000000000000000000000000000000000..93d6a2e62ac144ee4c35e079906a0fdd82f04492 GIT binary patch literal 1893 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 literal 0 HcmV?d00001 diff --git a/microservices-self-registration/greetingservice/application.log.2025-04-09.0.gz b/microservices-self-registration/greetingservice/application.log.2025-04-09.0.gz new file mode 100644 index 0000000000000000000000000000000000000000..59f2cbc3c8dfad5a5f90f9187eca0e58b6a796f2 GIT binary patch literal 18884 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%0DM?2 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 e0rKw!aGb> + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 3.4.4 + + com.learning + greetingservice + 0.0.1-SNAPSHOT + greetingservice + greetingservice + + + 2024.0.1 + + + + org.springframework.boot + spring-boot-starter-web + + + org.projectlombok + lombok + 1.18.38 + provided + + + org.springframework.cloud + spring-cloud-starter-netflix-eureka-client + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.boot + spring-boot-starter-actuator + + + + + + org.springframework.cloud + spring-cloud-dependencies + ${spring-cloud.version} + pom + import + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + org.apache.maven.plugins + maven-compiler-plugin + + + + + \ No newline at end of file diff --git a/microservices-self-registration/greetingservice/src/main/java/com/learning/greetingservice/GreetingserviceApplication.java b/microservices-self-registration/greetingservice/src/main/java/com/learning/greetingservice/GreetingserviceApplication.java new file mode 100644 index 000000000000..7a549a084284 --- /dev/null +++ b/microservices-self-registration/greetingservice/src/main/java/com/learning/greetingservice/GreetingserviceApplication.java @@ -0,0 +1,17 @@ +package com.learning.greetingservice; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.client.discovery.EnableDiscoveryClient; +import org.springframework.context.annotation.ComponentScan; + +@SpringBootApplication +@EnableDiscoveryClient +@ComponentScan("com.learning.greetingservice.controller") +public class GreetingserviceApplication { + + public static void main(String[] args) { + SpringApplication.run(GreetingserviceApplication.class, args); + } + +} diff --git a/microservices-self-registration/greetingservice/src/main/java/com/learning/greetingservice/MyCustomHealthCheck.java b/microservices-self-registration/greetingservice/src/main/java/com/learning/greetingservice/MyCustomHealthCheck.java new file mode 100644 index 000000000000..218a4ad002d4 --- /dev/null +++ b/microservices-self-registration/greetingservice/src/main/java/com/learning/greetingservice/MyCustomHealthCheck.java @@ -0,0 +1,41 @@ +package com.learning.greetingservice; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.actuate.health.Health; +import org.springframework.boot.actuate.health.HealthIndicator; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +@Component("myCustomHealthCheck") +public class MyCustomHealthCheck implements HealthIndicator { + + private static final Logger log = LoggerFactory.getLogger(MyCustomHealthCheck.class); + + private volatile boolean isHealthy = true; + + @Scheduled(fixedRate = 5000) // Run every 5 seconds + public void updateHealthStatus() { + // Perform checks here to determine the current health + // For example, check database connectivity, external service availability, etc. + isHealthy = performHealthCheck(); + log.info("Update health status : {}", isHealthy); + } + + boolean performHealthCheck() { + boolean current = System.currentTimeMillis() % 10000 < 5000; // Simulate fluctuating health + log.debug("Performing health check, current status: {}", current); + return current; // Simulate fluctuating health + } + + @Override + public Health health() { + if (isHealthy) { + log.info("Health check successful, service is UP"); + return Health.up().withDetail("message", "Service is running and scheduled checks are OK").build(); + } else { + log.warn("Health check failed, service is DOWN"); + return Health.down().withDetail("error", "Scheduled health checks failed").build(); + } + } +} diff --git a/microservices-self-registration/greetingservice/src/main/java/com/learning/greetingservice/controller/GreetingsController.java b/microservices-self-registration/greetingservice/src/main/java/com/learning/greetingservice/controller/GreetingsController.java new file mode 100644 index 000000000000..ea385beb1abe --- /dev/null +++ b/microservices-self-registration/greetingservice/src/main/java/com/learning/greetingservice/controller/GreetingsController.java @@ -0,0 +1,13 @@ +package com.learning.greetingservice.controller; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class GreetingsController { + + @GetMapping("/greeting") + public String getGreeting() { + return "Hello"; + } +} diff --git a/microservices-self-registration/greetingservice/src/main/resources/application.yml b/microservices-self-registration/greetingservice/src/main/resources/application.yml new file mode 100644 index 000000000000..adcfac884c2b --- /dev/null +++ b/microservices-self-registration/greetingservice/src/main/resources/application.yml @@ -0,0 +1,22 @@ +server: + port: 8081 + +spring: + application: + name: greetingservice +eureka: + client: + service-url.defaultZone: http://localhost:8761/eureka + +management: + endpoint: + health: + show-details: always + web: + exposure: + include: health + +logging: + file: + name: application.log + diff --git a/microservices-self-registration/greetingservice/src/test/java/com/learning/greetingservice/GreetingserviceApplicationTests.java b/microservices-self-registration/greetingservice/src/test/java/com/learning/greetingservice/GreetingserviceApplicationTests.java new file mode 100644 index 000000000000..945898278aa9 --- /dev/null +++ b/microservices-self-registration/greetingservice/src/test/java/com/learning/greetingservice/GreetingserviceApplicationTests.java @@ -0,0 +1,17 @@ +package com.learning.greetingservice; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class GreetingserviceApplicationTests { + + @Test + void contextLoads() { + // This is a basic integration test that checks if the Spring Application Context loads successfully. + // If the context loads without any exceptions, the test is considered passing. + // It is often left empty as the act of loading the context is the primary verification. + // You can add specific assertions here if you want to verify the presence or state of certain beans. + } + +} diff --git a/microservices-self-registration/greetingservice/src/test/java/com/learning/greetingservice/MyCustomHealthCheckTest.java b/microservices-self-registration/greetingservice/src/test/java/com/learning/greetingservice/MyCustomHealthCheckTest.java new file mode 100644 index 000000000000..8ba8b2a30f93 --- /dev/null +++ b/microservices-self-registration/greetingservice/src/test/java/com/learning/greetingservice/MyCustomHealthCheckTest.java @@ -0,0 +1,22 @@ +package com.learning.greetingservice; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.actuate.health.Health; +import org.springframework.test.util.ReflectionTestUtils; +import org.springframework.boot.actuate.health.Status; +import static org.junit.jupiter.api.Assertions.*; + +class MyCustomHealthCheckTest { + + @Test + void testHealthUp() { + MyCustomHealthCheck healthCheck = new MyCustomHealthCheck(); + // Simulate a healthy state + ReflectionTestUtils.setField(healthCheck, "isHealthy", true); + Health health = healthCheck.health(); + assertEquals(Status.UP, health.getStatus()); + assertTrue(health.getDetails().containsKey("message")); + assertEquals("Service is running and scheduled checks are OK", health.getDetails().get("message")); + } + +} \ No newline at end of file diff --git a/microservices-self-registration/greetingservice/src/test/java/com/learning/greetingservice/controller/GreetingControllerTest.java b/microservices-self-registration/greetingservice/src/test/java/com/learning/greetingservice/controller/GreetingControllerTest.java new file mode 100644 index 000000000000..5ae98c8b6aeb --- /dev/null +++ b/microservices-self-registration/greetingservice/src/test/java/com/learning/greetingservice/controller/GreetingControllerTest.java @@ -0,0 +1,36 @@ +package com.learning.greetingservice.controller; + +import com.learning.greetingservice.GreetingserviceApplication; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +@SpringBootTest(classes = GreetingserviceApplication.class) +@AutoConfigureMockMvc +@ActiveProfiles("test") +class GreetingControllerTest { + + @Autowired + private MockMvc mockMvc; + + @Test + void shouldReturnGreeting() throws Exception{ + mockMvc.perform(MockMvcRequestBuilders.get("/greeting") + .accept(MediaType.TEXT_PLAIN)) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.content().string("Hello")); + } + + @Test + void shouldReturnHealthStatusUp() throws Exception{ + mockMvc.perform(MockMvcRequestBuilders.get("/actuator/health")) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.content().string(org.hamcrest.Matchers.containsString("\"status\":\"UP\""))); + } +} diff --git a/microservices-self-registration/pom.xml b/microservices-self-registration/pom.xml new file mode 100644 index 000000000000..4b708cb0eb12 --- /dev/null +++ b/microservices-self-registration/pom.xml @@ -0,0 +1,63 @@ + + + + + java-design-patterns + com.iluwatar + 1.26.0-SNAPSHOT + + 4.0.0 + microservices-self-registration + pom + + eurekaserver + greetingservice + contextservice + + + + 21 + ${java.version} + ${java.version} + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + ${maven.compiler.source} + ${maven.compiler.target} + + + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml index 661abe365a18..a7fdcb7064d9 100644 --- a/pom.xml +++ b/pom.xml @@ -167,6 +167,7 @@ microservices-distributed-tracing microservices-idempotent-consumer microservices-log-aggregation + microservices-self-registration model-view-controller model-view-intent model-view-presenter From fecf7e7a8265116c358a4c7cd14c833b72d11b3e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 8 Feb 2026 21:11:22 +0200 Subject: [PATCH 3/8] build(deps-dev): bump io.projectreactor:reactor-test (#3377) Bumps [io.projectreactor:reactor-test](https://github.com/reactor/reactor-core) from 3.8.0-M1 to 3.8.0-RC1. - [Release notes](https://github.com/reactor/reactor-core/releases) - [Commits](https://github.com/reactor/reactor-core/compare/v3.8.0-M1...v3.8.0-RC1) --- updated-dependencies: - dependency-name: io.projectreactor:reactor-test dependency-version: 3.8.0-RC1 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- backpressure/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backpressure/pom.xml b/backpressure/pom.xml index fcc15892fb8a..8f6a54178799 100644 --- a/backpressure/pom.xml +++ b/backpressure/pom.xml @@ -55,7 +55,7 @@ io.projectreactor reactor-test - 3.8.0-M1 + 3.8.0-RC1 test From f92e6829c3664ac569cdbef86d68db11eff8b36d Mon Sep 17 00:00:00 2001 From: Thanh Nguyen Duc Date: Mon, 9 Feb 2026 02:11:47 +0700 Subject: [PATCH 4/8] feat: Implement DAO Factory pattern (#3282) * feat: implement dao factory * feat: done implement dao factory * test: Add unit test dao-factory * doc: add document for dao-factory * fix: h2 inmemory database to pass CI * fix: unit test pipeline * add license * fix SonarQube * add pom.xml * fix: throw exception + refactor --- dao-factory/README.md | 360 +++++++++++++ dao-factory/etc/dao-factory.png | Bin 0 -> 113583 bytes dao-factory/etc/dao-factory.puml | 74 +++ dao-factory/pom.xml | 82 +++ .../java/com/iluwatar/daofactory/App.java | 124 +++++ .../iluwatar/daofactory/CustomException.java | 36 ++ .../com/iluwatar/daofactory/Customer.java | 47 ++ .../com/iluwatar/daofactory/CustomerDAO.java | 85 +++ .../com/iluwatar/daofactory/DAOFactory.java | 45 ++ .../daofactory/DAOFactoryProvider.java | 62 +++ .../iluwatar/daofactory/DataSourceType.java | 32 ++ .../daofactory/FlatFileCustomerDAO.java | 175 ++++++ .../daofactory/FlatFileDataSourceFactory.java | 43 ++ .../iluwatar/daofactory/H2CustomerDAO.java | 179 +++++++ .../daofactory/H2DataSourceFactory.java | 48 ++ .../iluwatar/daofactory/MongoCustomerDAO.java | 106 ++++ .../daofactory/MongoDataSourceFactory.java | 51 ++ dao-factory/src/main/resources/logback.xml | 12 + .../java/com/iluwatar/daofactory/AppTest.java | 94 ++++ .../iluwatar/daofactory/DAOFactoryTest.java | 54 ++ .../daofactory/FlatFileCustomerDAOTest.java | 500 ++++++++++++++++++ .../daofactory/H2CustomerDAOTest.java | 300 +++++++++++ .../daofactory/MongoCustomerDAOTest.java | 163 ++++++ pom.xml | 1 + 24 files changed, 2673 insertions(+) create mode 100644 dao-factory/README.md create mode 100644 dao-factory/etc/dao-factory.png create mode 100644 dao-factory/etc/dao-factory.puml create mode 100644 dao-factory/pom.xml create mode 100644 dao-factory/src/main/java/com/iluwatar/daofactory/App.java create mode 100644 dao-factory/src/main/java/com/iluwatar/daofactory/CustomException.java create mode 100644 dao-factory/src/main/java/com/iluwatar/daofactory/Customer.java create mode 100644 dao-factory/src/main/java/com/iluwatar/daofactory/CustomerDAO.java create mode 100644 dao-factory/src/main/java/com/iluwatar/daofactory/DAOFactory.java create mode 100644 dao-factory/src/main/java/com/iluwatar/daofactory/DAOFactoryProvider.java create mode 100644 dao-factory/src/main/java/com/iluwatar/daofactory/DataSourceType.java create mode 100644 dao-factory/src/main/java/com/iluwatar/daofactory/FlatFileCustomerDAO.java create mode 100644 dao-factory/src/main/java/com/iluwatar/daofactory/FlatFileDataSourceFactory.java create mode 100644 dao-factory/src/main/java/com/iluwatar/daofactory/H2CustomerDAO.java create mode 100644 dao-factory/src/main/java/com/iluwatar/daofactory/H2DataSourceFactory.java create mode 100644 dao-factory/src/main/java/com/iluwatar/daofactory/MongoCustomerDAO.java create mode 100644 dao-factory/src/main/java/com/iluwatar/daofactory/MongoDataSourceFactory.java create mode 100644 dao-factory/src/main/resources/logback.xml create mode 100644 dao-factory/src/test/java/com/iluwatar/daofactory/AppTest.java create mode 100644 dao-factory/src/test/java/com/iluwatar/daofactory/DAOFactoryTest.java create mode 100644 dao-factory/src/test/java/com/iluwatar/daofactory/FlatFileCustomerDAOTest.java create mode 100644 dao-factory/src/test/java/com/iluwatar/daofactory/H2CustomerDAOTest.java create mode 100644 dao-factory/src/test/java/com/iluwatar/daofactory/MongoCustomerDAOTest.java diff --git a/dao-factory/README.md b/dao-factory/README.md new file mode 100644 index 000000000000..c3ee3c5e893d --- /dev/null +++ b/dao-factory/README.md @@ -0,0 +1,360 @@ +--- +title: "DAO Factory Pattern: Flexible Data Access Layer for Seamless Data Source Switching" +shortTitle: DAO Factory +description: "Learn the Data Access Object Pattern combine with Abstract Factory Pattern in Java with real-world examples, class diagrams, and tutorials. Understand its intent, applicability, benefits, and known uses to enhance your design pattern knowledge." +category: Structural +language: en +tag: + - Abstraction + - Data access + - Layer architecture + - Persistence +--- + +## Also known as + +* DAO Factory +* Factory for Data Access Object strategy using Abstract Factory + + +## Intent of Data Access Object Factory Design Pattern + +The DAO Factory combines the Data Access Object and Abstract Factory patterns to seperate business logic from data access logic, while increasing flexibility when switching between different data sources. + +## Detailed Explanation of Data Access Object Factory Pattern with Real-World Examples + +Real-world example + +> A real-world analogy for the DAO Factory pattern is a multilingual customer service center. Imagine a bank that serves customers speaking different languages—English, French, and Spanish. When a customer calls, an automated system first detects the customer's preferred language, then routes the call to the appropriate support team that speaks that language. Each team follows the same company policies (standard procedures), but handles interactions in a language-specific way. +> +> In the same way, the DAO Factory pattern uses a factory to determine the correct set of DAO implementations based on the data source (e.g., MySQL, MongoDB). Each DAO factory returns a group of DAOs tailored to a specific data source, all conforming to the same interfaces. This allows the application to interact with any supported database in a consistent manner, without changing the business logic—just like how the customer service system handles multiple languages while following the same support protocols. + +In plain words + +> The DAO Factory pattern abstracts the creation of Data Access Objects (DAOs), allowing you to request a specific DAO from a central factory without worrying about its underlying implementation. This makes the code easier to maintain and flexible to change, especially when switching between databases or storage mechanisms. + +Wikipedia says + +> The Data Access Object (DAO) design pattern is a structural pattern that provides an abstract interface to some type of database or other persistence mechanism. By mapping application calls to the persistence layer, the DAO provides some specific data operations without exposing details of the database. The DAO Factory is an extension of this concept, responsible for generating the required DAO implementations. + +Class diagram + +![Data Access Object Factory class diagram](./etc/dao-factory.png "Data Access Object Factory class diagram") + +## Programmatic Example of Data Access Object Factory in Java + +In this example, the persistence object represents a Customer. + +We are considering a flexible storage strategy where the application should be able to work with three different types of data sources: an H2 in-memory relational database (RDBMS), a MongoDB (object-oriented database), and a JSON flat file (flat file storage). + +``` java +public enum DataSourceType { +H2, +Mongo, +FlatFile +} +``` + +First, we define a Customer class that will be persisted in different storage systems. The ID field is generic to maintain compatibility with both relational and object-oriented databases. + +``` java +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@ToString +public class Customer implements Serializable { +private T id; +private String name; +} +``` + +Next, we define a CustomerDAO interface that outlines the standard CRUD operations on the Customer model. This interface will have three concrete implementations, each corresponding to a specific data source: H2 in-memory database, MongoDB, and JSON file. + +``` java +public interface CustomerDAO { + + void save(Customer customer); + + void update(Customer customer); + + void delete(T id); + + List> findAll(); + + Optional> findById(T id); +} +``` + +Here is the implementations + +``` java +@Slf4j +@RequiredArgsConstructor +public class H2CustomerDAO implements CustomerDAO { +private final DataSource dataSource; +private final String INSERT_CUSTOMER = "INSERT INTO customer(id, name) VALUES (?, ?)"; +private final String UPDATE_CUSTOMER = "UPDATE customer SET name = ? WHERE id = ?"; +private final String DELETE_CUSTOMER = "DELETE FROM customer WHERE id = ?"; +private final String SELECT_CUSTOMER_BY_ID = "SELECT * FROM customer WHERE id= ?"; +private final String SELECT_ALL_CUSTOMERS = "SELECT * FROM customer"; +private final String CREATE_SCHEMA = +"CREATE TABLE IF NOT EXISTS customer (id BIGINT PRIMARY KEY, name VARCHAR(255))"; +private final String DROP_SCHEMA = "DROP TABLE IF EXISTS customer"; + + @Override + public void save(Customer customer) { + // Implement operation save for H2 + } + + @Override + public void update(Customer customer) { + // Implement operation save for H2 + } + + @Override + public void delete(Long id) { + // Implement operation delete for H2 + } + + @Override + public List> findAll() { + // Implement operation find all for H2 + } + + @Override + public Optional> findById(Long id) { + // Implement operation find by id for H2 + } +} +``` + +``` java +@Slf4j +@RequiredArgsConstructor +public class MongoCustomerDAO implements CustomerDAO { +private final MongoCollection customerCollection; + + // Implement CRUD operation with MongoDB data source +} +``` + +``` java +@Slf4j +@RequiredArgsConstructor +public class FlatFileCustomerDAO implements CustomerDAO { + private final Path filePath; + private final Gson gson; + Type customerListType = new TypeToken>>() { + }.getType(); + + // Implement CRUD operation with Flat file data source +} +``` + +After that, we create an abstract class DAOFactory that defines two key methods: a static method getDataSource() and an abstract method createCustomerDAO(). + +- The getDataSource() method is a factory selector—it returns a concrete DAOFactory instance based on the type of data source requested. + +- Each subclass of DAOFactory will implement the createCustomerDAO() method to provide the corresponding CustomerDAO implementation. + +``` java +public abstract class DAOFactory { + public static DAOFactory getDataSource(DataSourceType dataSourceType) { + return switch (dataSourceType) { + case H2 -> new H2DataSourceFactory(); + case Mongo -> new MongoDataSourceFactory(); + case FlatFile -> new FlatFileDataSourceFactory(); + }; + } + + public abstract CustomerDAO createCustomerDAO(); +} +``` + +We then implement three specific factory classes: + +H2DataSourceFactory for H2 in-memory RDBMS +``` java +public class H2DataSourceFactory extends DAOFactory { + private final String DB_URL = "jdbc:h2:~/test"; + private final String USER = "sa"; + private final String PASS = ""; + + @Override + public CustomerDAO createCustomerDAO() { + return new H2CustomerDAO(createDataSource()); + } + + private DataSource createDataSource() { + var dataSource = new JdbcDataSource(); + dataSource.setURL(DB_URL); + dataSource.setUser(USER); + dataSource.setPassword(PASS); + return dataSource; + } +} +``` + +MongoDataSourceFactory for MongoDB +``` java +public class MongoDataSourceFactory extends DAOFactory { + private final String CONN_STR = "mongodb://localhost:27017/"; + private final String DB_NAME = "dao_factory"; + private final String COLLECTION_NAME = "customer"; + + @Override + public CustomerDAO createCustomerDAO() { + try { + MongoClient mongoClient = MongoClients.create(CONN_STR); + MongoDatabase database = mongoClient.getDatabase(DB_NAME); + MongoCollection customerCollection = database.getCollection(COLLECTION_NAME); + return new MongoCustomerDAO(customerCollection); + } catch (RuntimeException e) { + throw new RuntimeException("Error: " + e); + } + } +} +``` + +FlatFileDataSourceFactory for flat file storage using JSON +``` java +public class FlatFileDataSourceFactory extends DAOFactory { + private final String FILE_PATH = System.getProperty("user.home") + "/Desktop/customer.json"; + @Override + public CustomerDAO createCustomerDAO() { + Path filePath = Paths.get(FILE_PATH); + Gson gson = new GsonBuilder() + .setPrettyPrinting() + .serializeNulls() + .create(); + return new FlatFileCustomerDAO(filePath, gson); + } +} +``` + +Finally, in the main function of client code, we will demonstrate CRUD operations on the Customer using three data source type. +``` java + // Perform CRUD H2 Database + LOGGER.debug("H2 - Create customer"); + performCreateCustomer(customerDAO, + List.of(customerInmemory1, customerInmemory2, customerInmemory3)); + LOGGER.debug("H2 - Update customer"); + performUpdateCustomer(customerDAO, customerUpdateInmemory); + LOGGER.debug("H2 - Delete customer"); + performDeleteCustomer(customerDAO, 3L); + deleteSchema(customerDAO); + + // Perform CRUD MongoDb + daoFactory = DAOFactory.getDataSource(DataSourceType.Mongo); + customerDAO = daoFactory.createCustomerDAO(); + LOGGER.debug("Mongo - Create customer"); + performCreateCustomer(customerDAO, List.of(customer4, customer5)); + LOGGER.debug("Mongo - Update customer"); + performUpdateCustomer(customerDAO, customerUpdateMongo); + LOGGER.debug("Mongo - Delete customer"); + performDeleteCustomer(customerDAO, idCustomerMongo2); + deleteSchema(customerDAO); + + // Perform CRUD Flat file + daoFactory = DAOFactory.getDataSource(DataSourceType.FlatFile); + customerDAO = daoFactory.createCustomerDAO(); + LOGGER.debug("Flat file - Create customer"); + performCreateCustomer(customerDAO, + List.of(customerFlatFile1, customerFlatFile2, customerFlatFile3)); + LOGGER.debug("Flat file - Update customer"); + performUpdateCustomer(customerDAO, customerUpdateFlatFile); + LOGGER.debug("Flat file - Delete customer"); + performDeleteCustomer(customerDAO, 3L); + deleteSchema(customerDAO); +``` + +The program output +``` java +17:17:24.368 [main] DEBUG c.i.d.App com.iluwatar.daofactory.App - H2 - Create customer +17:17:24.514 [main] DEBUG c.i.d.App com.iluwatar.daofactory.App - Customer(id=1, name=Green) +17:17:24.514 [main] DEBUG c.i.d.App com.iluwatar.daofactory.App - Customer(id=2, name=Red) +17:17:24.514 [main] DEBUG c.i.d.App com.iluwatar.daofactory.App - Customer(id=3, name=Blue) +17:17:24.514 [main] DEBUG c.i.d.App com.iluwatar.daofactory.App - H2 - Update customer +17:17:24.573 [main] DEBUG c.i.d.App com.iluwatar.daofactory.App - Customer(id=1, name=Yellow) +17:17:24.573 [main] DEBUG c.i.d.App com.iluwatar.daofactory.App - Customer(id=2, name=Red) +17:17:24.573 [main] DEBUG c.i.d.App com.iluwatar.daofactory.App - Customer(id=3, name=Blue) +17:17:24.573 [main] DEBUG c.i.d.App com.iluwatar.daofactory.App - H2 - Delete customer +17:17:24.632 [main] DEBUG c.i.d.App com.iluwatar.daofactory.App - Customer(id=1, name=Yellow) +17:17:24.632 [main] DEBUG c.i.d.App com.iluwatar.daofactory.App - Customer(id=2, name=Red) +17:17:24.747 [main] DEBUG c.i.d.App com.iluwatar.daofactory.App - Mongo - Create customer +17:17:24.834 [main] DEBUG c.i.d.App com.iluwatar.daofactory.App - Customer(id=68173eb4c840286dbc2bc5c1, name=Masca) +17:17:24.834 [main] DEBUG c.i.d.App com.iluwatar.daofactory.App - Customer(id=68173eb4c840286dbc2bc5c2, name=Elliot) +17:17:24.834 [main] DEBUG c.i.d.App com.iluwatar.daofactory.App - Mongo - Update customer +17:17:24.845 [main] DEBUG c.i.d.App com.iluwatar.daofactory.App - Customer(id=68173eb4c840286dbc2bc5c1, name=Masca) +17:17:24.845 [main] DEBUG c.i.d.App com.iluwatar.daofactory.App - Customer(id=68173eb4c840286dbc2bc5c2, name=Henry) +17:17:24.845 [main] DEBUG c.i.d.App com.iluwatar.daofactory.App - Mongo - Delete customer +17:17:24.850 [main] DEBUG c.i.d.App com.iluwatar.daofactory.App - Customer(id=68173eb4c840286dbc2bc5c1, name=Masca) +17:17:24.876 [main] DEBUG c.i.d.App com.iluwatar.daofactory.App - Flat file - Create customer +17:17:24.895 [main] DEBUG c.i.d.App com.iluwatar.daofactory.App - Customer(id=1, name=Duc) +17:17:24.895 [main] DEBUG c.i.d.App com.iluwatar.daofactory.App - Customer(id=2, name=Quang) +17:17:24.895 [main] DEBUG c.i.d.App com.iluwatar.daofactory.App - Customer(id=3, name=Nhat) +17:17:24.895 [main] DEBUG c.i.d.App com.iluwatar.daofactory.App - Flat file - Update customer +17:17:24.897 [main] DEBUG c.i.d.App com.iluwatar.daofactory.App - Customer(id=1, name=Thanh) +17:17:24.897 [main] DEBUG c.i.d.App com.iluwatar.daofactory.App - Customer(id=2, name=Quang) +17:17:24.897 [main] DEBUG c.i.d.App com.iluwatar.daofactory.App - Customer(id=3, name=Nhat) +17:17:24.897 [main] DEBUG c.i.d.App com.iluwatar.daofactory.App - Flat file - Delete customer +17:17:24.898 [main] DEBUG c.i.d.App com.iluwatar.daofactory.App - Customer(id=1, name=Thanh) +17:17:24.898 [main] DEBUG c.i.d.App com.iluwatar.daofactory.App - Customer(id=2, name=Quang) +``` +## When to Use the Data Access Object Factory Pattern in Java + +Use the DAO Factory Pattern when: + +* The application needs to support multiple types of storage (RDBMS, NoSQL, file system, etc.) with minimal changes to business logic. +* You want to abstract and isolate persistence logic from the core application logic. +* You aim to make your data access layer pluggable and easy to extend with new storage technologies. +* You want to enable easier unit testing and dependency injection by providing mock implementations of DAOs. +* Runtime configuration (e.g., via environment variables or application settings) determines which data source to use. + +## Data Access Object Factory Pattern Java Tutorials + +* [Core J2EE Patterns - Data Access Object (Oracle)](https://www.oracle.com/java/technologies/dataaccessobject.html) +* [DAO Factories: Java Design Patterns (Youtube)](https://www.youtube.com/watch?v=5HGe9s9qM-o) +* [Java Design Patterns and Architecture (CaveofProgramming)](https://caveofprogramming.teachable.com/courses/2084/lectures/39549) + +## Real-World Applications of Data Access Object Factory Pattern in Java + +* Enterprise Java Applications: Where switching between test, dev, and production databases is common (e.g., MySQL ↔ MongoDB ↔ In-Memory). +* Spring Data JPA & Repository Abstraction: Though Spring provides its own abstraction, the concept is similar to DAO factory for modular and pluggable persistence. +* Microservices with Varying Storage Backends: Different microservices might store data in SQL, NoSQL, or even flat files; using a DAO Factory per service ensures consistency. +* Data Integration Tools: Tools that support importing/exporting from various formats (CSV, JSON, databases) often use DAO factories behind the scenes. +* Framework-Level Implementations: Custom internal frameworks where persistence layers need to support multiple database types. + +## Benefits and Trade-offs of Data Access Object Factory Pattern + +Benefits: + +* Abstraction of Data Source Logic: Client code interacts only with DAO interfaces, completely decoupled from how and where the data is stored. +* Flexibility in Persistence Strategy: Easily switch between databases (e.g., H2, MongoDB, flat files) by changing the factory configuration. +* Improved Maintainability: Storage logic for each data source is encapsulated within its own DAO implementation and factory, making it easier to update or extend. +* Code Reusability: Common data access logic (e.g., CRUD operations) can be reused across different implementations and projects. +* Testability: DAOs and factories can be mocked or stubbed easily, which supports unit testing and dependency injection. + +Trade-offs: +* Increased Complexity: Introducing abstract DAOs and multiple factory classes adds structural complexity to the codebase. +* Boilerplate Code: Requires defining many interfaces and implementations, even for simple data access needs. +* Less Transparent Behavior: Since clients access DAOs indirectly via factories, understanding the concrete data source behavior may require deeper inspection. + +## Related Java Design Patterns + +* [Factory Method](https://java-design-patterns.com/patterns/factory-method/): DAO Factory is a concrete application of the Factory Pattern, used to create DAO objects in a flexible way. +* [Abstract Factory](https://java-design-patterns.com/patterns/abstract-factory/): When supporting multiple data sources (e.g., MySQLDAO, OracleDAO), DAO Factory can act as an Abstract Factory. +* [Data Access Object (DAO)](https://java-design-patterns.com/patterns/data-access-object/): The core pattern managed by DAO Factory, it separates data access logic from business logic. +* [Singleton](https://java-design-patterns.com/patterns/singleton/): DAO Factory is often implemented as a Singleton to ensure only one instance manages DAO creation. +* [Service Locator](https://java-design-patterns.com/patterns/service-locator/): Can be used alongside DAO Factory to retrieve DAO services efficiently. +* [Dependency Injection](https://java-design-patterns.com/patterns/dependency-injection/): In frameworks like Spring, DAOs are typically injected into the service layer instead of being retrieved from a factory. + + +## References and Credits + +* [DAO Factory - J2EE Design Patterns Book](https://www.oreilly.com/library/view/j2ee-design-patterns/0596004273/re15.html) +* [DAO Factory patterns with Hibernate](http://www.giuseppeurso.eu/en/dao-factory-patterns-with-hibernate/) +* [Design Patterns - Java Means DURGA SOFT](https://www.scribd.com/document/407219980/2-DAO-Factory-Design-Pattern) +* [Generic DAO pattern - Hibernate](https://in.relation.to/2005/09/09/generic-dao-pattern-with-jdk-50/) + \ No newline at end of file diff --git a/dao-factory/etc/dao-factory.png b/dao-factory/etc/dao-factory.png new file mode 100644 index 0000000000000000000000000000000000000000..d93547d799575ecf42efa9c27aac4e16c437723b GIT binary patch literal 113583 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 { + T id + String name + } + + interface CustomerDAO { + void save(Customer customer) + void update(Customer customer) + void delete(ID id) + List> findAll() + Optional> findById(ID id) + void deleteSchema() + } + + abstract class DAOFactory { + {static} DAOFactory getDataSource(DataSourceType dataType) + {abstract} CustomerDAO createCustomerDAO() + } + + enum DataSourceType { + H2 + Mongo + FlatFile + } + + class FlatFileCustomerDAO implements CustomerDAO { + void save(Customer customer) + void update(Customer customer) + void delete(Long id) + List> findAll() + Optional> findById(Long id) + void deleteSchema() + } + + class H2CustomerDAO implements CustomerDAO { + void save(Customer customer) + void update(Customer customer) + void delete(Long id) + List> findAll() + Optional> findById(Long id) + void deleteSchema() + } + + class FlatFileDataSourceFactory extends DAOFactory { + CustomerDAO createCustomerDAO() + } + + class H2DataSourceFactory extends DAOFactory { + CustomerDAO createCustomerDAO() + } + + class MongoCustomerDAO implements CustomerDAO { + void save(Customer customer) + void update(Customer customer) + void delete(ObjectId id) + List> findAll() + Optional> findById(ObjectId id) + void deleteSchema() + } + class MongoDataSourceFactory extends DAOFactory { + CustomerDAO createCustomerDAO() + } + + DataSourceType ..+ DAOFactory + DAOFactory ..+ App + App --> Customer + } +@enduml \ No newline at end of file diff --git a/dao-factory/pom.xml b/dao-factory/pom.xml new file mode 100644 index 000000000000..2e771e736688 --- /dev/null +++ b/dao-factory/pom.xml @@ -0,0 +1,82 @@ + + + + 4.0.0 + + com.iluwatar + java-design-patterns + 1.26.0-SNAPSHOT + + + dao-factory + + + 21 + 21 + UTF-8 + + + + + com.h2database + h2 + + + + org.slf4j + slf4j-api + + + ch.qos.logback + logback-classic + + + org.mongodb + mongodb-driver-legacy + + + com.google.code.gson + gson + + + + org.junit.jupiter + junit-jupiter-engine + test + + + + org.mockito + mockito-core + test + + + + \ No newline at end of file diff --git a/dao-factory/src/main/java/com/iluwatar/daofactory/App.java b/dao-factory/src/main/java/com/iluwatar/daofactory/App.java new file mode 100644 index 000000000000..b80d3c5ac56a --- /dev/null +++ b/dao-factory/src/main/java/com/iluwatar/daofactory/App.java @@ -0,0 +1,124 @@ +/* + * 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.daofactory; + +import java.io.Serializable; +import java.util.List; +import lombok.extern.slf4j.Slf4j; +import org.bson.types.ObjectId; + +@Slf4j +public class App { + + public static void main(String[] args) { + var daoFactory = DAOFactoryProvider.getDataSource(DataSourceType.H2); + CustomerDAO customerDAO = daoFactory.createCustomerDAO(); + + // Perform CRUD H2 Database + if (customerDAO instanceof H2CustomerDAO h2CustomerDAO) { + h2CustomerDAO.deleteSchema(); + h2CustomerDAO.createSchema(); + } + Customer customerInmemory1 = new Customer<>(1L, "Green"); + Customer customerInmemory2 = new Customer<>(2L, "Red"); + Customer customerInmemory3 = new Customer<>(3L, "Blue"); + Customer customerUpdateInmemory = new Customer<>(1L, "Yellow"); + + LOGGER.debug("H2 - Create customer"); + performCreateCustomer( + customerDAO, List.of(customerInmemory1, customerInmemory2, customerInmemory3)); + LOGGER.debug("H2 - Update customer"); + performUpdateCustomer(customerDAO, customerUpdateInmemory); + LOGGER.debug("H2 - Delete customer"); + performDeleteCustomer(customerDAO, 3L); + deleteSchema(customerDAO); + + // Perform CRUD MongoDb + daoFactory = DAOFactoryProvider.getDataSource(DataSourceType.MONGO); + customerDAO = daoFactory.createCustomerDAO(); + ObjectId idCustomerMongo1 = new ObjectId(); + ObjectId idCustomerMongo2 = new ObjectId(); + Customer customer4 = new Customer<>(idCustomerMongo1, "Masca"); + Customer customer5 = new Customer<>(idCustomerMongo2, "Elliot"); + Customer customerUpdateMongo = new Customer<>(idCustomerMongo2, "Henry"); + + LOGGER.debug("Mongo - Create customer"); + performCreateCustomer(customerDAO, List.of(customer4, customer5)); + LOGGER.debug("Mongo - Update customer"); + performUpdateCustomer(customerDAO, customerUpdateMongo); + LOGGER.debug("Mongo - Delete customer"); + performDeleteCustomer(customerDAO, idCustomerMongo2); + deleteSchema(customerDAO); + + // Perform CRUD Flat file + daoFactory = DAOFactoryProvider.getDataSource(DataSourceType.FLAT_FILE); + customerDAO = daoFactory.createCustomerDAO(); + Customer customerFlatFile1 = new Customer<>(1L, "Duc"); + Customer customerFlatFile2 = new Customer<>(2L, "Quang"); + Customer customerFlatFile3 = new Customer<>(3L, "Nhat"); + Customer customerUpdateFlatFile = new Customer<>(1L, "Thanh"); + LOGGER.debug("Flat file - Create customer"); + performCreateCustomer( + customerDAO, List.of(customerFlatFile1, customerFlatFile2, customerFlatFile3)); + LOGGER.debug("Flat file - Update customer"); + performUpdateCustomer(customerDAO, customerUpdateFlatFile); + LOGGER.debug("Flat file - Delete customer"); + performDeleteCustomer(customerDAO, 3L); + deleteSchema(customerDAO); + } + + public static void deleteSchema(CustomerDAO customerDAO) { + customerDAO.deleteSchema(); + } + + public static void performCreateCustomer( + CustomerDAO customerDAO, List> customerList) { + for (Customer customer : customerList) { + customerDAO.save(customer); + } + List> customers = customerDAO.findAll(); + for (Customer customer : customers) { + LOGGER.debug(customer.toString()); + } + } + + public static void performUpdateCustomer( + CustomerDAO customerDAO, Customer customerUpdate) { + customerDAO.update(customerUpdate); + List> customers = customerDAO.findAll(); + for (Customer customer : customers) { + LOGGER.debug(customer.toString()); + } + } + + public static void performDeleteCustomer( + CustomerDAO customerDAO, T customerId) { + customerDAO.delete(customerId); + List> customers = customerDAO.findAll(); + for (Customer customer : customers) { + LOGGER.debug(customer.toString()); + } + } +} diff --git a/dao-factory/src/main/java/com/iluwatar/daofactory/CustomException.java b/dao-factory/src/main/java/com/iluwatar/daofactory/CustomException.java new file mode 100644 index 000000000000..9559e765c7d4 --- /dev/null +++ b/dao-factory/src/main/java/com/iluwatar/daofactory/CustomException.java @@ -0,0 +1,36 @@ +/* + * 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.daofactory; + +/** Customer exception */ +public class CustomException extends RuntimeException { + public CustomException(String message) { + super(message); + } + + public CustomException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/dao-factory/src/main/java/com/iluwatar/daofactory/Customer.java b/dao-factory/src/main/java/com/iluwatar/daofactory/Customer.java new file mode 100644 index 000000000000..95b675487d27 --- /dev/null +++ b/dao-factory/src/main/java/com/iluwatar/daofactory/Customer.java @@ -0,0 +1,47 @@ +/* + * 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.daofactory; + +import java.io.Serializable; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; + +/** + * A customer generic POJO that represents the data that can be stored in any supported data source. + * This class is designed t work with various ID types (e.g., Long, String, or ObjectId) through + * generic, making it adaptable to different persistence system. + */ +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@ToString +public class Customer implements Serializable { + private T id; + private String name; +} diff --git a/dao-factory/src/main/java/com/iluwatar/daofactory/CustomerDAO.java b/dao-factory/src/main/java/com/iluwatar/daofactory/CustomerDAO.java new file mode 100644 index 000000000000..34316b4c49af --- /dev/null +++ b/dao-factory/src/main/java/com/iluwatar/daofactory/CustomerDAO.java @@ -0,0 +1,85 @@ +/* + * 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.daofactory; + +import java.io.Serializable; +import java.util.List; +import java.util.Optional; + +/** + * The Data Access Object (DAO) pattern provides an abstraction layer between the application and + * the database. It encapsulates data access logic, allowing the application to work with domain + * objects instead of direct database operations. + * + *

Implementations handle specific storage mechanisms (e.g., in-memory, databases) while keeping + * client code unchanged. + * + * @see H2CustomerDAO + * @see MongoCustomerDAO + * @see FlatFileCustomerDAO + */ +public interface CustomerDAO { + /** + * Persist the given customer + * + * @param customer the customer to persist + */ + void save(Customer customer); + + /** + * Update the given customer + * + * @param customer the customer to update + */ + void update(Customer customer); + + /** + * Delete the customer with the given id + * + * @param id the id of the customer to delete + */ + void delete(T id); + + /** + * Find all customers + * + * @return a list of customers + */ + List> findAll(); + + /** + * Find the customer with the given id + * + * @param id the id of the customer to find + * @return the customer with the given id + */ + Optional> findById(T id); + + /** + * Delete the customer schema. After executing the statements, this function will be called to + * clean up the data and delete the records. + */ + void deleteSchema(); +} diff --git a/dao-factory/src/main/java/com/iluwatar/daofactory/DAOFactory.java b/dao-factory/src/main/java/com/iluwatar/daofactory/DAOFactory.java new file mode 100644 index 000000000000..e7d33186bec5 --- /dev/null +++ b/dao-factory/src/main/java/com/iluwatar/daofactory/DAOFactory.java @@ -0,0 +1,45 @@ +/* + * 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.daofactory; + +/** + * An abstract factory class that provides a way to create concrete DAO (Data Access Object) + * factories for different data sources types (e.g., H2, Mongo, FlatFile). + * + *

This class follows the Abstract Factory design pattern, allowing applications to retrieve the + * approriate DAO implementation without being tightly coupled to a specific data source. + * + * @see H2DataSourceFactory + * @see MongoDataSourceFactory + * @see FlatFileDataSourceFactory + */ +public abstract class DAOFactory { + /** + * Retrieves a {@link CustomerDAO} implementation specific to the underlying data source.. + * + * @return A data source-specific implementation of {@link CustomerDAO} + */ + public abstract CustomerDAO createCustomerDAO(); +} diff --git a/dao-factory/src/main/java/com/iluwatar/daofactory/DAOFactoryProvider.java b/dao-factory/src/main/java/com/iluwatar/daofactory/DAOFactoryProvider.java new file mode 100644 index 000000000000..08585622d00d --- /dev/null +++ b/dao-factory/src/main/java/com/iluwatar/daofactory/DAOFactoryProvider.java @@ -0,0 +1,62 @@ +/* + * 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.daofactory; + +/** + * {@code DAOFactoryProvider} is a utility class responsible for providing concrete implementations + * of the {@link DAOFactory} interface based on the specified data source type. + * + *

This class acts as an entry point to obtain DAO factories for different storage mechanisms + * such as relational databases (e.g., H2), document stores (e.g., MongoDB), or file-based systems. + * It uses the {@link DataSourceType} enumeration to determine which concrete factory to + * instantiate. + * + *

Example usage: + * + *

{@code
+ * DAOFactory factory = DAOFactoryProvider.getDataSource(DataSourceType.H2);
+ * }
+ */ +public class DAOFactoryProvider { + + private DAOFactoryProvider() {} + + /** + * Returns a concrete {@link DAOFactory} intance based on the specified data source type. + * + * @param dataSourceType The type of data source for which a factory is needed. Supported values: + * {@code H2}, {@code Mongo}, {@code FlatFile} + * @return A {@link DAOFactory} implementation corresponding to the given data source type. + * @throws IllegalArgumentException if the given data source type is not supported. + */ + public static DAOFactory getDataSource(DataSourceType dataSourceType) { + return switch (dataSourceType) { + case H2 -> new H2DataSourceFactory(); + case MONGO -> new MongoDataSourceFactory(); + case FLAT_FILE -> new FlatFileDataSourceFactory(); + default -> throw new IllegalArgumentException("Unsupported data source type"); + }; + } +} diff --git a/dao-factory/src/main/java/com/iluwatar/daofactory/DataSourceType.java b/dao-factory/src/main/java/com/iluwatar/daofactory/DataSourceType.java new file mode 100644 index 000000000000..da01d451f09e --- /dev/null +++ b/dao-factory/src/main/java/com/iluwatar/daofactory/DataSourceType.java @@ -0,0 +1,32 @@ +/* + * 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.daofactory; + +/** Enumerates the types of data sources supported by the application. */ +public enum DataSourceType { + H2, + MONGO, + FLAT_FILE +} diff --git a/dao-factory/src/main/java/com/iluwatar/daofactory/FlatFileCustomerDAO.java b/dao-factory/src/main/java/com/iluwatar/daofactory/FlatFileCustomerDAO.java new file mode 100644 index 000000000000..8f1f1f144f77 --- /dev/null +++ b/dao-factory/src/main/java/com/iluwatar/daofactory/FlatFileCustomerDAO.java @@ -0,0 +1,175 @@ +/* + * 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.daofactory; + +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.io.Reader; +import java.io.Writer; +import java.lang.reflect.Type; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.LinkedList; +import java.util.List; +import java.util.Optional; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * A Flat File implementation of {@link CustomerDAO}, which store the customer data in a JSON file + * at path {@code ~/Desktop/customer.json}. + */ +@Slf4j +@RequiredArgsConstructor +public class FlatFileCustomerDAO implements CustomerDAO { + private final Path filePath; + private final Gson gson; + Type customerListType = new TypeToken>>() {}.getType(); + + protected Reader createReader(Path filePath) throws IOException { + return new FileReader(filePath.toFile()); + } + + protected Writer createWriter(Path filePath) throws IOException { + return new FileWriter(filePath.toFile()); + } + + /** {@inheritDoc} */ + @Override + public void save(Customer customer) { + List> customers = new LinkedList<>(); + if (filePath.toFile().exists()) { + try (Reader reader = createReader(filePath)) { + customers = gson.fromJson(reader, customerListType); + } catch (IOException ex) { + throw new CustomException("Failed to read customer data", ex); + } + } + customers.add(customer); + try (Writer writer = createWriter(filePath)) { + gson.toJson(customers, writer); + } catch (IOException ex) { + throw new CustomException("Failed to write customer data", ex); + } + } + + /** {@inheritDoc} */ + @Override + public void update(Customer customer) { + if (!filePath.toFile().exists()) { + throw new CustomException("File not found"); + } + List> customers; + try (Reader reader = createReader(filePath)) { + customers = gson.fromJson(reader, customerListType); + } catch (IOException ex) { + throw new CustomException("Failed to read customer data", ex); + } + customers.stream() + .filter(c -> c.getId().equals(customer.getId())) + .findFirst() + .ifPresentOrElse( + c -> c.setName(customer.getName()), + () -> { + throw new CustomException("Customer not found with id: " + customer.getId()); + }); + try (Writer writer = createWriter(filePath)) { + gson.toJson(customers, writer); + } catch (IOException ex) { + throw new CustomException("Failed to write customer data", ex); + } + } + + /** {@inheritDoc} */ + @Override + public void delete(Long id) { + if (!filePath.toFile().exists()) { + throw new CustomException("File not found"); + } + List> customers; + try (Reader reader = createReader(filePath)) { + customers = gson.fromJson(reader, customerListType); + } catch (IOException ex) { + throw new CustomException("Failed to read customer data", ex); + } + Customer customerToRemove = + customers.stream() + .filter(c -> c.getId().equals(id)) + .findFirst() + .orElseThrow(() -> new CustomException("Customer not found with id: " + id)); + customers.remove(customerToRemove); + try (Writer writer = createWriter(filePath)) { + gson.toJson(customers, writer); + } catch (IOException ex) { + throw new CustomException("Failed to write customer data", ex); + } + } + + /** {@inheritDoc} */ + @Override + public List> findAll() { + if (!filePath.toFile().exists()) { + throw new CustomException("File not found"); + } + List> customers; + try (Reader reader = createReader(filePath)) { + customers = gson.fromJson(reader, customerListType); + } catch (IOException ex) { + throw new CustomException("Failed to read customer data", ex); + } + return customers; + } + + /** {@inheritDoc} */ + @Override + public Optional> findById(Long id) { + if (!filePath.toFile().exists()) { + throw new CustomException("File not found"); + } + List> customers = null; + try (Reader reader = createReader(filePath)) { + customers = gson.fromJson(reader, customerListType); + } catch (IOException ex) { + throw new CustomException("Failed to read customer data", ex); + } + return customers.stream().filter(c -> c.getId().equals(id)).findFirst(); + } + + /** {@inheritDoc} */ + @Override + public void deleteSchema() { + if (!filePath.toFile().exists()) { + throw new CustomException("File not found"); + } + try { + Files.delete(filePath); + } catch (IOException ex) { + throw new CustomException("Failed to delete customer data"); + } + } +} diff --git a/dao-factory/src/main/java/com/iluwatar/daofactory/FlatFileDataSourceFactory.java b/dao-factory/src/main/java/com/iluwatar/daofactory/FlatFileDataSourceFactory.java new file mode 100644 index 000000000000..f423376703b5 --- /dev/null +++ b/dao-factory/src/main/java/com/iluwatar/daofactory/FlatFileDataSourceFactory.java @@ -0,0 +1,43 @@ +/* + * 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.daofactory; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import java.nio.file.Path; +import java.nio.file.Paths; + +/** FlatFileDataSourceFactory concrete factory. */ +public class FlatFileDataSourceFactory extends DAOFactory { + private static final String FILE_PATH = + System.getProperty("user.home") + "/Desktop/customer.json"; + + @Override + public CustomerDAO createCustomerDAO() { + Path filePath = Paths.get(FILE_PATH); + Gson gson = new GsonBuilder().setPrettyPrinting().serializeNulls().create(); + return new FlatFileCustomerDAO(filePath, gson); + } +} diff --git a/dao-factory/src/main/java/com/iluwatar/daofactory/H2CustomerDAO.java b/dao-factory/src/main/java/com/iluwatar/daofactory/H2CustomerDAO.java new file mode 100644 index 000000000000..fe027426391c --- /dev/null +++ b/dao-factory/src/main/java/com/iluwatar/daofactory/H2CustomerDAO.java @@ -0,0 +1,179 @@ +/* + * 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.daofactory; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.LinkedList; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import javax.sql.DataSource; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/** + * An implementation of {@link CustomerDAO} that uses H2 database (http://www.h2database.com/) which + * is an in-memory database and data will lost after application exits. + */ +@Slf4j +@RequiredArgsConstructor +public class H2CustomerDAO implements CustomerDAO { + private final DataSource dataSource; + private static final String INSERT_CUSTOMER = "INSERT INTO customer(id, name) VALUES (?, ?)"; + private static final String UPDATE_CUSTOMER = "UPDATE customer SET name = ? WHERE id = ?"; + private static final String DELETE_CUSTOMER = "DELETE FROM customer WHERE id = ?"; + private static final String SELECT_CUSTOMER_BY_ID = + "SELECT customer.id, customer.name FROM customer WHERE id= ?"; + private static final String SELECT_ALL_CUSTOMERS = "SELECT customer.* FROM customer"; + private static final String CREATE_SCHEMA = + "CREATE TABLE IF NOT EXISTS customer (id BIGINT PRIMARY KEY, name VARCHAR(255))"; + private static final String DROP_SCHEMA = "DROP TABLE IF EXISTS customer"; + + /** {@inheritDoc} */ + @Override + public void save(Customer customer) { + try (Connection connection = dataSource.getConnection(); + PreparedStatement saveStatement = connection.prepareStatement(INSERT_CUSTOMER)) { + saveStatement.setLong(1, customer.getId()); + saveStatement.setString(2, customer.getName()); + saveStatement.execute(); + } catch (SQLException e) { + throw new CustomException(e.getMessage(), e); + } + } + + /** {@inheritDoc} */ + @Override + public void update(Customer customer) { + if (Objects.isNull(customer) || Objects.isNull(customer.getId())) { + throw new CustomException("Custome null or customer id null"); + } + try (Connection connection = dataSource.getConnection(); + PreparedStatement selectStatement = connection.prepareStatement(SELECT_CUSTOMER_BY_ID); + PreparedStatement updateStatement = connection.prepareStatement(UPDATE_CUSTOMER)) { + selectStatement.setLong(1, customer.getId()); + try (ResultSet resultSet = selectStatement.executeQuery()) { + if (!resultSet.next()) { + throw new CustomException("Customer not found with id: " + customer.getId()); + } + } + updateStatement.setString(1, customer.getName()); + updateStatement.setLong(2, customer.getId()); + updateStatement.executeUpdate(); + } catch (SQLException e) { + throw new CustomException(e.getMessage(), e); + } + } + + /** {@inheritDoc} */ + @Override + public void delete(Long id) { + if (Objects.isNull(id)) { + throw new CustomException("Customer id null"); + } + try (Connection connection = dataSource.getConnection(); + PreparedStatement selectStatement = connection.prepareStatement(SELECT_CUSTOMER_BY_ID); + PreparedStatement deleteStatement = connection.prepareStatement(DELETE_CUSTOMER)) { + selectStatement.setLong(1, id); + try (ResultSet resultSet = selectStatement.executeQuery()) { + if (!resultSet.next()) { + throw new CustomException("Customer not found with id: " + id); + } + } + deleteStatement.setLong(1, id); + deleteStatement.execute(); + } catch (SQLException e) { + throw new CustomException(e.getMessage(), e); + } + } + + /** {@inheritDoc} */ + @Override + public List> findAll() { + List> customers = new LinkedList<>(); + try (Connection connection = dataSource.getConnection(); + PreparedStatement selectStatement = connection.prepareStatement(SELECT_ALL_CUSTOMERS)) { + try (ResultSet resultSet = selectStatement.executeQuery()) { + while (resultSet.next()) { + Long idCustomer = resultSet.getLong("id"); + String nameCustomer = resultSet.getString("name"); + customers.add(new Customer<>(idCustomer, nameCustomer)); + } + } + } catch (SQLException e) { + throw new CustomException(e.getMessage(), e); + } + return customers; + } + + /** {@inheritDoc} */ + @Override + public Optional> findById(Long id) { + if (Objects.isNull(id)) { + throw new CustomException("Customer id null"); + } + Customer customer = null; + try (Connection connection = dataSource.getConnection(); + PreparedStatement selectByIdStatement = + connection.prepareStatement(SELECT_CUSTOMER_BY_ID)) { + selectByIdStatement.setLong(1, id); + try (ResultSet resultSet = selectByIdStatement.executeQuery()) { + while (resultSet.next()) { + Long idCustomer = resultSet.getLong("id"); + String nameCustomer = resultSet.getString("name"); + customer = new Customer<>(idCustomer, nameCustomer); + } + } + } catch (SQLException e) { + throw new CustomException(e.getMessage(), e); + } + return Optional.ofNullable(customer); + } + + /** Create customer schema. */ + public void createSchema() { + try (Connection connection = dataSource.getConnection(); + Statement statement = connection.createStatement()) { + statement.execute(CREATE_SCHEMA); + } catch (SQLException e) { + throw new CustomException(e.getMessage(), e); + } + } + + /** {@inheritDoc}} */ + @Override + public void deleteSchema() { + try (Connection connection = dataSource.getConnection(); + Statement statement = connection.createStatement(); ) { + statement.execute(DROP_SCHEMA); + } catch (SQLException e) { + throw new CustomException(e.getMessage(), e); + } + } +} diff --git a/dao-factory/src/main/java/com/iluwatar/daofactory/H2DataSourceFactory.java b/dao-factory/src/main/java/com/iluwatar/daofactory/H2DataSourceFactory.java new file mode 100644 index 000000000000..dbb39dd98f3b --- /dev/null +++ b/dao-factory/src/main/java/com/iluwatar/daofactory/H2DataSourceFactory.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.daofactory; + +import javax.sql.DataSource; +import org.h2.jdbcx.JdbcDataSource; + +/** H2DataSourceFactory concrete factory. */ +public class H2DataSourceFactory extends DAOFactory { + private static final String DB_URL = "jdbc:h2:mem:test;DB_CLOSE_DELAY=-1"; + private static final String USER = "sa"; + private static final String PASS = ""; + + @Override + public CustomerDAO createCustomerDAO() { + return new H2CustomerDAO(createDataSource()); + } + + private DataSource createDataSource() { + var dataSource = new JdbcDataSource(); + dataSource.setURL(DB_URL); + dataSource.setUser(USER); + dataSource.setPassword(PASS); + return dataSource; + } +} diff --git a/dao-factory/src/main/java/com/iluwatar/daofactory/MongoCustomerDAO.java b/dao-factory/src/main/java/com/iluwatar/daofactory/MongoCustomerDAO.java new file mode 100644 index 000000000000..1870f61e85fd --- /dev/null +++ b/dao-factory/src/main/java/com/iluwatar/daofactory/MongoCustomerDAO.java @@ -0,0 +1,106 @@ +/* + * 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.daofactory; + +import com.mongodb.client.FindIterable; +import com.mongodb.client.MongoCollection; +import com.mongodb.client.model.Filters; +import com.mongodb.client.model.Updates; +import com.mongodb.client.result.DeleteResult; +import java.util.LinkedList; +import java.util.List; +import java.util.Optional; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.bson.Document; +import org.bson.conversions.Bson; +import org.bson.types.ObjectId; + +/** An implementation of {@link CustomerDAO} that uses MongoDB (https://www.mongodb.com/) */ +@Slf4j +@RequiredArgsConstructor +public class MongoCustomerDAO implements CustomerDAO { + private final MongoCollection customerCollection; + + /** {@inheritDoc} */ + @Override + public void save(Customer customer) { + Document customerDocument = new Document("_id", customer.getId()); + customerDocument.append("name", customer.getName()); + customerCollection.insertOne(customerDocument); + } + + /** {@inheritDoc} */ + @Override + public void update(Customer customer) { + Document updateQuery = new Document("_id", customer.getId()); + Bson update = Updates.set("name", customer.getName()); + customerCollection.updateOne(updateQuery, update); + } + + /** {@inheritDoc} */ + @Override + public void delete(ObjectId objectId) { + Bson deleteQuery = Filters.eq("_id", objectId); + DeleteResult deleteResult = customerCollection.deleteOne(deleteQuery); + if (deleteResult.getDeletedCount() == 0) { + throw new CustomException("Delete failed: No document found with id: " + objectId); + } + } + + /** {@inheritDoc} */ + @Override + public List> findAll() { + List> customers = new LinkedList<>(); + FindIterable customerDocuments = customerCollection.find(); + for (Document customerDocument : customerDocuments) { + Customer customer = + new Customer<>( + (ObjectId) customerDocument.get("_id"), customerDocument.getString("name")); + customers.add(customer); + } + return customers; + } + + /** {@inheritDoc} */ + @Override + public Optional> findById(ObjectId objectId) { + Bson filter = Filters.eq("_id", objectId); + Document customerDocument = customerCollection.find(filter).first(); + Customer customerResult = null; + if (customerDocument != null) { + customerResult = + new Customer<>( + (ObjectId) customerDocument.get("_id"), customerDocument.getString("name")); + } + return Optional.ofNullable(customerResult); + } + + /** {@inheritDoc} */ + @Override + public void deleteSchema() { + customerCollection.drop(); + } +} diff --git a/dao-factory/src/main/java/com/iluwatar/daofactory/MongoDataSourceFactory.java b/dao-factory/src/main/java/com/iluwatar/daofactory/MongoDataSourceFactory.java new file mode 100644 index 000000000000..5a7b1f1b1ece --- /dev/null +++ b/dao-factory/src/main/java/com/iluwatar/daofactory/MongoDataSourceFactory.java @@ -0,0 +1,51 @@ +/* + * 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.daofactory; + +import com.mongodb.client.MongoClient; +import com.mongodb.client.MongoClients; +import com.mongodb.client.MongoCollection; +import com.mongodb.client.MongoDatabase; +import org.bson.Document; +import org.bson.types.ObjectId; + +/** MongoDataSourceFactory concrete factory. */ +public class MongoDataSourceFactory extends DAOFactory { + private static final String CONN_STR = "mongodb://localhost:27017/"; + private static final String DB_NAME = "dao_factory"; + private static final String COLLECTION_NAME = "customer"; + + @Override + public CustomerDAO createCustomerDAO() { + try { + MongoClient mongoClient = MongoClients.create(CONN_STR); + MongoDatabase database = mongoClient.getDatabase(DB_NAME); + MongoCollection customerCollection = database.getCollection(COLLECTION_NAME); + return new MongoCustomerDAO(customerCollection); + } catch (CustomException e) { + throw new CustomException("Error: " + e); + } + } +} diff --git a/dao-factory/src/main/resources/logback.xml b/dao-factory/src/main/resources/logback.xml new file mode 100644 index 000000000000..f82341ebb2ab --- /dev/null +++ b/dao-factory/src/main/resources/logback.xml @@ -0,0 +1,12 @@ + + + + %d{HH:mm:ss.SSS} [%thread] %highlight(%-5level) %cyan(%logger{15}) %logger{36} - %msg%n + + + + + + + + \ No newline at end of file diff --git a/dao-factory/src/test/java/com/iluwatar/daofactory/AppTest.java b/dao-factory/src/test/java/com/iluwatar/daofactory/AppTest.java new file mode 100644 index 000000000000..12efea42bdc6 --- /dev/null +++ b/dao-factory/src/test/java/com/iluwatar/daofactory/AppTest.java @@ -0,0 +1,94 @@ +/* + * 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.daofactory; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.List; +import org.bson.types.ObjectId; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +/** {@link App} */ +class AppTest { + /** Test perform CRUD in main class */ + private CustomerDAO mockLongCustomerDAO; + + private CustomerDAO mockObjectIdCustomerDAO; + + @BeforeEach + void setUp() { + mockLongCustomerDAO = mock(CustomerDAO.class); + mockObjectIdCustomerDAO = mock(CustomerDAO.class); + } + + @Test + void testPerformCreateCustomerWithLongId() { + Customer c1 = new Customer<>(1L, "Test1"); + Customer c2 = new Customer<>(2L, "Test2"); + + when(mockLongCustomerDAO.findAll()).thenReturn(List.of(c1, c2)); + + App.performCreateCustomer(mockLongCustomerDAO, List.of(c1, c2)); + + verify(mockLongCustomerDAO).save(c1); + verify(mockLongCustomerDAO).save(c2); + verify(mockLongCustomerDAO).findAll(); + } + + @Test + void testPerformUpdateCustomerWithObjectId() { + ObjectId id = new ObjectId(); + Customer updatedCustomer = new Customer<>(id, "Updated"); + + when(mockObjectIdCustomerDAO.findAll()).thenReturn(List.of(updatedCustomer)); + + App.performUpdateCustomer(mockObjectIdCustomerDAO, updatedCustomer); + + verify(mockObjectIdCustomerDAO).update(updatedCustomer); + verify(mockObjectIdCustomerDAO).findAll(); + } + + @Test + void testPerformDeleteCustomerWithLongId() { + Long id = 100L; + Customer remainingCustomer = new Customer<>(1L, "Remaining"); + + when(mockLongCustomerDAO.findAll()).thenReturn(List.of(remainingCustomer)); + + App.performDeleteCustomer(mockLongCustomerDAO, id); + + verify(mockLongCustomerDAO).delete(id); + verify(mockLongCustomerDAO).findAll(); + } + + @Test + void testDeleteSchema() { + App.deleteSchema(mockLongCustomerDAO); + verify(mockLongCustomerDAO).deleteSchema(); + } +} diff --git a/dao-factory/src/test/java/com/iluwatar/daofactory/DAOFactoryTest.java b/dao-factory/src/test/java/com/iluwatar/daofactory/DAOFactoryTest.java new file mode 100644 index 000000000000..f8aaf199762d --- /dev/null +++ b/dao-factory/src/test/java/com/iluwatar/daofactory/DAOFactoryTest.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.daofactory; + +import static org.junit.jupiter.api.Assertions.assertInstanceOf; + +import org.junit.jupiter.api.Test; + +/** {@link DAOFactory} */ +class DAOFactoryTest { + + @Test + void verifyH2CustomerDAOCreation() { + var daoFactory = DAOFactoryProvider.getDataSource(DataSourceType.H2); + var customerDAO = daoFactory.createCustomerDAO(); + assertInstanceOf(H2CustomerDAO.class, customerDAO); + } + + @Test + void verifyMongoCustomerDAOCreation() { + var daoFactory = DAOFactoryProvider.getDataSource(DataSourceType.MONGO); + var customerDAO = daoFactory.createCustomerDAO(); + assertInstanceOf(MongoCustomerDAO.class, customerDAO); + } + + @Test + void verifyFlatFileCustomerDAOCreation() { + var daoFactory = DAOFactoryProvider.getDataSource(DataSourceType.FLAT_FILE); + var customerDAO = daoFactory.createCustomerDAO(); + assertInstanceOf(FlatFileCustomerDAO.class, customerDAO); + } +} diff --git a/dao-factory/src/test/java/com/iluwatar/daofactory/FlatFileCustomerDAOTest.java b/dao-factory/src/test/java/com/iluwatar/daofactory/FlatFileCustomerDAOTest.java new file mode 100644 index 000000000000..470964f4217a --- /dev/null +++ b/dao-factory/src/test/java/com/iluwatar/daofactory/FlatFileCustomerDAOTest.java @@ -0,0 +1,500 @@ +/* + * 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.daofactory; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.io.Reader; +import java.io.Writer; +import java.lang.reflect.Type; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.LinkedList; +import java.util.List; +import java.util.Optional; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.mockito.MockedStatic; + +/** {@link FlatFileCustomerDAO} */ +class FlatFileCustomerDAOTest { + private Path filePath; + private File file; + private Gson gson; + + private final Type customerListType = new TypeToken>>() {}.getType(); + private final Customer existingCustomer = new Customer<>(1L, "Thanh"); + private FlatFileCustomerDAO flatFileCustomerDAO; + private FileReader fileReader; + private FileWriter fileWriter; + + @BeforeEach + void setUp() { + filePath = mock(Path.class); + file = mock(File.class); + gson = mock(Gson.class); + fileReader = mock(FileReader.class); + fileWriter = mock(FileWriter.class); + flatFileCustomerDAO = + new FlatFileCustomerDAO(filePath, gson) { + @Override + protected Reader createReader(Path filePath) throws IOException { + return fileReader; + } + + @Override + protected Writer createWriter(Path filePath) throws IOException { + return fileWriter; + } + }; + when(filePath.toFile()).thenReturn(file); + } + + /** Class test with scenario Save Customer */ + @Nested + class Save { + @Test + void giveFilePathNotExist_whenSaveCustomer_thenCreateNewFileWithCustomer() { + when(file.exists()).thenReturn(false); + flatFileCustomerDAO.save(existingCustomer); + + verify(gson) + .toJson( + argThat( + (List> list) -> + list.size() == 1 && list.getFirst().equals(existingCustomer)), + eq(fileWriter)); + } + + @Test + void givenEmptyFileExist_whenSaveCustomer_thenAddCustomer() { + when(file.exists()).thenReturn(true); + when(gson.fromJson(any(Reader.class), eq(customerListType))).thenReturn(new LinkedList<>()); + flatFileCustomerDAO.save(existingCustomer); + + verify(gson).fromJson(fileReader, customerListType); + verify(gson) + .toJson( + argThat( + (List> list) -> + list.size() == 1 && list.getFirst().equals(existingCustomer)), + eq(fileWriter)); + } + + @Test + void givenFileWithCustomerExist_whenSaveCustomer_thenShouldAppendCustomer() { + List> customers = new LinkedList<>(); + customers.add(new Customer<>(2L, "Duc")); + customers.add(new Customer<>(3L, "Nguyen")); + when(file.exists()).thenReturn(true); + when(gson.fromJson(any(Reader.class), eq(customerListType))).thenReturn(customers); + + flatFileCustomerDAO.save(existingCustomer); + + verify(gson).fromJson(fileReader, customerListType); + verify(gson).toJson(argThat((List> list) -> list.size() == 3), eq(fileWriter)); + } + + @Test + void whenReadFails_thenThrowException() { + flatFileCustomerDAO = + new FlatFileCustomerDAO(filePath, gson) { + @Override + protected Reader createReader(Path filePath) throws IOException { + throw new IOException("Failed to read file"); + } + + @Override + protected Writer createWriter(Path filePath) { + return fileWriter; + } + }; + when(file.exists()).thenReturn(true); + assertThrows(CustomException.class, () -> flatFileCustomerDAO.save(existingCustomer)); + } + + @Test + void whenWriteFails_thenThrowException() { + when(gson.fromJson(any(Reader.class), eq(customerListType))).thenReturn(new LinkedList<>()); + flatFileCustomerDAO = + new FlatFileCustomerDAO(filePath, gson) { + @Override + protected Reader createReader(Path filePath) { + return fileReader; + } + + @Override + protected Writer createWriter(Path filePath) throws IOException { + throw new IOException("Failed to write file"); + } + }; + when(file.exists()).thenReturn(true); + assertThrows(CustomException.class, () -> flatFileCustomerDAO.save(existingCustomer)); + } + } + + /** Class test with scenario Update Customer */ + @Nested + class Update { + @Test + void givenFilePathNotExist_whenUpdateCustomer_thenThrowException() { + when(file.exists()).thenReturn(false); + assertThrows(CustomException.class, () -> flatFileCustomerDAO.update(existingCustomer)); + } + + @Test + void whenReadFails_thenThrowException() { + when(file.exists()).thenReturn(true); + flatFileCustomerDAO = + new FlatFileCustomerDAO(filePath, gson) { + @Override + protected Reader createReader(Path filePath) throws IOException { + throw new IOException("Failed to read file"); + } + + @Override + protected Writer createWriter(Path filePath) throws IOException { + return fileWriter; + } + }; + assertThrows(CustomException.class, () -> flatFileCustomerDAO.update(existingCustomer)); + } + + @Test + void whenWriteFails_thenThrowException() { + when(file.exists()).thenReturn(true); + when(gson.fromJson(any(Reader.class), eq(customerListType))) + .thenReturn( + new LinkedList<>() { + { + add(new Customer<>(1L, "Quang")); + } + }); + flatFileCustomerDAO = + new FlatFileCustomerDAO(filePath, gson) { + @Override + protected Reader createReader(Path filePath) { + return fileReader; + } + + @Override + protected Writer createWriter(Path filePath) throws IOException { + throw new IOException("Failed to write file"); + } + }; + assertThrows(CustomException.class, () -> flatFileCustomerDAO.update(existingCustomer)); + } + + @Test + void givenValidCustomer_whenUpdateCustomer_thenUpdateSucceed() { + when(file.exists()).thenReturn(true); + List> existingListCustomer = new LinkedList<>(); + existingListCustomer.add(new Customer<>(1L, "Quang")); + when(gson.fromJson(any(Reader.class), eq(customerListType))).thenReturn(existingListCustomer); + flatFileCustomerDAO = + new FlatFileCustomerDAO(filePath, gson) { + @Override + protected Reader createReader(Path filePath) { + return fileReader; + } + + @Override + protected Writer createWriter(Path filePath) throws IOException { + return fileWriter; + } + }; + flatFileCustomerDAO.update(existingCustomer); + verify(gson) + .toJson( + argThat( + (List> customers) -> + customers.size() == 1 + && customers.stream() + .anyMatch(c -> c.getId().equals(1L) && c.getName().equals("Thanh"))), + eq(fileWriter)); + } + + @Test + void givenIdCustomerNotExist_whenUpdateCustomer_thenThrowException() { + when(file.exists()).thenReturn(true); + List> existingListCustomer = new LinkedList<>(); + existingListCustomer.add(new Customer<>(2L, "Quang")); + when(gson.fromJson(any(Reader.class), eq(customerListType))).thenReturn(existingListCustomer); + flatFileCustomerDAO = + new FlatFileCustomerDAO(filePath, gson) { + @Override + protected Reader createReader(Path filePath) { + return fileReader; + } + + @Override + protected Writer createWriter(Path filePath) { + return fileWriter; + } + }; + assertThrows(CustomException.class, () -> flatFileCustomerDAO.update(existingCustomer)); + } + } + + /** Class test with scenario Delete Customer */ + @Nested + class Delete { + @Test + void givenFilePathNotExist_whenDeleteCustomer_thenThrowException() { + when(file.exists()).thenReturn(false); + assertThrows(CustomException.class, () -> flatFileCustomerDAO.delete(1L)); + } + + @Test + void whenReadFails_thenThrowException() { + when(file.exists()).thenReturn(true); + flatFileCustomerDAO = + new FlatFileCustomerDAO(filePath, gson) { + @Override + protected Reader createReader(Path filePath) throws IOException { + throw new IOException("Failed to read file"); + } + + @Override + protected Writer createWriter(Path filePath) { + return fileWriter; + } + }; + assertThrows(CustomException.class, () -> flatFileCustomerDAO.delete(1L)); + } + + @Test + void whenWriteFails_thenThrowException() { + when(file.exists()).thenReturn(true); + List> existingListCustomer = new LinkedList<>(); + existingListCustomer.add(new Customer<>(1L, "Quang")); + when(gson.fromJson(any(Reader.class), eq(customerListType))).thenReturn(existingListCustomer); + flatFileCustomerDAO = + new FlatFileCustomerDAO(filePath, gson) { + @Override + protected Reader createReader(Path filePath) { + return fileReader; + } + + @Override + protected Writer createWriter(Path filePath) throws IOException { + throw new IOException("Failed to write file"); + } + }; + assertThrows(CustomException.class, () -> flatFileCustomerDAO.delete(1L)); + } + + @Test + void givenValidId_whenDeleteCustomer_thenDeleteSucceed() { + when(file.exists()).thenReturn(true); + List> existingListCustomer = new LinkedList<>(); + existingListCustomer.add(new Customer<>(1L, "Quang")); + existingListCustomer.add(new Customer<>(2L, "Thanh")); + when(gson.fromJson(any(Reader.class), eq(customerListType))).thenReturn(existingListCustomer); + flatFileCustomerDAO = + new FlatFileCustomerDAO(filePath, gson) { + @Override + protected Reader createReader(Path filePath) { + return fileReader; + } + + @Override + protected Writer createWriter(Path filePath) { + return fileWriter; + } + }; + + flatFileCustomerDAO.delete(1L); + assertEquals(1, existingListCustomer.size()); + verify(gson) + .toJson( + argThat( + (List> customers) -> + customers.stream() + .noneMatch(c -> c.getId().equals(1L) && c.getName().equals("Quang"))), + eq(fileWriter)); + } + + @Test + void givenIdNotExist_whenDeleteCustomer_thenThrowException() { + when(file.exists()).thenReturn(true); + List> existingListCustomer = new LinkedList<>(); + existingListCustomer.add(new Customer<>(1L, "Quang")); + existingListCustomer.add(new Customer<>(2L, "Thanh")); + when(gson.fromJson(any(Reader.class), eq(customerListType))).thenReturn(existingListCustomer); + flatFileCustomerDAO = + new FlatFileCustomerDAO(filePath, gson) { + @Override + protected Reader createReader(Path filePath) { + return fileReader; + } + + @Override + protected Writer createWriter(Path filePath) { + return fileWriter; + } + }; + assertThrows(CustomException.class, () -> flatFileCustomerDAO.delete(3L)); + } + } + + /** Class test with scenario Find All Customer */ + @Nested + class FindAll { + @Test + void givenFileNotExist_thenThrowException() { + when(file.exists()).thenReturn(false); + assertThrows(CustomException.class, () -> flatFileCustomerDAO.findAll()); + } + + @Test + void whenReadFails_thenThrowException() { + when(file.exists()).thenReturn(true); + flatFileCustomerDAO = + new FlatFileCustomerDAO(filePath, gson) { + @Override + protected Reader createReader(Path filePath) throws IOException { + throw new IOException("Failed to read file"); + } + + @Override + protected Writer createWriter(Path filePath) { + return fileWriter; + } + }; + assertThrows(CustomException.class, () -> flatFileCustomerDAO.findAll()); + } + + @Test + void givenEmptyCustomer_thenReturnEmptyList() { + when(file.exists()).thenReturn(true); + when(gson.fromJson(any(Reader.class), eq(customerListType))).thenReturn(new LinkedList<>()); + List> customers = flatFileCustomerDAO.findAll(); + assertEquals(0, customers.size()); + verify(gson).fromJson(fileReader, customerListType); + } + + @Test + void givenCustomerExist_thenReturnCustomerList() { + when(file.exists()).thenReturn(true); + List> existingListCustomer = new LinkedList<>(); + existingListCustomer.add(new Customer<>(1L, "Quang")); + existingListCustomer.add(new Customer<>(2L, "Thanh")); + when(gson.fromJson(any(Reader.class), eq(customerListType))).thenReturn(existingListCustomer); + List> customers = flatFileCustomerDAO.findAll(); + assertEquals(2, customers.size()); + } + } + + /** Class test with scenario Find By Id Customer */ + @Nested + class FindById { + + @Test + void givenFilePathNotExist_whenFindById_thenThrowException() { + when(file.exists()).thenReturn(false); + assertThrows(CustomException.class, () -> flatFileCustomerDAO.findById(1L)); + } + + @Test + void whenReadFails_thenThrowException() { + when(file.exists()).thenReturn(true); + flatFileCustomerDAO = + new FlatFileCustomerDAO(filePath, gson) { + @Override + protected Reader createReader(Path filePath) throws IOException { + throw new IOException("Failed to read file"); + } + + @Override + protected Writer createWriter(Path filePath) { + return fileWriter; + } + }; + assertThrows(CustomException.class, () -> flatFileCustomerDAO.findById(1L)); + } + + @Test + void givenIdCustomerExist_whenFindById_thenReturnCustomer() { + when(file.exists()).thenReturn(true); + List> existingListCustomer = new LinkedList<>(); + existingListCustomer.add(new Customer<>(1L, "Quang")); + existingListCustomer.add(new Customer<>(2L, "Thanh")); + when(gson.fromJson(any(Reader.class), eq(customerListType))).thenReturn(existingListCustomer); + Optional> customer = flatFileCustomerDAO.findById(1L); + assertTrue(customer.isPresent()); + assertEquals("Quang", customer.get().getName()); + } + + @Test + void givenIdCustomerNotExist_whenFindById_thenReturnEmpty() { + when(file.exists()).thenReturn(true); + when(gson.fromJson(any(Reader.class), eq(customerListType))).thenReturn(new LinkedList<>()); + Optional> customers = flatFileCustomerDAO.findById(1L); + assertTrue(customers.isEmpty()); + } + } + + /** Clas test with scenario Delete schema */ + @Nested + class DeleteSchema { + @Test + void givenFilePathExist_thenDeleteFile() { + when(file.exists()).thenReturn(true); + + try (MockedStatic mockedFiles = mockStatic(Files.class)) { + flatFileCustomerDAO.deleteSchema(); + mockedFiles.verify(() -> Files.delete(filePath), times(1)); + } + } + + @Test + void givenFilePathNotExist_thenThrowException() { + when(file.exists()).thenReturn(false); + + try (MockedStatic mockedFiles = mockStatic(Files.class)) { + assertThrows(CustomException.class, () -> flatFileCustomerDAO.deleteSchema()); + mockedFiles.verify(() -> Files.delete(filePath), times(0)); + } + } + } +} diff --git a/dao-factory/src/test/java/com/iluwatar/daofactory/H2CustomerDAOTest.java b/dao-factory/src/test/java/com/iluwatar/daofactory/H2CustomerDAOTest.java new file mode 100644 index 000000000000..ce7def36e5bc --- /dev/null +++ b/dao-factory/src/test/java/com/iluwatar/daofactory/H2CustomerDAOTest.java @@ -0,0 +1,300 @@ +/* + * 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.daofactory; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.util.List; +import javax.sql.DataSource; +import org.h2.jdbcx.JdbcDataSource; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +/** Tests {@link H2CustomerDAO} */ +class H2CustomerDAOTest { + private static final String DB_URL = "jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1"; + private static final String USER = "sa"; + private static final String PASS = ""; + private static final String CREATE_SCHEMA = + "CREATE TABLE IF NOT EXISTS customer (id BIGINT PRIMARY KEY, name VARCHAR(255))"; + private static final String DROP_SCHEMA = "DROP TABLE IF EXISTS customer"; + private final Customer existingCustomer = new Customer<>(1L, "Nguyen"); + private H2CustomerDAO h2CustomerDAO; + + @BeforeEach + void createSchema() throws SQLException { + try (var connection = DriverManager.getConnection(DB_URL, USER, PASS); + var statement = connection.createStatement()) { + statement.execute(CREATE_SCHEMA); + } + } + + @AfterEach + void deleteSchema() throws SQLException { + try (var connection = DriverManager.getConnection(DB_URL, USER, PASS); + var statement = connection.createStatement()) { + statement.execute(DROP_SCHEMA); + } + } + + /** Class test for scenario connect with datasource succeed */ + @Nested + class ConnectionSucceed { + + @BeforeEach + void setUp() { + var dataSource = new JdbcDataSource(); + dataSource.setURL(DB_URL); + dataSource.setUser(USER); + dataSource.setPassword(PASS); + h2CustomerDAO = new H2CustomerDAO(dataSource); + assertDoesNotThrow(() -> h2CustomerDAO.save(existingCustomer)); + var customer = h2CustomerDAO.findById(existingCustomer.getId()); + assertTrue(customer.isPresent()); + assertEquals(customer.get().getName(), existingCustomer.getName()); + assertEquals(customer.get().getId(), existingCustomer.getId()); + } + + @Nested + class SaveCustomer { + @Test + void givenValidCustomer_whenSaveCustomer_thenAddSucceed() { + var customer = new Customer<>(2L, "Duc"); + assertDoesNotThrow(() -> h2CustomerDAO.save(customer)); + var customerInDb = h2CustomerDAO.findById(customer.getId()); + assertTrue(customerInDb.isPresent()); + assertEquals(customerInDb.get().getName(), customer.getName()); + assertEquals(customerInDb.get().getId(), customer.getId()); + List> customers = h2CustomerDAO.findAll(); + assertEquals(2, customers.size()); + } + + @Test + void givenIdCustomerDuplicated_whenSaveCustomer_thenThrowException() { + var customer = new Customer<>(existingCustomer.getId(), "Duc"); + assertThrows(CustomException.class, () -> h2CustomerDAO.save(customer)); + List> customers = h2CustomerDAO.findAll(); + assertEquals(1, customers.size()); + } + } + + @Nested + class UpdateCustomer { + @Test + void givenValidCustomer_whenUpdateCustomer_thenUpdateSucceed() { + var customerUpdate = new Customer<>(existingCustomer.getId(), "Duc"); + assertDoesNotThrow(() -> h2CustomerDAO.update(customerUpdate)); + var customerInDb = h2CustomerDAO.findById(customerUpdate.getId()); + assertTrue(customerInDb.isPresent()); + assertEquals(customerInDb.get().getName(), customerUpdate.getName()); + } + + @Test + void givenIdCustomerNotExist_whenUpdateCustomer_thenThrowException() { + var customerUpdate = new Customer<>(100L, "Duc"); + var customerInDb = h2CustomerDAO.findById(customerUpdate.getId()); + assertTrue(customerInDb.isEmpty()); + assertThrows(CustomException.class, () -> h2CustomerDAO.update(customerUpdate)); + } + + @Test + void givenNull_whenUpdateCustomer_thenThrowException() { + assertThrows(CustomException.class, () -> h2CustomerDAO.update(null)); + List> customers = h2CustomerDAO.findAll(); + assertEquals(1, customers.size()); + } + } + + @Nested + class DeleteCustomer { + @Test + void givenValidId_whenDeleteCustomer_thenDeleteSucceed() { + assertDoesNotThrow(() -> h2CustomerDAO.delete(existingCustomer.getId())); + var customerInDb = h2CustomerDAO.findById(existingCustomer.getId()); + assertTrue(customerInDb.isEmpty()); + List> customers = h2CustomerDAO.findAll(); + assertEquals(0, customers.size()); + } + + @Test + void givenIdCustomerNotExist_whenDeleteCustomer_thenThrowException() { + var customerInDb = h2CustomerDAO.findById(100L); + assertTrue(customerInDb.isEmpty()); + assertThrows(CustomException.class, () -> h2CustomerDAO.delete(100L)); + List> customers = h2CustomerDAO.findAll(); + assertEquals(1, customers.size()); + assertEquals(existingCustomer.getName(), customers.get(0).getName()); + assertEquals(existingCustomer.getId(), customers.get(0).getId()); + } + + @Test + void givenNull_whenDeleteCustomer_thenThrowException() { + assertThrows(CustomException.class, () -> h2CustomerDAO.delete(null)); + List> customers = h2CustomerDAO.findAll(); + assertEquals(1, customers.size()); + assertEquals(existingCustomer.getName(), customers.get(0).getName()); + } + } + + @Nested + class FindAllCustomers { + @Test + void givenNonCustomerInDb_whenFindAllCustomer_thenReturnEmptyList() { + assertDoesNotThrow(() -> h2CustomerDAO.delete(existingCustomer.getId())); + List> customers = h2CustomerDAO.findAll(); + assertEquals(0, customers.size()); + } + + @Test + void givenCustomerExistInDb_whenFindAllCustomer_thenReturnCustomers() { + List> customers = h2CustomerDAO.findAll(); + assertEquals(1, customers.size()); + assertEquals(existingCustomer.getName(), customers.get(0).getName()); + assertEquals(existingCustomer.getId(), customers.get(0).getId()); + } + } + + @Nested + class FindCustomerById { + @Test + void givenValidId_whenFindById_thenReturnCustomer() { + var customerInDb = h2CustomerDAO.findById(existingCustomer.getId()); + assertTrue(customerInDb.isPresent()); + assertEquals(existingCustomer.getName(), customerInDb.get().getName()); + assertEquals(existingCustomer.getId(), customerInDb.get().getId()); + } + + @Test + void givenIdCustomerNotExist_whenFindById_thenReturnEmpty() { + var customerNotExist = h2CustomerDAO.findById(100L); + assertTrue(customerNotExist.isEmpty()); + } + + @Test + void givenNull_whenFindById_thenThrowException() { + assertThrows(CustomException.class, () -> h2CustomerDAO.findById(null)); + } + } + + @Nested + class CreateSchema { + @Test + void whenCreateSchema_thenNotThrowException() { + assertDoesNotThrow(() -> h2CustomerDAO.createSchema()); + } + } + + @Nested + class DeleteSchema { + @Test + void whenDeleteSchema_thenNotThrowException() { + assertDoesNotThrow(() -> h2CustomerDAO.deleteSchema()); + } + } + } + + /** Class test with scenario connect with data source failed */ + @Nested + class ConnectionFailed { + private static final String EXCEPTION_CAUSE = "Connection not available"; + + @BeforeEach + void setUp() throws SQLException { + h2CustomerDAO = new H2CustomerDAO(mockedDataSource()); + } + + private DataSource mockedDataSource() throws SQLException { + var mockedDataSource = mock(DataSource.class); + var mockedConnection = mock(Connection.class); + var exception = new SQLException(EXCEPTION_CAUSE); + doThrow(exception).when(mockedConnection).prepareStatement(Mockito.anyString()); + doThrow(exception).when(mockedConnection).createStatement(); + doReturn(mockedConnection).when(mockedDataSource).getConnection(); + return mockedDataSource; + } + + @Test + void givenValidCustomer_whenSaveCustomer_thenThrowException() { + var customer = new Customer<>(2L, "Duc"); + CustomException exception = + assertThrows(CustomException.class, () -> h2CustomerDAO.save(customer)); + assertEquals(EXCEPTION_CAUSE, exception.getMessage()); + } + + @Test + void givenValidCustomer_whenUpdateCustomer_thenThrowException() { + var customerUpdate = new Customer<>(existingCustomer.getId(), "Duc"); + CustomException exception = + assertThrows(CustomException.class, () -> h2CustomerDAO.update(customerUpdate)); + assertEquals(EXCEPTION_CAUSE, exception.getMessage()); + } + + @Test + void givenValidId_whenDeleteCustomer_thenThrowException() { + Long idCustomer = existingCustomer.getId(); + CustomException exception = + assertThrows(CustomException.class, () -> h2CustomerDAO.delete(idCustomer)); + assertEquals(EXCEPTION_CAUSE, exception.getMessage()); + } + + @Test + void whenFindAll_thenThrowException() { + CustomException exception = assertThrows(CustomException.class, h2CustomerDAO::findAll); + assertEquals(EXCEPTION_CAUSE, exception.getMessage()); + } + + @Test + void whenFindById_thenThrowException() { + Long idCustomer = existingCustomer.getId(); + CustomException exception = + assertThrows(CustomException.class, () -> h2CustomerDAO.findById(idCustomer)); + assertEquals(EXCEPTION_CAUSE, exception.getMessage()); + } + + @Test + void whenCreateSchema_thenThrowException() { + CustomException exception = assertThrows(CustomException.class, h2CustomerDAO::createSchema); + assertEquals(EXCEPTION_CAUSE, exception.getMessage()); + } + + @Test + void whenDeleteSchema_thenThrowException() { + CustomException exception = assertThrows(CustomException.class, h2CustomerDAO::deleteSchema); + assertEquals(EXCEPTION_CAUSE, exception.getMessage()); + } + } +} diff --git a/dao-factory/src/test/java/com/iluwatar/daofactory/MongoCustomerDAOTest.java b/dao-factory/src/test/java/com/iluwatar/daofactory/MongoCustomerDAOTest.java new file mode 100644 index 000000000000..c56e72c30389 --- /dev/null +++ b/dao-factory/src/test/java/com/iluwatar/daofactory/MongoCustomerDAOTest.java @@ -0,0 +1,163 @@ +/* + * 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.daofactory; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import com.mongodb.client.FindIterable; +import com.mongodb.client.MongoCollection; +import com.mongodb.client.MongoCursor; +import com.mongodb.client.model.Filters; +import com.mongodb.client.result.DeleteResult; +import com.mongodb.client.result.UpdateResult; +import java.util.List; +import java.util.Optional; +import org.bson.BsonDocument; +import org.bson.Document; +import org.bson.conversions.Bson; +import org.bson.types.ObjectId; +import org.junit.jupiter.api.Test; + +/** Tests {@link MongoCustomerDAO} */ +class MongoCustomerDAOTest { + MongoCollection customerCollection = mock(MongoCollection.class); + MongoCustomerDAO mongoCustomerDAO = new MongoCustomerDAO(customerCollection); + + @Test + void givenValidCustomer_whenSaveCustomer_thenSaveSucceed() { + Customer customer = new Customer<>(new ObjectId(), "John"); + mongoCustomerDAO.save(customer); + verify(customerCollection) + .insertOne( + argThat( + document -> + document.get("_id").equals(customer.getId()) + && document.get("name").equals(customer.getName()))); + } + + @Test + void givenValidCustomer_whenUpdateCustomer_thenUpdateSucceed() { + ObjectId customerId = new ObjectId(); + Customer customerUpdated = new Customer<>(customerId, "John"); + when(customerCollection.updateOne(any(Bson.class), any(Bson.class))) + .thenReturn(UpdateResult.acknowledged(1L, 1L, null)); + mongoCustomerDAO.update(customerUpdated); + verify(customerCollection) + .updateOne( + argThat( + (Bson filter) -> { + Document filterDoc = (Document) filter; + return filterDoc.getObjectId("_id").equals(customerId); + }), + argThat( + (Bson update) -> { + BsonDocument bsonDoc = update.toBsonDocument(); + BsonDocument setDoc = bsonDoc.getDocument("$set"); + return setDoc.getString("name").getValue().equals(customerUpdated.getName()); + })); + } + + @Test + void givenValidObjectId_whenDeleteCustomer_thenDeleteSucceed() { + ObjectId customerId = new ObjectId(); + when(customerCollection.deleteOne(any(Bson.class))).thenReturn(DeleteResult.acknowledged(1)); + mongoCustomerDAO.delete(customerId); + verify(customerCollection) + .deleteOne( + argThat( + (Bson filter) -> { + BsonDocument filterDoc = filter.toBsonDocument(); + return filterDoc.getObjectId("_id").getValue().equals(customerId); + })); + } + + @Test + void givenIdNotExist_whenDeleteCustomer_thenThrowException() { + ObjectId customerId = new ObjectId(); + when(customerCollection.deleteOne(any(Bson.class))).thenReturn(DeleteResult.acknowledged(0)); + assertThrows(CustomException.class, () -> mongoCustomerDAO.delete(customerId)); + verify(customerCollection) + .deleteOne( + argThat( + (Bson filter) -> { + BsonDocument filterDoc = filter.toBsonDocument(); + return filterDoc.getObjectId("_id").getValue().equals(customerId); + })); + } + + @Test + void findAll_thenReturnAllCustomers() { + FindIterable findIterable = mock(FindIterable.class); + MongoCursor cursor = mock(MongoCursor.class); + Document customerDoc1 = new Document("_id", new ObjectId()).append("name", "Duc"); + Document customerDoc2 = new Document("_id", new ObjectId()).append("name", "Thanh"); + when(customerCollection.find()).thenReturn(findIterable); + when(findIterable.iterator()).thenReturn(cursor); + when(cursor.hasNext()).thenReturn(true, true, false); + when(cursor.next()).thenReturn(customerDoc1, customerDoc2); + List> customerList = mongoCustomerDAO.findAll(); + assertEquals(2, customerList.size()); + verify(customerCollection).find(); + } + + @Test + void givenValidId_whenFindById_thenReturnCustomer() { + FindIterable findIterable = mock(FindIterable.class); + ObjectId customerId = new ObjectId(); + String customerName = "Duc"; + Document customerDoc = new Document("_id", customerId).append("name", customerName); + when(customerCollection.find(Filters.eq("_id", customerId))).thenReturn(findIterable); + when(findIterable.first()).thenReturn(customerDoc); + + Optional> customer = mongoCustomerDAO.findById(customerId); + assertTrue(customer.isPresent()); + assertEquals(customerId, customer.get().getId()); + assertEquals(customerName, customer.get().getName()); + } + + @Test + void givenNotExistingId_whenFindById_thenReturnEmpty() { + FindIterable findIterable = mock(FindIterable.class); + ObjectId customerId = new ObjectId(); + when(customerCollection.find(Filters.eq("_id", customerId))).thenReturn(findIterable); + when(findIterable.first()).thenReturn(null); + Optional> customer = mongoCustomerDAO.findById(customerId); + assertTrue(customer.isEmpty()); + verify(customerCollection).find(Filters.eq("_id", customerId)); + } + + @Test + void whenDeleteSchema_thenDeleteCollection() { + mongoCustomerDAO.deleteSchema(); + verify(customerCollection).drop(); + } +} diff --git a/pom.xml b/pom.xml index a7fdcb7064d9..2816ef0ca636 100644 --- a/pom.xml +++ b/pom.xml @@ -107,6 +107,7 @@ converter curiously-recurring-template-pattern currying + dao-factory data-access-object data-bus data-locality From 4caa0bfdbcf7bcb851b66ed6101ac2a0d68d49ac Mon Sep 17 00:00:00 2001 From: Maziyar Gerami <122622721+maziyar-gerami@users.noreply.github.com> Date: Sun, 8 Feb 2026 22:55:16 +0330 Subject: [PATCH 5/8] docs: Persian translation: Abstract Factory (#3280) * Persian Translation: Add persian translation to abstract-document * Persian Translation: Add abstract-document.png to abstract-document folder * Persian Translation: Add codes to README.md of abstract-document * Persian Translation: some improvements in abstract-document * Persian Translation: Add refrence links in abstract-document * Persian Translation: add rtl tag in abstract-document * -added persian translation of factory pattern * -renamed file * -changed wikipedia definition * -fixed table problem * active-object : translate * active-object: improve when to use * active-object: improve when to use * active-object: improve bullets (test) * active-object: improve bullets (test) * active-object: improve bullets (test) * active-object: improve bullets (test) * active-object: improve bullets * active-object: Fix all bullets * -fixed problems in bullet alignments * Update README.md -fixed alignment in bullets * Update README.md -changed tags to English * -added persian translation of factory pattern * -renamed file * -changed wikipedia definition * -fixed table problem * -fixed problems in bullet alignments * Update README.md -fixed alignment in bullets * Update README.md -changed tags to English * abstract-factory: added persian translation * abstract-factory: fixed bullets problems * "Minor improvement Co-authored-by: keivanshir " --------- Co-authored-by: Seyyed Keivan Shirkoubian --- localization/fa/abstract-factory/README.md | 223 ++++++++++++++++++ .../etc/abstract-factory.urm.png | Bin 0 -> 82368 bytes 2 files changed, 223 insertions(+) create mode 100644 localization/fa/abstract-factory/README.md create mode 100644 localization/fa/abstract-factory/etc/abstract-factory.urm.png diff --git a/localization/fa/abstract-factory/README.md b/localization/fa/abstract-factory/README.md new file mode 100644 index 000000000000..85dce3437ba4 --- /dev/null +++ b/localization/fa/abstract-factory/README.md @@ -0,0 +1,223 @@ +--- +title: "الگوی طراحی Abstract Factory در جاوا: مهارت در ایجاد شیء با ظرافت" +shortTitle: Abstract Factory +description: "با مثال‌های دنیای واقعی، دیاگرام‌های کلاس و آموزش‌ها، الگوی Abstract Factory را در جاوا بیاموزید. منظور، کاربرد، مزایا و نمونه‌های واقعی آن را درک کنید و دانش طراحی الگوهایتان را افزایش دهید." +category: Creational +language: fa +tag: + - Abstraction + - Decoupling + - Gang of Four + - Instantiation + - Polymorphism +--- + +## همچنین به این عنوان شناخته می‌شود + +* کیت + +## هدف از الگوی طراحی Abstract Factory + +الگوی Abstract Factory در جاوا یک واسط برای ایجاد خانواده‌هایی از اشیای مرتبط یا وابسته فراهم می‌کند بدون آنکه کلاس‌های مشخص آن‌ها را تعیین کند، و این کار موجب افزایش مدولاریتی و انعطاف‌پذیری در طراحی نرم‌افزار می‌شود. + +## توضیح دقیق الگوی Abstract Factory با مثال‌های دنیای واقعی + +مثال دنیای واقعی + +> تصور کنید یک شرکت مبلمان وجود دارد که از الگوی Abstract Factory در جاوا برای تولید سبک‌های مختلف مبلمان استفاده می‌کند: مدرن، ویکتوریایی و روستایی. هر سبک شامل محصولاتی مانند صندلی‌ها، میزها و کاناپه‌ها است. برای اطمینان از یکنواختی در هر سبک، شرکت از یک الگوی Abstract Factory استفاده می‌کند. +> +> در این سناریو، Abstract Factory یک واسط برای ایجاد خانواده‌هایی از اشیای مبلمان مرتبط (صندلی‌ها، میزها، کاناپه‌ها) است. هر Factory مشخص (کارخانه‌ی مبلمان مدرن، کارخانه‌ی مبلمان ویکتوریایی، کارخانه‌ی مبلمان روستایی) این واسط را پیاده‌سازی می‌کند و مجموعه‌ای از محصولات مطابق با سبک خاص ایجاد می‌کند. به این ترتیب، مشتریان می‌توانند یک مجموعه کامل از مبلمان مدرن یا ویکتوریایی ایجاد کنند بدون اینکه نگران جزئیات ساخت آن‌ها باشند. این باعث حفظ یکنواختی سبک می‌شود و امکان تغییر آسان سبک مبلمان را فراهم می‌کند. + +به زبان ساده + +> کارخانه‌ای از کارخانه‌ها؛ یک Factory یا کارخانه که مجموعه‌ای از کارخانه‌های مرتبط یا وابسته را بدون مشخص کردن کلاس‌های concrete آن‌ها گروه‌بندی می‌کند. + +ویکی‌پدیا می‌گوید + +> الگوی Abstract Factory راهی برای کپسوله کردن مجموعه‌ای از کارخانه‌های منحصر به فرد با یک تم مشترک بدون تعیین کلاس‌های concrete آن‌ها فراهم می‌کند. + +دیاگرام کلاس + +![Abstract Factory class diagram](./etc/abstract-factory.urm.png "Abstract Factory class diagram") + +## مثال برنامه‌نویسی از Abstract Factory در جاوا + +برای ایجاد یک پادشاهی با استفاده از الگوی Abstract Factory در جاوا، ما به اشیایی با یک تم مشترک نیاز داریم. یک پادشاهی اِلف (Elf) به یک پادشاه اِلف، یک قلعه‌ی اِلف، و یک ارتش اِلف نیاز دارد، در حالی که یک پادشاهی اورک (Orc) به یک پادشاه اورک، یک قلعه‌ی اورک، و یک ارتش اورک نیاز دارد. بین اشیای موجود در پادشاهی وابستگی وجود دارد. + +ترجمه‌ی مثال پادشاهی بالا. ابتدا ما برخی واسط‌ها و پیاده‌سازی‌هایی برای اشیای موجود در پادشاهی داریم: + +```java +public interface Castle { + String getDescription(); +} + +public interface King { + String getDescription(); +} + +public interface Army { + String getDescription(); +} + +// Elven implementations -> +public class ElfCastle implements Castle { + static final String DESCRIPTION = "This is the elven castle!"; + + @Override + public String getDescription() { + return DESCRIPTION; + } +} + +public class ElfKing implements King { + static final String DESCRIPTION = "This is the elven king!"; + + @Override + public String getDescription() { + return DESCRIPTION; + } +} + +public class ElfArmy implements Army { + static final String DESCRIPTION = "This is the elven Army!"; + + @Override + public String getDescription() { + return DESCRIPTION; + } +} + +// Orcish implementations similarly -> ... +``` + +سپس واسط و پیاده‌سازی‌های کارخانه‌ی پادشاهی را داریم: + +```java +public interface KingdomFactory { + Castle createCastle(); + King createKing(); + Army createArmy(); +} + +public class ElfKingdomFactory implements KingdomFactory { + + @Override + public Castle createCastle() { + return new ElfCastle(); + } + + @Override + public King createKing() { + return new ElfKing(); + } + + @Override + public Army createArmy() { + return new ElfArmy(); + } +} + +// Orcish implementations similarly -> ... +``` + +اکنون می‌توانیم یک کارخانه برای کارخانه‌های مختلف پادشاهی طراحی کنیم. در این مثال، ما `FactoryMaker` را ایجاد کردیم که مسئول برگرداندن یک نمونه از `ElfKingdomFactory` یا `OrcKingdomFactory` است. مشتری می تواند از `FactoryMaker` برای ایجاد کارخانه concrete مورد نظر استفاده کند که به نوبه خود اشیاء concrete مختلف (مشتق شده از ارتش، پادشاه، قلعه) را تولید می‌کند. در این مثال، ما همچنین از یک enum برای پارامتری کردن نوع کارخانه پادشاهی که مشتری درخواست خواهد کرد استفاده کردیم. + +```java +public static class FactoryMaker { + + public enum KingdomType { + ELF, ORC + } + + public static KingdomFactory makeFactory(KingdomType type) { + return switch (type) { + case ELF -> new ElfKingdomFactory(); + case ORC -> new OrcKingdomFactory(); + }; + } +} +``` + +نمونه‌ای از تابع اصلی برنامه: + +```java +LOGGER.info("elf kingdom"); +createKingdom(Kingdom.FactoryMaker.KingdomType.ELF); +LOGGER.info(kingdom.getArmy().getDescription()); +LOGGER.info(kingdom.getCastle().getDescription()); +LOGGER.info(kingdom.getKing().getDescription()); + +LOGGER.info("orc kingdom"); +createKingdom(Kingdom.FactoryMaker.KingdomType.ORC); +LOGGER.info(kingdom.getArmy().getDescription()); +LOGGER.info(kingdom.getCastle().getDescription()); +LOGGER.info(kingdom.getKing().getDescription()); +``` + +خروجی برنامه: + +``` +07:35:46.340 [main] INFO com.iluwatar.abstractfactory.App -- elf kingdom +07:35:46.343 [main] INFO com.iluwatar.abstractfactory.App -- This is the elven army! +07:35:46.343 [main] INFO com.iluwatar.abstractfactory.App -- This is the elven castle! +07:35:46.343 [main] INFO com.iluwatar.abstractfactory.App -- This is the elven king! +07:35:46.343 [main] INFO com.iluwatar.abstractfactory.App -- orc kingdom +07:35:46.343 [main] INFO com.iluwatar.abstractfactory.App -- This is the orc army! +07:35:46.343 [main] INFO com.iluwatar.abstractfactory.App -- This is the orc castle! +07:35:46.343 [main] INFO com.iluwatar.abstractfactory.App -- This is the orc king! +``` + +## چه زمانی باید از الگوی Abstract Factory در جاوا استفاده کرد؟ + +* زمانی که سیستم باید مستقل از نحوه‌ی ایجاد، ترکیب و نمایش محصولاتش باشد. +* زمانی که نیاز به پیکربندی سیستم با یکی از چند خانواده محصول دارید. +* زمانی که باید خانواده‌ای از اشیای مرتبط با هم استفاده شوند، برای اطمینان از یکنواختی. +* زمانی که می‌خواهید کتابخانه‌ای از محصولات را فراهم کنید و فقط واسط‌های آن‌ها را نمایان کنید، نه پیاده‌سازی‌ها را. +* زمانی که طول عمر وابستگی‌ها کوتاه‌تر از مصرف‌کننده باشد. +* زمانی که نیاز به ساخت وابستگی‌ها با مقادیر یا پارامترهای زمان اجرا باشد. +* زمانی که باید در زمان اجرا انتخاب کنید که کدام خانواده از محصول را استفاده کنید. +* زمانی که افزودن محصولات یا خانواده های جدید نباید نیاز به تغییر در کد موجود داشته باشد. + +## آموزش‌های الگوی Abstract Factory در جاوا + +* [Abstract Factory Design Pattern in Java (DigitalOcean)](https://www.digitalocean.com/community/tutorials/abstract-factory-design-pattern-in-java) +* [Abstract Factory (Refactoring Guru)](https://refactoring.guru/design-patterns/abstract-factory) + +## مزایا و معایب الگوی Abstract Factory + +مزایا: + +> * انعطاف‌پذیری: به راحتی می‌توان خانواده‌های محصول را تعویض کرد بدون تغییر کد. + +> * جداسازی (Decoupling): کد مشتری فقط با واسط‌های انتزاعی کار می‌کند که باعث قابلیت حمل و نگهداری می‌شود. + +> * قابلیت استفاده مجدد: کارخانه‌های انتزاعی و محصولات امکان استفاده مجدد از مؤلفه‌ها را فراهم می‌کنند. + +> * قابلیت نگهداری: تغییرات در خانواده‌های محصول محلی شده و به‌روزرسانی را ساده‌تر می‌کند. + +معایب: + +> * پیچیدگی: تعریف واسط‌های انتزاعی و کارخانه‌های مشخص سربار اولیه ایجاد می‌کند. + +> * غیرمستقیم بودن: کد مشتری از طریق کارخانه‌ها با محصولات کار می‌کند که ممکن است شفافیت را کاهش دهد. + +## نمونه‌های واقعی استفاده از الگوی Abstract Factory در جاوا + +* کلاس‌های `LookAndFeel` در Java Swing برای ارائه گزینه های مختلف look-and-feel +* پیاده‌سازی‌های مختلف در Java AWT برای ایجاد اجزای مختلف GUI +* [javax.xml.parsers.DocumentBuilderFactory](http://docs.oracle.com/javase/8/docs/api/javax/xml/parsers/DocumentBuilderFactory.html) +* [javax.xml.transform.TransformerFactory](http://docs.oracle.com/javase/8/docs/api/javax/xml/transform/TransformerFactory.html#newInstance--) +* [javax.xml.xpath.XPathFactory](http://docs.oracle.com/javase/8/docs/api/javax/xml/xpath/XPathFactory.html#newInstance--) + +## الگوهای طراحی مرتبط با جاوا + +* الگوی [Factory Method](https://java-design-patterns.com/patterns/factory-method/): الگوی کارخانه‌ی انتزاعی از روش‌های کارخانه‌ای برای ایجاد محصولات استفاده می‌کند. +* الگوی [Singleton](https://java-design-patterns.com/patterns/singleton/): کلاس‌های کارخانه‌ی انتزاعی اغلب به صورت Singleton پیاده‌سازی می‌شوند. +* الگوی [Factory Kit](https://java-design-patterns.com/patterns/factory-kit/): مشابه کارخانه‌ی انتزاعی اما بر پیکربندی و مدیریت مجموعه‌ای از اشیای مرتبط تمرکز دارد. + +## منابع و ارجاعات + +* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI) +* [Design Patterns in Java](https://amzn.to/3Syw0vC) +* [Head First Design Patterns: Building Extensible and Maintainable Object-Oriented Software](https://amzn.to/49NGldq) +* [Java Design Patterns: A Hands-On Experience with Real-World Examples](https://amzn.to/3HWNf4U) diff --git a/localization/fa/abstract-factory/etc/abstract-factory.urm.png b/localization/fa/abstract-factory/etc/abstract-factory.urm.png new file mode 100644 index 0000000000000000000000000000000000000000..836858a2c652f55723cff879d1058248e1d2799c GIT binary patch literal 82368 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 MUHx3vIVCg!0PQSJ00000 literal 0 HcmV?d00001 From 7c12643b2772a4b96f58db2c88f00d5efa92ea1e Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Sun, 8 Feb 2026 21:27:30 +0200 Subject: [PATCH 6/8] docs: add naman-sriv as a contributor for code (#3428) * docs: update README.md [skip ci] * docs: update .all-contributorsrc [skip ci] --------- Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> --- .all-contributorsrc | 9 +++++++++ README.md | 3 ++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index 90ce80d3a163..c0b72d0364f8 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -3539,6 +3539,15 @@ "contributions": [ "doc" ] + }, + { + "login": "naman-sriv", + "name": "Naman Srivastava", + "avatar_url": "https://avatars.githubusercontent.com/u/82610773?v=4", + "profile": "https://github.com/naman-sriv", + "contributions": [ + "code" + ] } ], "contributorsPerLine": 6, diff --git a/README.md b/README.md index bfcdd0f63dbf..8a69a33f879d 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ [![Coverage](https://sonarcloud.io/api/project_badges/measure?project=iluwatar_java-design-patterns&metric=coverage)](https://sonarcloud.io/dashboard?id=iluwatar_java-design-patterns) [![Join the chat at https://gitter.im/iluwatar/java-design-patterns](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/iluwatar/java-design-patterns?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -[![All Contributors](https://img.shields.io/badge/all_contributors-388-orange.svg?style=flat-square)](#contributors-) +[![All Contributors](https://img.shields.io/badge/all_contributors-389-orange.svg?style=flat-square)](#contributors-)
@@ -577,6 +577,7 @@ This project is licensed under the terms of the MIT license.
Maziyar Gerami
Maziyar Gerami

🌍 yoobin_mion
yoobin_mion

💻 Soumik Sarker
Soumik Sarker

📖 + Naman Srivastava
Naman Srivastava

💻 From dc3425dd0e4643658c876304430fe0173e4144e2 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Sun, 8 Feb 2026 21:28:19 +0200 Subject: [PATCH 7/8] docs: add letdtcode as a contributor for code (#3429) * docs: update README.md [skip ci] * docs: update .all-contributorsrc [skip ci] --------- Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> --- .all-contributorsrc | 9 +++++++++ README.md | 3 ++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index c0b72d0364f8..59c7a7b92a6b 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -3548,6 +3548,15 @@ "contributions": [ "code" ] + }, + { + "login": "letdtcode", + "name": "Thanh Nguyen Duc", + "avatar_url": "https://avatars.githubusercontent.com/u/92111552?v=4", + "profile": "https://github.com/letdtcode", + "contributions": [ + "code" + ] } ], "contributorsPerLine": 6, diff --git a/README.md b/README.md index 8a69a33f879d..1aeab8760ae0 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ [![Coverage](https://sonarcloud.io/api/project_badges/measure?project=iluwatar_java-design-patterns&metric=coverage)](https://sonarcloud.io/dashboard?id=iluwatar_java-design-patterns) [![Join the chat at https://gitter.im/iluwatar/java-design-patterns](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/iluwatar/java-design-patterns?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -[![All Contributors](https://img.shields.io/badge/all_contributors-389-orange.svg?style=flat-square)](#contributors-) +[![All Contributors](https://img.shields.io/badge/all_contributors-390-orange.svg?style=flat-square)](#contributors-)
@@ -578,6 +578,7 @@ This project is licensed under the terms of the MIT license. yoobin_mion
yoobin_mion

💻 Soumik Sarker
Soumik Sarker

📖 Naman Srivastava
Naman Srivastava

💻 + Thanh Nguyen Duc
Thanh Nguyen Duc

💻 From a3fcc631672a3e418523af0c61c403caf5c137bf Mon Sep 17 00:00:00 2001 From: e5LA <208197507+e5LA@users.noreply.github.com> Date: Sun, 8 Feb 2026 20:44:17 +0100 Subject: [PATCH 8/8] feat: Implement View Helper pattern (#3278) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * #1263 - creating new module for view-helper * #1263 - creating Product and ProductViewModel * #1263 - creating interfaces for View and ViewHelper * #1263 - creating ProductViewHelper and its test * #1263 - creating Console View for Product * #1263 - creating ProductController * #1263 - creating main App and its test * #1263 - adding license header * #1263 - keeping module in alphabetical order * #1263 - creating README and diagrams * #1263 apply spotless --------- Co-authored-by: Ilkka Seppälä --- pom.xml | 3 +- view-helper/README.md | 98 ++++++++++++++++++ .../etc/view-helper-sequence-diagram.png | Bin 0 -> 27969 bytes .../etc/view-helper-sequence-diagram.puml | 15 +++ view-helper/etc/view-helper.png | Bin 0 -> 56099 bytes view-helper/etc/view-helper.puml | 45 ++++++++ view-helper/pom.xml | 70 +++++++++++++ .../java/com/iluwatar/viewhelper/App.java | 52 ++++++++++ .../viewhelper/ConsoleProductView.java | 36 +++++++ .../java/com/iluwatar/viewhelper/Product.java | 31 ++++++ .../viewhelper/ProductController.java | 49 +++++++++ .../viewhelper/ProductViewHelper.java | 45 ++++++++ .../iluwatar/viewhelper/ProductViewModel.java | 28 +++++ .../java/com/iluwatar/viewhelper/View.java | 30 ++++++ .../com/iluwatar/viewhelper/ViewHelper.java | 29 ++++++ .../java/com/iluwatar/viewhelper/AppTest.java | 39 +++++++ .../viewhelper/ProductViewHelperTest.java | 60 +++++++++++ 17 files changed, 628 insertions(+), 2 deletions(-) create mode 100644 view-helper/README.md create mode 100644 view-helper/etc/view-helper-sequence-diagram.png create mode 100644 view-helper/etc/view-helper-sequence-diagram.puml create mode 100644 view-helper/etc/view-helper.png create mode 100644 view-helper/etc/view-helper.puml create mode 100644 view-helper/pom.xml create mode 100644 view-helper/src/main/java/com/iluwatar/viewhelper/App.java create mode 100644 view-helper/src/main/java/com/iluwatar/viewhelper/ConsoleProductView.java create mode 100644 view-helper/src/main/java/com/iluwatar/viewhelper/Product.java create mode 100644 view-helper/src/main/java/com/iluwatar/viewhelper/ProductController.java create mode 100644 view-helper/src/main/java/com/iluwatar/viewhelper/ProductViewHelper.java create mode 100644 view-helper/src/main/java/com/iluwatar/viewhelper/ProductViewModel.java create mode 100644 view-helper/src/main/java/com/iluwatar/viewhelper/View.java create mode 100644 view-helper/src/main/java/com/iluwatar/viewhelper/ViewHelper.java create mode 100644 view-helper/src/test/java/com/iluwatar/viewhelper/AppTest.java create mode 100644 view-helper/src/test/java/com/iluwatar/viewhelper/ProductViewHelperTest.java diff --git a/pom.xml b/pom.xml index 2816ef0ca636..5926820b7fb4 100644 --- a/pom.xml +++ b/pom.xml @@ -71,7 +71,6 @@ Java Design Patterns - abstract-document abstract-factory active-object @@ -244,11 +243,11 @@ update-method value-object version-number + view-helper virtual-proxy visitor backpressure actor-model - diff --git a/view-helper/README.md b/view-helper/README.md new file mode 100644 index 000000000000..fbc93acba6fd --- /dev/null +++ b/view-helper/README.md @@ -0,0 +1,98 @@ +--- +title: "View Helper Pattern in Java: Simplifying Presentation Logic in MVC Applications" +shortTitle: View Helper +description: "Discover the View Helper Design Pattern in Java, a powerful technique for separating view-related logic from business logic in MVC-based web applications. This pattern enhances maintainability, reusability, and testability by delegating complex UI operations to reusable helper components. Ideal for developers aiming to keep views clean and focused on presentation." +category: Architectural +language: en +tag: + - Architecture + - Presentation + - Decoupling + - Code reuse +--- + +## Intent of View Helper Design Pattern +The View Helper Design Pattern separates presentation logic from the view by delegating complex UI tasks — like formatting or conditional display — to reusable helper components. This keeps views clean, promotes reuse, and aligns with the MVC principle of separating concerns between the view and the business logic. + +## Detailed Explanation with Real‑World Analogy +Real‑world example +> Imagine you're putting together a slideshow for a business presentation. You focus on arranging the slides, choosing the layout, and telling the story. But for tasks like resizing images, formatting charts, or converting data into visual form, you use tools or templates that automate those parts. +> +> In this analogy, you are the view, and the tools/templates are the helpers. They handle the heavy lifting behind the scenes so you can concentrate on the presentation. Similarly, in the View Helper pattern, the view delegates logic-heavy tasks—such as formatting or conditionally displaying data—to helper classes, keeping the view layer clean and presentation-focused. + +### In plain words +> The View Helper pattern is about keeping your UI code clean by moving any logic—like formatting, calculations, or decision-making—into separate helper classes. Instead of stuffing all the logic into the HTML or template files, you delegate it to helpers, so the view just focuses on showing the final result. + +### Sequence diagram +![Sequence diagram for View Helper](etc/view-helper-sequence-diagram.png) + +## Programmatic Example of View Helper Pattern in Java +Raw domain object +```java +public record Product(String name, BigDecimal price, LocalDate releaseDate, boolean discounted) {} +``` + +View model object for display +```java +public record ProductViewModel(String name, String price, String releasedDate) {} +``` + +View Helper formats data for display +```java +class ProductViewHelper implements ViewHelper { + + private static final String DISCOUNT_TAG = " (ON SALE)"; + + public ProductViewModel prepare(Product product) { + var displayName = product.name() + (product.discounted() ? DISCOUNT_TAG : ""); + var priceWithCurrency = NumberFormat.getCurrencyInstance(US).format(product.price()); + var formattedDate = product.releaseDate().format(ISO_DATE); + + return new ProductViewModel(displayName, priceWithCurrency, formattedDate); + } +} +``` + +View renders the formatted data +```java +public class ConsoleProductView implements View { + + @Override + public void render(ProductViewModel productViewModel) { + LOGGER.info(productViewModel.toString()); + } +} +``` +The `App.java` class simulates how the View Helper pattern works in a real application. It starts with a raw `Product` object containing unformatted data. +Then it: +1. Initializes a helper (`ProductViewHelper`) to format the product data for display. +1. Creates a view (`ConsoleProductView`) to render the formatted data. +1. Uses a controller (`ProductController`) to coordinate the flow between raw data, helper logic, and view rendering. + +Finally, it simulates a user request by passing the product to the controller, which prepares the view model using the helper and displays it using the view. This demonstrates a clean separation between data, presentation logic, and rendering. + +## When to Use the View Helper Pattern in Java +Use the View Helper pattern when your view layer starts containing logic such as formatting data, applying conditional styles, or transforming domain objects for display. It's especially useful in MVC architectures where you want to keep views clean and focused on rendering, while delegating non-trivial presentation logic to reusable helper classes. This pattern helps improve maintainability, testability, and separation of concerns in your application's UI layer. + +## Real‑World Uses of View Helper Pattern in Java +The View Helper pattern is widely used in web frameworks that follow the MVC architecture. In Java-based web applications (e.g., JSP, Spring MVC), it's common to use helper classes or utility methods to format dates, currencies, or apply conditional logic before rendering views. Technologies like Thymeleaf or JSF often rely on custom tags or expression helpers to achieve the same effect. + +## Benefits and Trade‑offs +Benefits: +* Separation of concerns: Keeps view templates clean by moving logic into dedicated helpers. +* Reusability: Common formatting and display logic can be reused across multiple views. +* Improved maintainability: Easier to update presentation logic without touching the view. +* Testability: Helpers can be unit tested independently from the UI layer. + +Trade‑offs: +* Added complexity: Introduces extra classes, which may feel unnecessary for very simple views. +* Overuse risk: Excessive use of helpers can spread logic thinly across many files, making it harder to trace behavior. +* Tight coupling risk: If not designed carefully, helpers can become tightly coupled to specific views or data formats. + +## Related Java Design Patterns +* [Model-View-Controller (MVC)](https://java-design-patterns.com/patterns/model-view-controller/): View Helper supports the View layer in MVC by offloading logic from the view to helper classes. +* [Template Method](https://java-design-patterns.com/patterns/template-method/): Can structure the steps of rendering or data transformation, with helpers handling specific formatting tasks. +* [Data Transfer Object (DTO)](https://java-design-patterns.com/patterns/data-transfer-object/): Often used alongside View Helper when transferring raw data that needs formatting before being displayed. + +## References & Credits +* [Core J2EE Patterns: View Helper.](https://www.oracle.com/java/technologies/viewhelper.html) diff --git a/view-helper/etc/view-helper-sequence-diagram.png b/view-helper/etc/view-helper-sequence-diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..22e53c6b8afe625ae8604ca8f37659e69e6ef8e2 GIT binary patch literal 27969 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 literal 0 HcmV?d00001 diff --git a/view-helper/etc/view-helper-sequence-diagram.puml b/view-helper/etc/view-helper-sequence-diagram.puml new file mode 100644 index 000000000000..d5be27e51510 --- /dev/null +++ b/view-helper/etc/view-helper-sequence-diagram.puml @@ -0,0 +1,15 @@ +@startuml +actor Client +participant Controller +participant ViewHelper +participant View +participant Product +participant ProductViewModel + +Client -> Controller : handle(product) +Controller -> ViewHelper : prepare(product) +ViewHelper -> Product : access data +ViewHelper -> ProductViewModel : return formatted view model +Controller -> View : render(viewModel) +View -> Console : display output +@enduml \ No newline at end of file diff --git a/view-helper/etc/view-helper.png b/view-helper/etc/view-helper.png new file mode 100644 index 0000000000000000000000000000000000000000..9550b80d7acb2496f8ededf8ad9a85237203b28b GIT binary patch literal 56099 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 { + +render(T model) + } + + interface ViewHelper { + +prepare(S source): T + } + + class Product { + -name: String + -price: BigDecimal + -releaseDate: LocalDate + -discounted: boolean + } + + class ProductViewModel { + -name: String + -price: String + -releasedDate: String + } + + class ProductViewHelper { + +prepare(Product): ProductViewModel + } + + class ConsoleProductView { + +render(ProductViewModel) + } + + class ProductController { + -helper: ViewHelper + -view: View + +handle(Product) + } +} +Product --> ProductViewHelper +ProductViewHelper ..|> ViewHelper +ConsoleProductView ..|> View +ProductViewHelper --> ProductViewModel +ProductController --> ProductViewHelper +ProductController --> ConsoleProductView + +@enduml \ No newline at end of file diff --git a/view-helper/pom.xml b/view-helper/pom.xml new file mode 100644 index 000000000000..e2f3afca3a08 --- /dev/null +++ b/view-helper/pom.xml @@ -0,0 +1,70 @@ + + + + 4.0.0 + + com.iluwatar + java-design-patterns + 1.26.0-SNAPSHOT + + view-helper + + + org.slf4j + slf4j-api + + + ch.qos.logback + logback-classic + + + org.junit.jupiter + junit-jupiter-engine + test + + + + + + org.apache.maven.plugins + maven-assembly-plugin + + + + + + com.iluwatar.value.object.App + + + + + + + + + diff --git a/view-helper/src/main/java/com/iluwatar/viewhelper/App.java b/view-helper/src/main/java/com/iluwatar/viewhelper/App.java new file mode 100644 index 000000000000..e427bc8f5e9b --- /dev/null +++ b/view-helper/src/main/java/com/iluwatar/viewhelper/App.java @@ -0,0 +1,52 @@ +/* + * 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.viewhelper; + +import java.math.BigDecimal; +import java.time.LocalDate; + +/** The main application class that sets up and runs the View Helper pattern demo. */ +public class App { + /** + * The entry point of the application. + * + * @param args the command line arguments + */ + public static void main(String[] args) { + // Raw Product data (no formatting, no UI tags) + var product = + new Product( + "Design patterns book", new BigDecimal("18.90"), LocalDate.of(2025, 4, 19), true); + + // Create view, viewHelper and viewHelper + var helper = new ProductViewHelper(); + var view = new ConsoleProductView(); + var controller = new ProductController(helper, view); + + // Handle “request” + controller.handle(product); + } +} diff --git a/view-helper/src/main/java/com/iluwatar/viewhelper/ConsoleProductView.java b/view-helper/src/main/java/com/iluwatar/viewhelper/ConsoleProductView.java new file mode 100644 index 000000000000..7f215a7514f6 --- /dev/null +++ b/view-helper/src/main/java/com/iluwatar/viewhelper/ConsoleProductView.java @@ -0,0 +1,36 @@ +/* + * 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.viewhelper; + +import lombok.extern.slf4j.Slf4j; + +/** Renders {@link ProductViewModel} to the console. */ +@Slf4j +public class ConsoleProductView implements View { + @Override + public void render(ProductViewModel productViewModel) { + LOGGER.info(productViewModel.toString()); + } +} diff --git a/view-helper/src/main/java/com/iluwatar/viewhelper/Product.java b/view-helper/src/main/java/com/iluwatar/viewhelper/Product.java new file mode 100644 index 000000000000..a0a75cf24188 --- /dev/null +++ b/view-helper/src/main/java/com/iluwatar/viewhelper/Product.java @@ -0,0 +1,31 @@ +/* + * 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.viewhelper; + +import java.math.BigDecimal; +import java.time.LocalDate; + +/** Definition of product. */ +public record Product(String name, BigDecimal price, LocalDate releaseDate, boolean discounted) {} diff --git a/view-helper/src/main/java/com/iluwatar/viewhelper/ProductController.java b/view-helper/src/main/java/com/iluwatar/viewhelper/ProductController.java new file mode 100644 index 000000000000..836f34a33167 --- /dev/null +++ b/view-helper/src/main/java/com/iluwatar/viewhelper/ProductController.java @@ -0,0 +1,49 @@ +/* + * 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.viewhelper; + +/** + * Controller delegates a {@link Product} to {@link ProductViewHelper} and then to {@link + * ConsoleProductView}. + */ +public class ProductController { + + private final ViewHelper viewHelper; + private final View view; + + public ProductController( + ViewHelper viewHelper, View view) { + this.viewHelper = viewHelper; + this.view = view; + } + + /** + * Passes the product to the helper for formatting and then forwards formatted product to the + * view. + */ + public void handle(Product product) { + view.render(viewHelper.prepare(product)); + } +} diff --git a/view-helper/src/main/java/com/iluwatar/viewhelper/ProductViewHelper.java b/view-helper/src/main/java/com/iluwatar/viewhelper/ProductViewHelper.java new file mode 100644 index 000000000000..4c739e9f14a8 --- /dev/null +++ b/view-helper/src/main/java/com/iluwatar/viewhelper/ProductViewHelper.java @@ -0,0 +1,45 @@ +/* + * 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.viewhelper; + +import static java.time.format.DateTimeFormatter.ISO_DATE; +import static java.util.Locale.US; + +import java.text.NumberFormat; + +/** Formats a {@link Product} into a {@link ProductViewModel}. */ +public class ProductViewHelper implements ViewHelper { + + private static final String DISCOUNT_TAG = " ON SALE"; + + @Override + public ProductViewModel prepare(Product product) { + var displayName = product.name() + (product.discounted() ? DISCOUNT_TAG : ""); + var priceWithCurrency = NumberFormat.getCurrencyInstance(US).format(product.price()); + var formattedDate = product.releaseDate().format(ISO_DATE); + + return new ProductViewModel(displayName, priceWithCurrency, formattedDate); + } +} diff --git a/view-helper/src/main/java/com/iluwatar/viewhelper/ProductViewModel.java b/view-helper/src/main/java/com/iluwatar/viewhelper/ProductViewModel.java new file mode 100644 index 000000000000..b133fc071da1 --- /dev/null +++ b/view-helper/src/main/java/com/iluwatar/viewhelper/ProductViewModel.java @@ -0,0 +1,28 @@ +/* + * 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.viewhelper; + +/** Class defining formatted display data of a {@link Product}. */ +public record ProductViewModel(String name, String price, String releasedDate) {} diff --git a/view-helper/src/main/java/com/iluwatar/viewhelper/View.java b/view-helper/src/main/java/com/iluwatar/viewhelper/View.java new file mode 100644 index 000000000000..7bc822166885 --- /dev/null +++ b/view-helper/src/main/java/com/iluwatar/viewhelper/View.java @@ -0,0 +1,30 @@ +/* + * 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.viewhelper; + +public interface View { + + void render(V data); +} diff --git a/view-helper/src/main/java/com/iluwatar/viewhelper/ViewHelper.java b/view-helper/src/main/java/com/iluwatar/viewhelper/ViewHelper.java new file mode 100644 index 000000000000..68756f46585d --- /dev/null +++ b/view-helper/src/main/java/com/iluwatar/viewhelper/ViewHelper.java @@ -0,0 +1,29 @@ +/* + * 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.viewhelper; + +public interface ViewHelper { + V prepare(M source); +} diff --git a/view-helper/src/test/java/com/iluwatar/viewhelper/AppTest.java b/view-helper/src/test/java/com/iluwatar/viewhelper/AppTest.java new file mode 100644 index 000000000000..bc4a31cc43a8 --- /dev/null +++ b/view-helper/src/test/java/com/iluwatar/viewhelper/AppTest.java @@ -0,0 +1,39 @@ +/* + * 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.viewhelper; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; + +import org.junit.jupiter.api.Test; + +/** Application test */ +class AppTest { + + @Test + void shouldExecuteApplicationWithoutException() { + assertDoesNotThrow(() -> App.main(new String[] {})); + } +} diff --git a/view-helper/src/test/java/com/iluwatar/viewhelper/ProductViewHelperTest.java b/view-helper/src/test/java/com/iluwatar/viewhelper/ProductViewHelperTest.java new file mode 100644 index 000000000000..49cc48556f47 --- /dev/null +++ b/view-helper/src/test/java/com/iluwatar/viewhelper/ProductViewHelperTest.java @@ -0,0 +1,60 @@ +/* + * 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.viewhelper; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.math.BigDecimal; +import java.time.LocalDate; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class ProductViewHelperTest { + + private ProductViewHelper helper; + + @BeforeEach + void setUp() { + helper = new ProductViewHelper(); + } + + @Test + void shouldFormatProductWithoutDiscount() { + var product = new Product("X", new BigDecimal("10.00"), LocalDate.of(2025, 1, 1), false); + ProductViewModel viewModel = helper.prepare(product); + + assertEquals("X", viewModel.name()); + assertEquals("$10.00", viewModel.price()); + assertEquals("2025-01-01", viewModel.releasedDate()); + } + + @Test + void shouldFormatProductWithDiscount() { + var product = new Product("X", new BigDecimal("10.00"), LocalDate.of(2025, 1, 1), true); + ProductViewModel viewModel = helper.prepare(product); + + assertEquals("X ON SALE", viewModel.name()); // locale follows JVM default + } +}