diff --git a/pom.xml b/pom.xml index 22dedc14a..4e8b76c78 100644 --- a/pom.xml +++ b/pom.xml @@ -183,6 +183,8 @@ data-locality subclass-sandbox circuit-breaker + role-object + saga diff --git a/saga/README.md b/saga/README.md new file mode 100644 index 000000000..12e4c8482 --- /dev/null +++ b/saga/README.md @@ -0,0 +1,45 @@ +--- +layout: pattern +title: Saga +folder: Communication +permalink: /patterns/saga/ +categories: Behavioral +tags: + - Java + - Difficulty-Expert + - Idiom + - Distributed communication +--- + +## Also known as +This pattern has a similar goal with two-phase commit (XA transaction) + +## Intent +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 performed in a distributed environment + +## Explanation +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. +There are two types of Saga: + +- Choreography-Based Saga. +In this approach, there is no central orchestrator. +Each service participating in the Saga performs their transaction and publish events. +The other services act upon those events and perform their transactions. +Also, they may or not publish other events based on the situation. + +- Orchestration-Based Saga +In this approach, there is a Saga orchestrator that manages all the transactions and directs +the participant services to execute local transactions based on events. +This orchestrator can also be though of as a Saga Manager. + +## Applicability +Use the Saga pattern, if: +- you need to perform a group of operations related to different microservices atomically +- you need to rollback changes in different places in case of failure one of the operation +- you need to take care of data consistency in different places including different databases +- you can not use 2PC(two phase commit) + +## Credits +- [pattern description](https://microservices.io/patterns/data/saga.html) \ No newline at end of file diff --git a/saga/pom.xml b/saga/pom.xml new file mode 100644 index 000000000..26c331237 --- /dev/null +++ b/saga/pom.xml @@ -0,0 +1,44 @@ + + + + 4.0.0 + + com.iluwatar + java-design-patterns + 1.22.0-SNAPSHOT + + + saga + + + junit + junit + test + + + + diff --git a/stirring-clicker/pom.xml b/stirring-clicker/pom.xml new file mode 100644 index 000000000..b0d223016 --- /dev/null +++ b/stirring-clicker/pom.xml @@ -0,0 +1,28 @@ + + + 4.0.0 + + ie.home.besok + move-clicker + 1.0 + + 1.8 + 1.8 + + + + + org.projectlombok + lombok + 1.18.10 + + + + junit + junit + 4.12 + + + \ No newline at end of file diff --git a/stirring-clicker/src/main/java/ie/home/besok/stirrings/Application.java b/stirring-clicker/src/main/java/ie/home/besok/stirrings/Application.java new file mode 100644 index 000000000..0835470bc --- /dev/null +++ b/stirring-clicker/src/main/java/ie/home/besok/stirrings/Application.java @@ -0,0 +1,15 @@ +package ie.home.besok.stirrings; + +import java.awt.*; +import java.io.IOException; + +public class Application { + public static void main(String[] args) throws IOException { + FileStorage storage = new FileStorage(); + + EventQueue.invokeLater(() -> { + Gui gui = new Gui(storage); + gui.setVisible(true); + }); + } +} diff --git a/stirring-clicker/src/main/java/ie/home/besok/stirrings/Counter.java b/stirring-clicker/src/main/java/ie/home/besok/stirrings/Counter.java new file mode 100644 index 000000000..b0f93f9d7 --- /dev/null +++ b/stirring-clicker/src/main/java/ie/home/besok/stirrings/Counter.java @@ -0,0 +1,14 @@ +package ie.home.besok.stirrings; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +public class Counter { + public Map count(List dates){ + return null; + } +} diff --git a/stirring-clicker/src/main/java/ie/home/besok/stirrings/FileStorage.java b/stirring-clicker/src/main/java/ie/home/besok/stirrings/FileStorage.java new file mode 100644 index 000000000..c5784eb50 --- /dev/null +++ b/stirring-clicker/src/main/java/ie/home/besok/stirrings/FileStorage.java @@ -0,0 +1,37 @@ +package ie.home.besok.stirrings; + +import lombok.extern.slf4j.Slf4j; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; +import java.time.LocalDateTime; +import java.util.List; + +public class FileStorage { + + private Path file; + + public FileStorage() throws IOException { + this.file = Paths.get("data.log"); + if(!Files.exists(file)){ + Files.createFile(file); + } + } + + public void plus() { + String line = LocalDateTime.now().toString()+System.lineSeparator(); + try { + Files.write(file, line.getBytes(), StandardOpenOption.APPEND); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public List get() throws IOException { + return Files.readAllLines(file); + } + +} diff --git a/stirring-clicker/src/main/java/ie/home/besok/stirrings/Gui.java b/stirring-clicker/src/main/java/ie/home/besok/stirrings/Gui.java new file mode 100644 index 000000000..3df3e2131 --- /dev/null +++ b/stirring-clicker/src/main/java/ie/home/besok/stirrings/Gui.java @@ -0,0 +1,73 @@ +package ie.home.besok.stirrings; + +import javax.imageio.ImageIO; +import javax.swing.*; +import java.awt.*; +import java.io.IOException; +import java.net.URL; + +public class Gui extends JFrame { + + private FileStorage storage; + + public Gui(FileStorage storage) { + this.storage = storage; + try { + createUI(storage); + } catch (IOException e) { + e.printStackTrace(); + } + } + + private void createUI(FileStorage storage) throws IOException { + setTitle("Stirring counter"); + setSize(300, 300); + setLocationRelativeTo(null); + + + JButton button = createButton(storage); + JButton graphick = new JButton(); + graphick.setIcon(getIcon("3.jpg")); + + + Container pane = getContentPane(); + GroupLayout gl = new GroupLayout(pane); + pane.setLayout(gl); + + gl.setAutoCreateContainerGaps(true); + + gl.setHorizontalGroup( + gl.createSequentialGroup().addComponent(button).addComponent(graphick) + ); + + gl.setVerticalGroup(gl.createSequentialGroup().addComponent(button).addComponent(graphick)); + + + button.addActionListener((event) -> { + storage.plus(); + try { + JOptionPane.showMessageDialog(null,"","",JOptionPane.INFORMATION_MESSAGE, getIcon("2.jpg")); + } catch (IOException e) { + e.printStackTrace(); + } + }); + + setDefaultCloseOperation(EXIT_ON_CLOSE); + } + + private JButton createButton(FileStorage storage) throws IOException { + ImageIcon babyIcon = getIcon("1.png"); + + JButton button = new JButton(); + + button.setIcon(babyIcon); + return button; + } + + private ImageIcon getIcon(String name) throws IOException { + URL file = this.getClass().getClassLoader().getResource(name); + return new ImageIcon(ImageIO.read(file)); + } + + +} diff --git a/stirring-clicker/src/main/resources/1.png b/stirring-clicker/src/main/resources/1.png new file mode 100644 index 000000000..1ff5944d6 Binary files /dev/null and b/stirring-clicker/src/main/resources/1.png differ diff --git a/stirring-clicker/src/main/resources/2.jpg b/stirring-clicker/src/main/resources/2.jpg new file mode 100644 index 000000000..6220fba24 Binary files /dev/null and b/stirring-clicker/src/main/resources/2.jpg differ diff --git a/stirring-clicker/src/main/resources/3.jpg b/stirring-clicker/src/main/resources/3.jpg new file mode 100644 index 000000000..f2b5f6443 Binary files /dev/null and b/stirring-clicker/src/main/resources/3.jpg differ diff --git a/stirring-clicker/src/test/java/ie/home/besok/stirrings/FileStorageTest.java b/stirring-clicker/src/test/java/ie/home/besok/stirrings/FileStorageTest.java new file mode 100644 index 000000000..1eaaba6d5 --- /dev/null +++ b/stirring-clicker/src/test/java/ie/home/besok/stirrings/FileStorageTest.java @@ -0,0 +1,25 @@ +package ie.home.besok.stirrings; + +import org.junit.Test; + +import java.io.IOException; +import java.util.List; + +import static org.junit.Assert.*; + +public class FileStorageTest { + + @Test + public void fsTest() throws IOException { + FileStorage fs = new FileStorage(); + List arrs = fs.get(); + int oldSize = arrs.size(); + fs.plus(); + fs.plus(); + fs.plus(); + fs.plus(); + arrs = fs.get(); + int newSize = arrs.size(); + assertEquals(4, newSize - oldSize); + } +} \ No newline at end of file