diff --git a/pom.xml b/pom.xml index fc4984802..f2b6b7ccb 100644 --- a/pom.xml +++ b/pom.xml @@ -145,7 +145,8 @@ cqrs event-sourcing data-transfer-object - + throttling + @@ -488,4 +489,4 @@ - + \ No newline at end of file diff --git a/throttling/README.md b/throttling/README.md new file mode 100644 index 000000000..efc966d04 --- /dev/null +++ b/throttling/README.md @@ -0,0 +1,20 @@ +--- +layout: pattern +title: Throttling pattern +folder: throttling +permalink: /patterns/throttling/ +tags: + - Java + - Difficulty-Beginner + - Throttling +--- + +## Intent +Ensure that a given client is not able to access service resources more than the assigned limit. +![alt text](./etc/throttling-patern.png "Throttling pattern") + +## Applicability +The Throttling pattern should be used: + +* when a service access needs to be restricted to not have high impacts on the performance of the service. +* when multiple clients are consuming the same service resources and restriction has to be made according to the usage per client. diff --git a/throttling/etc/throttling-pattern.png b/throttling/etc/throttling-pattern.png new file mode 100644 index 000000000..a31aa54ce Binary files /dev/null and b/throttling/etc/throttling-pattern.png differ diff --git a/throttling/etc/throttling.urm.puml b/throttling/etc/throttling.urm.puml new file mode 100644 index 000000000..8c97da50a --- /dev/null +++ b/throttling/etc/throttling.urm.puml @@ -0,0 +1,29 @@ +@startuml +package com.iluwatar.tls { + class App { + - LOGGER : Logger {static} + + App() + + main(args : String[]) {static} + - makeServiceCalls(service : B2BService) {static} + } + ~class B2BService { + - LOGGER : Logger {static} + - callsCounter : int + - tenant : Tenant + + B2BService(tenant : Tenant) + + dummyCustomerApi() : int + + getCurrentCallsCount() : int + - getRandomCustomerId() : int + } + class Tenant { + - allowedCallsPerSecond : int + - name : String + + Tenant(name : String, allowedCallsPerSecond : int) + + getAllowedCallsPerSecond() : int + + getName() : String + + setAllowedCallsPerSecond(allowedCallsPerSecond : int) + + setName(name : String) + } +} +B2BService --> "-tenant" Tenant +@enduml \ No newline at end of file diff --git a/throttling/pom.xml b/throttling/pom.xml new file mode 100644 index 000000000..2cbd7bf9e --- /dev/null +++ b/throttling/pom.xml @@ -0,0 +1,44 @@ + + + + + java-design-patterns + com.iluwatar + 1.17.0-SNAPSHOT + + 4.0.0 + + throttling + + + junit + junit + + + + \ No newline at end of file diff --git a/throttling/src/main/java/com/iluwatar/throttling/App.java b/throttling/src/main/java/com/iluwatar/throttling/App.java new file mode 100644 index 000000000..2dce68ab9 --- /dev/null +++ b/throttling/src/main/java/com/iluwatar/throttling/App.java @@ -0,0 +1,90 @@ +/** + * The MIT License + * Copyright (c) 2014-2016 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.throttling; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.iluwatar.throttling.timer.Throttler; +import com.iluwatar.throttling.timer.ThrottleTimerImpl; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; + +/** + * Throttling pattern is a design pattern to throttle or limit the use of resources or even a complete service by + * users or a particular tenant. This can allow systems to continue to function and meet service level agreements, + * even when an increase in demand places load on resources. + *

+ * In this example we have ({@link App}) as the initiating point of the service. + * This is a time based throttling, i.e. only a certain number of calls are allowed per second. + *

