mirror of
https://github.com/tiennm99/java-design-patterns.git
synced 2026-05-14 08:58:26 +00:00
* Implement Gateway pattern * Fixed docstrings * Fixed README.md * Fixed App * Fixed pom.xml * Fixed pom.xml * Fixed pom.xml * Fixed pom.xml * fixed checkstyle errors and directory names * fixed pom.xml * fixed checkstyle errors * Bug fixed * Bug fixed * Bug fixed * Bug fixed and code improvement * Bug fixed and code improvement * Bug fixed and update README.md * update APP.java * update gateway pattern * Revert "update gateway pattern" This reverts commit f31a00c268889b2c6b7690e07847df7247725999. * update gateway pattern --------- Co-authored-by: Finn <u7552286@anu.edu.au>
This commit is contained in:
@@ -0,0 +1,150 @@
|
||||
---
|
||||
title: Gateway
|
||||
category: Structural
|
||||
language: en
|
||||
tag:
|
||||
- Gang of Four
|
||||
- Decoupling
|
||||
|
||||
---
|
||||
|
||||
## Intent
|
||||
|
||||
Provide a interface to access a set of external systems or functionalities. Gateway provides a simple uniform view of
|
||||
external resources to the internals of an application.
|
||||
|
||||
## Explanation
|
||||
|
||||
Real-world example
|
||||
|
||||
> Gateway acts like a real front gate of a certain city. The people inside the city are called
|
||||
> internal system, and different outside cities are called external services. The gateway is here
|
||||
> to provide access for internal system to different external services.
|
||||
|
||||
In plain words
|
||||
|
||||
> Gateway can provide an interface which lets internal system to utilize external service.
|
||||
|
||||
Wikipedia says
|
||||
|
||||
> A server that acts as an API front-end, receives API requests, enforces throttling and security
|
||||
> policies, passes requests to the back-end service and then passes the response back to the requester.
|
||||
|
||||
**Programmatic Example**
|
||||
|
||||
The main class in our example is the `ExternalService` that contains items.
|
||||
|
||||
```java
|
||||
class ExternalServiceA implements Gateway {
|
||||
@Override
|
||||
public void execute() throws Exception {
|
||||
System.out.println("Executing Service A");
|
||||
// Simulate a time-consuming task
|
||||
Thread.sleep(1000);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ExternalServiceB is one of external services.
|
||||
*/
|
||||
class ExternalServiceB implements Gateway {
|
||||
@Override
|
||||
public void execute() throws Exception {
|
||||
System.out.println("Executing Service B");
|
||||
// Simulate a time-consuming task
|
||||
Thread.sleep(1000);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ExternalServiceC is one of external services.
|
||||
*/
|
||||
class ExternalServiceC implements Gateway {
|
||||
@Override
|
||||
public void execute() throws Exception {
|
||||
System.out.println("Executing Service C");
|
||||
// Simulate a time-consuming task
|
||||
Thread.sleep(1000);
|
||||
}
|
||||
|
||||
public void error() throws Exception {
|
||||
// Simulate an exception
|
||||
throw new RuntimeException("Service C encountered an error");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
To operate these external services, Here's the `App` class:
|
||||
|
||||
```java
|
||||
public class App {
|
||||
/**
|
||||
* Simulate an application calling external services.
|
||||
*/
|
||||
public static void main(String[] args) throws Exception {
|
||||
GatewayFactory gatewayFactory = new GatewayFactory();
|
||||
|
||||
// Register different gateways
|
||||
gatewayFactory.registerGateway("ServiceA", new ExternalServiceA());
|
||||
gatewayFactory.registerGateway("ServiceB", new ExternalServiceB());
|
||||
gatewayFactory.registerGateway("ServiceC", new ExternalServiceC());
|
||||
|
||||
// Use an executor service for asynchronous execution
|
||||
Gateway serviceA = gatewayFactory.getGateway("ServiceA");
|
||||
Gateway serviceB = gatewayFactory.getGateway("ServiceB");
|
||||
Gateway serviceC = gatewayFactory.getGateway("ServiceC");
|
||||
|
||||
// Execute external services
|
||||
try {
|
||||
serviceA.execute();
|
||||
serviceB.execute();
|
||||
serviceC.execute();
|
||||
} catch (ThreadDeath e) {
|
||||
System.out.println("Interrupted!" + e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The `Gateway` interface is extremely simple.
|
||||
|
||||
```java
|
||||
interface Gateway {
|
||||
void execute() throws Exception;
|
||||
}
|
||||
```
|
||||
|
||||
Program output:
|
||||
|
||||
```java
|
||||
Executing Service A
|
||||
Executing Service B
|
||||
Executing Service C
|
||||
```
|
||||
|
||||
## Class diagram
|
||||
|
||||

|
||||
|
||||
## Applicability
|
||||
|
||||
Use the Gateway pattern
|
||||
|
||||
* To access an aggregate object's contents without exposing its internal representation.
|
||||
* To integration with multiple external services or APIs.
|
||||
* To provide a uniform interface for traversing different aggregate structures.
|
||||
|
||||
## Tutorials
|
||||
|
||||
* [Pattern: API Gateway / Backends for Frontends](https://microservices.io/patterns/apigateway.html)
|
||||
|
||||
## Known uses
|
||||
|
||||
* [API Gateway](https://java-design-patterns.com/patterns/api-gateway/)
|
||||
* [10 most common use cases of an API Gateway](https://apisix.apache.org/blog/2022/10/27/ten-use-cases-api-gateway/)
|
||||
|
||||
## Credits
|
||||
|
||||
* [Gateway](https://martinfowler.com/articles/gateway-pattern.html)
|
||||
* [What is the difference between Facade and Gateway design patterns?](https://stackoverflow.com/questions/4422211/what-is-the-difference-between-facade-and-gateway-design-patterns)
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 45 KiB |
@@ -0,0 +1,43 @@
|
||||
@startuml GatewayPattern
|
||||
package com.iluwatar.gateway{
|
||||
class App {
|
||||
+main(args: String[]): void
|
||||
}
|
||||
|
||||
class GatewayFactory {
|
||||
-gateways: Map<String, Gateway>
|
||||
+registerGateway(key: String, gateway: Gateway): void
|
||||
+getGateway(key: String): Gateway
|
||||
}
|
||||
|
||||
interface Gateway {
|
||||
{abstract} +execute(): void
|
||||
}
|
||||
|
||||
class ExternalServiceA {
|
||||
+execute(): void
|
||||
}
|
||||
|
||||
class ExternalServiceB {
|
||||
+execute(): void
|
||||
}
|
||||
|
||||
class ExternalServiceC {
|
||||
+execute(): void
|
||||
+error(): void
|
||||
}
|
||||
|
||||
App --> GatewayFactory : Uses
|
||||
|
||||
|
||||
GatewayFactory --> Gateway : Creates
|
||||
|
||||
GatewayFactory --> ExternalServiceA : Registers
|
||||
GatewayFactory --> ExternalServiceB : Registers
|
||||
GatewayFactory --> ExternalServiceC : Registers
|
||||
|
||||
ExternalServiceA --> Gateway : Implements
|
||||
ExternalServiceB --> Gateway : Implements
|
||||
ExternalServiceC --> Gateway : Implements
|
||||
|
||||
@enduml
|
||||
@@ -0,0 +1,68 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
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.
|
||||
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.iluwatar</groupId>
|
||||
<artifactId>java-design-patterns</artifactId>
|
||||
<version>1.26.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<packaging>jar</packaging>
|
||||
<artifactId>gateway</artifactId>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-engine</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifest>
|
||||
<mainClass>com.iluwatar.gateway.App</mainClass>
|
||||
</manifest>
|
||||
</archive>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* 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.gateway;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* the Gateway design pattern is a structural design pattern that provides a unified interface to a set of
|
||||
* interfaces in a subsystem. It involves creating a Gateway interface that serves as a common entry point for
|
||||
* interacting with various services, and concrete implementations of this interface for different external services.
|
||||
*
|
||||
* <p>In this example, GateFactory is the factory class, and it provides a method to create different kinds of external
|
||||
* services. ExternalServiceA, B, and C are virtual implementations of the external services. Each service provides its
|
||||
* own implementation of the execute() method. The Gateway interface is the common interface for all external services.
|
||||
* The App class serves as the main entry point for the application implementing the Gateway design pattern. Through
|
||||
* the Gateway interface, the App class could call each service with much less complexity.
|
||||
*/
|
||||
@Slf4j
|
||||
public class App {
|
||||
/**
|
||||
* Simulate an application calling external services.
|
||||
*/
|
||||
public static void main(String[] args) throws Exception {
|
||||
GatewayFactory gatewayFactory = new GatewayFactory();
|
||||
|
||||
// Register different gateways
|
||||
gatewayFactory.registerGateway("ServiceA", new ExternalServiceA());
|
||||
gatewayFactory.registerGateway("ServiceB", new ExternalServiceB());
|
||||
gatewayFactory.registerGateway("ServiceC", new ExternalServiceC());
|
||||
|
||||
// Use an executor service for execution
|
||||
Gateway serviceA = gatewayFactory.getGateway("ServiceA");
|
||||
Gateway serviceB = gatewayFactory.getGateway("ServiceB");
|
||||
Gateway serviceC = gatewayFactory.getGateway("ServiceC");
|
||||
|
||||
// Execute external services
|
||||
try {
|
||||
serviceA.execute();
|
||||
serviceB.execute();
|
||||
serviceC.execute();
|
||||
} catch (ThreadDeath e) {
|
||||
LOGGER.info("Interrupted!" + e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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.gateway;
|
||||
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
/**
|
||||
* ExternalServiceA is one of external services.
|
||||
*/
|
||||
@Slf4j
|
||||
class ExternalServiceA implements Gateway {
|
||||
@Override
|
||||
public void execute() throws Exception {
|
||||
LOGGER.info("Executing Service A");
|
||||
// Simulate a time-consuming task
|
||||
Thread.sleep(1000);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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.gateway;
|
||||
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* ExternalServiceB is one of external services.
|
||||
*/
|
||||
@Slf4j
|
||||
class ExternalServiceB implements Gateway {
|
||||
@Override
|
||||
public void execute() throws Exception {
|
||||
LOGGER.info("Executing Service B");
|
||||
// Simulate a time-consuming task
|
||||
Thread.sleep(1000);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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.gateway;
|
||||
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* ExternalServiceC is one of external services.
|
||||
*/
|
||||
@Slf4j
|
||||
class ExternalServiceC implements Gateway {
|
||||
@Override
|
||||
public void execute() throws Exception {
|
||||
LOGGER.info("Executing Service C");
|
||||
// Simulate a time-consuming task
|
||||
Thread.sleep(1000);
|
||||
}
|
||||
|
||||
public void error() throws Exception {
|
||||
// Simulate an exception
|
||||
throw new RuntimeException("Service C encountered an error");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.iluwatar.gateway;
|
||||
|
||||
/**
|
||||
* Service interface.
|
||||
*/
|
||||
interface Gateway {
|
||||
void execute() throws Exception;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.iluwatar.gateway;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* The "GatewayFactory" class is responsible for providing different external services in this Gateway design pattern
|
||||
* example. It allows clients to register and retrieve specific gateways based on unique keys.
|
||||
*/
|
||||
public class GatewayFactory {
|
||||
private Map<String, Gateway> gateways = new HashMap<>();
|
||||
|
||||
public void registerGateway(String key, Gateway gateway) {
|
||||
gateways.put(key, gateway);
|
||||
}
|
||||
|
||||
public Gateway getGateway(String key) {
|
||||
return gateways.get(key);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package com.iluwatar.gateway;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
public class AppTest {
|
||||
private GatewayFactory gatewayFactory;
|
||||
private ExecutorService executorService;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
gatewayFactory = new GatewayFactory();
|
||||
executorService = Executors.newFixedThreadPool(2);
|
||||
gatewayFactory.registerGateway("ServiceA", new ExternalServiceA());
|
||||
gatewayFactory.registerGateway("ServiceB", new ExternalServiceB());
|
||||
gatewayFactory.registerGateway("ServiceC", new ExternalServiceC());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testServiceAExecution() throws InterruptedException, ExecutionException {
|
||||
// Test Service A execution
|
||||
Future<?> serviceAFuture = executorService.submit(() -> {
|
||||
try {
|
||||
Gateway serviceA = gatewayFactory.getGateway("ServiceA");
|
||||
serviceA.execute();
|
||||
} catch (Exception e) {
|
||||
fail("Service A should not throw an exception.");
|
||||
}
|
||||
});
|
||||
|
||||
// Wait for Service A to complete
|
||||
serviceAFuture.get();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testServiceCExecutionWithException() throws InterruptedException, ExecutionException {
|
||||
// Test Service B execution with an exception
|
||||
Future<?> serviceBFuture = executorService.submit(() -> {
|
||||
try {
|
||||
Gateway serviceB = gatewayFactory.getGateway("ServiceB");
|
||||
serviceB.execute();
|
||||
} catch (Exception e) {
|
||||
fail("Service B should not throw an exception.");
|
||||
}
|
||||
});
|
||||
|
||||
// Wait for Service B to complete
|
||||
serviceBFuture.get();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testServiceCExecution() throws InterruptedException, ExecutionException {
|
||||
// Test Service C execution
|
||||
Future<?> serviceCFuture = executorService.submit(() -> {
|
||||
try {
|
||||
Gateway serviceC = gatewayFactory.getGateway("ServiceC");
|
||||
serviceC.execute();
|
||||
} catch (Exception e) {
|
||||
fail("Service C should not throw an exception.");
|
||||
}
|
||||
});
|
||||
|
||||
// Wait for Service C to complete
|
||||
serviceCFuture.get();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testServiceCError() {
|
||||
try {
|
||||
ExternalServiceC serviceC = (ExternalServiceC) gatewayFactory.getGateway("ServiceC");
|
||||
serviceC.error();
|
||||
fail("Service C should throw an exception.");
|
||||
} catch (Exception e) {
|
||||
assertEquals("Service C encountered an error", e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package com.iluwatar.gateway;
|
||||
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
public class ServiceFactoryTest {
|
||||
private GatewayFactory gatewayFactory;
|
||||
private ExecutorService executorService;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
gatewayFactory = new GatewayFactory();
|
||||
executorService = Executors.newFixedThreadPool(2);
|
||||
gatewayFactory.registerGateway("ServiceA", new ExternalServiceA());
|
||||
gatewayFactory.registerGateway("ServiceB", new ExternalServiceB());
|
||||
gatewayFactory.registerGateway("ServiceC", new ExternalServiceC());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGatewayFactoryRegistrationAndRetrieval() {
|
||||
Gateway serviceA = gatewayFactory.getGateway("ServiceA");
|
||||
Gateway serviceB = gatewayFactory.getGateway("ServiceB");
|
||||
Gateway serviceC = gatewayFactory.getGateway("ServiceC");
|
||||
|
||||
// Check if the retrieved instances match their expected types
|
||||
assertTrue("ServiceA should be an instance of ExternalServiceA", serviceA instanceof ExternalServiceA);
|
||||
assertTrue("ServiceB should be an instance of ExternalServiceB", serviceB instanceof ExternalServiceB);
|
||||
assertTrue("ServiceC should be an instance of ExternalServiceC", serviceC instanceof ExternalServiceC);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGatewayFactoryRegistrationWithNonExistingKey() {
|
||||
Gateway nonExistingService = gatewayFactory.getGateway("NonExistingService");
|
||||
assertEquals(null, nonExistingService);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGatewayFactoryConcurrency() throws InterruptedException {
|
||||
int numThreads = 10;
|
||||
CountDownLatch latch = new CountDownLatch(numThreads);
|
||||
AtomicBoolean failed = new AtomicBoolean(false);
|
||||
|
||||
for (int i = 0; i < numThreads; i++) {
|
||||
executorService.submit(() -> {
|
||||
try {
|
||||
Gateway serviceA = gatewayFactory.getGateway("ServiceA");
|
||||
serviceA.execute();
|
||||
} catch (Exception e) {
|
||||
failed.set(true);
|
||||
} finally {
|
||||
latch.countDown();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
latch.await();
|
||||
assertTrue("This should not fail", !failed.get());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user