Skip to content

Commit

Permalink
feat: fork pizza e vino showcase from thomas github
Browse files Browse the repository at this point in the history
  • Loading branch information
DaAnda97 committed Apr 5, 2023
1 parent 5da54ac commit 3cb1822
Show file tree
Hide file tree
Showing 45 changed files with 1,591 additions and 2 deletions.
77 changes: 77 additions & 0 deletions pizza-e-vino-showcase/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@

##############################
## Java
##############################
.mtj.tmp/
*.class
*.jar
*.war
*.ear
*.nar
hs_err_pid*

##############################
## Maven
##############################
target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.next
release.properties
dependency-reduced-pom.xml
buildNumber.properties
.mvn/timing.properties
.mvn/wrapper/maven-wrapper.jar

##############################
## Gradle
##############################
bin/
build/
.gradle
.gradletasknamecache
gradle-app.setting
!gradle-wrapper.jar

##############################
## IntelliJ
##############################
out/
.idea/
.idea_modules/
*.iml
*.ipr
*.iws

##############################
## Eclipse
##############################
.settings/
bin/
tmp/
.metadata
.classpath
.project
*.tmp
*.bak
*.swp
*~.nib
local.properties
.loadpath

##############################
## NetBeans
##############################
nbproject/private/
build/
nbbuild/
dist/
nbdist/
nbactions.xml
nb-configuration.xml

