Resolves checkstyle errors for collection-pipeline, command, commander (#1061)

* Reduces checkstyle errors in collection-pipeline

* Reduces checkstyle errors in command

* Reduces checkstyle errors in commander
This commit is contained in:
Anurag Agarwal 2019-11-10 01:05:15 +05:30 committed by Ilkka Seppälä
parent 31f27a720b
commit 2f49648047
41 changed files with 646 additions and 574 deletions

View File

@ -23,21 +23,18 @@
package com.iluwatar.collectionpipeline; package com.iluwatar.collectionpipeline;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.List;
import java.util.Map;
/** /**
* In imperative-style programming, it is common to use for and while loops for * In imperative-style programming, it is common to use for and while loops for most kinds of data
* most kinds of data processing. Function composition is a simple technique * processing. Function composition is a simple technique that lets you sequence modular functions
* that lets you sequence modular functions to create more complex operations. * to create more complex operations. When you run data through the sequence, you have a collection
* When you run data through the sequence, you have a collection pipeline. * pipeline. Together, the Function Composition and Collection Pipeline patterns enable you to
* Together, the Function Composition and Collection Pipeline patterns enable * create sophisticated programs where data flow from upstream to downstream and is passed through a
* you to create sophisticated programs where data flow from upstream to * series of transformations.
* downstream and is passed through a series of transformations.
*
*/ */
public class App { public class App {
@ -45,32 +42,35 @@ public class App {
/** /**
* Program entry point. * Program entry point.
* *
* @param args * @param args command line args
* command line args
*/ */
public static void main(String[] args) { public static void main(String[] args) {
List<Car> cars = CarFactory.createCars(); List<Car> cars = CarFactory.createCars();
List<String> modelsImperative = ImperativeProgramming.getModelsAfter2000(cars); List<String> modelsImperative = ImperativeProgramming.getModelsAfter2000(cars);
LOGGER.info(modelsImperative.toString()); LOGGER.info(modelsImperative.toString());
List<String> modelsFunctional = FunctionalProgramming.getModelsAfter2000(cars); List<String> modelsFunctional = FunctionalProgramming.getModelsAfter2000(cars);
LOGGER.info(modelsFunctional.toString()); LOGGER.info(modelsFunctional.toString());
Map<Category, List<Car>> groupingByCategoryImperative = ImperativeProgramming.getGroupingOfCarsByCategory(cars); Map<Category, List<Car>> groupingByCategoryImperative =
ImperativeProgramming.getGroupingOfCarsByCategory(cars);
LOGGER.info(groupingByCategoryImperative.toString()); LOGGER.info(groupingByCategoryImperative.toString());
Map<Category, List<Car>> groupingByCategoryFunctional = FunctionalProgramming.getGroupingOfCarsByCategory(cars); Map<Category, List<Car>> groupingByCategoryFunctional =
FunctionalProgramming.getGroupingOfCarsByCategory(cars);
LOGGER.info(groupingByCategoryFunctional.toString()); LOGGER.info(groupingByCategoryFunctional.toString());
Person john = new Person(cars); Person john = new Person(cars);
List<Car> sedansOwnedImperative = ImperativeProgramming.getSedanCarsOwnedSortedByDate(List.of(john)); List<Car> sedansOwnedImperative =
ImperativeProgramming.getSedanCarsOwnedSortedByDate(List.of(john));
LOGGER.info(sedansOwnedImperative.toString()); LOGGER.info(sedansOwnedImperative.toString());
List<Car> sedansOwnedFunctional = FunctionalProgramming.getSedanCarsOwnedSortedByDate(List.of(john)); List<Car> sedansOwnedFunctional =
FunctionalProgramming.getSedanCarsOwnedSortedByDate(List.of(john));
LOGGER.info(sedansOwnedFunctional.toString()); LOGGER.info(sedansOwnedFunctional.toString());
} }
} }

View File

@ -34,10 +34,11 @@ public class Car {
/** /**
* Constructor to create an instance of car. * Constructor to create an instance of car.
* @param make the make of the car *
* @param model the model of the car * @param make the make of the car
* @param model the model of the car
* @param yearOfMake the year of built of the car * @param yearOfMake the year of built of the car
* @param category the {@link Category} of the car * @param category the {@link Category} of the car
*/ */
public Car(String make, String model, int yearOfMake, Category category) { public Car(String make, String model, int yearOfMake, Category category) {
this.make = make; this.make = make;
@ -103,7 +104,7 @@ public class Car {
public int getYear() { public int getYear() {
return year; return year;
} }
public Category getCategory() { public Category getCategory() {
return category; return category;
} }

View File

@ -34,6 +34,7 @@ public class CarFactory {
/** /**
* Factory method to create a {@link List} of {@link Car} instances. * Factory method to create a {@link List} of {@link Car} instances.
*
* @return {@link List} of {@link Car} * @return {@link List} of {@link Car}
*/ */
public static List<Car> createCars() { public static List<Car> createCars() {

View File

@ -24,7 +24,7 @@
package com.iluwatar.collectionpipeline; package com.iluwatar.collectionpipeline;
/** /**
* Enum for the category of car * Enum for the category of car.
*/ */
public enum Category { public enum Category {
JEEP, SEDAN, CONVERTIBLE JEEP, SEDAN, CONVERTIBLE

View File

@ -30,20 +30,17 @@ import java.util.stream.Collectors;
/** /**
* Iterating and sorting with a collection pipeline * Iterating and sorting with a collection pipeline
* *
* <p>In functional programming, it's common to sequence complex operations through * <p>In functional programming, it's common to sequence complex operations through
* a series of smaller modular functions or operations. The series is called a * a series of smaller modular functions or operations. The series is called a composition of
* composition of functions, or a function composition. When a collection of * functions, or a function composition. When a collection of data flows through a function
* data flows through a function composition, it becomes a collection pipeline. * composition, it becomes a collection pipeline. Function Composition and Collection Pipeline are
* Function Composition and Collection Pipeline are two design patterns * two design patterns frequently used in functional-style programming.
* frequently used in functional-style programming. *
*
* <p>Instead of passing a lambda expression to the map method, we passed the * <p>Instead of passing a lambda expression to the map method, we passed the
* method reference Car::getModel. Likewise, instead of passing the lambda * method reference Car::getModel. Likewise, instead of passing the lambda expression car ->
* expression car -> car.getYear() to the comparing method, we passed the method * car.getYear() to the comparing method, we passed the method reference Car::getYear. Method
* reference Car::getYear. Method references are short, concise, and expressive. * references are short, concise, and expressive. It is best to use them wherever possible.
* It is best to use them wherever possible.
*
*/ */
public class FunctionalProgramming { public class FunctionalProgramming {
private FunctionalProgramming() { private FunctionalProgramming() {
@ -51,35 +48,35 @@ public class FunctionalProgramming {
/** /**
* Method to get models using for collection pipeline. * Method to get models using for collection pipeline.
* *
* @param cars {@link List} of {@link Car} to be used for filtering * @param cars {@link List} of {@link Car} to be used for filtering
* @return {@link List} of {@link String} representing models built after year 2000 * @return {@link List} of {@link String} representing models built after year 2000
*/ */
public static List<String> getModelsAfter2000(List<Car> cars) { public static List<String> getModelsAfter2000(List<Car> cars) {
return cars.stream().filter(car -> car.getYear() > 2000) return cars.stream().filter(car -> car.getYear() > 2000)
.sorted(Comparator.comparing(Car::getYear)) .sorted(Comparator.comparing(Car::getYear))
.map(Car::getModel).collect(Collectors.toList()); .map(Car::getModel).collect(Collectors.toList());
} }
/** /**
* Method to group cars by category using groupingBy * Method to group cars by category using groupingBy.
* *
* @param cars {@link List} of {@link Car} to be used for grouping * @param cars {@link List} of {@link Car} to be used for grouping
* @return {@link Map} with category as key and cars belonging to that category as value * @return {@link Map} with category as key and cars belonging to that category as value
*/ */
public static Map<Category, List<Car>> getGroupingOfCarsByCategory(List<Car> cars) { public static Map<Category, List<Car>> getGroupingOfCarsByCategory(List<Car> cars) {
return cars.stream().collect(Collectors.groupingBy(Car::getCategory)); return cars.stream().collect(Collectors.groupingBy(Car::getCategory));
} }
/** /**
* Method to get all Sedan cars belonging to a group of persons sorted by year of manufacture * Method to get all Sedan cars belonging to a group of persons sorted by year of manufacture.
* *
* @param persons {@link List} of {@link Person} to be used * @param persons {@link List} of {@link Person} to be used
* @return {@link List} of {@link Car} to belonging to the group * @return {@link List} of {@link Car} to belonging to the group
*/ */
public static List<Car> getSedanCarsOwnedSortedByDate(List<Person> persons) { public static List<Car> getSedanCarsOwnedSortedByDate(List<Person> persons) {
return persons.stream().map(Person::getCars).flatMap(List::stream) return persons.stream().map(Person::getCars).flatMap(List::stream)
.filter(car -> Category.SEDAN.equals(car.getCategory())) .filter(car -> Category.SEDAN.equals(car.getCategory()))
.sorted(Comparator.comparing(Car::getYear)).collect(Collectors.toList()); .sorted(Comparator.comparing(Car::getYear)).collect(Collectors.toList());
} }
} }

View File

@ -31,23 +31,20 @@ import java.util.List;
import java.util.Map; import java.util.Map;
/** /**
* Imperative-style programming to iterate over the list and get the names of * Imperative-style programming to iterate over the list and get the names of cars made later than
* cars made later than the year 2000. We then sort the models in ascending * the year 2000. We then sort the models in ascending order by year.
* order by year. *
*
* <p>As you can see, there's a lot of looping in this code. First, the * <p>As you can see, there's a lot of looping in this code. First, the
* getModelsAfter2000UsingFor method takes a list of cars as its parameter. It * getModelsAfter2000UsingFor method takes a list of cars as its parameter. It extracts or filters
* extracts or filters out cars made after the year 2000, putting them into a * out cars made after the year 2000, putting them into a new list named carsSortedByYear. Next, it
* new list named carsSortedByYear. Next, it sorts that list in ascending order * sorts that list in ascending order by year-of-make. Finally, it loops through the list
* by year-of-make. Finally, it loops through the list carsSortedByYear to get * carsSortedByYear to get the model names and returns them in a list.
* the model names and returns them in a list. *
*
* <p>This short example demonstrates what I call the effect of statements. While * <p>This short example demonstrates what I call the effect of statements. While
* functions and methods in general can be used as expressions, the {@link Collections} * functions and methods in general can be used as expressions, the {@link Collections} sort method
* sort method doesn't return a result. Because it is used as a statement, it * doesn't return a result. Because it is used as a statement, it mutates the list given as
* mutates the list given as argument. Both of the for loops also mutate lists * argument. Both of the for loops also mutate lists as they iterate. Being statements, that's just
* as they iterate. Being statements, that's just how these elements work. As a * how these elements work. As a result, the code contains unnecessary garbage variables
* result, the code contains unnecessary garbage variables
*/ */
public class ImperativeProgramming { public class ImperativeProgramming {
private ImperativeProgramming() { private ImperativeProgramming() {
@ -55,6 +52,7 @@ public class ImperativeProgramming {
/** /**
* Method to return the car models built after year 2000 using for loops. * Method to return the car models built after year 2000 using for loops.
*
* @param cars {@link List} of {@link Car} to iterate over * @param cars {@link List} of {@link Car} to iterate over
* @return {@link List} of {@link String} of car models built after year 2000 * @return {@link List} of {@link String} of car models built after year 2000
*/ */
@ -80,16 +78,16 @@ public class ImperativeProgramming {
return models; return models;
} }
/** /**
* Method to group cars by category using for loops * Method to group cars by category using for loops.
* *
* @param cars {@link List} of {@link Car} to be used for grouping * @param cars {@link List} of {@link Car} to be used for grouping
* @return {@link Map} with category as key and cars belonging to that category as value * @return {@link Map} with category as key and cars belonging to that category as value
*/ */
public static Map<Category, List<Car>> getGroupingOfCarsByCategory(List<Car> cars) { public static Map<Category, List<Car>> getGroupingOfCarsByCategory(List<Car> cars) {
Map<Category, List<Car>> groupingByCategory = new HashMap<>(); Map<Category, List<Car>> groupingByCategory = new HashMap<>();
for (Car car: cars) { for (Car car : cars) {
if (groupingByCategory.containsKey(car.getCategory())) { if (groupingByCategory.containsKey(car.getCategory())) {
groupingByCategory.get(car.getCategory()).add(car); groupingByCategory.get(car.getCategory()).add(car);
} else { } else {
@ -100,33 +98,34 @@ public class ImperativeProgramming {
} }
return groupingByCategory; return groupingByCategory;
} }
/** /**
* Method to get all Sedan cars belonging to a group of persons sorted by year of manufacture using for loops * Method to get all Sedan cars belonging to a group of persons sorted by year of manufacture
* * using for loops.
*
* @param persons {@link List} of {@link Person} to be used * @param persons {@link List} of {@link Person} to be used
* @return {@link List} of {@link Car} to belonging to the group * @return {@link List} of {@link Car} to belonging to the group
*/ */
public static List<Car> getSedanCarsOwnedSortedByDate(List<Person> persons) { public static List<Car> getSedanCarsOwnedSortedByDate(List<Person> persons) {
List<Car> cars = new ArrayList<>(); List<Car> cars = new ArrayList<>();
for (Person person: persons) { for (Person person : persons) {
cars.addAll(person.getCars()); cars.addAll(person.getCars());
} }
List<Car> sedanCars = new ArrayList<>(); List<Car> sedanCars = new ArrayList<>();
for (Car car: cars) { for (Car car : cars) {
if (Category.SEDAN.equals(car.getCategory())) { if (Category.SEDAN.equals(car.getCategory())) {
sedanCars.add(car); sedanCars.add(car);
} }
} }
sedanCars.sort(new Comparator<Car>() { sedanCars.sort(new Comparator<Car>() {
@Override @Override
public int compare(Car o1, Car o2) { public int compare(Car o1, Car o2) {
return o1.getYear() - o2.getYear(); return o1.getYear() - o2.getYear();
} }
}); });
return sedanCars; return sedanCars;
} }
} }

View File

@ -33,6 +33,7 @@ public class Person {
/** /**
* Constructor to create an instance of person. * Constructor to create an instance of person.
*
* @param cars the list of cars owned * @param cars the list of cars owned
*/ */
public Person(List<Car> cars) { public Person(List<Car> cars) {

View File

@ -23,14 +23,13 @@
package com.iluwatar.collectionpipeline; package com.iluwatar.collectionpipeline;
import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals; import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** /**
* Tests that Collection Pipeline methods work as expected. * Tests that Collection Pipeline methods work as expected.
@ -39,35 +38,35 @@ public class AppTest {
private static final Logger LOGGER = LoggerFactory.getLogger(AppTest.class); private static final Logger LOGGER = LoggerFactory.getLogger(AppTest.class);
private List<Car> cars = CarFactory.createCars(); private List<Car> cars = CarFactory.createCars();
@Test @Test
public void testGetModelsAfter2000UsingFor() { public void testGetModelsAfter2000UsingFor() {
var models = ImperativeProgramming.getModelsAfter2000(cars); var models = ImperativeProgramming.getModelsAfter2000(cars);
assertEquals(List.of("Avenger", "Wrangler", "Focus", "Cascada"), models); assertEquals(List.of("Avenger", "Wrangler", "Focus", "Cascada"), models);
} }
@Test @Test
public void testGetModelsAfter2000UsingPipeline() { public void testGetModelsAfter2000UsingPipeline() {
var models = FunctionalProgramming.getModelsAfter2000(cars); var models = FunctionalProgramming.getModelsAfter2000(cars);
assertEquals(List.of("Avenger", "Wrangler", "Focus", "Cascada"), models); assertEquals(List.of("Avenger", "Wrangler", "Focus", "Cascada"), models);
} }
@Test @Test
public void testGetGroupingOfCarsByCategory() { public void testGetGroupingOfCarsByCategory() {
var modelsExpected = Map.of( var modelsExpected = Map.of(
Category.CONVERTIBLE, List.of(new Car("Buick", "Cascada", 2016, Category.CONVERTIBLE), Category.CONVERTIBLE, List.of(new Car("Buick", "Cascada", 2016, Category.CONVERTIBLE),
new Car("Chevrolet", "Geo Metro", 1992, Category.CONVERTIBLE)), new Car("Chevrolet", "Geo Metro", 1992, Category.CONVERTIBLE)),
Category.SEDAN, List.of(new Car("Dodge", "Avenger", 2010, Category.SEDAN), Category.SEDAN, List.of(new Car("Dodge", "Avenger", 2010, Category.SEDAN),
new Car("Ford", "Focus", 2012, Category.SEDAN)), new Car("Ford", "Focus", 2012, Category.SEDAN)),
Category.JEEP, List.of(new Car("Jeep", "Wrangler", 2011, Category.JEEP), Category.JEEP, List.of(new Car("Jeep", "Wrangler", 2011, Category.JEEP),
new Car("Jeep", "Comanche", 1990, Category.JEEP))); new Car("Jeep", "Comanche", 1990, Category.JEEP)));
var modelsFunctional = FunctionalProgramming.getGroupingOfCarsByCategory(cars); var modelsFunctional = FunctionalProgramming.getGroupingOfCarsByCategory(cars);
var modelsImperative = ImperativeProgramming.getGroupingOfCarsByCategory(cars); var modelsImperative = ImperativeProgramming.getGroupingOfCarsByCategory(cars);
LOGGER.info("Category " + modelsFunctional); LOGGER.info("Category " + modelsFunctional);
assertEquals(modelsExpected, modelsFunctional); assertEquals(modelsExpected, modelsFunctional);
assertEquals(modelsExpected, modelsImperative); assertEquals(modelsExpected, modelsImperative);
} }
@Test @Test
public void testGetSedanCarsOwnedSortedByDate() { public void testGetSedanCarsOwnedSortedByDate() {
var john = new Person(cars); var john = new Person(cars);

View File

@ -24,31 +24,28 @@
package com.iluwatar.command; package com.iluwatar.command;
/** /**
*
* The Command pattern is a behavioral design pattern in which an object is used to encapsulate all * The Command pattern is a behavioral design pattern in which an object is used to encapsulate all
* information needed to perform an action or trigger an event at a later time. This information * information needed to perform an action or trigger an event at a later time. This information
* includes the method name, the object that owns the method and values for the method parameters. * includes the method name, the object that owns the method and values for the method parameters.
* <p> *
* Four terms always associated with the command pattern are command, receiver, invoker and client. * <p>Four terms always associated with the command pattern are command, receiver, invoker and
* A command object (spell) knows about the receiver (target) and invokes a method of the receiver. * client. A command object (spell) knows about the receiver (target) and invokes a method of the
* Values for parameters of the receiver method are stored in the command. The receiver then does * receiver. Values for parameters of the receiver method are stored in the command. The receiver
* the work. An invoker object (wizard) knows how to execute a command, and optionally does * then does the work. An invoker object (wizard) knows how to execute a command, and optionally
* bookkeeping about the command execution. The invoker does not know anything about a concrete * does bookkeeping about the command execution. The invoker does not know anything about a concrete
* command, it knows only about command interface. Both an invoker object and several command * command, it knows only about command interface. Both an invoker object and several command
* objects are held by a client object (app). The client decides which commands to execute at which * objects are held by a client object (app). The client decides which commands to execute at which
* points. To execute a command, it passes the command object to the invoker object. * points. To execute a command, it passes the command object to the invoker object.
* <p> *
* In other words, in this example the wizard casts spells on the goblin. The wizard keeps track of * <p>In other words, in this example the wizard casts spells on the goblin. The wizard keeps track
* the previous spells cast, so it is easy to undo them. In addition, the wizard keeps track of the * of the previous spells cast, so it is easy to undo them. In addition, the wizard keeps track of
* spells undone, so they can be redone. * the spells undone, so they can be redone.
*
*
*/ */
public class App { public class App {
/** /**
* Program entry point * Program entry point.
* *
* @param args command line args * @param args command line args
*/ */
public static void main(String[] args) { public static void main(String[] args) {

View File

@ -24,9 +24,7 @@
package com.iluwatar.command; package com.iluwatar.command;
/** /**
*
* Interface for Commands. * Interface for Commands.
*
*/ */
public abstract class Command { public abstract class Command {

View File

@ -24,9 +24,7 @@
package com.iluwatar.command; package com.iluwatar.command;
/** /**
* * Goblin is the target of the spells.
* Goblin is the target of the spells
*
*/ */
public class Goblin extends Target { public class Goblin extends Target {

View File

@ -24,9 +24,7 @@
package com.iluwatar.command; package com.iluwatar.command;
/** /**
* * InvisibilitySpell is a concrete command.
* InvisibilitySpell is a concrete command
*
*/ */
public class InvisibilitySpell extends Command { public class InvisibilitySpell extends Command {

View File

@ -24,9 +24,7 @@
package com.iluwatar.command; package com.iluwatar.command;
/** /**
* * ShrinkSpell is a concrete command.
* ShrinkSpell is a concrete command
*
*/ */
public class ShrinkSpell extends Command { public class ShrinkSpell extends Command {

View File

@ -24,9 +24,7 @@
package com.iluwatar.command; package com.iluwatar.command;
/** /**
*
* Enumeration for target size. * Enumeration for target size.
*
*/ */
public enum Size { public enum Size {

View File

@ -27,9 +27,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
/** /**
*
* Base class for spell targets. * Base class for spell targets.
*
*/ */
public abstract class Target { public abstract class Target {
@ -59,7 +57,7 @@ public abstract class Target {
public abstract String toString(); public abstract String toString();
/** /**
* Print status * Print status.
*/ */
public void printStatus() { public void printStatus() {
LOGGER.info("{}, [size={}] [visibility={}]", this, getSize(), getVisibility()); LOGGER.info("{}, [size={}] [visibility={}]", this, getSize(), getVisibility());

View File

@ -24,9 +24,7 @@
package com.iluwatar.command; package com.iluwatar.command;
/** /**
*
* Enumeration for target visibility. * Enumeration for target visibility.
*
*/ */
public enum Visibility { public enum Visibility {

View File

@ -23,16 +23,13 @@
package com.iluwatar.command; package com.iluwatar.command;
import java.util.Deque;
import java.util.LinkedList;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.Deque;
import java.util.LinkedList;
/** /**
* * Wizard is the invoker of the commands.
* Wizard is the invoker of the commands
*
*/ */
public class Wizard { public class Wizard {
@ -46,7 +43,7 @@ public class Wizard {
} }
/** /**
* Cast spell * Cast spell.
*/ */
public void castSpell(Command command, Target target) { public void castSpell(Command command, Target target) {
LOGGER.info("{} casts {} at {}", this, command, target); LOGGER.info("{} casts {} at {}", this, command, target);
@ -55,7 +52,7 @@ public class Wizard {
} }
/** /**
* Undo last spell * Undo last spell.
*/ */
public void undoLastSpell() { public void undoLastSpell() {
if (!undoStack.isEmpty()) { if (!undoStack.isEmpty()) {
@ -67,7 +64,7 @@ public class Wizard {
} }
/** /**
* Redo last spell * Redo last spell.
*/ */
public void redoLastSpell() { public void redoLastSpell() {
if (!redoStack.isEmpty()) { if (!redoStack.isEmpty()) {

View File

@ -31,16 +31,15 @@ import com.iluwatar.commander.messagingservice.MessagingDatabase;
import com.iluwatar.commander.messagingservice.MessagingService; import com.iluwatar.commander.messagingservice.MessagingService;
import com.iluwatar.commander.paymentservice.PaymentDatabase; import com.iluwatar.commander.paymentservice.PaymentDatabase;
import com.iluwatar.commander.paymentservice.PaymentService; import com.iluwatar.commander.paymentservice.PaymentService;
import com.iluwatar.commander.queue.QueueDatabase;
import com.iluwatar.commander.shippingservice.ShippingDatabase; import com.iluwatar.commander.shippingservice.ShippingDatabase;
import com.iluwatar.commander.shippingservice.ShippingService; import com.iluwatar.commander.shippingservice.ShippingService;
import com.iluwatar.commander.queue.QueueDatabase;
/** /**
* AppEmployeeDbFailCases class looks at possible cases when Employee handle service is * AppEmployeeDbFailCases class looks at possible cases when Employee handle service is
* available/unavailable. * available/unavailable.
*/ */
public class AppEmployeeDbFailCases {
public class AppEmployeeDbFailCases {
final int numOfRetries = 3; final int numOfRetries = 3;
final long retryDuration = 30000; final long retryDuration = 30000;
final long queueTime = 240000; //4 mins final long queueTime = 240000; //4 mins
@ -50,33 +49,40 @@ public class AppEmployeeDbFailCases {
final long employeeTime = 240000; //4 mins final long employeeTime = 240000; //4 mins
void employeeDatabaseUnavailableCase() throws Exception { void employeeDatabaseUnavailableCase() throws Exception {
PaymentService ps = new PaymentService(new PaymentDatabase(), new DatabaseUnavailableException(), PaymentService ps =
new DatabaseUnavailableException(), new DatabaseUnavailableException(), new DatabaseUnavailableException(), new PaymentService(new PaymentDatabase(), new DatabaseUnavailableException(),
new DatabaseUnavailableException(), new DatabaseUnavailableException()); new DatabaseUnavailableException(), new DatabaseUnavailableException(),
new DatabaseUnavailableException(), new DatabaseUnavailableException(),
new DatabaseUnavailableException());
ShippingService ss = new ShippingService(new ShippingDatabase()); ShippingService ss = new ShippingService(new ShippingDatabase());
MessagingService ms = new MessagingService(new MessagingDatabase()); MessagingService ms = new MessagingService(new MessagingDatabase());
EmployeeHandle eh = new EmployeeHandle(new EmployeeDatabase(), new DatabaseUnavailableException(), EmployeeHandle eh =
new DatabaseUnavailableException(), new DatabaseUnavailableException(), new DatabaseUnavailableException(), new EmployeeHandle(new EmployeeDatabase(), 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()); QueueDatabase qdb =
Commander c = new Commander(eh,ps,ss,ms,qdb,numOfRetries,retryDuration, new QueueDatabase(new DatabaseUnavailableException(), new DatabaseUnavailableException(),
queueTime,queueTaskTime,paymentTime,messageTime,employeeTime); 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"); User user = new User("Jim", "ABCD");
Order order = new Order(user, "book", 10f); Order order = new Order(user, "book", 10f);
c.placeOrder(order); c.placeOrder(order);
} }
void employeeDbSuccessCase() throws Exception { void employeeDbSuccessCase() throws Exception {
PaymentService ps = new PaymentService(new PaymentDatabase()); PaymentService ps = new PaymentService(new PaymentDatabase());
ShippingService ss = new ShippingService(new ShippingDatabase(), new ItemUnavailableException()); ShippingService ss =
new ShippingService(new ShippingDatabase(), new ItemUnavailableException());
MessagingService ms = new MessagingService(new MessagingDatabase()); MessagingService ms = new MessagingService(new MessagingDatabase());
EmployeeHandle eh = new EmployeeHandle(new EmployeeDatabase(), new DatabaseUnavailableException(), EmployeeHandle eh =
new DatabaseUnavailableException()); new EmployeeHandle(new EmployeeDatabase(), new DatabaseUnavailableException(),
new DatabaseUnavailableException());
QueueDatabase qdb = new QueueDatabase(); QueueDatabase qdb = new QueueDatabase();
Commander c = new Commander(eh,ps,ss,ms,qdb,numOfRetries,retryDuration, Commander c = new Commander(eh, ps, ss, ms, qdb, numOfRetries, retryDuration,
queueTime,queueTaskTime,paymentTime,messageTime,employeeTime); queueTime, queueTaskTime, paymentTime, messageTime, employeeTime);
User user = new User("Jim", "ABCD"); User user = new User("Jim", "ABCD");
Order order = new Order(user, "book", 10f); Order order = new Order(user, "book", 10f);
c.placeOrder(order); c.placeOrder(order);
@ -87,7 +93,7 @@ public class AppEmployeeDbFailCases {
* *
* @param args command line args * @param args command line args
*/ */
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
AppEmployeeDbFailCases aefc = new AppEmployeeDbFailCases(); AppEmployeeDbFailCases aefc = new AppEmployeeDbFailCases();
//aefc.employeeDatabaseUnavailableCase(); //aefc.employeeDatabaseUnavailableCase();

View File

@ -30,12 +30,12 @@ import com.iluwatar.commander.messagingservice.MessagingDatabase;
import com.iluwatar.commander.messagingservice.MessagingService; import com.iluwatar.commander.messagingservice.MessagingService;
import com.iluwatar.commander.paymentservice.PaymentDatabase; import com.iluwatar.commander.paymentservice.PaymentDatabase;
import com.iluwatar.commander.paymentservice.PaymentService; import com.iluwatar.commander.paymentservice.PaymentService;
import com.iluwatar.commander.queue.QueueDatabase;
import com.iluwatar.commander.shippingservice.ShippingDatabase; import com.iluwatar.commander.shippingservice.ShippingDatabase;
import com.iluwatar.commander.shippingservice.ShippingService; import com.iluwatar.commander.shippingservice.ShippingService;
import com.iluwatar.commander.queue.QueueDatabase;
/** /**
* AppMessagingFailCases class looks at possible cases when Messaging service is * AppMessagingFailCases class looks at possible cases when Messaging service is
* available/unavailable. * available/unavailable.
*/ */
@ -50,15 +50,17 @@ public class AppMessagingFailCases {
void messagingDatabaseUnavailableCasePaymentSuccess() throws Exception { void messagingDatabaseUnavailableCasePaymentSuccess() throws Exception {
//rest is successful //rest is successful
PaymentService ps = new PaymentService(new PaymentDatabase()); PaymentService ps = new PaymentService(new PaymentDatabase());
ShippingService ss = new ShippingService(new ShippingDatabase()); ShippingService ss = new ShippingService(new ShippingDatabase());
MessagingService ms = new MessagingService(new MessagingDatabase(), new DatabaseUnavailableException(), MessagingService ms =
new DatabaseUnavailableException(), new DatabaseUnavailableException(), new DatabaseUnavailableException(), new MessagingService(new MessagingDatabase(), new DatabaseUnavailableException(),
new DatabaseUnavailableException(), new DatabaseUnavailableException()); new DatabaseUnavailableException(), new DatabaseUnavailableException(),
new DatabaseUnavailableException(), new DatabaseUnavailableException(),
new DatabaseUnavailableException());
EmployeeHandle eh = new EmployeeHandle(new EmployeeDatabase()); EmployeeHandle eh = new EmployeeHandle(new EmployeeDatabase());
QueueDatabase qdb = new QueueDatabase(); QueueDatabase qdb = new QueueDatabase();
Commander c = new Commander(eh,ps,ss,ms,qdb,numOfRetries,retryDuration, Commander c = new Commander(eh, ps, ss, ms, qdb, numOfRetries, retryDuration,
queueTime,queueTaskTime,paymentTime,messageTime,employeeTime); queueTime, queueTaskTime, paymentTime, messageTime, employeeTime);
User user = new User("Jim", "ABCD"); User user = new User("Jim", "ABCD");
Order order = new Order(user, "book", 10f); Order order = new Order(user, "book", 10f);
c.placeOrder(order); c.placeOrder(order);
@ -66,40 +68,52 @@ public class AppMessagingFailCases {
void messagingDatabaseUnavailableCasePaymentError() throws Exception { void messagingDatabaseUnavailableCasePaymentError() throws Exception {
//rest is successful //rest is successful
PaymentService ps = new PaymentService(new PaymentDatabase(), new DatabaseUnavailableException(), PaymentService ps =
new DatabaseUnavailableException(), new DatabaseUnavailableException(), new DatabaseUnavailableException(), new PaymentService(new PaymentDatabase(), new DatabaseUnavailableException(),
new DatabaseUnavailableException(), new DatabaseUnavailableException()); new DatabaseUnavailableException(), new DatabaseUnavailableException(),
new DatabaseUnavailableException(), new DatabaseUnavailableException(),
new DatabaseUnavailableException());
ShippingService ss = new ShippingService(new ShippingDatabase()); ShippingService ss = new ShippingService(new ShippingDatabase());
MessagingService ms = new MessagingService(new MessagingDatabase(), new DatabaseUnavailableException(), MessagingService ms =
new DatabaseUnavailableException(), new DatabaseUnavailableException(), new DatabaseUnavailableException(), 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(),
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()); EmployeeHandle eh = new EmployeeHandle(new EmployeeDatabase());
QueueDatabase qdb = new QueueDatabase(); QueueDatabase qdb = new QueueDatabase();
Commander c = new Commander(eh,ps,ss,ms,qdb,numOfRetries,retryDuration, Commander c = new Commander(eh, ps, ss, ms, qdb, numOfRetries, retryDuration,
queueTime,queueTaskTime,paymentTime,messageTime,employeeTime); queueTime, queueTaskTime, paymentTime, messageTime, employeeTime);
User user = new User("Jim", "ABCD"); User user = new User("Jim", "ABCD");
Order order = new Order(user, "book", 10f); Order order = new Order(user, "book", 10f);
c.placeOrder(order); c.placeOrder(order);
} }
void messagingDatabaseUnavailableCasePaymentFailure() throws Exception { void messagingDatabaseUnavailableCasePaymentFailure() throws Exception {
//rest is successful //rest is successful
PaymentService ps = new PaymentService(new PaymentDatabase(), new DatabaseUnavailableException(), PaymentService ps =
new DatabaseUnavailableException(), new DatabaseUnavailableException(), new DatabaseUnavailableException(), new PaymentService(new PaymentDatabase(), new DatabaseUnavailableException(),
new DatabaseUnavailableException(), new DatabaseUnavailableException()); new DatabaseUnavailableException(), new DatabaseUnavailableException(),
new DatabaseUnavailableException(), new DatabaseUnavailableException(),
new DatabaseUnavailableException());
ShippingService ss = new ShippingService(new ShippingDatabase()); ShippingService ss = new ShippingService(new ShippingDatabase());
MessagingService ms = new MessagingService(new MessagingDatabase(), new DatabaseUnavailableException(), MessagingService ms =
new DatabaseUnavailableException(), new DatabaseUnavailableException(), new DatabaseUnavailableException(), new MessagingService(new MessagingDatabase(), new DatabaseUnavailableException(),
new DatabaseUnavailableException(), new DatabaseUnavailableException()); new DatabaseUnavailableException(), new DatabaseUnavailableException(),
new DatabaseUnavailableException(), new DatabaseUnavailableException(),
new DatabaseUnavailableException());
EmployeeHandle eh = new EmployeeHandle(new EmployeeDatabase()); EmployeeHandle eh = new EmployeeHandle(new EmployeeDatabase());
QueueDatabase qdb = new QueueDatabase(new DatabaseUnavailableException(), new DatabaseUnavailableException(), QueueDatabase qdb =
new DatabaseUnavailableException(), new DatabaseUnavailableException(), new DatabaseUnavailableException(), new QueueDatabase(new DatabaseUnavailableException(), new DatabaseUnavailableException(),
new DatabaseUnavailableException()); new DatabaseUnavailableException(), new DatabaseUnavailableException(),
Commander c = new Commander(eh,ps,ss,ms,qdb,numOfRetries,retryDuration,queueTime,queueTaskTime, new DatabaseUnavailableException(), new DatabaseUnavailableException());
paymentTime,messageTime,employeeTime); Commander c =
new Commander(eh, ps, ss, ms, qdb, numOfRetries, retryDuration, queueTime, queueTaskTime,
paymentTime, messageTime, employeeTime);
User user = new User("Jim", "ABCD"); User user = new User("Jim", "ABCD");
Order order = new Order(user, "book", 10f); Order order = new Order(user, "book", 10f);
c.placeOrder(order); c.placeOrder(order);
@ -107,16 +121,19 @@ public class AppMessagingFailCases {
void messagingSuccessCase() throws Exception { void messagingSuccessCase() throws Exception {
//done here //done here
PaymentService ps = new PaymentService(new PaymentDatabase(), new DatabaseUnavailableException(), PaymentService ps =
new DatabaseUnavailableException(), new DatabaseUnavailableException(), new DatabaseUnavailableException(), new PaymentService(new PaymentDatabase(), new DatabaseUnavailableException(),
new DatabaseUnavailableException(), new DatabaseUnavailableException()); new DatabaseUnavailableException(), new DatabaseUnavailableException(),
new DatabaseUnavailableException(), new DatabaseUnavailableException(),
new DatabaseUnavailableException());
ShippingService ss = new ShippingService(new ShippingDatabase()); ShippingService ss = new ShippingService(new ShippingDatabase());
MessagingService ms = new MessagingService(new MessagingDatabase(), new DatabaseUnavailableException(), MessagingService ms =
new DatabaseUnavailableException()); new MessagingService(new MessagingDatabase(), new DatabaseUnavailableException(),
new DatabaseUnavailableException());
EmployeeHandle eh = new EmployeeHandle(new EmployeeDatabase()); EmployeeHandle eh = new EmployeeHandle(new EmployeeDatabase());
QueueDatabase qdb = new QueueDatabase(); QueueDatabase qdb = new QueueDatabase();
Commander c = new Commander(eh,ps,ss,ms,qdb,numOfRetries,retryDuration, Commander c = new Commander(eh, ps, ss, ms, qdb, numOfRetries, retryDuration,
queueTime,queueTaskTime,paymentTime,messageTime,employeeTime); queueTime, queueTaskTime, paymentTime, messageTime, employeeTime);
User user = new User("Jim", "ABCD"); User user = new User("Jim", "ABCD");
Order order = new Order(user, "book", 10f); Order order = new Order(user, "book", 10f);
c.placeOrder(order); c.placeOrder(order);
@ -127,7 +144,7 @@ public class AppMessagingFailCases {
* *
* @param args command line args * @param args command line args
*/ */
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
AppMessagingFailCases amfc = new AppMessagingFailCases(); AppMessagingFailCases amfc = new AppMessagingFailCases();
//amfc.messagingDatabaseUnavailableCasePaymentSuccess(); //amfc.messagingDatabaseUnavailableCasePaymentSuccess();

View File

@ -31,13 +31,12 @@ import com.iluwatar.commander.messagingservice.MessagingDatabase;
import com.iluwatar.commander.messagingservice.MessagingService; import com.iluwatar.commander.messagingservice.MessagingService;
import com.iluwatar.commander.paymentservice.PaymentDatabase; import com.iluwatar.commander.paymentservice.PaymentDatabase;
import com.iluwatar.commander.paymentservice.PaymentService; import com.iluwatar.commander.paymentservice.PaymentService;
import com.iluwatar.commander.queue.QueueDatabase;
import com.iluwatar.commander.shippingservice.ShippingDatabase; import com.iluwatar.commander.shippingservice.ShippingDatabase;
import com.iluwatar.commander.shippingservice.ShippingService; import com.iluwatar.commander.shippingservice.ShippingService;
import com.iluwatar.commander.queue.QueueDatabase;
/** /**
* AppPaymentFailCases class looks at possible cases when Payment service is * AppPaymentFailCases class looks at possible cases when Payment service is available/unavailable.
* available/unavailable.
*/ */
public class AppPaymentFailCases { public class AppPaymentFailCases {
@ -50,14 +49,16 @@ public class AppPaymentFailCases {
final long employeeTime = 240000; //4 mins final long employeeTime = 240000; //4 mins
void paymentNotPossibleCase() throws Exception { void paymentNotPossibleCase() throws Exception {
PaymentService ps = new PaymentService(new PaymentDatabase(), new DatabaseUnavailableException(), PaymentService ps =
new PaymentDetailsErrorException()); new PaymentService(new PaymentDatabase(), new DatabaseUnavailableException(),
new PaymentDetailsErrorException());
ShippingService ss = new ShippingService(new ShippingDatabase()); ShippingService ss = new ShippingService(new ShippingDatabase());
MessagingService ms = new MessagingService(new MessagingDatabase(), new DatabaseUnavailableException()); MessagingService ms =
new MessagingService(new MessagingDatabase(), new DatabaseUnavailableException());
EmployeeHandle eh = new EmployeeHandle(new EmployeeDatabase()); EmployeeHandle eh = new EmployeeHandle(new EmployeeDatabase());
QueueDatabase qdb = new QueueDatabase(new DatabaseUnavailableException()); QueueDatabase qdb = new QueueDatabase(new DatabaseUnavailableException());
Commander c = new Commander(eh,ps,ss,ms,qdb,numOfRetries,retryDuration, Commander c = new Commander(eh, ps, ss, ms, qdb, numOfRetries, retryDuration,
queueTime,queueTaskTime,paymentTime,messageTime,employeeTime); queueTime, queueTaskTime, paymentTime, messageTime, employeeTime);
User user = new User("Jim", "ABCD"); User user = new User("Jim", "ABCD");
Order order = new Order(user, "book", 10f); Order order = new Order(user, "book", 10f);
c.placeOrder(order); c.placeOrder(order);
@ -65,15 +66,17 @@ public class AppPaymentFailCases {
void paymentDatabaseUnavailableCase() throws Exception { void paymentDatabaseUnavailableCase() throws Exception {
//rest is successful //rest is successful
PaymentService ps = new PaymentService(new PaymentDatabase(), new DatabaseUnavailableException(), PaymentService ps =
new DatabaseUnavailableException(), new DatabaseUnavailableException(), new DatabaseUnavailableException(), new PaymentService(new PaymentDatabase(), new DatabaseUnavailableException(),
new DatabaseUnavailableException(), new DatabaseUnavailableException()); new DatabaseUnavailableException(), new DatabaseUnavailableException(),
new DatabaseUnavailableException(), new DatabaseUnavailableException(),
new DatabaseUnavailableException());
ShippingService ss = new ShippingService(new ShippingDatabase()); ShippingService ss = new ShippingService(new ShippingDatabase());
MessagingService ms = new MessagingService(new MessagingDatabase()); MessagingService ms = new MessagingService(new MessagingDatabase());
EmployeeHandle eh = new EmployeeHandle(new EmployeeDatabase()); EmployeeHandle eh = new EmployeeHandle(new EmployeeDatabase());
QueueDatabase qdb = new QueueDatabase(); QueueDatabase qdb = new QueueDatabase();
Commander c = new Commander(eh,ps,ss,ms,qdb,numOfRetries,retryDuration, Commander c = new Commander(eh, ps, ss, ms, qdb, numOfRetries, retryDuration,
queueTime,queueTaskTime,paymentTime,messageTime,employeeTime); queueTime, queueTaskTime, paymentTime, messageTime, employeeTime);
User user = new User("Jim", "ABCD"); User user = new User("Jim", "ABCD");
Order order = new Order(user, "book", 10f); Order order = new Order(user, "book", 10f);
c.placeOrder(order); c.placeOrder(order);
@ -81,14 +84,16 @@ public class AppPaymentFailCases {
void paymentSuccessCase() throws Exception { void paymentSuccessCase() throws Exception {
//goes to message after 2 retries maybe - rest is successful for now //goes to message after 2 retries maybe - rest is successful for now
PaymentService ps = new PaymentService(new PaymentDatabase(), new DatabaseUnavailableException(), PaymentService ps =
new DatabaseUnavailableException()); new PaymentService(new PaymentDatabase(), new DatabaseUnavailableException(),
new DatabaseUnavailableException());
ShippingService ss = new ShippingService(new ShippingDatabase()); ShippingService ss = new ShippingService(new ShippingDatabase());
MessagingService ms = new MessagingService(new MessagingDatabase(), new DatabaseUnavailableException()); MessagingService ms =
new MessagingService(new MessagingDatabase(), new DatabaseUnavailableException());
EmployeeHandle eh = new EmployeeHandle(new EmployeeDatabase()); EmployeeHandle eh = new EmployeeHandle(new EmployeeDatabase());
QueueDatabase qdb = new QueueDatabase(new DatabaseUnavailableException()); QueueDatabase qdb = new QueueDatabase(new DatabaseUnavailableException());
Commander c = new Commander(eh,ps,ss,ms,qdb,numOfRetries,retryDuration, Commander c = new Commander(eh, ps, ss, ms, qdb, numOfRetries, retryDuration,
queueTime,queueTaskTime,paymentTime,messageTime,employeeTime); queueTime, queueTaskTime, paymentTime, messageTime, employeeTime);
User user = new User("Jim", "ABCD"); User user = new User("Jim", "ABCD");
Order order = new Order(user, "book", 10f); Order order = new Order(user, "book", 10f);
c.placeOrder(order); c.placeOrder(order);
@ -99,7 +104,7 @@ public class AppPaymentFailCases {
* *
* @param args command line args * @param args command line args
*/ */
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
AppPaymentFailCases apfc = new AppPaymentFailCases(); AppPaymentFailCases apfc = new AppPaymentFailCases();
//apfc.paymentNotPossibleCase(); //apfc.paymentNotPossibleCase();

View File

@ -31,13 +31,12 @@ import com.iluwatar.commander.messagingservice.MessagingDatabase;
import com.iluwatar.commander.messagingservice.MessagingService; import com.iluwatar.commander.messagingservice.MessagingService;
import com.iluwatar.commander.paymentservice.PaymentDatabase; import com.iluwatar.commander.paymentservice.PaymentDatabase;
import com.iluwatar.commander.paymentservice.PaymentService; import com.iluwatar.commander.paymentservice.PaymentService;
import com.iluwatar.commander.queue.QueueDatabase;
import com.iluwatar.commander.shippingservice.ShippingDatabase; import com.iluwatar.commander.shippingservice.ShippingDatabase;
import com.iluwatar.commander.shippingservice.ShippingService; import com.iluwatar.commander.shippingservice.ShippingService;
import com.iluwatar.commander.queue.QueueDatabase;
/** /**
* AppQueueFailCases class looks at possible cases when Queue Database is * AppQueueFailCases class looks at possible cases when Queue Database is available/unavailable.
* available/unavailable.
*/ */
public class AppQueueFailCases { public class AppQueueFailCases {
@ -50,71 +49,87 @@ public class AppQueueFailCases {
final long employeeTime = 240000; //4 mins final long employeeTime = 240000; //4 mins
void queuePaymentTaskDatabaseUnavailableCase() throws Exception { void queuePaymentTaskDatabaseUnavailableCase() throws Exception {
PaymentService ps = new PaymentService(new PaymentDatabase(), new DatabaseUnavailableException(), PaymentService ps =
new DatabaseUnavailableException(), new DatabaseUnavailableException(), new DatabaseUnavailableException(), new PaymentService(new PaymentDatabase(), new DatabaseUnavailableException(),
new DatabaseUnavailableException(), new DatabaseUnavailableException()); new DatabaseUnavailableException(), new DatabaseUnavailableException(),
new DatabaseUnavailableException(), new DatabaseUnavailableException(),
new DatabaseUnavailableException());
ShippingService ss = new ShippingService(new ShippingDatabase()); ShippingService ss = new ShippingService(new ShippingDatabase());
MessagingService ms = new MessagingService(new MessagingDatabase()); MessagingService ms = new MessagingService(new MessagingDatabase());
EmployeeHandle eh = new EmployeeHandle(new EmployeeDatabase()); EmployeeHandle eh = new EmployeeHandle(new EmployeeDatabase());
QueueDatabase qdb = new QueueDatabase(new DatabaseUnavailableException(), new DatabaseUnavailableException(), QueueDatabase qdb =
new DatabaseUnavailableException(), new DatabaseUnavailableException(), new DatabaseUnavailableException(), new QueueDatabase(new DatabaseUnavailableException(), new DatabaseUnavailableException(),
new DatabaseUnavailableException()); new DatabaseUnavailableException(), new DatabaseUnavailableException(),
Commander c = new Commander(eh,ps,ss,ms,qdb,numOfRetries,retryDuration, new DatabaseUnavailableException(), new DatabaseUnavailableException());
queueTime,queueTaskTime,paymentTime,messageTime,employeeTime); Commander c = new Commander(eh, ps, ss, ms, qdb, numOfRetries, retryDuration,
queueTime, queueTaskTime, paymentTime, messageTime, employeeTime);
User user = new User("Jim", "ABCD"); User user = new User("Jim", "ABCD");
Order order = new Order(user, "book", 10f); Order order = new Order(user, "book", 10f);
c.placeOrder(order); c.placeOrder(order);
} }
void queueMessageTaskDatabaseUnavailableCase() throws Exception { void queueMessageTaskDatabaseUnavailableCase() throws Exception {
PaymentService ps = new PaymentService(new PaymentDatabase()); PaymentService ps = new PaymentService(new PaymentDatabase());
ShippingService ss = new ShippingService(new ShippingDatabase()); ShippingService ss = new ShippingService(new ShippingDatabase());
MessagingService ms = new MessagingService(new MessagingDatabase(), new DatabaseUnavailableException(), MessagingService ms =
new DatabaseUnavailableException(), new DatabaseUnavailableException(), new DatabaseUnavailableException(), new MessagingService(new MessagingDatabase(), new DatabaseUnavailableException(),
new DatabaseUnavailableException(), new DatabaseUnavailableException()); new DatabaseUnavailableException(), new DatabaseUnavailableException(),
new DatabaseUnavailableException(), new DatabaseUnavailableException(),
new DatabaseUnavailableException());
EmployeeHandle eh = new EmployeeHandle(new EmployeeDatabase()); EmployeeHandle eh = new EmployeeHandle(new EmployeeDatabase());
QueueDatabase qdb = new QueueDatabase(new DatabaseUnavailableException(), new DatabaseUnavailableException(), QueueDatabase qdb =
new DatabaseUnavailableException(), new DatabaseUnavailableException(), new DatabaseUnavailableException(), new QueueDatabase(new DatabaseUnavailableException(), new DatabaseUnavailableException(),
new DatabaseUnavailableException()); new DatabaseUnavailableException(), new DatabaseUnavailableException(),
Commander c = new Commander(eh,ps,ss,ms,qdb,numOfRetries,retryDuration, new DatabaseUnavailableException(), new DatabaseUnavailableException());
queueTime,queueTaskTime,paymentTime,messageTime,employeeTime); Commander c = new Commander(eh, ps, ss, ms, qdb, numOfRetries, retryDuration,
queueTime, queueTaskTime, paymentTime, messageTime, employeeTime);
User user = new User("Jim", "ABCD"); User user = new User("Jim", "ABCD");
Order order = new Order(user, "book", 10f); Order order = new Order(user, "book", 10f);
c.placeOrder(order); c.placeOrder(order);
} }
void queueEmployeeDbTaskDatabaseUnavailableCase() throws Exception { void queueEmployeeDbTaskDatabaseUnavailableCase() throws Exception {
PaymentService ps = new PaymentService(new PaymentDatabase()); PaymentService ps = new PaymentService(new PaymentDatabase());
ShippingService ss = new ShippingService(new ShippingDatabase(), new ItemUnavailableException()); ShippingService ss =
new ShippingService(new ShippingDatabase(), new ItemUnavailableException());
MessagingService ms = new MessagingService(new MessagingDatabase()); MessagingService ms = new MessagingService(new MessagingDatabase());
EmployeeHandle eh = new EmployeeHandle(new EmployeeDatabase(), new DatabaseUnavailableException(), EmployeeHandle eh =
new DatabaseUnavailableException(), new DatabaseUnavailableException(), new DatabaseUnavailableException(), 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(), 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(), new DatabaseUnavailableException());
new DatabaseUnavailableException(), new DatabaseUnavailableException(), new DatabaseUnavailableException(), QueueDatabase qdb =
new DatabaseUnavailableException()); new QueueDatabase(new DatabaseUnavailableException(), new DatabaseUnavailableException(),
Commander c = new Commander(eh,ps,ss,ms,qdb,numOfRetries,retryDuration, new DatabaseUnavailableException(), new DatabaseUnavailableException(),
queueTime,queueTaskTime,paymentTime,messageTime,employeeTime); 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"); User user = new User("Jim", "ABCD");
Order order = new Order(user, "book", 10f); Order order = new Order(user, "book", 10f);
c.placeOrder(order); c.placeOrder(order);
} }
void queueSuccessCase() throws Exception { void queueSuccessCase() throws Exception {
PaymentService ps = new PaymentService(new PaymentDatabase(), new DatabaseUnavailableException(), PaymentService ps =
new DatabaseUnavailableException(), new DatabaseUnavailableException(), new DatabaseUnavailableException(), new PaymentService(new PaymentDatabase(), new DatabaseUnavailableException(),
new DatabaseUnavailableException(), new DatabaseUnavailableException()); new DatabaseUnavailableException(), new DatabaseUnavailableException(),
new DatabaseUnavailableException(), new DatabaseUnavailableException(),
new DatabaseUnavailableException());
ShippingService ss = new ShippingService(new ShippingDatabase()); ShippingService ss = new ShippingService(new ShippingDatabase());
MessagingService ms = new MessagingService(new MessagingDatabase(), new DatabaseUnavailableException(), MessagingService ms =
new DatabaseUnavailableException()); new MessagingService(new MessagingDatabase(), new DatabaseUnavailableException(),
new DatabaseUnavailableException());
EmployeeHandle eh = new EmployeeHandle(new EmployeeDatabase()); EmployeeHandle eh = new EmployeeHandle(new EmployeeDatabase());
QueueDatabase qdb = new QueueDatabase(new DatabaseUnavailableException(), new DatabaseUnavailableException()); QueueDatabase qdb =
Commander c = new Commander(eh,ps,ss,ms,qdb,numOfRetries,retryDuration, new QueueDatabase(new DatabaseUnavailableException(), new DatabaseUnavailableException());
queueTime,queueTaskTime,paymentTime,messageTime,employeeTime); Commander c = new Commander(eh, ps, ss, ms, qdb, numOfRetries, retryDuration,
queueTime, queueTaskTime, paymentTime, messageTime, employeeTime);
User user = new User("Jim", "ABCD"); User user = new User("Jim", "ABCD");
Order order = new Order(user, "book", 10f); Order order = new Order(user, "book", 10f);
c.placeOrder(order); c.placeOrder(order);

View File

@ -32,12 +32,12 @@ import com.iluwatar.commander.messagingservice.MessagingDatabase;
import com.iluwatar.commander.messagingservice.MessagingService; import com.iluwatar.commander.messagingservice.MessagingService;
import com.iluwatar.commander.paymentservice.PaymentDatabase; import com.iluwatar.commander.paymentservice.PaymentDatabase;
import com.iluwatar.commander.paymentservice.PaymentService; import com.iluwatar.commander.paymentservice.PaymentService;
import com.iluwatar.commander.queue.QueueDatabase;
import com.iluwatar.commander.shippingservice.ShippingDatabase; import com.iluwatar.commander.shippingservice.ShippingDatabase;
import com.iluwatar.commander.shippingservice.ShippingService; import com.iluwatar.commander.shippingservice.ShippingService;
import com.iluwatar.commander.queue.QueueDatabase;
/** /**
* AppShippingFailCases class looks at possible cases when Shipping service is * AppShippingFailCases class looks at possible cases when Shipping service is
* available/unavailable. * available/unavailable.
*/ */
@ -51,26 +51,28 @@ public class AppShippingFailCases {
final long employeeTime = 240000; //4 mins final long employeeTime = 240000; //4 mins
void itemUnavailableCase() throws Exception { void itemUnavailableCase() throws Exception {
PaymentService ps = new PaymentService(new PaymentDatabase()); PaymentService ps = new PaymentService(new PaymentDatabase());
ShippingService ss = new ShippingService(new ShippingDatabase(), new ItemUnavailableException()); ShippingService ss =
new ShippingService(new ShippingDatabase(), new ItemUnavailableException());
MessagingService ms = new MessagingService(new MessagingDatabase()); MessagingService ms = new MessagingService(new MessagingDatabase());
EmployeeHandle eh = new EmployeeHandle(new EmployeeDatabase()); EmployeeHandle eh = new EmployeeHandle(new EmployeeDatabase());
QueueDatabase qdb = new QueueDatabase(); QueueDatabase qdb = new QueueDatabase();
Commander c = new Commander(eh,ps,ss,ms,qdb,numOfRetries,retryDuration, Commander c = new Commander(eh, ps, ss, ms, qdb, numOfRetries, retryDuration,
queueTime,queueTaskTime,paymentTime,messageTime,employeeTime); queueTime, queueTaskTime, paymentTime, messageTime, employeeTime);
User user = new User("Jim", "ABCD"); User user = new User("Jim", "ABCD");
Order order = new Order(user, "book", 10f); Order order = new Order(user, "book", 10f);
c.placeOrder(order); c.placeOrder(order);
} }
void shippingNotPossibleCase() throws Exception { void shippingNotPossibleCase() throws Exception {
PaymentService ps = new PaymentService(new PaymentDatabase()); PaymentService ps = new PaymentService(new PaymentDatabase());
ShippingService ss = new ShippingService(new ShippingDatabase(), new ShippingNotPossibleException()); ShippingService ss =
new ShippingService(new ShippingDatabase(), new ShippingNotPossibleException());
MessagingService ms = new MessagingService(new MessagingDatabase()); MessagingService ms = new MessagingService(new MessagingDatabase());
EmployeeHandle eh = new EmployeeHandle(new EmployeeDatabase()); EmployeeHandle eh = new EmployeeHandle(new EmployeeDatabase());
QueueDatabase qdb = new QueueDatabase(); QueueDatabase qdb = new QueueDatabase();
Commander c = new Commander(eh,ps,ss,ms,qdb,numOfRetries,retryDuration, Commander c = new Commander(eh, ps, ss, ms, qdb, numOfRetries, retryDuration,
queueTime,queueTaskTime,paymentTime,messageTime,employeeTime); queueTime, queueTaskTime, paymentTime, messageTime, employeeTime);
User user = new User("Jim", "ABCD"); User user = new User("Jim", "ABCD");
Order order = new Order(user, "book", 10f); Order order = new Order(user, "book", 10f);
c.placeOrder(order); c.placeOrder(order);
@ -78,15 +80,17 @@ public class AppShippingFailCases {
void shippingDatabaseUnavailableCase() throws Exception { void shippingDatabaseUnavailableCase() throws Exception {
//rest is successful //rest is successful
PaymentService ps = new PaymentService(new PaymentDatabase()); PaymentService ps = new PaymentService(new PaymentDatabase());
ShippingService ss = new ShippingService(new ShippingDatabase(), new DatabaseUnavailableException(), ShippingService ss =
new DatabaseUnavailableException(), new DatabaseUnavailableException(), new DatabaseUnavailableException(), new ShippingService(new ShippingDatabase(), new DatabaseUnavailableException(),
new DatabaseUnavailableException(), new DatabaseUnavailableException()); new DatabaseUnavailableException(), new DatabaseUnavailableException(),
new DatabaseUnavailableException(), new DatabaseUnavailableException(),
new DatabaseUnavailableException());
MessagingService ms = new MessagingService(new MessagingDatabase()); MessagingService ms = new MessagingService(new MessagingDatabase());
EmployeeHandle eh = new EmployeeHandle(new EmployeeDatabase()); EmployeeHandle eh = new EmployeeHandle(new EmployeeDatabase());
QueueDatabase qdb = new QueueDatabase(); QueueDatabase qdb = new QueueDatabase();
Commander c = new Commander(eh,ps,ss,ms,qdb,numOfRetries,retryDuration, Commander c = new Commander(eh, ps, ss, ms, qdb, numOfRetries, retryDuration,
queueTime,queueTaskTime,paymentTime,messageTime,employeeTime); queueTime, queueTaskTime, paymentTime, messageTime, employeeTime);
User user = new User("Jim", "ABCD"); User user = new User("Jim", "ABCD");
Order order = new Order(user, "book", 10f); Order order = new Order(user, "book", 10f);
c.placeOrder(order); c.placeOrder(order);
@ -94,25 +98,28 @@ public class AppShippingFailCases {
void shippingSuccessCase() throws Exception { void shippingSuccessCase() throws Exception {
//goes to payment after 2 retries maybe - rest is successful for now //goes to payment after 2 retries maybe - rest is successful for now
PaymentService ps = new PaymentService(new PaymentDatabase(), new DatabaseUnavailableException()); PaymentService ps =
ShippingService ss = new ShippingService(new ShippingDatabase(), new DatabaseUnavailableException(), new PaymentService(new PaymentDatabase(), new DatabaseUnavailableException());
new DatabaseUnavailableException()); ShippingService ss =
MessagingService ms = new MessagingService(new MessagingDatabase(), new DatabaseUnavailableException()); new ShippingService(new ShippingDatabase(), new DatabaseUnavailableException(),
new DatabaseUnavailableException());
MessagingService ms =
new MessagingService(new MessagingDatabase(), new DatabaseUnavailableException());
EmployeeHandle eh = new EmployeeHandle(new EmployeeDatabase()); EmployeeHandle eh = new EmployeeHandle(new EmployeeDatabase());
QueueDatabase qdb = new QueueDatabase(); QueueDatabase qdb = new QueueDatabase();
Commander c = new Commander(eh,ps,ss,ms,qdb,numOfRetries,retryDuration, Commander c = new Commander(eh, ps, ss, ms, qdb, numOfRetries, retryDuration,
queueTime,queueTaskTime,paymentTime,messageTime,employeeTime); queueTime, queueTaskTime, paymentTime, messageTime, employeeTime);
User user = new User("Jim", "ABCD"); User user = new User("Jim", "ABCD");
Order order = new Order(user, "book", 10f); Order order = new Order(user, "book", 10f);
c.placeOrder(order); c.placeOrder(order);
} }
/** /**
* Program entry point. * Program entry point.
* *
* @param args command line args * @param args command line args
*/ */
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
AppShippingFailCases asfc = new AppShippingFailCases(); AppShippingFailCases asfc = new AppShippingFailCases();
//asfc.itemUnavailableCase(); //asfc.itemUnavailableCase();

View File

@ -23,53 +23,51 @@
package com.iluwatar.commander; package com.iluwatar.commander;
import java.util.ArrayList; import com.iluwatar.commander.Order.MessageSent;
import com.iluwatar.commander.Order.PaymentStatus;
import com.iluwatar.commander.employeehandle.EmployeeHandle; import com.iluwatar.commander.employeehandle.EmployeeHandle;
import com.iluwatar.commander.exceptions.DatabaseUnavailableException; import com.iluwatar.commander.exceptions.DatabaseUnavailableException;
import com.iluwatar.commander.exceptions.ItemUnavailableException; import com.iluwatar.commander.exceptions.ItemUnavailableException;
import com.iluwatar.commander.exceptions.PaymentDetailsErrorException; import com.iluwatar.commander.exceptions.PaymentDetailsErrorException;
import com.iluwatar.commander.exceptions.ShippingNotPossibleException; import com.iluwatar.commander.exceptions.ShippingNotPossibleException;
import com.iluwatar.commander.messagingservice.MessagingService; import com.iluwatar.commander.messagingservice.MessagingService;
import com.iluwatar.commander.Order.MessageSent;
import com.iluwatar.commander.Order.PaymentStatus;
import com.iluwatar.commander.paymentservice.PaymentService; import com.iluwatar.commander.paymentservice.PaymentService;
import com.iluwatar.commander.queue.QueueDatabase; import com.iluwatar.commander.queue.QueueDatabase;
import com.iluwatar.commander.queue.QueueTask; import com.iluwatar.commander.queue.QueueTask;
import com.iluwatar.commander.queue.QueueTask.TaskType; import com.iluwatar.commander.queue.QueueTask.TaskType;
import com.iluwatar.commander.shippingservice.ShippingService; import com.iluwatar.commander.shippingservice.ShippingService;
import java.util.ArrayList;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
/** /**
*<p>Commander pattern is used to handle all issues that can come up while making a * <p>Commander pattern is used to handle all issues that can come up while making a
* distributed transaction. The idea is to have a commander, which coordinates the * distributed transaction. The idea is to have a commander, which coordinates the execution of all
* execution of all instructions and ensures proper completion using retries and * instructions and ensures proper completion using retries and taking care of idempotence. By
* taking care of idempotence. By queueing instructions while they haven't been done, * queueing instructions while they haven't been done, we can ensure a state of 'eventual
* we can ensure a state of 'eventual consistency'.</p> * consistency'.</p>
* <p>In our example, we have an e-commerce application. When the user places an order, * <p>In our example, we have an e-commerce application. When the user places an order,
* the shipping service is intimated first. If the service does not respond for some * the shipping service is intimated first. If the service does not respond for some reason, the
* reason, the order is not placed. If response is received, the commander then calls * order is not placed. If response is received, the commander then calls for the payment service to
* for the payment service to be intimated. If this fails, the shipping still takes * be intimated. If this fails, the shipping still takes place (order converted to COD) and the item
* place (order converted to COD) and the item is queued. If the queue is also found * is queued. If the queue is also found to be unavailable, the payment is noted to be not done and
* to be unavailable, the payment is noted to be not done and this is added to an * this is added to an employee database. Three types of messages are sent to the user - one, if
* employee database. Three types of messages are sent to the user - one, if payment * payment succeeds; two, if payment fails definitively; and three, if payment fails in the first
* succeeds; two, if payment fails definitively; and three, if payment fails in the * attempt. If the message is not sent, this is also queued and is added to employee db. We also
* first attempt. If the message is not sent, this is also queued and is added to employee * have a time limit for each instruction to be completed, after which, the instruction is not
* db. We also have a time limit for each instruction to be completed, after which, the * executed, thereby ensuring that resources are not held for too long. In the rare occasion in
* instruction is not executed, thereby ensuring that resources are not held for too long. * which everything fails, an individual would have to step in to figure out how to solve the
* In the rare occasion in which everything fails, an individual would have to step in to * issue.</p>
* figure out how to solve the issue.</p>
* <p>We have abstract classes {@link Database} and {@link Service} which are extended * <p>We have abstract classes {@link Database} and {@link Service} which are extended
* by all the databases and services. Each service has a database to be updated, and * by all the databases and services. Each service has a database to be updated, and receives
* receives request from an outside user (the {@link Commander} class here). There are * request from an outside user (the {@link Commander} class here). There are 5 microservices -
* 5 microservices - {@link ShippingService}, {@link PaymentService}, {@link MessagingService}, * {@link ShippingService}, {@link PaymentService}, {@link MessagingService}, {@link EmployeeHandle}
* {@link EmployeeHandle} and a {@link QueueDatabase}. We use retries to execute any * and a {@link QueueDatabase}. We use retries to execute any instruction using {@link Retry} class,
* instruction using {@link Retry} class, and idempotence is ensured by going through some * and idempotence is ensured by going through some checks before making requests to services and
* checks before making requests to services and making change in {@link Order} class fields * making change in {@link Order} class fields if request succeeds or definitively fails. There are
* if request succeeds or definitively fails. There are 5 classes - * 5 classes - {@link AppShippingFailCases}, {@link AppPaymentFailCases}, {@link
* {@link AppShippingFailCases}, {@link AppPaymentFailCases}, {@link AppMessagingFailCases}, * AppMessagingFailCases}, {@link AppQueueFailCases} and {@link AppEmployeeDbFailCases}, which look
* {@link AppQueueFailCases} and {@link AppEmployeeDbFailCases}, which look at the different * at the different scenarios that may be encountered during the placing of an order.</p>
* scenarios that may be encountered during the placing of an order.</p>
*/ */
public class Commander { public class Commander {
@ -86,17 +84,18 @@ public class Commander {
private final long queueTaskTime; private final long queueTaskTime;
private final long paymentTime; private final long paymentTime;
private final long messageTime; private final long messageTime;
private final long employeeTime; private final long employeeTime;
private boolean finalSiteMsgShown; private boolean finalSiteMsgShown;
static final Logger LOG = LoggerFactory.getLogger(Commander.class); static final Logger LOG = LoggerFactory.getLogger(Commander.class);
//we could also have another db where it stores all orders //we could also have another db where it stores all orders
Commander(EmployeeHandle empDb, PaymentService pService, ShippingService sService, Commander(EmployeeHandle empDb, PaymentService paymentService, ShippingService shippingService,
MessagingService mService, QueueDatabase qdb, int numOfRetries, long retryDuration, MessagingService messagingService, QueueDatabase qdb, int numOfRetries,
long queueTime, long queueTaskTime, long paymentTime, long messageTime, long employeeTime) { long retryDuration, long queueTime, long queueTaskTime, long paymentTime,
this.paymentService = pService; long messageTime, long employeeTime) {
this.shippingService = sService; this.paymentService = paymentService;
this.messagingService = mService; this.shippingService = shippingService;
this.messagingService = messagingService;
this.employeeDb = empDb; this.employeeDb = empDb;
this.queue = qdb; this.queue = qdb;
this.numOfRetries = numOfRetries; this.numOfRetries = numOfRetries;
@ -106,7 +105,7 @@ public class Commander {
this.paymentTime = paymentTime; this.paymentTime = paymentTime;
this.messageTime = messageTime; this.messageTime = messageTime;
this.employeeTime = employeeTime; this.employeeTime = employeeTime;
this.finalSiteMsgShown = false; this.finalSiteMsgShown = false;
} }
void placeOrder(Order order) throws Exception { void placeOrder(Order order) throws Exception {
@ -118,40 +117,43 @@ public class Commander {
Retry.Operation op = (l) -> { Retry.Operation op = (l) -> {
if (!l.isEmpty()) { if (!l.isEmpty()) {
if (DatabaseUnavailableException.class.isAssignableFrom(l.get(0).getClass())) { if (DatabaseUnavailableException.class.isAssignableFrom(l.get(0).getClass())) {
LOG.debug("Order " + order.id + ": Error in connecting to shipping service, trying again.."); LOG.debug("Order " + order.id + ": Error in connecting to shipping service, "
+ "trying again..");
} else { } else {
LOG.debug("Order " + order.id + ": Error in creating shipping request.."); LOG.debug("Order " + order.id + ": Error in creating shipping request..");
} }
throw l.remove(0); throw l.remove(0);
} }
String transactionId = shippingService.receiveRequest(order.item, order.user.address); String transactionId = shippingService.receiveRequest(order.item, order.user.address);
//could save this transaction id in a db too //could save this transaction id in a db too
LOG.info("Order " + order.id + ": Shipping placed successfully, transaction id: " + transactionId); LOG.info("Order " + order.id + ": Shipping placed successfully, transaction id: "
+ transactionId);
LOG.info("Order has been placed and will be shipped to you. Please wait while we make your" LOG.info("Order has been placed and will be shipped to you. Please wait while we make your"
+ " payment... "); + " payment... ");
sendPaymentRequest(order); sendPaymentRequest(order);
return; return;
}; };
Retry.HandleErrorIssue<Order> handleError = (o,err) -> { Retry.HandleErrorIssue<Order> handleError = (o, err) -> {
if (ShippingNotPossibleException.class.isAssignableFrom(err.getClass())) { if (ShippingNotPossibleException.class.isAssignableFrom(err.getClass())) {
LOG.info("Shipping is currently not possible to your address. We are working on the problem " LOG.info("Shipping is currently not possible to your address. We are working on the problem"
+ "and will get back to you asap."); + " and will get back to you asap.");
finalSiteMsgShown = true; finalSiteMsgShown = true;
LOG.info("Order " + order.id + ": Shipping not possible to address, trying to add problem to employee db.."); LOG.info("Order " + order.id + ": Shipping not possible to address, trying to add problem "
+ "to employee db..");
employeeHandleIssue(o); employeeHandleIssue(o);
} else if (ItemUnavailableException.class.isAssignableFrom(err.getClass())) { } else if (ItemUnavailableException.class.isAssignableFrom(err.getClass())) {
LOG.info("This item is currently unavailable. We will inform you as soon as the item becomes " LOG.info("This item is currently unavailable. We will inform you as soon as the item "
+ "available again."); + "becomes available again.");
finalSiteMsgShown = true; finalSiteMsgShown = true;
LOG.info("Order " + order.id + ": Item " + order.item + " unavailable, trying to add problem to employee " LOG.info("Order " + order.id + ": Item " + order.item + " unavailable, trying to add "
+ "handle.."); + "problem to employee handle..");
employeeHandleIssue(o); employeeHandleIssue(o);
} else { } else {
LOG.info("Sorry, there was a problem in creating your order. Please try later."); LOG.info("Sorry, there was a problem in creating your order. Please try later.");
LOG.error("Order " + order.id + ": Shipping service unavailable, order not placed.."); LOG.error("Order " + order.id + ": Shipping service unavailable, order not placed..");
finalSiteMsgShown = true; finalSiteMsgShown = true;
} }
return; return;
}; };
Retry<Order> r = new Retry<Order>(op, handleError, numOfRetries, retryDuration, Retry<Order> r = new Retry<Order>(op, handleError, numOfRetries, retryDuration,
e -> DatabaseUnavailableException.class.isAssignableFrom(e.getClass())); e -> DatabaseUnavailableException.class.isAssignableFrom(e.getClass()));
@ -174,28 +176,31 @@ public class Commander {
Retry.Operation op = (l) -> { Retry.Operation op = (l) -> {
if (!l.isEmpty()) { if (!l.isEmpty()) {
if (DatabaseUnavailableException.class.isAssignableFrom(l.get(0).getClass())) { if (DatabaseUnavailableException.class.isAssignableFrom(l.get(0).getClass())) {
LOG.debug("Order " + order.id + ": Error in connecting to payment service, trying again.."); LOG.debug("Order " + order.id + ": Error in connecting to payment service,"
+ " trying again..");
} else { } else {
LOG.debug("Order " + order.id + ": Error in creating payment request.."); LOG.debug("Order " + order.id + ": Error in creating payment request..");
} }
throw l.remove(0); throw l.remove(0);
} }
if (order.paid.equals(PaymentStatus.Trying)) { if (order.paid.equals(PaymentStatus.Trying)) {
String transactionId = paymentService.receiveRequest(order.price); String transactionId = paymentService.receiveRequest(order.price);
order.paid = PaymentStatus.Done; order.paid = PaymentStatus.Done;
LOG.info("Order " + order.id + ": Payment successful, transaction Id: " + transactionId); LOG.info("Order " + order.id + ": Payment successful, transaction Id: "
if (!finalSiteMsgShown) { + transactionId);
LOG.info("Payment made successfully, thank you for shopping with us!!"); if (!finalSiteMsgShown) {
finalSiteMsgShown = true; LOG.info("Payment made successfully, thank you for shopping with us!!");
} finalSiteMsgShown = true;
sendSuccessMessage(order); }
return; sendSuccessMessage(order);
} return;
}
}; };
Retry.HandleErrorIssue<Order> handleError = (o,err) -> { Retry.HandleErrorIssue<Order> handleError = (o, err) -> {
if (PaymentDetailsErrorException.class.isAssignableFrom(err.getClass())) { if (PaymentDetailsErrorException.class.isAssignableFrom(err.getClass())) {
if (!finalSiteMsgShown) { if (!finalSiteMsgShown) {
LOG.info("There was an error in payment. Your account/card details may have been incorrect. " LOG.info("There was an error in payment. Your account/card details "
+ "may have been incorrect. "
+ "Meanwhile, your order has been converted to COD and will be shipped."); + "Meanwhile, your order has been converted to COD and will be shipped.");
finalSiteMsgShown = true; finalSiteMsgShown = true;
} }
@ -213,15 +218,16 @@ public class Commander {
LOG.warn("Order " + order.id + ": Payment error, going to queue.."); LOG.warn("Order " + order.id + ": Payment error, going to queue..");
sendPaymentPossibleErrorMsg(o); sendPaymentPossibleErrorMsg(o);
} }
if (o.paid.equals(PaymentStatus.Trying) && System.currentTimeMillis() - o.createdTime < paymentTime) { if (o.paid.equals(PaymentStatus.Trying) && System
QueueTask qt = new QueueTask(o, TaskType.Payment,-1); .currentTimeMillis() - o.createdTime < paymentTime) {
QueueTask qt = new QueueTask(o, TaskType.Payment, -1);
updateQueue(qt); updateQueue(qt);
} }
} catch (InterruptedException e1) { } catch (InterruptedException e1) {
e1.printStackTrace(); e1.printStackTrace();
} }
} }
return; return;
}; };
Retry<Order> r = new Retry<Order>(op, handleError, numOfRetries, retryDuration, Retry<Order> r = new Retry<Order>(op, handleError, numOfRetries, retryDuration,
e -> DatabaseUnavailableException.class.isAssignableFrom(e.getClass())); e -> DatabaseUnavailableException.class.isAssignableFrom(e.getClass()));
@ -229,7 +235,7 @@ public class Commander {
r.perform(list, order); r.perform(list, order);
} catch (Exception e1) { } catch (Exception e1) {
e1.printStackTrace(); e1.printStackTrace();
} }
} }
}); });
t.start(); t.start();
@ -237,17 +243,18 @@ public class Commander {
private void updateQueue(QueueTask qt) throws InterruptedException { private void updateQueue(QueueTask qt) throws InterruptedException {
if (System.currentTimeMillis() - qt.order.createdTime >= this.queueTime) { if (System.currentTimeMillis() - qt.order.createdTime >= this.queueTime) {
//since payment time is lesser than queuetime it would have already failed..additional check not needed // since payment time is lesser than queuetime it would have already failed..
// additional check not needed
LOG.trace("Order " + qt.order.id + ": Queue time for order over, failed.."); LOG.trace("Order " + qt.order.id + ": Queue time for order over, failed..");
return; return;
} else if (qt.taskType.equals(TaskType.Payment) && !qt.order.paid.equals(PaymentStatus.Trying) } else if (qt.taskType.equals(TaskType.Payment) && !qt.order.paid.equals(PaymentStatus.Trying)
|| qt.taskType.equals(TaskType.Messaging) && (qt.messageType == 1 || qt.taskType.equals(TaskType.Messaging) && (qt.messageType == 1
&& !qt.order.messageSent.equals(MessageSent.NoneSent) && !qt.order.messageSent.equals(MessageSent.NoneSent)
|| qt.order.messageSent.equals(MessageSent.PaymentFail) || qt.order.messageSent.equals(MessageSent.PaymentFail)
|| qt.order.messageSent.equals(MessageSent.PaymentSuccessful)) || qt.order.messageSent.equals(MessageSent.PaymentSuccessful))
|| qt.taskType.equals(TaskType.EmployeeDb) && qt.order.addedToEmployeeHandle) { || qt.taskType.equals(TaskType.EmployeeDb) && qt.order.addedToEmployeeHandle) {
LOG.trace("Order " + qt.order.id + ": Not queueing task since task already done.."); LOG.trace("Order " + qt.order.id + ": Not queueing task since task already done..");
return; return;
} }
ArrayList<Exception> list = queue.exceptionsList; ArrayList<Exception> list = queue.exceptionsList;
Thread t = new Thread(new Runnable() { Thread t = new Thread(new Runnable() {
@ -256,24 +263,25 @@ public class Commander {
Retry.Operation op = (list) -> { Retry.Operation op = (list) -> {
if (!list.isEmpty()) { if (!list.isEmpty()) {
LOG.warn("Order " + qt.order.id + ": Error in connecting to queue db, trying again.."); LOG.warn("Order " + qt.order.id + ": Error in connecting to queue db, trying again..");
throw list.remove(0); throw list.remove(0);
} }
queue.add(qt); queue.add(qt);
queueItems++; queueItems++;
LOG.info("Order " + qt.order.id + ": " + qt.getType() + " task enqueued.."); LOG.info("Order " + qt.order.id + ": " + qt.getType() + " task enqueued..");
tryDoingTasksInQueue(); tryDoingTasksInQueue();
return; return;
}; };
Retry.HandleErrorIssue<QueueTask> handleError = (qt,err) -> { Retry.HandleErrorIssue<QueueTask> handleError = (qt, err) -> {
if (qt.taskType.equals(TaskType.Payment)) { if (qt.taskType.equals(TaskType.Payment)) {
qt.order.paid = PaymentStatus.NotDone; qt.order.paid = PaymentStatus.NotDone;
sendPaymentFailureMessage(qt.order); sendPaymentFailureMessage(qt.order);
LOG.error("Order " + qt.order.id + ": Unable to enqueue payment task, payment failed.."); LOG.error("Order " + qt.order.id + ": Unable to enqueue payment task,"
+ " payment failed..");
} }
LOG.error("Order " + qt.order.id + ": Unable to enqueue task of type " + qt.getType() LOG.error("Order " + qt.order.id + ": Unable to enqueue task of type " + qt.getType()
+ ", trying to add to employee handle.."); + ", trying to add to employee handle..");
employeeHandleIssue(qt.order); employeeHandleIssue(qt.order);
return; return;
}; };
Retry<QueueTask> r = new Retry<QueueTask>(op, handleError, numOfRetries, retryDuration, Retry<QueueTask> r = new Retry<QueueTask>(op, handleError, numOfRetries, retryDuration,
e -> DatabaseUnavailableException.class.isAssignableFrom(e.getClass())); e -> DatabaseUnavailableException.class.isAssignableFrom(e.getClass()));
@ -281,8 +289,8 @@ public class Commander {
r.perform(list, qt); r.perform(list, qt);
} catch (Exception e1) { } catch (Exception e1) {
e1.printStackTrace(); e1.printStackTrace();
} }
} }
}); });
t.start(); t.start();
} }
@ -295,13 +303,13 @@ public class Commander {
Retry.Operation op = (list) -> { Retry.Operation op = (list) -> {
if (!list.isEmpty()) { if (!list.isEmpty()) {
LOG.warn("Error in accessing queue db to do tasks, trying again.."); LOG.warn("Error in accessing queue db to do tasks, trying again..");
throw list.remove(0); throw list.remove(0);
} }
doTasksInQueue(); doTasksInQueue();
return; return;
}; };
Retry.HandleErrorIssue<QueueTask> handleError = (o,err) -> { Retry.HandleErrorIssue<QueueTask> handleError = (o, err) -> {
return; return;
}; };
Retry<QueueTask> r = new Retry<QueueTask>(op, handleError, numOfRetries, retryDuration, Retry<QueueTask> r = new Retry<QueueTask>(op, handleError, numOfRetries, retryDuration,
e -> DatabaseUnavailableException.class.isAssignableFrom(e.getClass())); e -> DatabaseUnavailableException.class.isAssignableFrom(e.getClass()));
@ -309,8 +317,8 @@ public class Commander {
r.perform(list, null); r.perform(list, null);
} catch (Exception e1) { } catch (Exception e1) {
e1.printStackTrace(); e1.printStackTrace();
} }
} }
}); });
t2.start(); t2.start();
} }
@ -323,14 +331,14 @@ public class Commander {
Retry.Operation op = (list) -> { Retry.Operation op = (list) -> {
if (!list.isEmpty()) { if (!list.isEmpty()) {
LOG.warn("Error in accessing queue db to dequeue task, trying again.."); LOG.warn("Error in accessing queue db to dequeue task, trying again..");
throw list.remove(0); throw list.remove(0);
} }
queue.dequeue(); queue.dequeue();
queueItems--; queueItems--;
return; return;
}; };
Retry.HandleErrorIssue<QueueTask> handleError = (o,err) -> { Retry.HandleErrorIssue<QueueTask> handleError = (o, err) -> {
return; return;
}; };
Retry<QueueTask> r = new Retry<QueueTask>(op, handleError, numOfRetries, retryDuration, Retry<QueueTask> r = new Retry<QueueTask>(op, handleError, numOfRetries, retryDuration,
e -> DatabaseUnavailableException.class.isAssignableFrom(e.getClass())); e -> DatabaseUnavailableException.class.isAssignableFrom(e.getClass()));
@ -338,12 +346,12 @@ public class Commander {
r.perform(list, null); r.perform(list, null);
} catch (Exception e1) { } catch (Exception e1) {
e1.printStackTrace(); e1.printStackTrace();
} }
} }
}); });
t3.start(); t3.start();
} }
private void sendSuccessMessage(Order order) { private void sendSuccessMessage(Order order) {
if (System.currentTimeMillis() - order.createdTime >= this.messageTime) { if (System.currentTimeMillis() - order.createdTime >= this.messageTime) {
LOG.trace("Order " + order.id + ": Message time for order over, returning.."); LOG.trace("Order " + order.id + ": Message time for order over, returning..");
@ -359,32 +367,35 @@ public class Commander {
LOG.debug("Order " + order.id + ": Error in connecting to messaging service " LOG.debug("Order " + order.id + ": Error in connecting to messaging service "
+ "(Payment Success msg), trying again.."); + "(Payment Success msg), trying again..");
} else { } else {
LOG.debug("Order " + order.id + ": Error in creating Payment Success messaging request.."); LOG.debug("Order " + order.id + ": Error in creating Payment Success"
+ " messaging request..");
} }
throw l.remove(0); throw l.remove(0);
} }
if (!order.messageSent.equals(MessageSent.PaymentFail) if (!order.messageSent.equals(MessageSent.PaymentFail)
&& !order.messageSent.equals(MessageSent.PaymentSuccessful)) { && !order.messageSent.equals(MessageSent.PaymentSuccessful)) {
String requestId = messagingService.receiveRequest(2); String requestId = messagingService.receiveRequest(2);
order.messageSent = MessageSent.PaymentSuccessful; order.messageSent = MessageSent.PaymentSuccessful;
LOG.info("Order " + order.id + ": Payment Success message sent, request Id: " + requestId); LOG.info("Order " + order.id + ": Payment Success message sent,"
} + " request Id: " + requestId);
return; }
return;
}; };
Retry.HandleErrorIssue<Order> handleError = (o,err) -> { Retry.HandleErrorIssue<Order> handleError = (o, err) -> {
try { try {
if ((o.messageSent.equals(MessageSent.NoneSent) || o.messageSent.equals(MessageSent.PaymentTrying)) if ((o.messageSent.equals(MessageSent.NoneSent) || o.messageSent
.equals(MessageSent.PaymentTrying))
&& System.currentTimeMillis() - o.createdTime < messageTime) { && System.currentTimeMillis() - o.createdTime < messageTime) {
QueueTask qt = new QueueTask(order, TaskType.Messaging,2); QueueTask qt = new QueueTask(order, TaskType.Messaging, 2);
updateQueue(qt); updateQueue(qt);
LOG.info("Order " + order.id + ": Error in sending Payment Success message, trying to " LOG.info("Order " + order.id + ": Error in sending Payment Success message, trying to"
+ "queue task and add to employee handle.."); + " queue task and add to employee handle..");
employeeHandleIssue(order); employeeHandleIssue(order);
} }
} catch (InterruptedException e1) { } catch (InterruptedException e1) {
e1.printStackTrace(); e1.printStackTrace();
} }
return; return;
}; };
Retry<Order> r = new Retry<Order>(op, handleError, numOfRetries, retryDuration, Retry<Order> r = new Retry<Order>(op, handleError, numOfRetries, retryDuration,
e -> DatabaseUnavailableException.class.isAssignableFrom(e.getClass())); e -> DatabaseUnavailableException.class.isAssignableFrom(e.getClass()));
@ -392,8 +403,8 @@ public class Commander {
r.perform(list, order); r.perform(list, order);
} catch (Exception e1) { } catch (Exception e1) {
e1.printStackTrace(); e1.printStackTrace();
} }
} }
}); });
t.start(); t.start();
} }
@ -413,32 +424,35 @@ public class Commander {
LOG.debug("Order " + order.id + ": Error in connecting to messaging service " LOG.debug("Order " + order.id + ": Error in connecting to messaging service "
+ "(Payment Failure msg), trying again.."); + "(Payment Failure msg), trying again..");
} else { } else {
LOG.debug("Order " + order.id + ": Error in creating Payment Failure message request.."); LOG.debug("Order " + order.id + ": Error in creating Payment Failure"
+ " message request..");
} }
throw l.remove(0); throw l.remove(0);
} }
if (!order.messageSent.equals(MessageSent.PaymentFail) if (!order.messageSent.equals(MessageSent.PaymentFail)
&& !order.messageSent.equals(MessageSent.PaymentSuccessful)) { && !order.messageSent.equals(MessageSent.PaymentSuccessful)) {
String requestId = messagingService.receiveRequest(0); String requestId = messagingService.receiveRequest(0);
order.messageSent = MessageSent.PaymentFail; order.messageSent = MessageSent.PaymentFail;
LOG.info("Order " + order.id + ": Payment Failure message sent successfully, request Id: " + requestId); LOG.info("Order " + order.id + ": Payment Failure message sent successfully,"
} + " request Id: " + requestId);
return; }
return;
}; };
Retry.HandleErrorIssue<Order> handleError = (o,err) -> { Retry.HandleErrorIssue<Order> handleError = (o, err) -> {
if ((o.messageSent.equals(MessageSent.NoneSent) || o.messageSent.equals(MessageSent.PaymentTrying)) if ((o.messageSent.equals(MessageSent.NoneSent) || o.messageSent
.equals(MessageSent.PaymentTrying))
&& System.currentTimeMillis() - o.createdTime < messageTime) { && System.currentTimeMillis() - o.createdTime < messageTime) {
try { try {
QueueTask qt = new QueueTask(order, TaskType.Messaging,0); QueueTask qt = new QueueTask(order, TaskType.Messaging, 0);
updateQueue(qt); updateQueue(qt);
LOG.warn("Order " + order.id + ": Error in sending Payment Failure message, " LOG.warn("Order " + order.id + ": Error in sending Payment Failure message, "
+ "trying to queue task and add to employee handle.."); + "trying to queue task and add to employee handle..");
employeeHandleIssue(o); employeeHandleIssue(o);
} catch (InterruptedException e1) { } catch (InterruptedException e1) {
e1.printStackTrace(); e1.printStackTrace();
} }
return; return;
} }
}; };
Retry<Order> r = new Retry<Order>(op, handleError, numOfRetries, retryDuration, Retry<Order> r = new Retry<Order>(op, handleError, numOfRetries, retryDuration,
e -> DatabaseUnavailableException.class.isAssignableFrom(e.getClass())); e -> DatabaseUnavailableException.class.isAssignableFrom(e.getClass()));
@ -446,8 +460,8 @@ public class Commander {
r.perform(list, order); r.perform(list, order);
} catch (Exception e1) { } catch (Exception e1) {
e1.printStackTrace(); e1.printStackTrace();
} }
} }
}); });
t.start(); t.start();
} }
@ -467,31 +481,35 @@ public class Commander {
LOG.debug("Order " + order.id + ": Error in connecting to messaging service " LOG.debug("Order " + order.id + ": Error in connecting to messaging service "
+ "(Payment Error msg), trying again.."); + "(Payment Error msg), trying again..");
} else { } else {
LOG.debug("Order " + order.id + ": Error in creating Payment Error messaging request.."); LOG.debug("Order " + order.id + ": Error in creating Payment Error"
+ " messaging request..");
} }
throw l.remove(0); throw l.remove(0);
} }
if (order.paid.equals(PaymentStatus.Trying) && order.messageSent.equals(MessageSent.NoneSent)) { if (order.paid.equals(PaymentStatus.Trying) && order.messageSent
String requestId = messagingService.receiveRequest(1); .equals(MessageSent.NoneSent)) {
order.messageSent = MessageSent.PaymentTrying; String requestId = messagingService.receiveRequest(1);
LOG.info("Order " + order.id + ": Payment Error message sent successfully, request Id: " + requestId); order.messageSent = MessageSent.PaymentTrying;
} LOG.info("Order " + order.id + ": Payment Error message sent successfully,"
return; + " request Id: " + requestId);
}
return;
}; };
Retry.HandleErrorIssue<Order> handleError = (o,err) -> { Retry.HandleErrorIssue<Order> handleError = (o, err) -> {
try { try {
if (o.messageSent.equals(MessageSent.NoneSent) && order.paid.equals(PaymentStatus.Trying) if (o.messageSent.equals(MessageSent.NoneSent) && order.paid
.equals(PaymentStatus.Trying)
&& System.currentTimeMillis() - o.createdTime < messageTime) { && System.currentTimeMillis() - o.createdTime < messageTime) {
QueueTask qt = new QueueTask(order,TaskType.Messaging,1); QueueTask qt = new QueueTask(order, TaskType.Messaging, 1);
updateQueue(qt); updateQueue(qt);
LOG.warn("Order " + order.id + ": Error in sending Payment Error message, " LOG.warn("Order " + order.id + ": Error in sending Payment Error message, "
+ "trying to queue task and add to employee handle.."); + "trying to queue task and add to employee handle..");
employeeHandleIssue(o); employeeHandleIssue(o);
} }
} catch (InterruptedException e1) { } catch (InterruptedException e1) {
e1.printStackTrace(); e1.printStackTrace();
} }
return; return;
}; };
Retry<Order> r = new Retry<Order>(op, handleError, numOfRetries, retryDuration, Retry<Order> r = new Retry<Order>(op, handleError, numOfRetries, retryDuration,
e -> DatabaseUnavailableException.class.isAssignableFrom(e.getClass())); e -> DatabaseUnavailableException.class.isAssignableFrom(e.getClass()));
@ -516,28 +534,31 @@ public class Commander {
public void run() { public void run() {
Retry.Operation op = (l) -> { Retry.Operation op = (l) -> {
if (!l.isEmpty()) { if (!l.isEmpty()) {
LOG.warn("Order " + order.id + ": Error in connecting to employee handle, trying again.."); LOG.warn("Order " + order.id + ": Error in connecting to employee handle,"
throw l.remove(0); + " trying again..");
} throw l.remove(0);
}
if (!order.addedToEmployeeHandle) { if (!order.addedToEmployeeHandle) {
employeeDb.receiveRequest(order); employeeDb.receiveRequest(order);
order.addedToEmployeeHandle = true; order.addedToEmployeeHandle = true;
LOG.info("Order " + order.id + ": Added order to employee database"); LOG.info("Order " + order.id + ": Added order to employee database");
} }
return; return;
}; };
Retry.HandleErrorIssue<Order> handleError = (o,err) -> { Retry.HandleErrorIssue<Order> handleError = (o, err) -> {
try { try {
if (!o.addedToEmployeeHandle && System.currentTimeMillis() - order.createdTime < employeeTime) { if (!o.addedToEmployeeHandle && System
QueueTask qt = new QueueTask(order, TaskType.EmployeeDb,-1); .currentTimeMillis() - order.createdTime < employeeTime) {
QueueTask qt = new QueueTask(order, TaskType.EmployeeDb, -1);
updateQueue(qt); updateQueue(qt);
LOG.warn("Order " + order.id + ": Error in adding to employee db, trying to queue task.."); LOG.warn("Order " + order.id + ": Error in adding to employee db,"
+ " trying to queue task..");
return; return;
} }
} catch (InterruptedException e1) { } catch (InterruptedException e1) {
e1.printStackTrace(); e1.printStackTrace();
} }
return; return;
}; };
Retry<Order> r = new Retry<Order>(op, handleError, numOfRetries, retryDuration, Retry<Order> r = new Retry<Order>(op, handleError, numOfRetries, retryDuration,
e -> DatabaseUnavailableException.class.isAssignableFrom(e.getClass())); e -> DatabaseUnavailableException.class.isAssignableFrom(e.getClass()));
@ -558,7 +579,7 @@ public class Commander {
LOG.trace("Order " + qt.order.id + ": Started doing task of type " + qt.getType()); LOG.trace("Order " + qt.order.id + ": Started doing task of type " + qt.getType());
if (qt.firstAttemptTime == -1) { if (qt.firstAttemptTime == -1) {
qt.firstAttemptTime = System.currentTimeMillis(); qt.firstAttemptTime = System.currentTimeMillis();
} }
if (System.currentTimeMillis() - qt.firstAttemptTime >= queueTaskTime) { if (System.currentTimeMillis() - qt.firstAttemptTime >= queueTaskTime) {
tryDequeue(); tryDequeue();
LOG.trace("Order " + qt.order.id + ": This queue task of type " + qt.getType() LOG.trace("Order " + qt.order.id + ": This queue task of type " + qt.getType()
@ -573,14 +594,15 @@ public class Commander {
LOG.debug("Order " + qt.order.id + ": Trying to connect to payment service.."); LOG.debug("Order " + qt.order.id + ": Trying to connect to payment service..");
} }
} else if (qt.taskType.equals(TaskType.Messaging)) { } else if (qt.taskType.equals(TaskType.Messaging)) {
if (qt.order.messageSent.equals(MessageSent.PaymentFail) if (qt.order.messageSent.equals(MessageSent.PaymentFail)
|| qt.order.messageSent.equals(MessageSent.PaymentSuccessful)) { || qt.order.messageSent.equals(MessageSent.PaymentSuccessful)) {
tryDequeue(); tryDequeue();
LOG.trace("Order " + qt.order.id + ": This messaging task already done, dequeue.."); LOG.trace("Order " + qt.order.id + ": This messaging task already done, dequeue..");
} else if (qt.messageType == 1 && (!qt.order.messageSent.equals(MessageSent.NoneSent) } else if (qt.messageType == 1 && (!qt.order.messageSent.equals(MessageSent.NoneSent)
|| !qt.order.paid.equals(PaymentStatus.Trying))) { || !qt.order.paid.equals(PaymentStatus.Trying))) {
tryDequeue(); tryDequeue();
LOG.trace("Order " + qt.order.id + ": This messaging task does not need to be done, dequeue.."); LOG.trace("Order " + qt.order.id + ": This messaging task does not need to be done,"
+ " dequeue..");
} else if (qt.messageType == 0) { } else if (qt.messageType == 0) {
sendPaymentFailureMessage(qt.order); sendPaymentFailureMessage(qt.order);
LOG.debug("Order " + qt.order.id + ": Trying to connect to messaging service.."); LOG.debug("Order " + qt.order.id + ": Trying to connect to messaging service..");
@ -594,7 +616,8 @@ public class Commander {
} else if (qt.taskType.equals(TaskType.EmployeeDb)) { } else if (qt.taskType.equals(TaskType.EmployeeDb)) {
if (qt.order.addedToEmployeeHandle) { if (qt.order.addedToEmployeeHandle) {
tryDequeue(); tryDequeue();
LOG.trace("Order " + qt.order.id + ": This employee handle task already done, dequeue.."); LOG.trace("Order " + qt.order.id + ": This employee handle task already done,"
+ " dequeue..");
} else { } else {
employeeHandleIssue(qt.order); employeeHandleIssue(qt.order);
LOG.debug("Order " + qt.order.id + ": Trying to connect to employee handle.."); LOG.debug("Order " + qt.order.id + ": Trying to connect to employee handle..");

View File

@ -26,12 +26,14 @@ package com.iluwatar.commander;
import com.iluwatar.commander.exceptions.DatabaseUnavailableException; import com.iluwatar.commander.exceptions.DatabaseUnavailableException;
/** /**
* Database abstract class is extended by all databases in our example. The add and get * Database abstract class is extended by all databases in our example. The add and get methods are
* methods are used by the respective service to add to database or get from database. * 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. * @param <T> T is the type of object being held by database.
*/ */
public abstract class Database<T> { public abstract class Database<T> {
public abstract T add(T obj) throws DatabaseUnavailableException; public abstract T add(T obj) throws DatabaseUnavailableException;
public abstract T get(String tId) throws DatabaseUnavailableException;
public abstract T get(String id) throws DatabaseUnavailableException;
} }

View File

@ -34,11 +34,15 @@ public class Order { //can store all transactions ids also
enum PaymentStatus { enum PaymentStatus {
NotDone, Trying, Done NotDone, Trying, Done
}; }
;
enum MessageSent { enum MessageSent {
NoneSent, PaymentFail, PaymentTrying, PaymentSuccessful NoneSent, PaymentFail, PaymentTrying, PaymentSuccessful
}; }
;
final User user; final User user;
final String item; final String item;
@ -78,5 +82,5 @@ public class Order { //can store all transactions ids also
} }
return random.toString(); return random.toString();
} }
} }

View File

@ -30,29 +30,31 @@ import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Predicate; import java.util.function.Predicate;
/** /**
* Retry pattern * Retry pattern.
*
* @param <T> is the type of object passed into HandleErrorIssue as a parameter. * @param <T> is the type of object passed into HandleErrorIssue as a parameter.
*/ */
public class Retry<T> { public class Retry<T> {
/** /**
* Operation Interface will define method to be implemented. * Operation Interface will define method to be implemented.
*/ */
public interface Operation { public interface Operation {
void operation(ArrayList<Exception> list) throws Exception; void operation(ArrayList<Exception> list) throws Exception;
} }
/** /**
* HandleErrorIssue defines how to handle errors. * HandleErrorIssue defines how to handle errors.
* @param <T> is the type of object to be passed into the method as parameter. *
*/ * @param <T> is the type of object to be passed into the method as parameter.
*/
public interface HandleErrorIssue<T> { public interface HandleErrorIssue<T> {
void handleIssue(T obj, Exception e); void handleIssue(T obj, Exception e);
} }
private static final Random RANDOM = new Random(); private static final Random RANDOM = new Random();
private final Operation op; private final Operation op;
@ -64,7 +66,7 @@ public class Retry<T> {
private final ArrayList<Exception> errors; private final ArrayList<Exception> errors;
Retry(Operation op, HandleErrorIssue handleError, int maxAttempts, Retry(Operation op, HandleErrorIssue handleError, int maxAttempts,
long maxDelay, Predicate<Exception>... ignoreTests) { long maxDelay, Predicate<Exception>... ignoreTests) {
this.op = op; this.op = op;
this.handleError = handleError; this.handleError = handleError;
this.maxAttempts = maxAttempts; this.maxAttempts = maxAttempts;
@ -76,10 +78,11 @@ public class Retry<T> {
/** /**
* Performing the operation with retries. * Performing the operation with retries.
*
* @param list is the exception list * @param list is the exception list
* @param obj is the parameter to be passed into handleIsuue method * @param obj is the parameter to be passed into handleIsuue method
*/ */
public void perform(ArrayList<Exception> list, T obj) throws Exception { public void perform(ArrayList<Exception> list, T obj) throws Exception {
do { do {
try { try {
@ -92,15 +95,15 @@ public class Retry<T> {
return; //return here...dont go further return; //return here...dont go further
} }
try { try {
long testDelay = (long) Math.pow(2, this.attempts.intValue()) * 1000 + RANDOM.nextInt(1000); long testDelay =
(long) Math.pow(2, this.attempts.intValue()) * 1000 + RANDOM.nextInt(1000);
long delay = testDelay < this.maxDelay ? testDelay : maxDelay; long delay = testDelay < this.maxDelay ? testDelay : maxDelay;
Thread.sleep(delay); Thread.sleep(delay);
} catch (InterruptedException f) { } catch (InterruptedException f) {
//ignore //ignore
} }
} }
} } while (true);
while (true);
} }
} }

View File

@ -23,35 +23,37 @@
package com.iluwatar.commander; package com.iluwatar.commander;
import java.util.*;
import com.iluwatar.commander.exceptions.DatabaseUnavailableException; import com.iluwatar.commander.exceptions.DatabaseUnavailableException;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.Random;
/** /**
* Service class is an abstract class extended by all services in this example. They * Service class is an abstract class extended by all services in this example. They all have a
* all have a public receiveRequest method to receive requests, which could also contain * public receiveRequest method to receive requests, which could also contain details of the user
* details of the user other than the implementation details (though we are not doing * other than the implementation details (though we are not doing that here) and updateDb method
* that here) and updateDb method which adds to their respective databases. There is a * which adds to their respective databases. There is a method to generate transaction/request id
* method to generate transaction/request id for the transactions/requests, which are * for the transactions/requests, which are then sent back. These could be stored by the {@link
* then sent back. These could be stored by the {@link Commander} class in a separate * Commander} class in a separate database for reference (though we are not doing that here).
* database for reference (though we are not doing that here).
*/ */
public abstract class Service { public abstract class Service {
protected final Database database; protected final Database database;
public ArrayList<Exception> exceptionsList; public ArrayList<Exception> exceptionsList;
private static final Random RANDOM = new Random(); private static final Random RANDOM = new Random();
private static final String ALL_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"; private static final String ALL_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
private static final Hashtable<String, Boolean> USED_IDS = new Hashtable<>(); private static final Hashtable<String, Boolean> USED_IDS = new Hashtable<>();
protected Service(Database db, Exception...exc) { protected Service(Database db, Exception... exc) {
this.database = db; this.database = db;
this.exceptionsList = new ArrayList<>(List.of(exc)); this.exceptionsList = new ArrayList<>(List.of(exc));
} }
public abstract String receiveRequest(Object...parameters) throws DatabaseUnavailableException; public abstract String receiveRequest(Object... parameters) throws DatabaseUnavailableException;
protected abstract String updateDb(Object...parameters) throws DatabaseUnavailableException;
protected abstract String updateDb(Object... parameters) throws DatabaseUnavailableException;
protected String generateId() { protected String generateId() {
StringBuilder random = new StringBuilder(); StringBuilder random = new StringBuilder();

View File

@ -23,10 +23,10 @@
package com.iluwatar.commander.employeehandle; package com.iluwatar.commander.employeehandle;
import java.util.Hashtable;
import com.iluwatar.commander.Database; import com.iluwatar.commander.Database;
import com.iluwatar.commander.Order; import com.iluwatar.commander.Order;
import com.iluwatar.commander.exceptions.DatabaseUnavailableException; import com.iluwatar.commander.exceptions.DatabaseUnavailableException;
import java.util.Hashtable;
/** /**
* The Employee Database is where orders which have encountered some issue(s) are added. * The Employee Database is where orders which have encountered some issue(s) are added.
@ -41,11 +41,11 @@ public class EmployeeDatabase extends Database<Order> {
@Override @Override
public Order add(Order o) throws DatabaseUnavailableException { public Order add(Order o) throws DatabaseUnavailableException {
return data.put(o.id,o); return data.put(o.id, o);
} }
@Override @Override
public Order get(String oId) throws DatabaseUnavailableException { public Order get(String orderId) throws DatabaseUnavailableException {
return data.get(oId); return data.get(orderId);
} }
} }

View File

@ -28,21 +28,21 @@ import com.iluwatar.commander.Service;
import com.iluwatar.commander.exceptions.DatabaseUnavailableException; import com.iluwatar.commander.exceptions.DatabaseUnavailableException;
/** /**
* The EmployeeHandle class is the middle-man between {@link Commander} and * The EmployeeHandle class is the middle-man between {@link Commander} and {@link
* {@link EmployeeDatabase}. * EmployeeDatabase}.
*/ */
public class EmployeeHandle extends Service { public class EmployeeHandle extends Service {
public EmployeeHandle(EmployeeDatabase db, Exception...exc) { public EmployeeHandle(EmployeeDatabase db, Exception... exc) {
super(db, exc); super(db, exc);
} }
public String receiveRequest(Object...parameters) throws DatabaseUnavailableException { public String receiveRequest(Object... parameters) throws DatabaseUnavailableException {
return updateDb((Order)parameters[0]); return updateDb((Order) parameters[0]);
} }
protected String updateDb(Object...parameters) throws DatabaseUnavailableException { protected String updateDb(Object... parameters) throws DatabaseUnavailableException {
Order o = (Order) parameters[0]; Order o = (Order) parameters[0];
if (database.get(o.id) == null) { if (database.get(o.id) == null) {
database.add(o); database.add(o);

View File

@ -24,8 +24,8 @@
package com.iluwatar.commander.exceptions; package com.iluwatar.commander.exceptions;
/** /**
* DatabaseUnavailableException is thrown when database is unavailable and nothing * DatabaseUnavailableException is thrown when database is unavailable and nothing can be added or
* can be added or retrieved. * retrieved.
*/ */
public class DatabaseUnavailableException extends Exception { public class DatabaseUnavailableException extends Exception {

View File

@ -24,8 +24,8 @@
package com.iluwatar.commander.exceptions; package com.iluwatar.commander.exceptions;
/** /**
* PaymentDetailsErrorException is thrown when the details entered are incorrect or * PaymentDetailsErrorException is thrown when the details entered are incorrect or payment cannot
* payment cannot be made with the details given. * be made with the details given.
*/ */
public class PaymentDetailsErrorException extends Exception { public class PaymentDetailsErrorException extends Exception {

View File

@ -24,8 +24,8 @@
package com.iluwatar.commander.exceptions; package com.iluwatar.commander.exceptions;
/** /**
* ShippingNotPossibleException is thrown when the address entered cannot be shipped to * ShippingNotPossibleException is thrown when the address entered cannot be shipped to by service
* by service currently for some reason. * currently for some reason.
*/ */
public class ShippingNotPossibleException extends Exception { public class ShippingNotPossibleException extends Exception {

View File

@ -23,10 +23,10 @@
package com.iluwatar.commander.messagingservice; package com.iluwatar.commander.messagingservice;
import java.util.Hashtable;
import com.iluwatar.commander.Database; import com.iluwatar.commander.Database;
import com.iluwatar.commander.exceptions.DatabaseUnavailableException; import com.iluwatar.commander.exceptions.DatabaseUnavailableException;
import com.iluwatar.commander.messagingservice.MessagingService.MessageRequest; import com.iluwatar.commander.messagingservice.MessagingService.MessageRequest;
import java.util.Hashtable;
/** /**
* The MessagingDatabase is where the MessageRequest is added. * The MessagingDatabase is where the MessageRequest is added.
@ -45,8 +45,8 @@ public class MessagingDatabase extends Database<MessageRequest> {
} }
@Override @Override
public MessageRequest get(String rId) throws DatabaseUnavailableException { public MessageRequest get(String requestId) throws DatabaseUnavailableException {
return data.get(rId); return data.get(requestId);
} }
} }

View File

@ -29,9 +29,9 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
/** /**
* The MessagingService is used to send messages to user regarding their order and * The MessagingService is used to send messages to user regarding their order and payment status.
* payment status. In case an error is encountered in payment and this service is * In case an error is encountered in payment and this service is found to be unavailable, the order
* found to be unavailable, the order is added to the {@link EmployeeDatabase}. * is added to the {@link EmployeeDatabase}.
*/ */
public class MessagingService extends Service { public class MessagingService extends Service {
@ -39,7 +39,9 @@ public class MessagingService extends Service {
enum MessageToSend { enum MessageToSend {
PaymentFail, PaymentTrying, PaymentSuccessful PaymentFail, PaymentTrying, PaymentSuccessful
}; }
;
class MessageRequest { class MessageRequest {
String reqId; String reqId;
@ -51,17 +53,16 @@ public class MessagingService extends Service {
} }
} }
public MessagingService(MessagingDatabase db, Exception...exc) { public MessagingService(MessagingDatabase db, Exception... exc) {
super(db, exc); super(db, exc);
} }
/** /**
* Public method which will receive request from {@link Commander}. * Public method which will receive request from {@link Commander}.
*/ */
public String receiveRequest(Object... parameters) throws DatabaseUnavailableException {
public String receiveRequest(Object...parameters) throws DatabaseUnavailableException {
int messageToSend = (int) parameters[0]; int messageToSend = (int) parameters[0];
String rId = generateId(); String id = generateId();
MessageToSend msg = null; MessageToSend msg = null;
if (messageToSend == 0) { if (messageToSend == 0) {
msg = MessageToSend.PaymentFail; msg = MessageToSend.PaymentFail;
@ -70,11 +71,11 @@ public class MessagingService extends Service {
} else { //messageToSend == 2 } else { //messageToSend == 2
msg = MessageToSend.PaymentSuccessful; msg = MessageToSend.PaymentSuccessful;
} }
MessageRequest req = new MessageRequest(rId, msg); MessageRequest req = new MessageRequest(id, msg);
return updateDb(req); return updateDb(req);
} }
protected String updateDb(Object...parameters) throws DatabaseUnavailableException { protected String updateDb(Object... parameters) throws DatabaseUnavailableException {
MessageRequest req = (MessageRequest) parameters[0]; MessageRequest req = (MessageRequest) parameters[0];
if (this.database.get(req.reqId) == null) { //idempotence, in case db fails here if (this.database.get(req.reqId) == null) { //idempotence, in case db fails here
database.add(req); //if successful: database.add(req); //if successful:
@ -86,13 +87,17 @@ public class MessagingService extends Service {
String sendMessage(MessageToSend m) { String sendMessage(MessageToSend m) {
if (m.equals(MessageToSend.PaymentSuccessful)) { if (m.equals(MessageToSend.PaymentSuccessful)) {
return "Msg: Your order has been placed and paid for successfully! Thank you for shopping with us!"; return "Msg: Your order has been placed and paid for successfully!"
+ " Thank you for shopping with us!";
} else if (m.equals(MessageToSend.PaymentTrying)) { } 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" return "Msg: There was an error in your payment process,"
+ " shortly. Meanwhile, your order has been placed and will be shipped."; + " we are working on it and will return back to you shortly."
+ " Meanwhile, your order has been placed and will be shipped.";
} else { } else {
return "Msg: There was an error in your payment process. Your order is placed and has been converted to COD." return "Msg: There was an error in your payment process."
+ " Please reach us on CUSTOMER-CARE-NUBER in case of any queries. Thank you for shopping with us!"; + " 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!";
} }
} }
} }

View File

@ -23,11 +23,10 @@
package com.iluwatar.commander.paymentservice; package com.iluwatar.commander.paymentservice;
import java.util.Hashtable;
import com.iluwatar.commander.Database; import com.iluwatar.commander.Database;
import com.iluwatar.commander.exceptions.DatabaseUnavailableException; import com.iluwatar.commander.exceptions.DatabaseUnavailableException;
import com.iluwatar.commander.paymentservice.PaymentService.PaymentRequest; import com.iluwatar.commander.paymentservice.PaymentService.PaymentRequest;
import java.util.Hashtable;
/** /**
* PaymentDatabase is where the PaymentRequest is added, along with details. * PaymentDatabase is where the PaymentRequest is added, along with details.
@ -48,8 +47,8 @@ public class PaymentDatabase extends Database<PaymentRequest> {
} }
@Override @Override
public PaymentRequest get(String tId) throws DatabaseUnavailableException { public PaymentRequest get(String requestId) throws DatabaseUnavailableException {
return data.get(tId); return data.get(requestId);
} }
} }

View File

@ -27,8 +27,8 @@ import com.iluwatar.commander.Service;
import com.iluwatar.commander.exceptions.DatabaseUnavailableException; import com.iluwatar.commander.exceptions.DatabaseUnavailableException;
/** /**
* The PaymentService class receives request from the {@link Commander} and adds * The PaymentService class receives request from the {@link Commander} and adds to the {@link
* to the {@link PaymentDatabase}. * PaymentDatabase}.
*/ */
public class PaymentService extends Service { public class PaymentService extends Service {
@ -45,22 +45,22 @@ public class PaymentService extends Service {
} }
} }
public PaymentService(PaymentDatabase db, Exception...exc) { public PaymentService(PaymentDatabase db, Exception... exc) {
super(db, exc); super(db, exc);
} }
/** /**
* Public method which will receive request from {@link Commander}. * Public method which will receive request from {@link Commander}.
*/ */
public String receiveRequest(Object...parameters) throws DatabaseUnavailableException { public String receiveRequest(Object... parameters) throws DatabaseUnavailableException {
//it could also be sending a userid, payment details here or something, not added here //it could also be sending a userid, payment details here or something, not added here
String tId = generateId(); String id = generateId();
PaymentRequest req = new PaymentRequest(tId, (float)parameters[0]); PaymentRequest req = new PaymentRequest(id, (float) parameters[0]);
return updateDb(req); return updateDb(req);
} }
protected String updateDb(Object...parameters) throws DatabaseUnavailableException { protected String updateDb(Object... parameters) throws DatabaseUnavailableException {
PaymentRequest req = (PaymentRequest) parameters[0]; PaymentRequest req = (PaymentRequest) parameters[0];
if (database.get(req.transactionId) == null || !req.paid) { if (database.get(req.transactionId) == null || !req.paid) {
database.add(req); database.add(req);

View File

@ -27,6 +27,7 @@ import com.iluwatar.commander.exceptions.IsEmptyException;
/** /**
* Queue data structure implementation. * Queue data structure implementation.
*
* @param <T> is the type of object the queue will hold. * @param <T> is the type of object the queue will hold.
*/ */
@ -47,15 +48,14 @@ public class Queue<T> {
} }
/** /**
* Queue constructor * Queue constructor.
*/ */
Queue() { Queue() {
front = null; front = null;
rear = null; rear = null;
size = 0; size = 0;
} }
boolean isEmpty() { boolean isEmpty() {
if (size == 0) { if (size == 0) {
return true; return true;
@ -63,7 +63,7 @@ public class Queue<T> {
return false; return false;
} }
} }
void enqueue(T obj) { void enqueue(T obj) {
if (front == null) { if (front == null) {
front = new Node(obj, null); front = new Node(obj, null);
@ -75,7 +75,7 @@ public class Queue<T> {
} }
size++; size++;
} }
T dequeue() throws IsEmptyException { T dequeue() throws IsEmptyException {
if (isEmpty()) { if (isEmpty()) {
throw new IsEmptyException(); throw new IsEmptyException();
@ -86,12 +86,12 @@ public class Queue<T> {
return (T) temp.value; return (T) temp.value;
} }
} }
T peek() throws IsEmptyException { T peek() throws IsEmptyException {
if (isEmpty()) { if (isEmpty()) {
throw new IsEmptyException(); throw new IsEmptyException();
} else { } else {
return (T)front.value; return (T) front.value;
} }
} }
} }

View File

@ -26,7 +26,6 @@ package com.iluwatar.commander.queue;
import com.iluwatar.commander.Database; import com.iluwatar.commander.Database;
import com.iluwatar.commander.exceptions.DatabaseUnavailableException; import com.iluwatar.commander.exceptions.DatabaseUnavailableException;
import com.iluwatar.commander.exceptions.IsEmptyException; import com.iluwatar.commander.exceptions.IsEmptyException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -39,7 +38,7 @@ public class QueueDatabase extends Database<QueueTask> {
private Queue<QueueTask> data; private Queue<QueueTask> data;
public ArrayList<Exception> exceptionsList; public ArrayList<Exception> exceptionsList;
public QueueDatabase(Exception...exc) { public QueueDatabase(Exception... exc) {
this.data = new Queue<>(); this.data = new Queue<>();
this.exceptionsList = new ArrayList<>(List.of(exc)); this.exceptionsList = new ArrayList<>(List.of(exc));
} }
@ -52,31 +51,33 @@ public class QueueDatabase extends Database<QueueTask> {
} }
/** /**
* peek method returns object at front without removing it from queue * peek method returns object at front without removing it from queue.
*
* @return object at front of queue * @return object at front of queue
* @throws IsEmptyException if queue is empty * @throws IsEmptyException if queue is empty
* @throws DatabaseUnavailableException if queue db is unavailable * @throws DatabaseUnavailableException if queue db is unavailable
*/ */
public QueueTask peek() throws IsEmptyException, DatabaseUnavailableException { public QueueTask peek() throws IsEmptyException, DatabaseUnavailableException {
QueueTask qt = this.data.peek(); QueueTask qt = this.data.peek();
return qt; return qt;
} }
/** /**
* dequeue method removes the object at front and returns it * dequeue method removes the object at front and returns it.
*
* @return object at front of queue * @return object at front of queue
* @throws IsEmptyException if queue is empty * @throws IsEmptyException if queue is empty
* @throws DatabaseUnavailableException if queue db is unavailable * @throws DatabaseUnavailableException if queue db is unavailable
*/ */
public QueueTask dequeue() throws IsEmptyException, DatabaseUnavailableException { public QueueTask dequeue() throws IsEmptyException, DatabaseUnavailableException {
QueueTask qt = this.data.dequeue(); QueueTask qt = this.data.dequeue();
return qt; return qt;
} }
@Override @Override
public QueueTask get(String tId) throws DatabaseUnavailableException { public QueueTask get(String taskId) throws DatabaseUnavailableException {
return null; return null;
} }

View File

@ -31,13 +31,15 @@ import com.iluwatar.commander.Order;
public class QueueTask { public class QueueTask {
/** /**
* TaskType is the type of task to be done. * TaskType is the type of task to be done.
*/ */
public enum TaskType { public enum TaskType {
Messaging, Payment, EmployeeDb Messaging, Payment, EmployeeDb
}; }
;
public Order order; public Order order;
public TaskType taskType; public TaskType taskType;
@ -46,26 +48,28 @@ public class QueueTask {
but keeping it simple here*/ but keeping it simple here*/
public long firstAttemptTime; //when first time attempt made to do task public long firstAttemptTime; //when first time attempt made to do task
/** /**
* QueueTask constructor * 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 o is the order for which the queuetask is being created
* @param messageType if it is a message, which type of message - this could have instead been object varargs, * @param t is the type of task to be done
* and contained all additional details related to tasktype. * @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) { public QueueTask(Order o, TaskType t, int messageType) {
this.order = o; this.order = o;
this.taskType = t; this.taskType = t;
this.messageType = messageType; this.messageType = messageType;
this.firstAttemptTime = -1; this.firstAttemptTime = -1;
} }
/** /**
* getType method * getType method.
*
* @return String representing type of task * @return String representing type of task
*/ */
public String getType() { public String getType() {
if (!this.taskType.equals(TaskType.Messaging)) { if (!this.taskType.equals(TaskType.Messaging)) {
return this.taskType.toString(); return this.taskType.toString();

View File

@ -23,17 +23,17 @@
package com.iluwatar.commander.shippingservice; package com.iluwatar.commander.shippingservice;
import java.util.Hashtable;
import com.iluwatar.commander.Database; import com.iluwatar.commander.Database;
import com.iluwatar.commander.exceptions.DatabaseUnavailableException; import com.iluwatar.commander.exceptions.DatabaseUnavailableException;
import com.iluwatar.commander.shippingservice.ShippingService.ShippingRequest; import com.iluwatar.commander.shippingservice.ShippingService.ShippingRequest;
import java.util.Hashtable;
/** /**
* ShippingDatabase is where the ShippingRequest objects are added. * ShippingDatabase is where the ShippingRequest objects are added.
*/ */
public class ShippingDatabase extends Database<ShippingRequest> { public class ShippingDatabase extends Database<ShippingRequest> {
private Hashtable<String, ShippingRequest> data; private Hashtable<String, ShippingRequest> data;
public ShippingDatabase() { public ShippingDatabase() {
@ -45,8 +45,8 @@ public class ShippingDatabase extends Database<ShippingRequest> {
return data.put(r.transactionId, r); return data.put(r.transactionId, r);
} }
public ShippingRequest get(String transactionId) throws DatabaseUnavailableException { public ShippingRequest get(String trasnactionId) throws DatabaseUnavailableException {
return data.get(transactionId); return data.get(trasnactionId);
} }
} }

View File

@ -27,8 +27,8 @@ import com.iluwatar.commander.Service;
import com.iluwatar.commander.exceptions.DatabaseUnavailableException; import com.iluwatar.commander.exceptions.DatabaseUnavailableException;
/** /**
* ShippingService class receives request from {@link Commander} class and adds it * ShippingService class receives request from {@link Commander} class and adds it to the {@link
* to the {@link ShippingDatabase}. * ShippingDatabase}.
*/ */
public class ShippingService extends Service { public class ShippingService extends Service {
@ -45,21 +45,22 @@ public class ShippingService extends Service {
} }
} }
public ShippingService(ShippingDatabase db, Exception...exc) { public ShippingService(ShippingDatabase db, Exception... exc) {
super(db, exc); super(db, exc);
} }
/** /**
* Public method which will receive request from {@link Commander}. * Public method which will receive request from {@link Commander}.
*/ */
public String receiveRequest(Object...parameters) throws DatabaseUnavailableException { public String receiveRequest(Object... parameters) throws DatabaseUnavailableException {
String tId = generateId(); String id = generateId();
ShippingRequest req = new ShippingRequest(tId, (String) parameters[0] /*item*/, (String) parameters[1]/*address*/); ShippingRequest req =
new ShippingRequest(id, (String) parameters[0] /*item*/, (String) parameters[1]/*address*/);
return updateDb(req); return updateDb(req);
} }
protected String updateDb(Object...parameters) throws DatabaseUnavailableException { protected String updateDb(Object... parameters) throws DatabaseUnavailableException {
ShippingRequest req = (ShippingRequest) parameters[0]; ShippingRequest req = (ShippingRequest) parameters[0];
if (this.database.get(req.transactionId) == null) { if (this.database.get(req.transactionId) == null) {
database.add(req); database.add(req);