From de56cbb971207e7d754e0d86038e5ac9f998ea79 Mon Sep 17 00:00:00 2001 From: Besok Date: Sun, 10 Nov 2019 13:09:41 +0000 Subject: [PATCH] change according to cgeckstyle --- saga/README.md | 4 +- saga/pom.xml | 33 +-- ...{Chapter.java => ChoreographyChapter.java} | 53 ++-- .../saga/choreography/FlyBookingService.java | 14 +- .../choreography/HotelBookingService.java | 16 +- .../saga/choreography/OrderService.java | 16 +- .../com/iluwatar/saga/choreography/Saga.java | 266 +++++++++++------- .../saga/choreography/SagaApplication.java | 53 ++-- .../iluwatar/saga/choreography/Service.java | 132 ++++----- .../choreography/ServiceDiscoveryService.java | 39 +-- .../choreography/WithdrawMoneyService.java | 36 +-- .../saga/orchestration/ChapterResult.java | 46 +-- .../saga/orchestration/FlyBookingService.java | 8 +- .../orchestration/HotelBookingService.java | 36 +-- ...Chapter.java => OrchestrationChapter.java} | 39 +-- .../saga/orchestration/OrderService.java | 8 +- .../com/iluwatar/saga/orchestration/Saga.java | 83 +++--- .../saga/orchestration/SagaApplication.java | 58 ++-- .../saga/orchestration/SagaOrchestrator.java | 187 ++++++------ .../iluwatar/saga/orchestration/Service.java | 35 +-- .../ServiceDiscoveryService.java | 22 +- .../orchestration/WithdrawMoneyService.java | 26 +- .../choreography/SagaApplicationTest.java | 12 +- .../choreography/SagaChoreographyTest.java | 53 ++-- .../orchestration/SagaApplicationTest.java | 11 +- .../SagaOrchestratorInternallyTest.java | 186 ++++++------ .../orchestration/SagaOrchestratorTest.java | 51 ++-- 27 files changed, 817 insertions(+), 706 deletions(-) rename saga/src/main/java/com/iluwatar/saga/choreography/{Chapter.java => ChoreographyChapter.java} (65%) rename saga/src/main/java/com/iluwatar/saga/orchestration/{Chapter.java => OrchestrationChapter.java} (69%) diff --git a/saga/README.md b/saga/README.md index 276f12ee1..546ad598b 100644 --- a/saga/README.md +++ b/saga/README.md @@ -1,7 +1,7 @@ --- layout: pattern title: Saga -folder: Communication +folder: saga permalink: /patterns/saga/ categories: Behavioral tags: @@ -43,4 +43,4 @@ Use the Saga pattern, if: - you can not use 2PC(two phase commit) ## Credits -- [pattern description](https://microservices.io/patterns/data/saga.html) \ No newline at end of file +- [Pattern: Saga](https://microservices.io/patterns/data/saga.html) \ No newline at end of file diff --git a/saga/pom.xml b/saga/pom.xml index 26c331237..111f4e7b8 100644 --- a/saga/pom.xml +++ b/saga/pom.xml @@ -23,22 +23,23 @@ THE SOFTWARE. --> - - 4.0.0 - - com.iluwatar - java-design-patterns - 1.22.0-SNAPSHOT - + + 4.0.0 + + com.iluwatar + java-design-patterns + 1.22.0-SNAPSHOT + - saga - - - junit - junit - test - - + saga + + + junit + junit + test + + diff --git a/saga/src/main/java/com/iluwatar/saga/choreography/Chapter.java b/saga/src/main/java/com/iluwatar/saga/choreography/ChoreographyChapter.java similarity index 65% rename from saga/src/main/java/com/iluwatar/saga/choreography/Chapter.java rename to saga/src/main/java/com/iluwatar/saga/choreography/ChoreographyChapter.java index 51b0ce6b8..caa377a1e 100644 --- a/saga/src/main/java/com/iluwatar/saga/choreography/Chapter.java +++ b/saga/src/main/java/com/iluwatar/saga/choreography/ChoreographyChapter.java @@ -24,37 +24,40 @@ package com.iluwatar.saga.choreography; /** - * Chapter is an interface representing a contract for an external service. + * ChoreographyChapter is an interface representing a contract for an external service. * In that case, a service needs to make a decision what to do further * hence the server needs to get all context representing {@link Saga} - * */ -public interface Chapter { + */ +public interface ChoreographyChapter { - /** - * In that case, every method is responsible to make a decision on what to do then - * @param saga incoming saga - * @return saga result - */ - Saga execute(Saga saga); + /** + * In that case, every method is responsible to make a decision on what to do then + * + * @param saga incoming saga + * @return saga result + */ + Saga execute(Saga saga); - /** - * @return service name. - */ - String getName(); + /** + * @return service name. + */ + String getName(); - /** - * The operation executed in general case. - * @param saga incoming saga - * @return result {@link Saga} - */ - Saga process(Saga saga); + /** + * The operation executed in general case. + * + * @param saga incoming saga + * @return result {@link Saga} + */ + Saga process(Saga saga); - /** - * The operation executed in rollback case. - * @param saga incoming saga - * @return result {@link Saga} - */ - Saga rollback(Saga saga); + /** + * The operation executed in rollback case. + * + * @param saga incoming saga + * @return result {@link Saga} + */ + Saga rollback(Saga saga); } diff --git a/saga/src/main/java/com/iluwatar/saga/choreography/FlyBookingService.java b/saga/src/main/java/com/iluwatar/saga/choreography/FlyBookingService.java index 591324c52..60b183be3 100644 --- a/saga/src/main/java/com/iluwatar/saga/choreography/FlyBookingService.java +++ b/saga/src/main/java/com/iluwatar/saga/choreography/FlyBookingService.java @@ -27,12 +27,12 @@ package com.iluwatar.saga.choreography; * Class representing a service to book a fly */ public class FlyBookingService extends Service { - public FlyBookingService(ServiceDiscoveryService service) { - super(service); - } + public FlyBookingService(ServiceDiscoveryService service) { + super(service); + } - @Override - public String getName() { - return "booking a Fly"; - } + @Override + public String getName() { + return "booking a Fly"; + } } diff --git a/saga/src/main/java/com/iluwatar/saga/choreography/HotelBookingService.java b/saga/src/main/java/com/iluwatar/saga/choreography/HotelBookingService.java index e822a3568..0bbf1d3e3 100644 --- a/saga/src/main/java/com/iluwatar/saga/choreography/HotelBookingService.java +++ b/saga/src/main/java/com/iluwatar/saga/choreography/HotelBookingService.java @@ -27,14 +27,14 @@ package com.iluwatar.saga.choreography; * Class representing a service to book a hotel */ public class HotelBookingService extends Service { - public HotelBookingService(ServiceDiscoveryService service) { - super(service); - } + public HotelBookingService(ServiceDiscoveryService service) { + super(service); + } - @Override - public String getName() { - return "booking a Hotel"; - } + @Override + public String getName() { + return "booking a Hotel"; + } - } +} diff --git a/saga/src/main/java/com/iluwatar/saga/choreography/OrderService.java b/saga/src/main/java/com/iluwatar/saga/choreography/OrderService.java index 6c8b9912e..3a2c002b1 100644 --- a/saga/src/main/java/com/iluwatar/saga/choreography/OrderService.java +++ b/saga/src/main/java/com/iluwatar/saga/choreography/OrderService.java @@ -26,14 +26,14 @@ package com.iluwatar.saga.choreography; /** * Class representing a service to init a new order. */ -public class OrderService extends Service{ +public class OrderService extends Service { - public OrderService(ServiceDiscoveryService service) { - super(service); - } + public OrderService(ServiceDiscoveryService service) { + super(service); + } - @Override - public String getName() { - return "init an order"; - } + @Override + public String getName() { + return "init an order"; + } } diff --git a/saga/src/main/java/com/iluwatar/saga/choreography/Saga.java b/saga/src/main/java/com/iluwatar/saga/choreography/Saga.java index 34a8d6a0f..35069b80f 100644 --- a/saga/src/main/java/com/iluwatar/saga/choreography/Saga.java +++ b/saga/src/main/java/com/iluwatar/saga/choreography/Saga.java @@ -29,131 +29,187 @@ import java.util.List; /** * Saga representation. * Saga consists of chapters. - * Every Chapter is executed a certain service. + * Every ChoreographyChapter is executed a certain service. */ public class Saga { - private List chapters; - private int pos; - private boolean forward; - private boolean finished; + private List chapters; + private int pos; + private boolean forward; + private boolean finished; - public static Saga create() { - return new Saga(); - } - public SagaResult getResult() { - return !finished ? - SagaResult.PROGRESS : - forward ? - SagaResult.FINISHED : - SagaResult.ROLLBACKED; - } - public Saga chapter(String name) { - this.chapters.add(new Chapter(name)); - return this; - } - public Saga setInValue(Object value){ - if(chapters.isEmpty()){ - return this; - } - chapters.get(chapters.size()-1).setInValue(value); - return this; - } - public Object getCurrentValue(){ - return chapters.get(pos).getInValue(); - } - public void setCurrentValue(Object value){ - chapters.get(pos).setInValue(value); - } - public void setCurrentStatus(ChapterResult result){ - chapters.get(pos).setResult(result); + public static Saga create() { + return new Saga(); + } + + /** + * get resuzlt of saga + * + * @return result of saga @see {@link SagaResult} + */ + public SagaResult getResult() { + if (finished) { + return forward + ? SagaResult.FINISHED + : SagaResult.ROLLBACKED; } - void setFinished(boolean finished) { - this.finished = finished; - } - boolean isForward() { - return forward; - } - int forward() { - return ++pos; - } + return SagaResult.PROGRESS; + } - int back() { - this.forward = false; - return --pos; + /** + * add chapter to saga + * @param name chapter name + * @return this + */ + public Saga chapter(String name) { + this.chapters.add(new Chapter(name)); + return this; + } + + /** + * set value to last chapter + * @param value invalue + * @return this + */ + public Saga setInValue(Object value) { + if (chapters.isEmpty()) { + return this; } + chapters.get(chapters.size() - 1).setInValue(value); + return this; + } + + /** + * get value from current chapter + * @return value + */ + public Object getCurrentValue() { + return chapters.get(pos).getInValue(); + } + + /** + * set value to current chapter + * @param value to set + */ + public void setCurrentValue(Object value) { + chapters.get(pos).setInValue(value); + } + + /** + * set status for current chapter + * @param result to set + */ + public void setCurrentStatus(ChapterResult result) { + chapters.get(pos).setResult(result); + } + + void setFinished(boolean finished) { + this.finished = finished; + } + + boolean isForward() { + return forward; + } + + int forward() { + return ++pos; + } + + int back() { + this.forward = false; + return --pos; + } - public Saga() { - this.chapters = new ArrayList<>(); - this.pos = 0; - this.forward = true; - this.finished = false; - } + private Saga() { + this.chapters = new ArrayList<>(); + this.pos = 0; + this.forward = true; + this.finished = false; + } - Chapter getCurrent() { - return chapters.get(pos); - } + Chapter getCurrent() { + return chapters.get(pos); + } - boolean isPresent() { - return pos >= 0 && pos < chapters.size(); - } - boolean isCurrentSuccess(){ - return chapters.get(pos).isSuccess(); + boolean isPresent() { + return pos >= 0 && pos < chapters.size(); + } + + boolean isCurrentSuccess() { + return chapters.get(pos).isSuccess(); + } + + /*** + * Class presents a chapter status and incoming parameters(incoming parameter transforms to outcoming parameter) + */ + public static class Chapter { + private String name; + private ChapterResult result; + private Object inValue; + + + public Chapter(String name) { + this.name = name; + this.result = ChapterResult.INIT; } - /*** - * Class presents a chapter status and incoming parameters(incoming parameter transforms to outcoming parameter) + public Object getInValue() { + return inValue; + } + + public void setInValue(Object object) { + this.inValue = object; + } + + public String getName() { + return name; + } + + /** + * set result + * @param result {@link ChapterResult} */ - public static class Chapter { - private String name; - private ChapterResult result; - private Object inValue; - - - public Chapter(String name) { - this.name = name; - this.result = ChapterResult.INIT; - } - - public Object getInValue() { - return inValue; - } - - public void setInValue(Object object) { - this.inValue = object; - } - - public String getName() { - return name; - } - public void setResult(ChapterResult result){ - this.result = result; - } - - public boolean isSuccess(){ - return result == ChapterResult.SUCCESS; - } + public void setResult(ChapterResult result) { + this.result = result; } - - public enum ChapterResult { - INIT, SUCCESS, ROLLBACK + /** + * the result for chapter is good + * @return true if is good otherwise bad + */ + public boolean isSuccess() { + return result == ChapterResult.SUCCESS; } + } - public enum SagaResult { - PROGRESS, FINISHED, ROLLBACKED - } - @Override - public String toString() { - return "Saga{" + - "chapters=" + Arrays.toString(chapters.toArray()) + - ", pos=" + pos + - ", forward=" + forward + - '}'; - } + /** + * result for chapter + */ + public enum ChapterResult { + INIT, SUCCESS, ROLLBACK + } + + /** + * result for saga + */ + public enum SagaResult { + PROGRESS, FINISHED, ROLLBACKED + } + + @Override + public String toString() { + return "Saga{" + + "chapters=" + + Arrays.toString(chapters.toArray()) + + ", pos=" + + pos + + ", forward=" + + forward + + '}'; + } } diff --git a/saga/src/main/java/com/iluwatar/saga/choreography/SagaApplication.java b/saga/src/main/java/com/iluwatar/saga/choreography/SagaApplication.java index 46792adac..3aeb8672c 100644 --- a/saga/src/main/java/com/iluwatar/saga/choreography/SagaApplication.java +++ b/saga/src/main/java/com/iluwatar/saga/choreography/SagaApplication.java @@ -44,34 +44,37 @@ import org.slf4j.LoggerFactory; * @see Service */ public class SagaApplication { - private static final Logger logger = LoggerFactory.getLogger(SagaApplication.class); + private static final Logger LOGGER = LoggerFactory.getLogger(SagaApplication.class); - public static void main(String[] args) { - ServiceDiscoveryService sd = serviceDiscovery(); - Chapter service = sd.findAny(); - Saga goodOrderSaga = service.execute(newSaga("good_order")); - Saga badOrderSaga = service.execute(newSaga("bad_order")); - logger.info("orders: goodOrder is {}, badOrder is {}", - goodOrderSaga.getResult(), badOrderSaga.getResult()); + /** + * main method + */ + public static void main(String[] args) { + ServiceDiscoveryService sd = serviceDiscovery(); + ChoreographyChapter service = sd.findAny(); + Saga goodOrderSaga = service.execute(newSaga("good_order")); + Saga badOrderSaga = service.execute(newSaga("bad_order")); + LOGGER.info("orders: goodOrder is {}, badOrder is {}", + goodOrderSaga.getResult(), badOrderSaga.getResult()); - } + } - private static Saga newSaga(Object value) { - return Saga - .create() - .chapter("init an order").setInValue(value) - .chapter("booking a Fly") - .chapter("booking a Hotel") - .chapter("withdrawing Money"); - } + private static Saga newSaga(Object value) { + return Saga + .create() + .chapter("init an order").setInValue(value) + .chapter("booking a Fly") + .chapter("booking a Hotel") + .chapter("withdrawing Money"); + } - private static ServiceDiscoveryService serviceDiscovery() { - ServiceDiscoveryService sd = new ServiceDiscoveryService(); - return sd - .discover(new OrderService(sd)) - .discover(new FlyBookingService(sd)) - .discover(new HotelBookingService(sd)) - .discover(new WithdrawMoneyService(sd)); - } + private static ServiceDiscoveryService serviceDiscovery() { + ServiceDiscoveryService sd = new ServiceDiscoveryService(); + return sd + .discover(new OrderService(sd)) + .discover(new FlyBookingService(sd)) + .discover(new HotelBookingService(sd)) + .discover(new WithdrawMoneyService(sd)); + } } diff --git a/saga/src/main/java/com/iluwatar/saga/choreography/Service.java b/saga/src/main/java/com/iluwatar/saga/choreography/Service.java index 0f182e570..a602b1147 100644 --- a/saga/src/main/java/com/iluwatar/saga/choreography/Service.java +++ b/saga/src/main/java/com/iluwatar/saga/choreography/Service.java @@ -25,79 +25,85 @@ package com.iluwatar.saga.choreography; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.function.Supplier; + /** * Common abstraction class representing services - * implementing a general contract @see {@link Chapter} + * implementing a general contract @see {@link ChoreographyChapter} */ -public abstract class Service implements Chapter { - protected static final Logger logger = LoggerFactory.getLogger(Service.class); +public abstract class Service implements ChoreographyChapter { + protected static final Logger LOGGER = LoggerFactory.getLogger(Service.class); - private final ServiceDiscoveryService sd; + private final ServiceDiscoveryService sd; - public Service(ServiceDiscoveryService service) { - this.sd = service; - } + public Service(ServiceDiscoveryService service) { + this.sd = service; + } - @Override - public Saga execute(Saga saga) { - Saga nextSaga = saga; - Object nextVal; - String chapterName = saga.getCurrent().getName(); - if (chapterName.equals(getName())) { - if (saga.isForward()) { - nextSaga = process(saga); - nextVal = nextSaga.getCurrentValue(); - if (nextSaga.isCurrentSuccess()) { - nextSaga.forward(); - } else { - nextSaga.back(); - } - } else { - nextSaga = rollback(saga); - nextVal = nextSaga.getCurrentValue(); - nextSaga.back(); - } - - if (isSagaFinished(nextSaga)) { - return nextSaga; - } - - nextSaga.setCurrentValue(nextVal); + @Override + public Saga execute(Saga saga) { + Saga nextSaga = saga; + Object nextVal; + String chapterName = saga.getCurrent().getName(); + if (chapterName.equals(getName())) { + if (saga.isForward()) { + nextSaga = process(saga); + nextVal = nextSaga.getCurrentValue(); + if (nextSaga.isCurrentSuccess()) { + nextSaga.forward(); + } else { + nextSaga.back(); } - Saga finalNextSaga = nextSaga; + } else { + nextSaga = rollback(saga); + nextVal = nextSaga.getCurrentValue(); + nextSaga.back(); + } - return sd.find(chapterName).map(ch -> ch.execute(finalNextSaga)) - .orElseThrow(RuntimeException::new); + if (isSagaFinished(nextSaga)) { + return nextSaga; + } + + nextSaga.setCurrentValue(nextVal); } + Saga finalNextSaga = nextSaga; - @Override - public Saga process(Saga saga) { - Object inValue = saga.getCurrentValue(); - logger.info("The chapter '{}' has been started. The data {} has been stored or calculated successfully", - getName(), inValue); - saga.setCurrentStatus(Saga.ChapterResult.SUCCESS); - saga.setCurrentValue(inValue); - return saga; - } - - @Override - public Saga rollback(Saga saga) { - Object inValue = saga.getCurrentValue(); - logger.info("The Rollback for a chapter '{}' has been started. The data {} has been rollbacked successfully", - getName(), inValue); - - saga.setCurrentStatus(Saga.ChapterResult.ROLLBACK); - saga.setCurrentValue(inValue); - return saga; - } - - private boolean isSagaFinished(Saga saga) { - if (!saga.isPresent()) { - saga.setFinished(true); - logger.info(" the saga has been finished with {} status", saga.getResult()); - return true; - } - return false; + return sd.find(chapterName).map(ch -> ch.execute(finalNextSaga)) + .orElseThrow(serviceNotFoundException(chapterName)); + } + + private Supplier serviceNotFoundException(String chServiceName) { + return () -> new RuntimeException(String.format("the service %s has not been found", chServiceName)); + } + + @Override + public Saga process(Saga saga) { + Object inValue = saga.getCurrentValue(); + LOGGER.info("The chapter '{}' has been started. The data {} has been stored or calculated successfully", + getName(), inValue); + saga.setCurrentStatus(Saga.ChapterResult.SUCCESS); + saga.setCurrentValue(inValue); + return saga; + } + + @Override + public Saga rollback(Saga saga) { + Object inValue = saga.getCurrentValue(); + LOGGER.info("The Rollback for a chapter '{}' has been started. The data {} has been rollbacked successfully", + getName(), inValue); + + saga.setCurrentStatus(Saga.ChapterResult.ROLLBACK); + saga.setCurrentValue(inValue); + return saga; + } + + private boolean isSagaFinished(Saga saga) { + if (!saga.isPresent()) { + saga.setFinished(true); + LOGGER.info(" the saga has been finished with {} status", saga.getResult()); + return true; } + return false; + } } diff --git a/saga/src/main/java/com/iluwatar/saga/choreography/ServiceDiscoveryService.java b/saga/src/main/java/com/iluwatar/saga/choreography/ServiceDiscoveryService.java index 11512d112..919c99f02 100644 --- a/saga/src/main/java/com/iluwatar/saga/choreography/ServiceDiscoveryService.java +++ b/saga/src/main/java/com/iluwatar/saga/choreography/ServiceDiscoveryService.java @@ -32,29 +32,30 @@ import java.util.Optional; * The class representing a service discovery pattern. */ public class ServiceDiscoveryService { - private Map services; + private Map services; - /** - * find any service - * @return any service - * @throws NoSuchElementException if no elements further - */ - public Chapter findAny(){ - return services.values().iterator().next(); - } + /** + * find any service + * + * @return any service + * @throws NoSuchElementException if no elements further + */ + public ChoreographyChapter findAny() { + return services.values().iterator().next(); + } - public Optional find(String service) { - return Optional.ofNullable(services.getOrDefault(service, null)); - } + public Optional find(String service) { + return Optional.ofNullable(services.getOrDefault(service, null)); + } - public ServiceDiscoveryService discover(Chapter chapterService) { - services.put(chapterService.getName(), chapterService); - return this; - } + public ServiceDiscoveryService discover(ChoreographyChapter chapterService) { + services.put(chapterService.getName(), chapterService); + return this; + } - public ServiceDiscoveryService() { - this.services = new HashMap<>(); - } + public ServiceDiscoveryService() { + this.services = new HashMap<>(); + } } diff --git a/saga/src/main/java/com/iluwatar/saga/choreography/WithdrawMoneyService.java b/saga/src/main/java/com/iluwatar/saga/choreography/WithdrawMoneyService.java index c13b1b1f8..b30a05e95 100644 --- a/saga/src/main/java/com/iluwatar/saga/choreography/WithdrawMoneyService.java +++ b/saga/src/main/java/com/iluwatar/saga/choreography/WithdrawMoneyService.java @@ -28,26 +28,26 @@ package com.iluwatar.saga.choreography; */ public class WithdrawMoneyService extends Service { - public WithdrawMoneyService(ServiceDiscoveryService service) { - super(service); - } + public WithdrawMoneyService(ServiceDiscoveryService service) { + super(service); + } - @Override - public String getName() { - return "withdrawing Money"; - } + @Override + public String getName() { + return "withdrawing Money"; + } - @Override - public Saga process(Saga saga) { - Object inValue = saga.getCurrentValue(); + @Override + public Saga process(Saga saga) { + Object inValue = saga.getCurrentValue(); - if (inValue.equals("bad_order") ) { - logger.info("The chapter '{}' has been started. But the exception has been raised." + - "The rollback is about to start", - getName(), inValue); - saga.setCurrentStatus(Saga.ChapterResult.ROLLBACK); - return saga; - } - return super.process(saga); + if (inValue.equals("bad_order")) { + LOGGER.info("The chapter '{}' has been started. But the exception has been raised." + + "The rollback is about to start", + getName(), inValue); + saga.setCurrentStatus(Saga.ChapterResult.ROLLBACK); + return saga; } + return super.process(saga); + } } diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/ChapterResult.java b/saga/src/main/java/com/iluwatar/saga/orchestration/ChapterResult.java index eae95b339..a8a1e7b5e 100644 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/ChapterResult.java +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/ChapterResult.java @@ -24,34 +24,38 @@ package com.iluwatar.saga.orchestration; /** * Executing result for chapter + * * @param incoming value */ public class ChapterResult { - private K value; - private State state; + private K value; + private State state; - public K getValue() { - return value; - } + public K getValue() { + return value; + } - ChapterResult(K value, State state) { - this.value = value; - this.state = state; - } + ChapterResult(K value, State state) { + this.value = value; + this.state = state; + } - public boolean isSuccess(){ - return state == State.SUCCESS; - } + public boolean isSuccess() { + return state == State.SUCCESS; + } - public static ChapterResult success(K val) { - return new ChapterResult<>(val, State.SUCCESS); - } + public static ChapterResult success(K val) { + return new ChapterResult<>(val, State.SUCCESS); + } - public static ChapterResult failure(K val) { - return new ChapterResult<>(val, State.FAILURE); - } + public static ChapterResult failure(K val) { + return new ChapterResult<>(val, State.FAILURE); + } - public enum State { - SUCCESS, FAILURE - } + /** + * state for chapter + */ + public enum State { + SUCCESS, FAILURE + } } diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/FlyBookingService.java b/saga/src/main/java/com/iluwatar/saga/orchestration/FlyBookingService.java index 6cb8479c0..5dc0577bc 100644 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/FlyBookingService.java +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/FlyBookingService.java @@ -26,8 +26,8 @@ package com.iluwatar.saga.orchestration; * Class representing a service to book a fly */ public class FlyBookingService extends Service { - @Override - public String getName() { - return "booking a Fly"; - } + @Override + public String getName() { + return "booking a Fly"; + } } diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/HotelBookingService.java b/saga/src/main/java/com/iluwatar/saga/orchestration/HotelBookingService.java index e21046328..51d8d5aad 100644 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/HotelBookingService.java +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/HotelBookingService.java @@ -26,25 +26,25 @@ package com.iluwatar.saga.orchestration; * Class representing a service to book a hotel */ public class HotelBookingService extends Service { - @Override - public String getName() { - return "booking a Hotel"; + @Override + public String getName() { + return "booking a Hotel"; + } + + + @Override + public ChapterResult rollback(String value) { + if (value.equals("crashed_order")) { + LOGGER.info("The Rollback for a chapter '{}' has been started. " + + "The data {} has been failed.The saga has been crashed.", + getName(), value); + + return ChapterResult.failure(value); } + LOGGER.info("The Rollback for a chapter '{}' has been started. The data {} has been rollbacked successfully", + getName(), value); - @Override - public ChapterResult rollback(String value) { - if(value.equals("crashed_order")){ - logger.info("The Rollback for a chapter '{}' has been started. " + - "The data {} has been failed.The saga has been crashed.", - getName(), value); - - return ChapterResult.failure(value); - } - - logger.info("The Rollback for a chapter '{}' has been started. The data {} has been rollbacked successfully", - getName(), value); - - return super.rollback(value); - } + return super.rollback(value); + } } diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/Chapter.java b/saga/src/main/java/com/iluwatar/saga/orchestration/OrchestrationChapter.java similarity index 69% rename from saga/src/main/java/com/iluwatar/saga/orchestration/Chapter.java rename to saga/src/main/java/com/iluwatar/saga/orchestration/OrchestrationChapter.java index 961a88937..861382a00 100644 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/Chapter.java +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/OrchestrationChapter.java @@ -23,28 +23,31 @@ package com.iluwatar.saga.orchestration; /** - * Chapter is an interface representing a contract for an external service. + * ChoreographyChapter is an interface representing a contract for an external service. + * * @param is type for passing params */ -public interface Chapter { +public interface OrchestrationChapter { - /** - * @return service name. - */ - String getName(); + /** + * @return service name. + */ + String getName(); - /** - * The operation executed in general case. - * @param value incoming value - * @return result {@link ChapterResult} - */ - ChapterResult process(K value); + /** + * The operation executed in general case. + * + * @param value incoming value + * @return result {@link ChapterResult} + */ + ChapterResult process(K value); - /** - * The operation executed in rollback case. - * @param value incoming value - * @return result {@link ChapterResult} - */ - ChapterResult rollback(K value); + /** + * The operation executed in rollback case. + * + * @param value incoming value + * @return result {@link ChapterResult} + */ + ChapterResult rollback(K value); } diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/OrderService.java b/saga/src/main/java/com/iluwatar/saga/orchestration/OrderService.java index 6edd94ace..32b9ce90b 100644 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/OrderService.java +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/OrderService.java @@ -26,8 +26,8 @@ package com.iluwatar.saga.orchestration; * Class representing a service to init a new order. */ public class OrderService extends Service { - @Override - public String getName() { - return "init an order"; - } + @Override + public String getName() { + return "init an order"; + } } diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/Saga.java b/saga/src/main/java/com/iluwatar/saga/orchestration/Saga.java index f24a8366c..e42b06f9a 100644 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/Saga.java +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/Saga.java @@ -28,49 +28,56 @@ import java.util.List; /** * Saga representation. * Saga consists of chapters. - * Every Chapter is executed by a certain service. + * Every ChoreographyChapter is executed by a certain service. */ public class Saga { - private List chapters; + private List chapters; - public Saga() { - this.chapters = new ArrayList<>(); + + private Saga() { + this.chapters = new ArrayList<>(); + } + + + public Saga chapter(String name) { + this.chapters.add(new Chapter(name)); + return this; + } + + + public Chapter get(int idx) { + return chapters.get(idx); + } + + public boolean isPresent(int idx) { + return idx >= 0 && idx < chapters.size(); + } + + + public static Saga create() { + return new Saga(); + } + + /** + * result for saga + */ + public enum Result { + FINISHED, ROLLBACK, CRASHED + } + + /** + * class represents chapter name + */ + public static class Chapter { + String name; + + public Chapter(String name) { + this.name = name; } - - public Saga chapter(String name) { - this.chapters.add(new Chapter(name)); - return this; - } - - - public Chapter get(int idx) { - return chapters.get(idx); - } - - public boolean isPresent(int idx) { - return idx >= 0 && idx < chapters.size(); - } - - - public static Saga create() { - return new Saga(); - } - - public enum Result { - FINISHED, ROLLBACK, CRASHED - } - - public static class Chapter { - String name; - - public Chapter(String name) { - this.name = name; - } - - public String getName() { - return name; - } + public String getName() { + return name; } + } } diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/SagaApplication.java b/saga/src/main/java/com/iluwatar/saga/orchestration/SagaApplication.java index bbeca62bb..6d7e9fd8d 100644 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/SagaApplication.java +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/SagaApplication.java @@ -31,11 +31,12 @@ import org.slf4j.LoggerFactory; * This pattern is used in distributed services to perform a group of operations atomically. * This is an analog of transaction in a database but in terms of microservices architecture this is executed * in a distributed environment - * + *