+ * ({@link Tenant}) is the Tenant POJO class with which many tenants can be created + * ({@link B2BService}) is the service which is consumed by the tenants and is throttled. + */ +public class App { + + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + + /** + * Application entry point + * @param args main arguments + */ + public static void main(String[] args) { + + Tenant adidas = new Tenant("Adidas", 5); + Tenant nike = new Tenant("Nike", 6); + + ExecutorService executorService = Executors.newFixedThreadPool(2); + + executorService.execute(() -> makeServiceCalls(adidas)); + executorService.execute(() -> makeServiceCalls(nike)); + + executorService.shutdown(); + try { + executorService.awaitTermination(10, TimeUnit.SECONDS); + } catch (InterruptedException e) { + LOGGER.error("Executor Service terminated: {}", e.getMessage()); + } + } + + /** + * Make calls to the B2BService dummy API + * @param service an instance of B2BService + */ + private static void makeServiceCalls(Tenant tenant) { + Throttler timer = new ThrottleTimerImpl(10); + B2BService service = new B2BService(timer); + for (int i = 0; i < 20; i++) { + service.dummyCustomerApi(tenant); +// Sleep is introduced to keep the output in check and easy to view and analyze the results. + try { + Thread.sleep(1); + } catch (InterruptedException e) { + LOGGER.error("Thread interrupted: {}", e.getMessage()); + } + } + } +} diff --git a/throttling/src/main/java/com/iluwatar/throttling/B2BService.java b/throttling/src/main/java/com/iluwatar/throttling/B2BService.java new file mode 100644 index 000000000..c9acd4b73 --- /dev/null +++ b/throttling/src/main/java/com/iluwatar/throttling/B2BService.java @@ -0,0 +1,62 @@ +/** + * The MIT License + * Copyright (c) 2014 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.throttling; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.iluwatar.throttling.timer.Throttler; + +import java.util.concurrent.ThreadLocalRandom; + +/** + * A service which accepts a tenant and throttles the resource based on the time given to the tenant. + */ +class B2BService { + + private static final Logger LOGGER = LoggerFactory.getLogger(B2BService.class); + + public B2BService(Throttler timer) { + timer.start(); + } + + /** + * + * @return customer id which is randomly generated + */ + public int dummyCustomerApi(Tenant tenant) { + String tenantName = tenant.getName(); + int count = CallsCount.getCount(tenantName); + LOGGER.debug("Counter for {} : {} ", tenant.getName(), count); + if (count >= tenant.getAllowedCallsPerSecond()) { + LOGGER.error("API access per second limit reached for: {}", tenantName); + return -1; + } + CallsCount.incrementCount(tenantName); + return getRandomCustomerId(); + } + + private int getRandomCustomerId() { + return ThreadLocalRandom.current().nextInt(1, 10000); + } +} diff --git a/throttling/src/main/java/com/iluwatar/throttling/CallsCount.java b/throttling/src/main/java/com/iluwatar/throttling/CallsCount.java new file mode 100644 index 000000000..81195b074 --- /dev/null +++ b/throttling/src/main/java/com/iluwatar/throttling/CallsCount.java @@ -0,0 +1,72 @@ +/** + * The MIT License + * Copyright (c) 2014 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.throttling; + +import java.util.Map; +import java.util.Map.Entry; +import java.util.concurrent.ConcurrentHashMap; + +/** + * A class to keep track of the counter of different Tenants + * @author drastogi + * + */ +public final class CallsCount { + private static Map tenantCallsCount = new ConcurrentHashMap<>(); + + /** + * Add a new tenant to the map. + * @param tenantName name of the tenant. + */ + public static void addTenant(String tenantName) { + if (!tenantCallsCount.containsKey(tenantName)) { + tenantCallsCount.put(tenantName, 0); + } + } + + /** + * Increment the count of the specified tenant. + * @param tenantName name of the tenant. + */ + public static void incrementCount(String tenantName) { + tenantCallsCount.put(tenantName, tenantCallsCount.get(tenantName) + 1); + } + + /** + * + * @param tenantName name of the tenant. + * @return the count of the tenant. + */ + public static int getCount(String tenantName) { + return tenantCallsCount.get(tenantName); + } + + /** + * Resets the count of all the tenants in the map. + */ + public static void reset() { + for (Entry e : tenantCallsCount.entrySet()) { + tenantCallsCount.put(e.getKey(), 0); + } + } +} diff --git a/throttling/src/main/java/com/iluwatar/throttling/Tenant.java b/throttling/src/main/java/com/iluwatar/throttling/Tenant.java new file mode 100644 index 000000000..a720e154b --- /dev/null +++ b/throttling/src/main/java/com/iluwatar/throttling/Tenant.java @@ -0,0 +1,57 @@ +/** + * The MIT License + * Copyright (c) 2014 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.throttling; + +import java.security.InvalidParameterException; + +/** + * A Pojo class to create a basic Tenant with the allowed calls per second. + */ +public class Tenant { + + private String name; + private int allowedCallsPerSecond; + + /** + * + * @param name Name of the tenant + * @param allowedCallsPerSecond The number of calls allowed for a particular tenant. + * @throws InvalidParameterException If number of calls is less than 0, throws exception. + */ + public Tenant(String name, int allowedCallsPerSecond) { + if (allowedCallsPerSecond < 0) { + throw new InvalidParameterException("Number of calls less than 0 not allowed"); + } + this.name = name; + this.allowedCallsPerSecond = allowedCallsPerSecond; + CallsCount.addTenant(name); + } + + public String getName() { + return name; + } + + public int getAllowedCallsPerSecond() { + return allowedCallsPerSecond; + } +} diff --git a/throttling/src/main/java/com/iluwatar/throttling/timer/ThrottleTimerImpl.java b/throttling/src/main/java/com/iluwatar/throttling/timer/ThrottleTimerImpl.java new file mode 100644 index 000000000..51c5e3c28 --- /dev/null +++ b/throttling/src/main/java/com/iluwatar/throttling/timer/ThrottleTimerImpl.java @@ -0,0 +1,58 @@ +/** + * The MIT License + * Copyright (c) 2014 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.throttling.timer; + +import java.util.Timer; +import java.util.TimerTask; + +import com.iluwatar.throttling.CallsCount; + +/** + * Implementation of throttler interface. This class resets the counter every second. + * @author drastogi + * + */ +public class ThrottleTimerImpl implements Throttler{ + + private int throttlePeriod; + + public ThrottleTimerImpl(int throttlePeriod) { + this.throttlePeriod = throttlePeriod; + } + + /** + * A timer is initiated with this method. The timer runs every second and resets the + * counter. + */ + public void start() { + new Timer(true).schedule(new TimerTask() { + @Override + public void run() { + CallsCount.reset(); + } + }, 0, throttlePeriod); + } +} diff --git a/throttling/src/main/java/com/iluwatar/throttling/timer/Throttler.java b/throttling/src/main/java/com/iluwatar/throttling/timer/Throttler.java new file mode 100644 index 000000000..24b73d92f --- /dev/null +++ b/throttling/src/main/java/com/iluwatar/throttling/timer/Throttler.java @@ -0,0 +1,36 @@ +/** + * The MIT License + * Copyright (c) 2014 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.throttling.timer; + +/** + * An interface for defining the structure of different types of throttling ways. + * @author drastogi + * + */ +public interface Throttler { + + void start(); +} diff --git a/throttling/src/test/java/com/iluwatar/throttling/AppTest.java b/throttling/src/test/java/com/iluwatar/throttling/AppTest.java new file mode 100644 index 000000000..37c8e75ec --- /dev/null +++ b/throttling/src/test/java/com/iluwatar/throttling/AppTest.java @@ -0,0 +1,37 @@ +/** + * The MIT License + * Copyright (c) 2014 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.throttling; + +import org.junit.Test; + +/** + * Application test + */ +public class AppTest { + + @Test + public void test() { + final String[] args = {}; + App.main(args); + } +} diff --git a/throttling/src/test/java/com/iluwatar/throttling/B2BServiceTest.java b/throttling/src/test/java/com/iluwatar/throttling/B2BServiceTest.java new file mode 100644 index 000000000..b9ca1a1d8 --- /dev/null +++ b/throttling/src/test/java/com/iluwatar/throttling/B2BServiceTest.java @@ -0,0 +1,49 @@ +/** + * The MIT License + * Copyright (c) 2014 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.throttling; + +import org.junit.Assert; +import org.junit.Test; + +import com.iluwatar.throttling.timer.ThrottleTimerImpl; +import com.iluwatar.throttling.timer.Throttler; + +/** + * B2BServiceTest class to test the B2BService + */ +public class B2BServiceTest { + + @Test + public void dummyCustomerApiTest() { + Tenant tenant = new Tenant("testTenant", 2); + Throttler timer = new ThrottleTimerImpl(10); + B2BService service = new B2BService(timer); + + for (int i = 0; i < 5; i++) { + service.dummyCustomerApi(tenant); + } + + int counter = CallsCount.getCount(tenant.getName()); + Assert.assertTrue("Counter limit must be reached", counter == 2); + } +} diff --git a/throttling/src/test/java/com/iluwatar/throttling/TenantTest.java b/throttling/src/test/java/com/iluwatar/throttling/TenantTest.java new file mode 100644 index 000000000..2f0b5cf12 --- /dev/null +++ b/throttling/src/test/java/com/iluwatar/throttling/TenantTest.java @@ -0,0 +1,40 @@ +/** + * The MIT License + * Copyright (c) 2014 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.throttling; + +import org.junit.Test; + +import com.iluwatar.throttling.Tenant; + +import java.security.InvalidParameterException; + +/** + * TenantTest to test the creation of Tenant with valid parameters. + */ +public class TenantTest { + + @Test(expected = InvalidParameterException.class) + public void constructorTest() { + Tenant tenant = new Tenant("FailTenant", -1); + } +}