##############################
## OS X
##############################
.DS_Store
51 changes: 51 additions & 0 deletions pizza-e-vino-showcase/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Pizza e Vino
This is an example of how to decouple dependent microservices by adding Camunda Platform 8 as a dependency.
It was forked from [Thomas Heinrichs: Pizza e Vino Repository](https://github.com/Hafflgav/pizza-e-vino).

In total there are three services:
* a ``checkout``, where you can make orders to
* a ``service`` that is responsible for serving food and drinks
* and a ``cooking`` service if a pizza needs to be made.

There are two versions of this architecture
* **Synchronous:** All communication between services is completed in one transaction per request.
* **Asynchronous:** Each request is persisted and completed in a new transaction while waiting for the potential of additional requests.
This is manifested in the two different versions of our service. (Sync & Async)

## Run the project
1. Start the Checkout service in order to access the order frontend via ``http://localhost:8082``
2. Start the Cooking service
3. Either boot up Service-Sync or Service2-Async dependent on the architecture you want to run.
- If you decide to run the Async example make you have a Camunda Platform 8 Cluster up and running. Either SaaS or on-premise
- Update the Zeebe related properties in the [application.yaml](service-async/src/main/resources/application.yaml)

Now you can start a new order by filling out the form via the Checkout Service. Provide a ``pizza`` dish and some type of ``vino``.
Make sure to use these keywords. An example of this is shown in the picture below.

![Pizza e Vino Order](./img/pizza-e-vino.png)

Now you are able to see the progress of your order in the console of each of the services.
If you are running the asynchronous example you can also open up [Operate](https://docs.camunda.io/docs/components/operate/userguide/basic-operate-navigation/)
in Camunda Platform 8 to visualise how the order progresses through the process.

## About the Process
We use BPMN 2.0 to visualise the workflow modelled with Camunda Platform 8. It is used in the asynchronous example and can be found in the
[ressource folder](service-async/src/main/resources/howAreYou.bpmn).

![BPMN Process](./img/process.png)
The process starts after the order has been submitted by the checkout service. Depending on what is ordered, vino or pizza, we split or continue
the flow accordingly in the inclusive Gateway. After the Service components sorts the vino and pizza order. The latter is triggering the cooking
service. Though we do not serve Pizza Hawaii and throw a BPMN Error if someone orders it.

Once the order is sorted we are going to tell the cashier / waiter that it is ready. If the order fulfillment takes longer than 1 minute we are
going to tell checkout to calm down the customer.

## What's next?
Of course there is further potential in this example. An immediate next step would be to add Kafka to the equation. Instead of communicating through REST
our services could throw "Domain Events" and interpret them. A simple sketch of this architecture can be found in the picture below.

![Bringing Kafka into the equation](./img/Kafka.png)

Last but not least we can implement each of our services in such a way that they are technology neutral. Featuring in and out adapters and hexagonal
architecture so our domain is a free as even possible. This concept is what [Miranum](https://miranum.com) is all about. Once it is release as a maven
dependency it will be worth trying it out and refactoring our code accordingly.
42 changes: 42 additions & 0 deletions pizza-e-vino-showcase/checkout/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

<artifactId>checkout</artifactId>
<name>checkout</name>
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>

<parent>
<groupId>io.miragon.miranum.consulting</groupId>
<artifactId>pizza-e-vino-showcase</artifactId>
<version>0.1.0-SNAPSHOT</version>
</parent>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>webjars-locator-core</artifactId>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>sockjs-client</artifactId>
<version>1.5.1</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>stomp-websocket</artifactId>
<version>2.3.4</version>
</dependency>
</dependencies>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package checkout;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;

@SpringBootApplication
@ComponentScan
public class CheckoutApplication {
public static void main(String[] args) {
SpringApplication.run(CheckoutApplication.class, args);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package checkout;

import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.Scanner;

@Component
public class CheckoutConversation {

@PostConstruct
public void startChat() throws Exception{

Runnable newThread = () -> {
try {
Scanner scanner = new Scanner(System.in);
//new ServiceController().index(scanner.next());
while(true) {
System.out.println("Welcome to Pizza and Vino, What would you like?");
String order = scanner.nextLine();
System.out.println("And what is your name?");
String name = scanner.nextLine();
try {
// mike.sendOrder(order, name);
}catch(Exception e){
e.printStackTrace();
}

System.out.println("Who's next?");
System.out.println();
System.out.println();
System.out.println();
}
} catch (Exception ex) {
// silently ignore
}};
Thread.sleep(3000);
new Thread(newThread).start();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package checkout;

import checkout.websockets.NotificationApplicationListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MessageForCheckout {
@Autowired
NotificationApplicationListener notificationApp;

@RequestMapping(value = "/messageForCheckout", method = RequestMethod.PUT)
public String message(@RequestBody OrderMessageRequest orderMessageRequest) {

if (orderMessageRequest.orderMessage.contains("OUT OF STOCK") || orderMessageRequest.orderMessage.contains("No Pineapple")) {

notificationApp.notify("<p style=\"border:2px solid Red;\"> -- " + orderMessageRequest.orderMessage + " " +
"for" +
" " + orderMessageRequest.orderName + " -- </p>");

} else if (orderMessageRequest.orderMessage.contains("order is taking a little longer")) {
notificationApp.notify("<p style=\"border:2px solid Yellow;\"> -- " + orderMessageRequest.orderMessage +
" " +
"for" +
" " + orderMessageRequest.orderName + " -- </p>");
} else {
notificationApp.notify("<p style=\"border:2px solid Green;\"> -- " + orderMessageRequest.orderMessage + " for" +
" " + orderMessageRequest.orderName + " -- </p>");
}
return "success";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package checkout;

import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.net.URI;

@Component
@RestController
public class OrderController {
private final RestTemplate restTemplate;

RestTemplateBuilder restTemplateBuilder = new RestTemplateBuilder();

public OrderController() {
this.restTemplate = restTemplateBuilder.build();
}

@RequestMapping(value = "/localOrderUp", method = RequestMethod.POST)
public String sendOrder(@RequestBody OrderMessageRequest order){
System.out.println("-- Sending order "+ order.orderName + " to our " +
"Order Sorter -- >");
URI uri = URI.create("http://localhost:8080/orderUp/");
String response = restTemplate.postForObject(uri, order, String.class);
System.out.println("-- All good - the order has been sent -- ");
return response;
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package checkout;

public class OrderMessageRequest {
public String orderMessage;
public String orderName;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package checkout.websockets;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.messaging.simp.SimpMessageSendingOperations;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.messaging.SessionConnectedEvent;

@Component
public class NotificationApplicationListener {

@Autowired
private SimpMessageSendingOperations messagingTemplate;

@EventListener
public void handleWebSocketConnectListener(SessionConnectedEvent event) {
}

public void notify(String message) {
messagingTemplate.convertAndSend("/topic/message", message);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package checkout.websockets;

import org.springframework.stereotype.Controller;

@Controller
public class NotificationController {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package checkout.websockets;

import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic");
config.setApplicationDestinationPrefixes("/app");
}

@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/twitter-example").withSockJS();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
server:
port : 8082
Loading

0 comments on commit 3cb1822

Please sign in to comment.