* A saga is a sequence of local transactions in a certain context. If one transaction fails for some reason, * the saga executes compensating transactions(rollbacks) to undo the impact of the preceding transactions. - * - * In this approach, there is an orchestrator @see {@link SagaOrchestrator} that manages all the transactions and directs + *

+ * In this approach, there is an orchestrator @see {@link SagaOrchestrator} + * that manages all the transactions and directs * the participant services to execute local transactions based on events. * The major difference with choreography saga is an ability to handle crashed services * (otherwise in choreography services very hard to prevent a saga if one of them has been crashed) @@ -45,34 +46,37 @@ import org.slf4j.LoggerFactory; * @see Service */ public class SagaApplication { - private static final Logger logger = LoggerFactory.getLogger(SagaApplication.class); + private static final Logger LOGGER = LoggerFactory.getLogger(SagaApplication.class); - public static void main(String[] args) { - SagaOrchestrator sagaOrchestrator = new SagaOrchestrator(newSaga(), serviceDiscovery()); + /** + * method to show common saga logic + */ + public static void main(String[] args) { + SagaOrchestrator sagaOrchestrator = new SagaOrchestrator(newSaga(), serviceDiscovery()); - Saga.Result goodOrder = sagaOrchestrator.execute("good_order"); - Saga.Result badOrder = sagaOrchestrator.execute("bad_order"); - Saga.Result crashedOrder = sagaOrchestrator.execute("crashed_order"); + Saga.Result goodOrder = sagaOrchestrator.execute("good_order"); + Saga.Result badOrder = sagaOrchestrator.execute("bad_order"); + Saga.Result crashedOrder = sagaOrchestrator.execute("crashed_order"); - logger.info("orders: goodOrder is {}, badOrder is {},crashedOrder is {}",goodOrder,badOrder,crashedOrder); - } + LOGGER.info("orders: goodOrder is {}, badOrder is {},crashedOrder is {}", goodOrder, badOrder, crashedOrder); + } - private static Saga newSaga() { - return Saga - .create() - .chapter("init an order") - .chapter("booking a Fly") - .chapter("booking a Hotel") - .chapter("withdrawing Money"); - } + private static Saga newSaga() { + return Saga + .create() + .chapter("init an order") + .chapter("booking a Fly") + .chapter("booking a Hotel") + .chapter("withdrawing Money"); + } - private static ServiceDiscoveryService serviceDiscovery() { - return - new ServiceDiscoveryService() - .discover(new OrderService()) - .discover(new FlyBookingService()) - .discover(new HotelBookingService()) - .discover(new WithdrawMoneyService()); - } + private static ServiceDiscoveryService serviceDiscovery() { + return + new ServiceDiscoveryService() + .discover(new OrderService()) + .discover(new FlyBookingService()) + .discover(new HotelBookingService()) + .discover(new WithdrawMoneyService()); + } } diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/SagaOrchestrator.java b/saga/src/main/java/com/iluwatar/saga/orchestration/SagaOrchestrator.java index c005d70df..2f25ebd46 100644 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/SagaOrchestrator.java +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/SagaOrchestrator.java @@ -34,107 +34,112 @@ import static com.iluwatar.saga.orchestration.Saga.Result.*; * the participant services to execute local transactions based on events. */ public class SagaOrchestrator { - private static final Logger logger = LoggerFactory.getLogger(SagaOrchestrator.class); - private final Saga saga; - private final ServiceDiscoveryService sd; - private final CurrentState state; + private static final Logger LOGGER = LoggerFactory.getLogger(SagaOrchestrator.class); + private final Saga saga; + private final ServiceDiscoveryService sd; + private final CurrentState state; - public SagaOrchestrator(Saga saga, ServiceDiscoveryService sd) { - this.saga = saga; - this.sd = sd; - this.state = new CurrentState(); + /** + * Create a new service to orchetrate sagas + * @param saga saga to process + * @param sd service discovery @see {@link ServiceDiscoveryService} + */ + public SagaOrchestrator(Saga saga, ServiceDiscoveryService sd) { + this.saga = saga; + this.sd = sd; + this.state = new CurrentState(); + } + + /** + * pipeline to execute saga process/story + * + * @param value incoming value + * @param type for incoming value + * @return result @see {@link Saga.Result} + */ + @SuppressWarnings("unchecked") + public Saga.Result execute(K value) { + state.cleanUp(); + LOGGER.info(" The new saga is about to start"); + Saga.Result result = FINISHED; + K tempVal = value; + + while (true) { + int next = state.current(); + Saga.Chapter ch = saga.get(next); + Optional srvOpt = sd.find(ch.name); + + if (!srvOpt.isPresent()) { + state.directionToBack(); + state.back(); + continue; + } + + OrchestrationChapter srv = srvOpt.get(); + + if (state.isForward()) { + ChapterResult processRes = srv.process(tempVal); + if (processRes.isSuccess()) { + next = state.forward(); + tempVal = (K) processRes.getValue(); + } else { + state.directionToBack(); + } + } else { + ChapterResult rlRes = srv.rollback(tempVal); + if (rlRes.isSuccess()) { + next = state.back(); + tempVal = (K) rlRes.getValue(); + } else { + result = CRASHED; + next = state.back(); + } + } + + + if (!saga.isPresent(next)) { + return state.isForward() ? FINISHED : result == CRASHED ? CRASHED : ROLLBACK; + } } - /** - * pipeline to execute saga process/story - * - * @param value incoming value - * @param type for incoming value - * @return result @see {@link Saga.Result} - */ - @SuppressWarnings("unchecked") - public Saga.Result execute(K value) { - state.cleanUp(); - logger.info(" The new saga is about to start"); - Saga.Result result = FINISHED; - K tempVal = value; - - while (true) { - int next = state.current(); - Saga.Chapter ch = saga.get(next); - Optional srvOpt = sd.find(ch.name); - - if (!srvOpt.isPresent()) { - state.directionToBack(); - state.back(); - continue; - } - - Chapter srv = srvOpt.get(); - - if (state.isForward()) { - ChapterResult processRes = srv.process(tempVal); - if (processRes.isSuccess()) { - next = state.forward(); - tempVal = (K) processRes.getValue(); - } else { - state.directionToBack(); - } - } else { - ChapterResult rlRes = srv.rollback(tempVal); - if (rlRes.isSuccess()) { - next = state.back(); - tempVal = (K) rlRes.getValue(); - } else { - result = CRASHED; - next = state.back(); - } - } + } - if (!saga.isPresent(next)) { - return state.isForward() ? FINISHED : result == CRASHED ? CRASHED : ROLLBACK; - } - } + private static class CurrentState { + int currentNumber; + boolean isForward; + void cleanUp() { + currentNumber = 0; + isForward = true; + } + + CurrentState() { + this.currentNumber = 0; + this.isForward = true; } - private static class CurrentState { - int currentNumber; - boolean isForward; - - void cleanUp() { - currentNumber = 0; - isForward = true; - } - - CurrentState() { - this.currentNumber = 0; - this.isForward = true; - } - - - boolean isForward() { - return isForward; - } - - void directionToBack() { - isForward = false; - } - - int forward() { - return ++currentNumber; - } - - int back() { - return --currentNumber; - } - - int current() { - return currentNumber; - } + boolean isForward() { + return isForward; } + void directionToBack() { + isForward = false; + } + + int forward() { + return ++currentNumber; + } + + int back() { + return --currentNumber; + } + + int current() { + return currentNumber; + } + } + } diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/Service.java b/saga/src/main/java/com/iluwatar/saga/orchestration/Service.java index 20b34f55a..c4ba2a9e1 100644 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/Service.java +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/Service.java @@ -27,29 +27,30 @@ import org.slf4j.LoggerFactory; /** * Common abstraction class representing services - * implementing a general contract @see {@link Chapter} + * implementing a general contract @see {@link OrchestrationChapter} + * * @param type of incoming param */ -public abstract class Service implements Chapter { - protected static final Logger logger = LoggerFactory.getLogger(Service.class); +public abstract class Service implements OrchestrationChapter { + protected static final Logger LOGGER = LoggerFactory.getLogger(Service.class); - @Override - public abstract String getName(); + @Override + public abstract String getName(); - @Override - public ChapterResult process(K value) { - logger.info("The chapter '{}' has been started. The data {} has been stored or calculated successfully", - getName(),value); - return ChapterResult.success(value); - } + @Override + public ChapterResult process(K value) { + LOGGER.info("The chapter '{}' has been started. The data {} has been stored or calculated successfully", + getName(), value); + return ChapterResult.success(value); + } - @Override - public ChapterResult rollback(K value) { - logger.info("The Rollback for a chapter '{}' has been started. The data {} has been rollbacked successfully", - getName(),value); - return ChapterResult.success(value); - } + @Override + public ChapterResult rollback(K value) { + LOGGER.info("The Rollback for a chapter '{}' has been started. The data {} has been rollbacked successfully", + getName(), value); + return ChapterResult.success(value); + } } diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/ServiceDiscoveryService.java b/saga/src/main/java/com/iluwatar/saga/orchestration/ServiceDiscoveryService.java index 652740051..4831730a7 100644 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/ServiceDiscoveryService.java +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/ServiceDiscoveryService.java @@ -30,20 +30,20 @@ import java.util.Optional; * The class representing a service discovery pattern. */ public class ServiceDiscoveryService { - private Map> services; + private Map> services; - public Optional find(String service) { - return Optional.ofNullable(services.getOrDefault(service, null)); - } + public Optional find(String service) { + return Optional.ofNullable(services.getOrDefault(service, null)); + } - public ServiceDiscoveryService discover(Chapter chapterService) { - services.put(chapterService.getName(), chapterService); - return this; - } + public ServiceDiscoveryService discover(OrchestrationChapter orchestrationChapterService) { + services.put(orchestrationChapterService.getName(), orchestrationChapterService); + return this; + } - public ServiceDiscoveryService() { - this.services = new HashMap<>(); - } + public ServiceDiscoveryService() { + this.services = new HashMap<>(); + } } diff --git a/saga/src/main/java/com/iluwatar/saga/orchestration/WithdrawMoneyService.java b/saga/src/main/java/com/iluwatar/saga/orchestration/WithdrawMoneyService.java index dad15cec3..f5a0c90f3 100644 --- a/saga/src/main/java/com/iluwatar/saga/orchestration/WithdrawMoneyService.java +++ b/saga/src/main/java/com/iluwatar/saga/orchestration/WithdrawMoneyService.java @@ -26,19 +26,19 @@ package com.iluwatar.saga.orchestration; * Class representing a service to withdraw a money */ public class WithdrawMoneyService extends Service { - @Override - public String getName() { - return "withdrawing Money"; - } + @Override + public String getName() { + return "withdrawing Money"; + } - @Override - public ChapterResult process(String value) { - if (value.equals("bad_order") || value.equals("crashed_order")) { - logger.info("The chapter '{}' has been started. But the exception has been raised." + - "The rollback is about to start", - getName(), value); - return ChapterResult.failure(value); - } - return super.process(value); + @Override + public ChapterResult process(String value) { + if (value.equals("bad_order") || value.equals("crashed_order")) { + LOGGER.info("The chapter '{}' has been started. But the exception has been raised." + + "The rollback is about to start", + getName(), value); + return ChapterResult.failure(value); } + return super.process(value); + } } diff --git a/saga/src/test/java/com/iluwatar/saga/choreography/SagaApplicationTest.java b/saga/src/test/java/com/iluwatar/saga/choreography/SagaApplicationTest.java index 5802f54ec..d7a2a34b2 100644 --- a/saga/src/test/java/com/iluwatar/saga/choreography/SagaApplicationTest.java +++ b/saga/src/test/java/com/iluwatar/saga/choreography/SagaApplicationTest.java @@ -25,11 +25,13 @@ package com.iluwatar.saga.choreography; import com.iluwatar.saga.orchestration.SagaApplication; import org.junit.Test; -import static org.junit.Assert.*; +/*** + * empty test + */ public class SagaApplicationTest { - @Test - public void mainTest() { - SagaApplication.main(new String[]{}); - } + @Test + public void mainTest() { + SagaApplication.main(new String[]{}); + } } \ No newline at end of file diff --git a/saga/src/test/java/com/iluwatar/saga/choreography/SagaChoreographyTest.java b/saga/src/test/java/com/iluwatar/saga/choreography/SagaChoreographyTest.java index 8c8daa7c9..4300d4057 100644 --- a/saga/src/test/java/com/iluwatar/saga/choreography/SagaChoreographyTest.java +++ b/saga/src/test/java/com/iluwatar/saga/choreography/SagaChoreographyTest.java @@ -25,35 +25,38 @@ package com.iluwatar.saga.choreography; import org.junit.Assert; import org.junit.Test; +/** + * test to check choreography saga + */ public class SagaChoreographyTest { - @Test - public void executeTest() { - ServiceDiscoveryService sd = serviceDiscovery(); - Chapter service = sd.findAny(); - Saga badOrderSaga = service.execute(newSaga("bad_order")); - Saga goodOrderSaga = service.execute(newSaga("good_order")); + @Test + public void executeTest() { + ServiceDiscoveryService sd = serviceDiscovery(); + ChoreographyChapter service = sd.findAny(); + Saga badOrderSaga = service.execute(newSaga("bad_order")); + Saga goodOrderSaga = service.execute(newSaga("good_order")); - Assert.assertEquals(badOrderSaga.getResult(), Saga.SagaResult.ROLLBACKED); - Assert.assertEquals(goodOrderSaga.getResult(), Saga.SagaResult.FINISHED); - } + Assert.assertEquals(badOrderSaga.getResult(), Saga.SagaResult.ROLLBACKED); + Assert.assertEquals(goodOrderSaga.getResult(), Saga.SagaResult.FINISHED); + } - private static Saga newSaga(Object value) { - return Saga - .create() - .chapter("init an order").setInValue(value) - .chapter("booking a Fly") - .chapter("booking a Hotel") - .chapter("withdrawing Money"); - } + private static Saga newSaga(Object value) { + return Saga + .create() + .chapter("init an order").setInValue(value) + .chapter("booking a Fly") + .chapter("booking a Hotel") + .chapter("withdrawing Money"); + } - private static ServiceDiscoveryService serviceDiscovery() { - ServiceDiscoveryService sd = new ServiceDiscoveryService(); - return sd - .discover(new OrderService(sd)) - .discover(new FlyBookingService(sd)) - .discover(new HotelBookingService(sd)) - .discover(new WithdrawMoneyService(sd)); - } + private static ServiceDiscoveryService serviceDiscovery() { + ServiceDiscoveryService sd = new ServiceDiscoveryService(); + return sd + .discover(new OrderService(sd)) + .discover(new FlyBookingService(sd)) + .discover(new HotelBookingService(sd)) + .discover(new WithdrawMoneyService(sd)); + } } diff --git a/saga/src/test/java/com/iluwatar/saga/orchestration/SagaApplicationTest.java b/saga/src/test/java/com/iluwatar/saga/orchestration/SagaApplicationTest.java index 4e4d86644..aa3c8773f 100644 --- a/saga/src/test/java/com/iluwatar/saga/orchestration/SagaApplicationTest.java +++ b/saga/src/test/java/com/iluwatar/saga/orchestration/SagaApplicationTest.java @@ -26,10 +26,13 @@ import org.junit.Test; import static org.junit.Assert.*; +/** + * empty test + */ public class SagaApplicationTest { - @Test - public void mainTest() { - SagaApplication.main(new String[]{}); - } + @Test + public void mainTest() { + SagaApplication.main(new String[]{}); + } } \ No newline at end of file diff --git a/saga/src/test/java/com/iluwatar/saga/orchestration/SagaOrchestratorInternallyTest.java b/saga/src/test/java/com/iluwatar/saga/orchestration/SagaOrchestratorInternallyTest.java index ce3b926a3..a93bf5280 100644 --- a/saga/src/test/java/com/iluwatar/saga/orchestration/SagaOrchestratorInternallyTest.java +++ b/saga/src/test/java/com/iluwatar/saga/orchestration/SagaOrchestratorInternallyTest.java @@ -28,112 +28,118 @@ import org.junit.Test; import java.util.ArrayList; import java.util.List; +/** + * test to test orchestration logic + */ public class SagaOrchestratorInternallyTest { - private List records = new ArrayList<>(); + private List records = new ArrayList<>(); - @Test - public void executeTest() { - SagaOrchestrator sagaOrchestrator = new SagaOrchestrator(newSaga(), serviceDiscovery()); - Saga.Result result = sagaOrchestrator.execute(1); - Assert.assertEquals(result, Saga.Result.ROLLBACK); - Assert.assertArrayEquals( - records.toArray(new String[]{}), - new String[]{"+1","+2","+3","+4","-4","-3","-2","-1"}); + @Test + public void executeTest() { + SagaOrchestrator sagaOrchestrator = new SagaOrchestrator(newSaga(), serviceDiscovery()); + Saga.Result result = sagaOrchestrator.execute(1); + Assert.assertEquals(result, Saga.Result.ROLLBACK); + Assert.assertArrayEquals( + records.toArray(new String[]{}), + new String[]{"+1", "+2", "+3", "+4", "-4", "-3", "-2", "-1"}); + } + + private static Saga newSaga() { + return Saga + .create() + .chapter("1") + .chapter("2") + .chapter("3") + .chapter("4"); + } + + private ServiceDiscoveryService serviceDiscovery() { + return + new ServiceDiscoveryService() + .discover(new Service1()) + .discover(new Service2()) + .discover(new Service3()) + .discover(new Service4()); + } + + class Service1 extends Service { + + @Override + public String getName() { + return "1"; } - private static Saga newSaga() { - return Saga - .create() - .chapter("1") - .chapter("2") - .chapter("3") - .chapter("4"); + @Override + public ChapterResult process(Integer value) { + records.add("+1"); + return ChapterResult.success(value); } - private ServiceDiscoveryService serviceDiscovery() { - return - new ServiceDiscoveryService() - .discover(new Service1()) - .discover(new Service2()) - .discover(new Service3()) - .discover(new Service4()); + @Override + public ChapterResult rollback(Integer value) { + records.add("-1"); + return ChapterResult.success(value); + } + } + + class Service2 extends Service { + + @Override + public String getName() { + return "2"; } - class Service1 extends Service { - - @Override - public String getName() { - return "1"; - } - - @Override - public ChapterResult process(Integer value) { - records.add("+1"); - return ChapterResult.success(value); - } - - @Override - public ChapterResult rollback(Integer value) { - records.add("-1"); - return ChapterResult.success(value); - } + @Override + public ChapterResult process(Integer value) { + records.add("+2"); + return ChapterResult.success(value); } - class Service2 extends Service { + @Override + public ChapterResult rollback(Integer value) { + records.add("-2"); + return ChapterResult.success(value); + } + } - @Override - public String getName() { - return "2"; - } - @Override - public ChapterResult process(Integer value) { - records.add("+2"); - return ChapterResult.success(value); - } + class Service3 extends Service { - @Override - public ChapterResult rollback(Integer value) { - records.add("-2"); - return ChapterResult.success(value); - } + @Override + public String getName() { + return "3"; } - class Service3 extends Service { - - @Override - public String getName() { - return "3"; - } - @Override - public ChapterResult process(Integer value) { - records.add("+3"); - return ChapterResult.success(value); - } - - @Override - public ChapterResult rollback(Integer value) { - records.add("-3"); - return ChapterResult.success(value); - } + @Override + public ChapterResult process(Integer value) { + records.add("+3"); + return ChapterResult.success(value); } - class Service4 extends Service { - - @Override - public String getName() { - return "4"; - } - @Override - public ChapterResult process(Integer value) { - records.add("+4"); - return ChapterResult.failure(value); - } - - @Override - public ChapterResult rollback(Integer value) { - records.add("-4"); - return ChapterResult.success(value); - } + @Override + public ChapterResult rollback(Integer value) { + records.add("-3"); + return ChapterResult.success(value); } + } + + class Service4 extends Service { + + @Override + public String getName() { + return "4"; + } + + @Override + public ChapterResult process(Integer value) { + records.add("+4"); + return ChapterResult.failure(value); + } + + @Override + public ChapterResult rollback(Integer value) { + records.add("-4"); + return ChapterResult.success(value); + } + } } \ No newline at end of file diff --git a/saga/src/test/java/com/iluwatar/saga/orchestration/SagaOrchestratorTest.java b/saga/src/test/java/com/iluwatar/saga/orchestration/SagaOrchestratorTest.java index bead0343d..d3522418c 100644 --- a/saga/src/test/java/com/iluwatar/saga/orchestration/SagaOrchestratorTest.java +++ b/saga/src/test/java/com/iluwatar/saga/orchestration/SagaOrchestratorTest.java @@ -25,33 +25,36 @@ package com.iluwatar.saga.orchestration; import org.junit.Assert; import org.junit.Test; +/** + * test to check general logic + */ public class SagaOrchestratorTest { - @Test - public void execute() { - SagaOrchestrator sagaOrchestrator = new SagaOrchestrator(newSaga(), serviceDiscovery()); - Saga.Result badOrder = sagaOrchestrator.execute("bad_order"); - Saga.Result crashedOrder = sagaOrchestrator.execute("crashed_order"); + @Test + public void execute() { + SagaOrchestrator sagaOrchestrator = new SagaOrchestrator(newSaga(), serviceDiscovery()); + Saga.Result badOrder = sagaOrchestrator.execute("bad_order"); + Saga.Result crashedOrder = sagaOrchestrator.execute("crashed_order"); - Assert.assertEquals(badOrder, Saga.Result.ROLLBACK); - Assert.assertEquals(crashedOrder, Saga.Result.CRASHED); - } + Assert.assertEquals(badOrder, Saga.Result.ROLLBACK); + Assert.assertEquals(crashedOrder, Saga.Result.CRASHED); + } - private static Saga newSaga() { - return Saga - .create() - .chapter("init an order") - .chapter("booking a Fly") - .chapter("booking a Hotel") - .chapter("withdrawing Money"); - } + private static Saga newSaga() { + return Saga + .create() + .chapter("init an order") + .chapter("booking a Fly") + .chapter("booking a Hotel") + .chapter("withdrawing Money"); + } - private static ServiceDiscoveryService serviceDiscovery() { - return - new ServiceDiscoveryService() - .discover(new OrderService()) - .discover(new FlyBookingService()) - .discover(new HotelBookingService()) - .discover(new WithdrawMoneyService()); - } + private static ServiceDiscoveryService serviceDiscovery() { + return + new ServiceDiscoveryService() + .discover(new OrderService()) + .discover(new FlyBookingService()) + .discover(new HotelBookingService()) + .discover(new WithdrawMoneyService()); + } } \ No newline at end of file