提交 d9a567cf 编写于 作者: A AnaghaSasikumar 提交者: Ilkka Seppälä

Commander pattern #505 (#857)

* Commander pattern

* Fix checkstyle errors

* Update Commander.java

* Update README.md

* Update PaymentService.java

* Update Commander.java

* Update README.md
上级 a113de6a
---
layout: pattern
title: Commander
folder: commander
permalink: /patterns/commander/
categories:
tags:
- Java
- Difficulty-Intermediate
---
## Intent
> Used to handle all problems that can be encountered when doing distributed transactions.
## Applicability
This pattern can be used when we need to make commits into 2 (or more) databases to complete transaction, which cannot be done atomically and can thereby create problems.
## Explanation
Handling distributed transactions can be tricky, but if we choose to not handle it carefully, there could be unwanted consequences. Say, we have an e-commerce website which has a Payment microservice and a Shipping microservice. If the shipping is available currently but payment service is not up, or vice versa, how would we deal with it after having already received the order from the user?
We need a mechanism in place which can handle these kinds of situations. We have to direct the order to either one of the services (in this example, shipping) and then add the order into the database of the other service (in this example, payment), since two databses cannot be updated atomically. If currently unable to do it, there should be a queue where this request can be queued, and there has to be a mechanism which allows for a failure in the queueing as well. All this needs to be done by constant retries while ensuring idempotence (even if the request is made several times, the change should only be applied once) by a commander class, to reach a state of eventual consistency.
## Credits
* [https://www.grahamlea.com/2016/08/distributed-transactions-microservices-icebergs/]
<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.21.0-SNAPSHOT</version>
</parent>
<artifactId>commander</artifactId>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
</project>
\ No newline at end of file
#Define root logger options
log4j.rootLogger=TRACE, file, console
#Define console appender
log4j.appender.console=org.apache.log4j.ConsoleAppender
logrj.appender.console.Target=System.out
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d{yyyy-MM-dd} %d{HH:mm:ss} %5p[%t] %m%n
#Define rolling file appender
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.File=/log/logFile.log
log4j.appender.file.Append=true
log4j.appender.file.ImmediateFlush=true
log4j.appender.file.MaxFileSize=10MB
log4j.appender.file.MaxBackupIndex=5
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d %d{HH:mm:ss} %5p[%t] %m%n
/**
* 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.commander;
import com.iluwatar.commander.employeehandle.EmployeeDatabase;
import com.iluwatar.commander.employeehandle.EmployeeHandle;
import com.iluwatar.commander.exceptions.DatabaseUnavailableException;
import com.iluwatar.commander.exceptions.ItemUnavailableException;
import com.iluwatar.commander.messagingservice.MessagingDatabase;
import com.iluwatar.commander.messagingservice.MessagingService;
import com.iluwatar.commander.paymentservice.PaymentDatabase;
import com.iluwatar.commander.paymentservice.PaymentService;
import com.iluwatar.commander.shippingservice.ShippingDatabase;
import com.iluwatar.commander.shippingservice.ShippingService;
import com.iluwatar.commander.queue.QueueDatabase;
/**
* AppEmployeeDbFailCases class looks at possible cases when Employee handle service is
* available/unavailable.
*/
public class AppEmployeeDbFailCases {
final int numOfRetries = 3;
final long retryDuration = 30000;
final long queueTime = 240000; //4 mins
final long queueTaskTime = 60000; //1 min
final long paymentTime = 120000; //2 mins
final long messageTime = 150000; //2.5 mins
final long employeeTime = 240000; //4 mins
void employeeDatabaseUnavailableCase() throws Exception {
PaymentService ps = new PaymentService(new PaymentDatabase(), new DatabaseUnavailableException(),
new DatabaseUnavailableException(), new DatabaseUnavailableException(), new DatabaseUnavailableException(),
new DatabaseUnavailableException(), new DatabaseUnavailableException());
ShippingService ss = new ShippingService(new ShippingDatabase());
MessagingService ms = new MessagingService(new MessagingDatabase());
EmployeeHandle eh = new EmployeeHandle(new EmployeeDatabase(), new DatabaseUnavailableException(),
new DatabaseUnavailableException(), new DatabaseUnavailableException(), new DatabaseUnavailableException(),
new DatabaseUnavailableException(), new DatabaseUnavailableException());
QueueDatabase qdb = new QueueDatabase(new DatabaseUnavailableException(), new DatabaseUnavailableException(),
new DatabaseUnavailableException(), new DatabaseUnavailableException(), new DatabaseUnavailableException(),
new DatabaseUnavailableException());
Commander c = new Commander(eh,ps,ss,ms,qdb,numOfRetries,retryDuration,
queueTime,queueTaskTime,paymentTime,messageTime,employeeTime);
User user = new User("Jim", "ABCD");
Order order = new Order(user, "book", 10f);
c.placeOrder(order);
}
void employeeDbSuccessCase() throws Exception {
PaymentService ps = new PaymentService(new PaymentDatabase());
ShippingService ss = new ShippingService(new ShippingDatabase(), new ItemUnavailableException());
MessagingService ms = new MessagingService(new MessagingDatabase());
EmployeeHandle eh = new EmployeeHandle(new EmployeeDatabase(), new DatabaseUnavailableException(),
new DatabaseUnavailableException());
QueueDatabase qdb = new QueueDatabase();
Commander c = new Commander(eh,ps,ss,ms,qdb,numOfRetries,retryDuration,
queueTime,queueTaskTime,paymentTime,messageTime,employeeTime);
User user = new User("Jim", "ABCD");
Order order = new Order(user, "book", 10f);
c.placeOrder(order);
}
/**
* Program entry point.
*
* @param args command line args
*/
public static void main(String[] args) throws Exception {
AppEmployeeDbFailCases aefc = new AppEmployeeDbFailCases();
//aefc.employeeDatabaseUnavailableCase();
aefc.employeeDbSuccessCase();
}
}
/**
* 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.commander;
import com.iluwatar.commander.employeehandle.EmployeeDatabase;
import com.iluwatar.commander.employeehandle.EmployeeHandle;
import com.iluwatar.commander.exceptions.DatabaseUnavailableException;
import com.iluwatar.commander.messagingservice.MessagingDatabase;
import com.iluwatar.commander.messagingservice.MessagingService;
import com.iluwatar.commander.paymentservice.PaymentDatabase;
import com.iluwatar.commander.paymentservice.PaymentService;
import com.iluwatar.commander.shippingservice.ShippingDatabase;
import com.iluwatar.commander.shippingservice.ShippingService;
import com.iluwatar.commander.queue.QueueDatabase;
/**
* AppMessagingFailCases class looks at possible cases when Messaging service is
* available/unavailable.
*/
public class AppMessagingFailCases {
final int numOfRetries = 3;
final long retryDuration = 30000;
final long queueTime = 240000; //4 mins
final long queueTaskTime = 60000; //1 min
final long paymentTime = 120000; //2 mins
final long messageTime = 150000; //2.5 mins
final long employeeTime = 240000; //4 mins
void messagingDatabaseUnavailableCasePaymentSuccess() throws Exception {
//rest is successful
PaymentService ps = new PaymentService(new PaymentDatabase());
ShippingService ss = new ShippingService(new ShippingDatabase());
MessagingService ms = new MessagingService(new MessagingDatabase(), new DatabaseUnavailableException(),
new DatabaseUnavailableException(), new DatabaseUnavailableException(), new DatabaseUnavailableException(),
new DatabaseUnavailableException(), new DatabaseUnavailableException());
EmployeeHandle eh = new EmployeeHandle(new EmployeeDatabase());
QueueDatabase qdb = new QueueDatabase();
Commander c = new Commander(eh,ps,ss,ms,qdb,numOfRetries,retryDuration,
queueTime,queueTaskTime,paymentTime,messageTime,employeeTime);
User user = new User("Jim", "ABCD");
Order order = new Order(user, "book", 10f);
c.placeOrder(order);
}
void messagingDatabaseUnavailableCasePaymentError() throws Exception {
//rest is successful
PaymentService ps = new PaymentService(new PaymentDatabase(), new DatabaseUnavailableException(),
new DatabaseUnavailableException(), new DatabaseUnavailableException(), new DatabaseUnavailableException(),
new DatabaseUnavailableException(), new DatabaseUnavailableException());
ShippingService ss = new ShippingService(new ShippingDatabase());
MessagingService ms = new MessagingService(new MessagingDatabase(), new DatabaseUnavailableException(),
new DatabaseUnavailableException(), new DatabaseUnavailableException(), new DatabaseUnavailableException(),
new DatabaseUnavailableException(), new DatabaseUnavailableException(), new DatabaseUnavailableException(),
new DatabaseUnavailableException(), new DatabaseUnavailableException(), new DatabaseUnavailableException(),
new DatabaseUnavailableException(), new DatabaseUnavailableException(), new DatabaseUnavailableException(),
new DatabaseUnavailableException(), new DatabaseUnavailableException(), new DatabaseUnavailableException());
EmployeeHandle eh = new EmployeeHandle(new EmployeeDatabase());
QueueDatabase qdb = new QueueDatabase();
Commander c = new Commander(eh,ps,ss,ms,qdb,numOfRetries,retryDuration,
queueTime,queueTaskTime,paymentTime,messageTime,employeeTime);
User user = new User("Jim", "ABCD");
Order order = new Order(user, "book", 10f);
c.placeOrder(order);
}
void messagingDatabaseUnavailableCasePaymentFailure() throws Exception {
//rest is successful
PaymentService ps = new PaymentService(new PaymentDatabase(), new DatabaseUnavailableException(),
new DatabaseUnavailableException(), new DatabaseUnavailableException(), new DatabaseUnavailableException(),
new DatabaseUnavailableException(), new DatabaseUnavailableException());
ShippingService ss = new ShippingService(new ShippingDatabase());
MessagingService ms = new MessagingService(new MessagingDatabase(), new DatabaseUnavailableException(),
new DatabaseUnavailableException(), new DatabaseUnavailableException(), new DatabaseUnavailableException(),
new DatabaseUnavailableException(), new DatabaseUnavailableException());
EmployeeHandle eh = new EmployeeHandle(new EmployeeDatabase());
QueueDatabase qdb = new QueueDatabase(new DatabaseUnavailableException(), new DatabaseUnavailableException(),
new DatabaseUnavailableException(), new DatabaseUnavailableException(), new DatabaseUnavailableException(),
new DatabaseUnavailableException());
Commander c = new Commander(eh,ps,ss,ms,qdb,numOfRetries,retryDuration,queueTime,queueTaskTime,
paymentTime,messageTime,employeeTime);
User user = new User("Jim", "ABCD");
Order order = new Order(user, "book", 10f);
c.placeOrder(order);
}
void messagingSuccessCase() throws Exception {
//done here
PaymentService ps = new PaymentService(new PaymentDatabase(), new DatabaseUnavailableException(),
new DatabaseUnavailableException(), new DatabaseUnavailableException(), new DatabaseUnavailableException(),
new DatabaseUnavailableException(), new DatabaseUnavailableException());
ShippingService ss = new ShippingService(new ShippingDatabase());
MessagingService ms = new MessagingService(new MessagingDatabase(), new DatabaseUnavailableException(),
new DatabaseUnavailableException());
EmployeeHandle eh = new EmployeeHandle(new EmployeeDatabase());
QueueDatabase qdb = new QueueDatabase();
Commander c = new Commander(eh,ps,ss,ms,qdb,numOfRetries,retryDuration,
queueTime,queueTaskTime,paymentTime,messageTime,employeeTime);
User user = new User("Jim", "ABCD");
Order order = new Order(user, "book", 10f);
c.placeOrder(order);
}
/**
* Program entry point.
*
* @param args command line args
*/
public static void main(String[] args) throws Exception {
AppMessagingFailCases amfc = new AppMessagingFailCases();
//amfc.messagingDatabaseUnavailableCasePaymentSuccess();
//amfc.messagingDatabaseUnavailableCasePaymentError();
//amfc.messagingDatabaseUnavailableCasePaymentFailure();
amfc.messagingSuccessCase();
}
}
/**
* 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.commander;
import com.iluwatar.commander.employeehandle.EmployeeDatabase;
import com.iluwatar.commander.employeehandle.EmployeeHandle;
import com.iluwatar.commander.exceptions.DatabaseUnavailableException;
import com.iluwatar.commander.exceptions.PaymentDetailsErrorException;
import com.iluwatar.commander.messagingservice.MessagingDatabase;
import com.iluwatar.commander.messagingservice.MessagingService;
import com.iluwatar.commander.paymentservice.PaymentDatabase;
import com.iluwatar.commander.paymentservice.PaymentService;
import com.iluwatar.commander.shippingservice.ShippingDatabase;
import com.iluwatar.commander.shippingservice.ShippingService;
import com.iluwatar.commander.queue.QueueDatabase;
/**
* AppPaymentFailCases class looks at possible cases when Payment service is
* available/unavailable.
*/
public class AppPaymentFailCases {
final int numOfRetries = 3;
final long retryDuration = 30000;
final long queueTime = 240000; //4 mins
final long queueTaskTime = 60000; //1 min
final long paymentTime = 120000; //2 mins
final long messageTime = 150000; //2.5 mins
final long employeeTime = 240000; //4 mins
void paymentNotPossibleCase() throws Exception {
PaymentService ps = new PaymentService(new PaymentDatabase(), new DatabaseUnavailableException(),
new PaymentDetailsErrorException());
ShippingService ss = new ShippingService(new ShippingDatabase());
MessagingService ms = new MessagingService(new MessagingDatabase(), new DatabaseUnavailableException());
EmployeeHandle eh = new EmployeeHandle(new EmployeeDatabase());
QueueDatabase qdb = new QueueDatabase(new DatabaseUnavailableException());
Commander c = new Commander(eh,ps,ss,ms,qdb,numOfRetries,retryDuration,
queueTime,queueTaskTime,paymentTime,messageTime,employeeTime);
User user = new User("Jim", "ABCD");
Order order = new Order(user, "book", 10f);
c.placeOrder(order);
}
void paymentDatabaseUnavailableCase() throws Exception {
//rest is successful
PaymentService ps = new PaymentService(new PaymentDatabase(), new DatabaseUnavailableException(),
new DatabaseUnavailableException(), new DatabaseUnavailableException(), new DatabaseUnavailableException(),
new DatabaseUnavailableException(), new DatabaseUnavailableException());
ShippingService ss = new ShippingService(new ShippingDatabase());
MessagingService ms = new MessagingService(new MessagingDatabase());
EmployeeHandle eh = new EmployeeHandle(new EmployeeDatabase());
QueueDatabase qdb = new QueueDatabase();
Commander c = new Commander(eh,ps,ss,ms,qdb,numOfRetries,retryDuration,
queueTime,queueTaskTime,paymentTime,messageTime,employeeTime);
User user = new User("Jim", "ABCD");
Order order = new Order(user, "book", 10f);
c.placeOrder(order);
}
void paymentSuccessCase() throws Exception {
//goes to message after 2 retries maybe - rest is successful for now
PaymentService ps = new PaymentService(new PaymentDatabase(), new DatabaseUnavailableException(),
new DatabaseUnavailableException());
ShippingService ss = new ShippingService(new ShippingDatabase());
MessagingService ms = new MessagingService(new MessagingDatabase(), new DatabaseUnavailableException());
EmployeeHandle eh = new EmployeeHandle(new EmployeeDatabase());
QueueDatabase qdb = new QueueDatabase(new DatabaseUnavailableException());
Commander c = new Commander(eh,ps,ss,ms,qdb,numOfRetries,retryDuration,
queueTime,queueTaskTime,paymentTime,messageTime,employeeTime);
User user = new User("Jim", "ABCD");
Order order = new Order(user, "book", 10f);
c.placeOrder(order);
}
/**
* Program entry point.
*
* @param args command line args
*/
public static void main(String[] args) throws Exception {
AppPaymentFailCases apfc = new AppPaymentFailCases();
//apfc.paymentNotPossibleCase();
//apfc.paymentDatabaseUnavailableCase();
apfc.paymentSuccessCase();
}
}
/**
* 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.commander;
import com.iluwatar.commander.employeehandle.EmployeeDatabase;
import com.iluwatar.commander.employeehandle.EmployeeHandle;
import com.iluwatar.commander.exceptions.DatabaseUnavailableException;
import com.iluwatar.commander.exceptions.ItemUnavailableException;
import com.iluwatar.commander.messagingservice.MessagingDatabase;
import com.iluwatar.commander.messagingservice.MessagingService;
import com.iluwatar.commander.paymentservice.PaymentDatabase;
import com.iluwatar.commander.paymentservice.PaymentService;
import com.iluwatar.commander.shippingservice.ShippingDatabase;
import com.iluwatar.commander.shippingservice.ShippingService;
import com.iluwatar.commander.queue.QueueDatabase;
/**
* AppQueueFailCases class looks at possible cases when Queue Database is
* available/unavailable.
*/
public class AppQueueFailCases {
final int numOfRetries = 3;
final long retryDuration = 30000;
final long queueTime = 240000; //4 mins
final long queueTaskTime = 60000; //1 min
final long paymentTime = 120000; //2 mins
final long messageTime = 150000; //2.5 mins
final long employeeTime = 240000; //4 mins
void queuePaymentTaskDatabaseUnavailableCase() throws Exception {
PaymentService ps = new PaymentService(new PaymentDatabase(), new DatabaseUnavailableException(),
new DatabaseUnavailableException(), new DatabaseUnavailableException(), new DatabaseUnavailableException(),
new DatabaseUnavailableException(), new DatabaseUnavailableException());
ShippingService ss = new ShippingService(new ShippingDatabase());
MessagingService ms = new MessagingService(new MessagingDatabase());
EmployeeHandle eh = new EmployeeHandle(new EmployeeDatabase());
QueueDatabase qdb = new QueueDatabase(new DatabaseUnavailableException(), new DatabaseUnavailableException(),
new DatabaseUnavailableException(), new DatabaseUnavailableException(), new DatabaseUnavailableException(),
new DatabaseUnavailableException());
Commander c = new Commander(eh,ps,ss,ms,qdb,numOfRetries,retryDuration,
queueTime,queueTaskTime,paymentTime,messageTime,employeeTime);
User user = new User("Jim", "ABCD");
Order order = new Order(user, "book", 10f);
c.placeOrder(order);
}
void queueMessageTaskDatabaseUnavailableCase() throws Exception {
PaymentService ps = new PaymentService(new PaymentDatabase());
ShippingService ss = new ShippingService(new ShippingDatabase());
MessagingService ms = new MessagingService(new MessagingDatabase(), new DatabaseUnavailableException(),
new DatabaseUnavailableException(), new DatabaseUnavailableException(), new DatabaseUnavailableException(),
new DatabaseUnavailableException(), new DatabaseUnavailableException());
EmployeeHandle eh = new EmployeeHandle(new EmployeeDatabase());
QueueDatabase qdb = new QueueDatabase(new DatabaseUnavailableException(), new DatabaseUnavailableException(),
new DatabaseUnavailableException(), new DatabaseUnavailableException(), new DatabaseUnavailableException(),
new DatabaseUnavailableException());
Commander c = new Commander(eh,ps,ss,ms,qdb,numOfRetries,retryDuration,
queueTime,queueTaskTime,paymentTime,messageTime,employeeTime);
User user = new User("Jim", "ABCD");
Order order = new Order(user, "book", 10f);
c.placeOrder(order);
}
void queueEmployeeDbTaskDatabaseUnavailableCase() throws Exception {
PaymentService ps = new PaymentService(new PaymentDatabase());
ShippingService ss = new ShippingService(new ShippingDatabase(), new ItemUnavailableException());
MessagingService ms = new MessagingService(new MessagingDatabase());
EmployeeHandle eh = new EmployeeHandle(new EmployeeDatabase(), new DatabaseUnavailableException(),
new DatabaseUnavailableException(), new DatabaseUnavailableException(), new DatabaseUnavailableException(),
new DatabaseUnavailableException(), new DatabaseUnavailableException(), new DatabaseUnavailableException(),
new DatabaseUnavailableException(), new DatabaseUnavailableException(), new DatabaseUnavailableException(),
new DatabaseUnavailableException(), new DatabaseUnavailableException());
QueueDatabase qdb = new QueueDatabase(new DatabaseUnavailableException(), new DatabaseUnavailableException(),
new DatabaseUnavailableException(), new DatabaseUnavailableException(), new DatabaseUnavailableException(),
new DatabaseUnavailableException(), new DatabaseUnavailableException(), new DatabaseUnavailableException(),
new DatabaseUnavailableException(), new DatabaseUnavailableException(), new DatabaseUnavailableException(),
new DatabaseUnavailableException());
Commander c = new Commander(eh,ps,ss,ms,qdb,numOfRetries,retryDuration,
queueTime,queueTaskTime,paymentTime,messageTime,employeeTime);
User user = new User("Jim", "ABCD");
Order order = new Order(user, "book", 10f);
c.placeOrder(order);
}
void queueSuccessCase() throws Exception {
PaymentService ps = new PaymentService(new PaymentDatabase(), new DatabaseUnavailableException(),
new DatabaseUnavailableException(), new DatabaseUnavailableException(), new DatabaseUnavailableException(),
new DatabaseUnavailableException(), new DatabaseUnavailableException());
ShippingService ss = new ShippingService(new ShippingDatabase());
MessagingService ms = new MessagingService(new MessagingDatabase(), new DatabaseUnavailableException(),
new DatabaseUnavailableException());
EmployeeHandle eh = new EmployeeHandle(new EmployeeDatabase());
QueueDatabase qdb = new QueueDatabase(new DatabaseUnavailableException(), new DatabaseUnavailableException());
Commander c = new Commander(eh,ps,ss,ms,qdb,numOfRetries,retryDuration,
queueTime,queueTaskTime,paymentTime,messageTime,employeeTime);
User user = new User("Jim", "ABCD");
Order order = new Order(user, "book", 10f);
c.placeOrder(order);
}
/**
* Program entry point.
*
* @param args command line args
*/
public static void main(String[] args) throws Exception {
AppQueueFailCases aqfc = new AppQueueFailCases();
//aqfc.queuePaymentTaskDatabaseUnavailableCase();
//aqfc.queueMessageTaskDatabaseUnavailableCase();
//aqfc.queueEmployeeDbTaskDatabaseUnavailableCase();
aqfc.queueSuccessCase();
}
}
/**
* 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.commander;
import com.iluwatar.commander.employeehandle.EmployeeDatabase;
import com.iluwatar.commander.employeehandle.EmployeeHandle;
import com.iluwatar.commander.exceptions.DatabaseUnavailableException;
import com.iluwatar.commander.exceptions.ItemUnavailableException;
import com.iluwatar.commander.exceptions.ShippingNotPossibleException;
import com.iluwatar.commander.messagingservice.MessagingDatabase;
import com.iluwatar.commander.messagingservice.MessagingService;
import com.iluwatar.commander.paymentservice.PaymentDatabase;
import com.iluwatar.commander.paymentservice.PaymentService;
import com.iluwatar.commander.shippingservice.ShippingDatabase;
import com.iluwatar.commander.shippingservice.ShippingService;
import com.iluwatar.commander.queue.QueueDatabase;
/**
* AppShippingFailCases class looks at possible cases when Shipping service is
* available/unavailable.
*/
public class AppShippingFailCases {
final int numOfRetries = 3;
final long retryDuration = 30000;
final long queueTime = 240000; //4 mins
final long queueTaskTime = 60000; //1 min
final long paymentTime = 120000; //2 mins
final long messageTime = 150000; //2.5 mins
final long employeeTime = 240000; //4 mins
void itemUnavailableCase() throws Exception {
PaymentService ps = new PaymentService(new PaymentDatabase());
ShippingService ss = new ShippingService(new ShippingDatabase(), new ItemUnavailableException());
MessagingService ms = new MessagingService(new MessagingDatabase());
EmployeeHandle eh = new EmployeeHandle(new EmployeeDatabase());
QueueDatabase qdb = new QueueDatabase();
Commander c = new Commander(eh,ps,ss,ms,qdb,numOfRetries,retryDuration,
queueTime,queueTaskTime,paymentTime,messageTime,employeeTime);
User user = new User("Jim", "ABCD");
Order order = new Order(user, "book", 10f);
c.placeOrder(order);
}
void shippingNotPossibleCase() throws Exception {
PaymentService ps = new PaymentService(new PaymentDatabase());
ShippingService ss = new ShippingService(new ShippingDatabase(), new ShippingNotPossibleException());
MessagingService ms = new MessagingService(new MessagingDatabase());
EmployeeHandle eh = new EmployeeHandle(new EmployeeDatabase());
QueueDatabase qdb = new QueueDatabase();
Commander c = new Commander(eh,ps,ss,ms,qdb,numOfRetries,retryDuration,
queueTime,queueTaskTime,paymentTime,messageTime,employeeTime);
User user = new User("Jim", "ABCD");
Order order = new Order(user, "book", 10f);
c.placeOrder(order);
}
void shippingDatabaseUnavailableCase() throws Exception {
//rest is successful
PaymentService ps = new PaymentService(new PaymentDatabase());
ShippingService ss = new ShippingService(new ShippingDatabase(), new DatabaseUnavailableException(),
new DatabaseUnavailableException(), new DatabaseUnavailableException(), new DatabaseUnavailableException(),
new DatabaseUnavailableException(), new DatabaseUnavailableException());
MessagingService ms = new MessagingService(new MessagingDatabase());
EmployeeHandle eh = new EmployeeHandle(new EmployeeDatabase());
QueueDatabase qdb = new QueueDatabase();
Commander c = new Commander(eh,ps,ss,ms,qdb,numOfRetries,retryDuration,
queueTime,queueTaskTime,paymentTime,messageTime,employeeTime);
User user = new User("Jim", "ABCD");
Order order = new Order(user, "book", 10f);
c.placeOrder(order);
}
void shippingSuccessCase() throws Exception {
//goes to payment after 2 retries maybe - rest is successful for now
PaymentService ps = new PaymentService(new PaymentDatabase(), new DatabaseUnavailableException());
ShippingService ss = new ShippingService(new ShippingDatabase(), new DatabaseUnavailableException(),
new DatabaseUnavailableException());
MessagingService ms = new MessagingService(new MessagingDatabase(), new DatabaseUnavailableException());
EmployeeHandle eh = new EmployeeHandle(new EmployeeDatabase());
QueueDatabase qdb = new QueueDatabase();
Commander c = new Commander(eh,ps,ss,ms,qdb,numOfRetries,retryDuration,
queueTime,queueTaskTime,paymentTime,messageTime,employeeTime);
User user = new User("Jim", "ABCD");
Order order = new Order(user, "book", 10f);
c.placeOrder(order);
}
/**
* Program entry point.
*
* @param args command line args
*/
public static void main(String[] args) throws Exception {
AppShippingFailCases asfc = new AppShippingFailCases();
//asfc.itemUnavailableCase();
//asfc.shippingNotPossibleCase();
//asfc.shippingDatabaseUnavailableCase();
asfc.shippingSuccessCase();
}
}
/**
* 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.commander;
import com.iluwatar.commander.exceptions.DatabaseUnavailableException;
/**
* Database abstract class is extended by all databases in our example. The add and get
* methods are used by the respective service to add to database or get from database.
* @param <T> T is the type of object being held by database.
*/
public abstract class Database<T> {
public abstract T add(T obj) throws DatabaseUnavailableException;
public abstract T get(String tId) throws DatabaseUnavailableException;
}
/**
* 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.commander;
import java.util.Hashtable;
import java.util.Random;
/**
* Order class holds details of the order.
*/
public class Order { //can store all transactions ids also
enum PaymentStatus {
NotDone, Trying, Done
};
enum MessageSent {
NoneSent, PaymentFail, PaymentTrying, PaymentSuccessful
};
final User user;
final String item;
public final String id;
final float price;
final long createdTime;
private static final String ALL_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
private static final Hashtable<String, Boolean> USED_IDS = new Hashtable<String, Boolean>();
PaymentStatus paid;
MessageSent messageSent; //to avoid sending error msg on page and text more than once
boolean addedToEmployeeHandle; //to avoid creating more to enqueue
Order(User user, String item, float price) {
this.createdTime = System.currentTimeMillis();
this.user = user;
this.item = item;
this.price = price;
String id = createUniqueId();
if (USED_IDS.get(id) != null) {
while (USED_IDS.get(id)) {
id = createUniqueId();
}
}
this.id = id;
USED_IDS.put(this.id, true);
this.paid = PaymentStatus.Trying;
this.messageSent = MessageSent.NoneSent;
this.addedToEmployeeHandle = false;
}
String createUniqueId() {
StringBuilder random = new StringBuilder();
Random rand = new Random();
while (random.length() < 12) { // length of the random string.
int index = (int) (rand.nextFloat() * ALL_CHARS.length());
random.append(ALL_CHARS.charAt(index));
}
return random.toString();
}
}
/**
* 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.commander;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Predicate;
/**
* Retry pattern
* @param <T> is the type of object passed into HandleErrorIssue as a parameter.
*/
public class Retry<T> {
/**
* Operation Interface will define method to be implemented.
*/
public interface Operation {
void operation(ArrayList<Exception> list) throws Exception;
}
/**
* HandleErrorIssue defines how to handle errors.
* @param <T> is the type of object to be passed into the method as parameter.
*/
public interface HandleErrorIssue<T> {
void handleIssue(T obj, Exception e);
}
private final Operation op;
private final HandleErrorIssue<T> handleError;
private final int maxAttempts;
private final long maxDelay;
private final AtomicInteger attempts;
private final Predicate<Exception> test;
private final ArrayList<Exception> errors;
Retry(Operation op, HandleErrorIssue handleError, int maxAttempts,
long maxDelay, Predicate<Exception>... ignoreTests) {
this.op = op;
this.handleError = handleError;
this.maxAttempts = maxAttempts;
this.maxDelay = maxDelay;
this.attempts = new AtomicInteger();
this.test = Arrays.stream(ignoreTests).reduce(Predicate::or).orElse(e -> false);
this.errors = new ArrayList<>();
}
/**
* Performing the operation with retries.
* @param list is the exception list
* @param obj is the parameter to be passed into handleIsuue method
*/
public void perform(ArrayList<Exception> list, T obj) throws Exception {
do {
try {
op.operation(list);
return;
} catch (Exception e) {
this.errors.add(e);
if (this.attempts.incrementAndGet() >= this.maxAttempts || !this.test.test(e)) {
this.handleError.handleIssue(obj, e);
return; //return here...dont go further
}
try {
Random rand = new Random();
long testDelay = (long) Math.pow(2, this.attempts.intValue()) * 1000 + rand.nextInt(1000);
long delay = testDelay < this.maxDelay ? testDelay : maxDelay;
Thread.sleep(delay);
} catch (InterruptedException f) {
//ignore
}
}
}
while (true);
}
}
/**
* 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.commander;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Hashtable;
import java.util.Random;
import com.iluwatar.commander.exceptions.DatabaseUnavailableException;
/**
* Service class is an abstract class extended by all services in this example. They
* all have a public receiveRequest method to receive requests, which could also contain
* details of the user other than the implementation details (though we are not doing
* that here) and updateDb method which adds to their respective databases. There is a
* method to generate transaction/request id for the transactions/requests, which are
* then sent back. These could be stored by the {@link Commander} class in a separate
* database for reference (though we are not doing that here).
*/
public abstract class Service {
protected final Database database;
public ArrayList<Exception> exceptionsList;
private static final String ALL_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
private static final Hashtable<String, Boolean> USED_IDS = new Hashtable<String, Boolean>();
protected Service(Database db, Exception...exc) {
this.database = db;
this.exceptionsList = new ArrayList<Exception>(Arrays.asList(exc));
}
public abstract String receiveRequest(Object...parameters) throws DatabaseUnavailableException;
protected abstract String updateDb(Object...parameters) throws DatabaseUnavailableException;
protected String generateId() {
StringBuilder random = new StringBuilder();
Random rand = new Random();
while (random.length() < 12) { // length of the random string.
int index = (int) (rand.nextFloat() * ALL_CHARS.length());
random.append(ALL_CHARS.charAt(index));
}
String id = random.toString();
if (USED_IDS.get(id) != null) {
while (USED_IDS.get(id)) {
id = generateId();
}
}
return id;
}
}
/**
* 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.commander;
/**
* User class contains details of user who places order.
*/
public class User {
String name;
String address;
User(String name, String address) {
this.name = name;
this.address = address;
}
}
/**
* 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.commander.employeehandle;
import java.util.Hashtable;
import com.iluwatar.commander.Database;
import com.iluwatar.commander.Order;
import com.iluwatar.commander.exceptions.DatabaseUnavailableException;
/**
* The Employee Database is where orders which have encountered some issue(s) are added.
*/
public class EmployeeDatabase extends Database<Order> {
private Hashtable<String, Order> data;
public EmployeeDatabase() {
this.data = new Hashtable<String, Order>();
}
@Override
public Order add(Order o) throws DatabaseUnavailableException {
return data.put(o.id,o);
}
@Override
public Order get(String oId) throws DatabaseUnavailableException {
return data.get(oId);
}
}
/**
* 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.commander.employeehandle;
import com.iluwatar.commander.Order;
import com.iluwatar.commander.Service;
import com.iluwatar.commander.exceptions.DatabaseUnavailableException;
/**
* The EmployeeHandle class is the middle-man between {@link Commander} and
* {@link EmployeeDatabase}.
*/
public class EmployeeHandle extends Service {
public EmployeeHandle(EmployeeDatabase db, Exception...exc) {
super(db, exc);
}
public String receiveRequest(Object...parameters) throws DatabaseUnavailableException {
return updateDb((Order)parameters[0]);
}
protected String updateDb(Object...parameters) throws DatabaseUnavailableException {
Order o = (Order) parameters[0];
if (database.get(o.id) == null) {
database.add(o);
return o.id; //true rcvd - change addedToEmployeeHandle to true else dont do anything
}
return null;
}
}
/**
* 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.commander.exceptions;
/**
* DatabaseUnavailableException is thrown when database is unavailable and nothing
* can be added or retrieved.
*/
public class DatabaseUnavailableException extends Exception {
private static final long serialVersionUID = 2459603L;
}
/**
* 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.commander.exceptions;
/**
* IsEmptyException is thrown when it is attempted to dequeue from an empty queue.
*/
public class IsEmptyException extends Exception {
private static final long serialVersionUID = 123546L;
}
/**
* 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.commander.exceptions;
/**
* ItemUnavailableException is thrown when item is not available for shipping.
*/
public class ItemUnavailableException extends Exception {
private static final long serialVersionUID = 575940L;
}
/**
* 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.commander.exceptions;
/**
* PaymentDetailsErrorException is thrown when the details entered are incorrect or
* payment cannot be made with the details given.
*/
public class PaymentDetailsErrorException extends Exception {
private static final long serialVersionUID = 867203L;
}
/**
* 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.commander.exceptions;
/**
* ShippingNotPossibleException is thrown when the address entered cannot be shipped to
* by service currently for some reason.
*/
public class ShippingNotPossibleException extends Exception {
private static final long serialVersionUID = 342055L;
}
/**
* 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.commander.messagingservice;
import java.util.Hashtable;
import com.iluwatar.commander.Database;
import com.iluwatar.commander.exceptions.DatabaseUnavailableException;
import com.iluwatar.commander.messagingservice.MessagingService.MessageRequest;
/**
* The MessagingDatabase is where the MessageRequest is added.
*/
public class MessagingDatabase extends Database<MessageRequest> {
private Hashtable<String, MessageRequest> data;
public MessagingDatabase() {
this.data = new Hashtable<String, MessageRequest>();
}
@Override
public MessageRequest add(MessageRequest r) throws DatabaseUnavailableException {
return data.put(r.reqId, r);
}
@Override
public MessageRequest get(String rId) throws DatabaseUnavailableException {
return data.get(rId);
}
}
/**
* 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.commander.messagingservice;
import com.iluwatar.commander.Service;
import com.iluwatar.commander.exceptions.DatabaseUnavailableException;
/**
* The MessagingService is used to send messages to user regarding their order and
* payment status. In case an error is encountered in payment and this service is
* found to be unavailable, the order is added to the {@link EmployeeDatabase}.
*/
public class MessagingService extends Service {
enum MessageToSend {
PaymentFail, PaymentTrying, PaymentSuccessful
};
class MessageRequest {
String reqId;
MessageToSend msg;
MessageRequest(String reqId, MessageToSend msg) {
this.reqId = reqId;
this.msg = msg;
}
}
public MessagingService(MessagingDatabase db, Exception...exc) {
super(db, exc);
}
/**
* Public method which will receive request from {@link Commander}.
*/
public String receiveRequest(Object...parameters) throws DatabaseUnavailableException {
int messageToSend = (int) parameters[0];
String rId = generateId();
MessageToSend msg = null;
if (messageToSend == 0) {
msg = MessageToSend.PaymentFail;
} else if (messageToSend == 1) {
msg = MessageToSend.PaymentTrying;
} else { //messageToSend == 2
msg = MessageToSend.PaymentSuccessful;
}
MessageRequest req = new MessageRequest(rId, msg);
return updateDb(req);
}
protected String updateDb(Object...parameters) throws DatabaseUnavailableException {
MessageRequest req = (MessageRequest) parameters[0];
if (this.database.get(req.reqId) == null) { //idempotence, in case db fails here
database.add(req); //if successful:
System.out.println(sendMessage(req.msg));
return req.reqId;
}
return null;
}
String sendMessage(MessageToSend m) {
if (m.equals(MessageToSend.PaymentSuccessful)) {
return "Msg: Your order has been placed and paid for successfully! Thank you for shopping with us!";
} else if (m.equals(MessageToSend.PaymentTrying)) {
return "Msg: There was an error in your payment process, we are working on it and will return back to you"
+ " shortly. Meanwhile, your order has been placed and will be shipped.";
} else {
return "Msg: There was an error in your payment process. Your order is placed and has been converted to COD."
+ " Please reach us on CUSTOMER-CARE-NUBER in case of any queries. Thank you for shopping with us!";
}
}
}
/**
* 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.commander.paymentservice;
import java.util.Hashtable;
import com.iluwatar.commander.Database;
import com.iluwatar.commander.exceptions.DatabaseUnavailableException;
import com.iluwatar.commander.paymentservice.PaymentService.PaymentRequest;
/**
* PaymentDatabase is where the PaymentRequest is added, along with details.
*/
public class PaymentDatabase extends Database<PaymentRequest> {
private Hashtable<String, PaymentRequest> data;
public PaymentDatabase() {
this.data = new Hashtable<String, PaymentRequest>();
//0-fail, 1-error, 2-success
}
@Override
public PaymentRequest add(PaymentRequest r) throws DatabaseUnavailableException {
return data.put(r.transactionId, r);
}
@Override
public PaymentRequest get(String tId) throws DatabaseUnavailableException {
return data.get(tId);
}
}
/**
* 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.commander.paymentservice;
import com.iluwatar.commander.Service;
import com.iluwatar.commander.exceptions.DatabaseUnavailableException;
/**
* The PaymentService class receives request from the {@link Commander} and adds
* to the {@link PaymentDatabase}.
*/
public class PaymentService extends Service {
class PaymentRequest {
String transactionId;
float payment;
boolean paid;
PaymentRequest(String transactionId, float payment) {
this.transactionId = transactionId;
this.payment = payment;
this.paid = false;
}
}
public PaymentService(PaymentDatabase db, Exception...exc) {
super(db, exc);
}
/**
* Public method which will receive request from {@link Commander}.
*/
public String receiveRequest(Object...parameters) throws DatabaseUnavailableException {
//it could also be sending a userid, payment details here or something, not added here
String tId = generateId();
PaymentRequest req = new PaymentRequest(tId, (float)parameters[0]);
return updateDb(req);
}
protected String updateDb(Object...parameters) throws DatabaseUnavailableException {
PaymentRequest req = (PaymentRequest) parameters[0];
if (database.get(req.transactionId) == null || !req.paid) {
database.add(req);
req.paid = true;
return req.transactionId;
}
return null;
}
}
/**
* 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.commander.queue;
import com.iluwatar.commander.exceptions.IsEmptyException;
/**
* Queue data structure implementation.
* @param <T> is the type of object the queue will hold.
*/
public class Queue<T> {
Node<T> front;
Node<T> rear;
public int size = 0;
class Node<T> {
T value;
Node<T> next;
Node(T obj, Node<T> b) {
value = obj;
next = b;
}
}
/**
* Queue constructor
*/
Queue() {
front = null;
rear = null;
size = 0;
}
boolean isEmpty() {
if (size == 0) {
return true;
} else {
return false;
}
}
void enqueue(T obj) {
if (front == null) {
front = new Node(obj, null);
rear = front;
} else {
Node temp = new Node(obj, null);
rear.next = temp;
rear = temp;
}
size++;
}
T dequeue() throws IsEmptyException {
if (isEmpty()) {
throw new IsEmptyException();
} else {
Node temp = front;
front = front.next;
size = size - 1;
return ((T) temp.value);
}
}
T peek() throws IsEmptyException {
if (isEmpty()) {
throw new IsEmptyException();
} else {
return ((T)front.value);
}
}
}
/**
* 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.commander.queue;
import java.util.ArrayList;
import java.util.Arrays;
import com.iluwatar.commander.Database;
import com.iluwatar.commander.exceptions.DatabaseUnavailableException;
import com.iluwatar.commander.exceptions.IsEmptyException;
/**
* QueueDatabase id where the instructions to be implemented are queued.
*/
public class QueueDatabase extends Database<QueueTask> {
private Queue<QueueTask> data;
public ArrayList<Exception> exceptionsList;
public QueueDatabase(Exception...exc) {
this.data = new Queue<QueueTask>();
this.exceptionsList = new ArrayList<Exception>(Arrays.asList(exc));
}
@Override
public QueueTask add(QueueTask t) throws DatabaseUnavailableException {
data.enqueue(t);
return t;
//even if same thing queued twice, it is taken care of in other dbs
}
/**
* peek method returns object at front without removing it from queue
* @return object at front of queue
* @throws IsEmptyException if queue is empty
* @throws DatabaseUnavailableException if queue db is unavailable
*/
public QueueTask peek() throws IsEmptyException, DatabaseUnavailableException {
QueueTask qt = this.data.peek();
return qt;
}
/**
* dequeue method removes the object at front and returns it
* @return object at front of queue
* @throws IsEmptyException if queue is empty
* @throws DatabaseUnavailableException if queue db is unavailable
*/
public QueueTask dequeue() throws IsEmptyException, DatabaseUnavailableException {
QueueTask qt = this.data.dequeue();
return qt;
}
@Override
public QueueTask get(String tId) throws DatabaseUnavailableException {
return null;
}
}
/**
* 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.commander.queue;
import com.iluwatar.commander.Order;
/**
* QueueTask object is the object enqueued in queue.
*/
public class QueueTask {
/**
* TaskType is the type of task to be done.
*/
public enum TaskType {
Messaging, Payment, EmployeeDb
};
public Order order;
public TaskType taskType;
public int messageType; //0-fail, 1-error, 2-success
/*we could have varargs Object instead to pass in any parameter instead of just message type
but keeping it simple here*/
public long firstAttemptTime; //when first time attempt made to do task
/**
* QueueTask constructor
* @param o is the order for which the queuetask is being created
* @param t is the type of task to be done
* @param messageType if it is a message, which type of message - this could have instead been object varargs,
* and contained all additional details related to tasktype.
*/
public QueueTask(Order o, TaskType t, int messageType) {
this.order = o;
this.taskType = t;
this.messageType = messageType;
this.firstAttemptTime = -1;
}
/**
* getType method
* @return String representing type of task
*/
public String getType() {
if (!this.taskType.equals(TaskType.Messaging)) {
return this.taskType.toString();
} else {
if (this.messageType == 0) {
return "Payment Failure Message";
} else if (this.messageType == 1) {
return "Payment Error Message";
} else {
return "Payment Success Message";
}
}
}
}
/**
* 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.commander.shippingservice;
import java.util.Hashtable;
import com.iluwatar.commander.Database;
import com.iluwatar.commander.exceptions.DatabaseUnavailableException;
import com.iluwatar.commander.shippingservice.ShippingService.ShippingRequest;
/**
* ShippingDatabase is where the ShippingRequest objects are added.
*/
public class ShippingDatabase extends Database<ShippingRequest> {
private Hashtable<String, ShippingRequest> data;
public ShippingDatabase() {
this.data = new Hashtable<String, ShippingRequest>();
}
@Override
public ShippingRequest add(ShippingRequest r) throws DatabaseUnavailableException {
return data.put(r.transactionId, r);
}
public ShippingRequest get(String transactionId) throws DatabaseUnavailableException {
return data.get(transactionId);
}
}
/**
* 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.commander.shippingservice;
import com.iluwatar.commander.Service;
import com.iluwatar.commander.exceptions.DatabaseUnavailableException;
/**
* ShippingService class receives request from {@link Commander} class and adds it
* to the {@link ShippingDatabase}.
*/
public class ShippingService extends Service {
class ShippingRequest {
String transactionId;
String item;
String address;
ShippingRequest(String transactionId, String item, String address) {
this.transactionId = transactionId;
this.item = item;
this.address = address;
}
}
public ShippingService(ShippingDatabase db, Exception...exc) {
super(db, exc);
}
/**
* Public method which will receive request from {@link Commander}.
*/
public String receiveRequest(Object...parameters) throws DatabaseUnavailableException {
String tId = generateId();
ShippingRequest req = new ShippingRequest(tId, (String) parameters[0] /*item*/, (String) parameters[1]/*address*/);
return updateDb(req);
}
protected String updateDb(Object...parameters) throws DatabaseUnavailableException {
ShippingRequest req = (ShippingRequest) parameters[0];
if (this.database.get(req.transactionId) == null) {
database.add(req);
return req.transactionId;
}
return null;
}
}
/**
* 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.commander;
import static org.junit.jupiter.api.Assertions.*;
import java.util.ArrayList;
import java.util.Arrays;
import org.junit.jupiter.api.Test;
import com.iluwatar.commander.Order;
import com.iluwatar.commander.Retry;
import com.iluwatar.commander.User;
import com.iluwatar.commander.Retry.HandleErrorIssue;
import com.iluwatar.commander.Retry.Operation;
import com.iluwatar.commander.exceptions.DatabaseUnavailableException;
import com.iluwatar.commander.exceptions.ItemUnavailableException;
class RetryTest {
@Test
void performTest() {
Retry.Operation op = (l) -> {
if (!l.isEmpty()) {
throw l.remove(0);
}
return;
};
Retry.HandleErrorIssue<Order> handleError = (o,e) -> {
return;
};
Retry<Order> r1 = new Retry<Order>(op, handleError, 3, 30000,
e -> DatabaseUnavailableException.class.isAssignableFrom(e.getClass()));
Retry<Order> r2 = new Retry<Order>(op, handleError, 3, 30000,
e -> DatabaseUnavailableException.class.isAssignableFrom(e.getClass()));
User user = new User("Jim", "ABCD");
Order order = new Order(user, "book", 10f);
ArrayList<Exception> arr1 = new ArrayList<Exception>(Arrays.asList(new Exception[]
{new ItemUnavailableException(), new DatabaseUnavailableException()}));
try {
r1.perform(arr1, order);
} catch (Exception e1) {
e1.printStackTrace();
}
ArrayList<Exception> arr2 = new ArrayList<Exception>(Arrays.asList(new Exception[]
{new DatabaseUnavailableException(), new ItemUnavailableException()}));
try {
r2.perform(arr2, order);
} catch (Exception e1) {
e1.printStackTrace();
}
//r1 stops at ItemUnavailableException, r2 retries because it encounters DatabaseUnavailableException
assertTrue(arr1.size() == 1 && arr2.size() == 0);
}
}
...@@ -166,6 +166,7 @@ ...@@ -166,6 +166,7 @@
<module>collection-pipeline</module> <module>collection-pipeline</module>
<module>master-worker-pattern</module> <module>master-worker-pattern</module>
<module>spatial-partition</module> <module>spatial-partition</module>
<module>commander</module>
<module>typeobjectpattern</module> <module>typeobjectpattern</module>
</modules> </modules>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册