diff --git a/pizza-e-vino-showcase/.gitignore b/pizza-e-vino-showcase/.gitignore new file mode 100644 index 0000000..9bd0fe3 --- /dev/null +++ b/pizza-e-vino-showcase/.gitignore @@ -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 diff --git a/pizza-e-vino-showcase/README.md b/pizza-e-vino-showcase/README.md new file mode 100644 index 0000000..3d6814d --- /dev/null +++ b/pizza-e-vino-showcase/README.md @@ -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. diff --git a/pizza-e-vino-showcase/checkout/pom.xml b/pizza-e-vino-showcase/checkout/pom.xml new file mode 100644 index 0000000..ef7cdd1 --- /dev/null +++ b/pizza-e-vino-showcase/checkout/pom.xml @@ -0,0 +1,42 @@ + + + + checkout + checkout + 4.0.0 + jar + + + io.miragon.miranum.consulting + pizza-e-vino-showcase + 0.1.0-SNAPSHOT + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-websocket + + + org.webjars + webjars-locator-core + + + org.webjars + sockjs-client + 1.5.1 + + + org.webjars + stomp-websocket + 2.3.4 + + + + diff --git a/pizza-e-vino-showcase/checkout/src/main/java/checkout/CheckoutApplication.java b/pizza-e-vino-showcase/checkout/src/main/java/checkout/CheckoutApplication.java new file mode 100644 index 0000000..fde2512 --- /dev/null +++ b/pizza-e-vino-showcase/checkout/src/main/java/checkout/CheckoutApplication.java @@ -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); + } +} diff --git a/pizza-e-vino-showcase/checkout/src/main/java/checkout/CheckoutConversation.java b/pizza-e-vino-showcase/checkout/src/main/java/checkout/CheckoutConversation.java new file mode 100644 index 0000000..4db4d1b --- /dev/null +++ b/pizza-e-vino-showcase/checkout/src/main/java/checkout/CheckoutConversation.java @@ -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(); + } +} diff --git a/pizza-e-vino-showcase/checkout/src/main/java/checkout/MessageForCheckout.java b/pizza-e-vino-showcase/checkout/src/main/java/checkout/MessageForCheckout.java new file mode 100644 index 0000000..a39f647 --- /dev/null +++ b/pizza-e-vino-showcase/checkout/src/main/java/checkout/MessageForCheckout.java @@ -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("

-- " + orderMessageRequest.orderMessage + " " + + "for" + + " " + orderMessageRequest.orderName + " --

"); + + } else if (orderMessageRequest.orderMessage.contains("order is taking a little longer")) { + notificationApp.notify("

-- " + orderMessageRequest.orderMessage + + " " + + "for" + + " " + orderMessageRequest.orderName + " --

"); + } else { + notificationApp.notify("

-- " + orderMessageRequest.orderMessage + " for" + + " " + orderMessageRequest.orderName + " --

"); + } + return "success"; + } +} diff --git a/pizza-e-vino-showcase/checkout/src/main/java/checkout/OrderController.java b/pizza-e-vino-showcase/checkout/src/main/java/checkout/OrderController.java new file mode 100644 index 0000000..2cc0326 --- /dev/null +++ b/pizza-e-vino-showcase/checkout/src/main/java/checkout/OrderController.java @@ -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; + } + + +} diff --git a/pizza-e-vino-showcase/checkout/src/main/java/checkout/OrderMessageRequest.java b/pizza-e-vino-showcase/checkout/src/main/java/checkout/OrderMessageRequest.java new file mode 100644 index 0000000..e8cca13 --- /dev/null +++ b/pizza-e-vino-showcase/checkout/src/main/java/checkout/OrderMessageRequest.java @@ -0,0 +1,6 @@ +package checkout; + +public class OrderMessageRequest { + public String orderMessage; + public String orderName; +} diff --git a/pizza-e-vino-showcase/checkout/src/main/java/checkout/websockets/NotificationApplicationListener.java b/pizza-e-vino-showcase/checkout/src/main/java/checkout/websockets/NotificationApplicationListener.java new file mode 100644 index 0000000..e85c9ba --- /dev/null +++ b/pizza-e-vino-showcase/checkout/src/main/java/checkout/websockets/NotificationApplicationListener.java @@ -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); + } + +} \ No newline at end of file diff --git a/pizza-e-vino-showcase/checkout/src/main/java/checkout/websockets/NotificationController.java b/pizza-e-vino-showcase/checkout/src/main/java/checkout/websockets/NotificationController.java new file mode 100644 index 0000000..d1d74f7 --- /dev/null +++ b/pizza-e-vino-showcase/checkout/src/main/java/checkout/websockets/NotificationController.java @@ -0,0 +1,8 @@ +package checkout.websockets; + +import org.springframework.stereotype.Controller; + +@Controller +public class NotificationController { + +} \ No newline at end of file diff --git a/pizza-e-vino-showcase/checkout/src/main/java/checkout/websockets/WebSocketConfig.java b/pizza-e-vino-showcase/checkout/src/main/java/checkout/websockets/WebSocketConfig.java new file mode 100644 index 0000000..1e5b733 --- /dev/null +++ b/pizza-e-vino-showcase/checkout/src/main/java/checkout/websockets/WebSocketConfig.java @@ -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(); + } + +} \ No newline at end of file diff --git a/pizza-e-vino-showcase/checkout/src/main/resources/application.yaml b/pizza-e-vino-showcase/checkout/src/main/resources/application.yaml new file mode 100644 index 0000000..2fa2c19 --- /dev/null +++ b/pizza-e-vino-showcase/checkout/src/main/resources/application.yaml @@ -0,0 +1,2 @@ +server: + port : 8082 diff --git a/pizza-e-vino-showcase/checkout/src/main/resources/static/css/styles.css b/pizza-e-vino-showcase/checkout/src/main/resources/static/css/styles.css new file mode 100644 index 0000000..6510d46 --- /dev/null +++ b/pizza-e-vino-showcase/checkout/src/main/resources/static/css/styles.css @@ -0,0 +1,91 @@ +#loadingDiv { + position:absolute; + top:0; + left:0; + width:100%; + height:100%; + background-color:grey; + opacity: .8; + z-index:1000; +} + +.loader { + color: #ffffff; + font-size: 90px; + text-indent: -9999em; + overflow: hidden; + width: 1em; + height: 1em; + border-radius: 50%; + margin: 72px auto; + position: relative; + -webkit-transform: translateZ(0); + -ms-transform: translateZ(0); + transform: translateZ(0); + -webkit-animation: load6 1.7s infinite ease, round 1.7s infinite ease; + animation: load6 1.7s infinite ease, round 1.7s infinite ease; +} +@-webkit-keyframes load6 { + 0% { + box-shadow: 0 -0.83em 0 -0.4em, 0 -0.83em 0 -0.42em, 0 -0.83em 0 -0.44em, 0 -0.83em 0 -0.46em, 0 -0.83em 0 -0.477em; + } + 5%, + 95% { + box-shadow: 0 -0.83em 0 -0.4em, 0 -0.83em 0 -0.42em, 0 -0.83em 0 -0.44em, 0 -0.83em 0 -0.46em, 0 -0.83em 0 -0.477em; + } + 10%, + 59% { + box-shadow: 0 -0.83em 0 -0.4em, -0.087em -0.825em 0 -0.42em, -0.173em -0.812em 0 -0.44em, -0.256em -0.789em 0 -0.46em, -0.297em -0.775em 0 -0.477em; + } + 20% { + box-shadow: 0 -0.83em 0 -0.4em, -0.338em -0.758em 0 -0.42em, -0.555em -0.617em 0 -0.44em, -0.671em -0.488em 0 -0.46em, -0.749em -0.34em 0 -0.477em; + } + 38% { + box-shadow: 0 -0.83em 0 -0.4em, -0.377em -0.74em 0 -0.42em, -0.645em -0.522em 0 -0.44em, -0.775em -0.297em 0 -0.46em, -0.82em -0.09em 0 -0.477em; + } + 100% { + box-shadow: 0 -0.83em 0 -0.4em, 0 -0.83em 0 -0.42em, 0 -0.83em 0 -0.44em, 0 -0.83em 0 -0.46em, 0 -0.83em 0 -0.477em; + } +} +@keyframes load6 { + 0% { + box-shadow: 0 -0.83em 0 -0.4em, 0 -0.83em 0 -0.42em, 0 -0.83em 0 -0.44em, 0 -0.83em 0 -0.46em, 0 -0.83em 0 -0.477em; + } + 5%, + 95% { + box-shadow: 0 -0.83em 0 -0.4em, 0 -0.83em 0 -0.42em, 0 -0.83em 0 -0.44em, 0 -0.83em 0 -0.46em, 0 -0.83em 0 -0.477em; + } + 10%, + 59% { + box-shadow: 0 -0.83em 0 -0.4em, -0.087em -0.825em 0 -0.42em, -0.173em -0.812em 0 -0.44em, -0.256em -0.789em 0 -0.46em, -0.297em -0.775em 0 -0.477em; + } + 20% { + box-shadow: 0 -0.83em 0 -0.4em, -0.338em -0.758em 0 -0.42em, -0.555em -0.617em 0 -0.44em, -0.671em -0.488em 0 -0.46em, -0.749em -0.34em 0 -0.477em; + } + 38% { + box-shadow: 0 -0.83em 0 -0.4em, -0.377em -0.74em 0 -0.42em, -0.645em -0.522em 0 -0.44em, -0.775em -0.297em 0 -0.46em, -0.82em -0.09em 0 -0.477em; + } + 100% { + box-shadow: 0 -0.83em 0 -0.4em, 0 -0.83em 0 -0.42em, 0 -0.83em 0 -0.44em, 0 -0.83em 0 -0.46em, 0 -0.83em 0 -0.477em; + } +} +@-webkit-keyframes round { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} +@keyframes round { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} diff --git a/pizza-e-vino-showcase/checkout/src/main/resources/static/index.html b/pizza-e-vino-showcase/checkout/src/main/resources/static/index.html new file mode 100644 index 0000000..640604b --- /dev/null +++ b/pizza-e-vino-showcase/checkout/src/main/resources/static/index.html @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + Welcome to Pizza e Vino + + + +
+
+
+
+

Welcome to... 🍕 and 🍷

+
+
+
+ + +
+
+ + +
+
+ +
+
+
+
+
+
+
+
+
+
+ + + + + + + \ No newline at end of file diff --git a/pizza-e-vino-showcase/checkout/src/main/resources/static/js/index.js b/pizza-e-vino-showcase/checkout/src/main/resources/static/js/index.js new file mode 100644 index 0000000..674615e --- /dev/null +++ b/pizza-e-vino-showcase/checkout/src/main/resources/static/js/index.js @@ -0,0 +1,42 @@ +var stompClient = null; +var $loading = $('#loadingDiv').hide(); +$(document) + .ajaxStart(function () { + $loading.show(); + }) + .ajaxStop(function () { + $loading.hide(); + }); + +function connect() { + var socket = new SockJS('/twitter-example'); + stompClient = Stomp.over(socket); + stompClient.connect({}, function (frame) { + + stompClient.subscribe('/topic/message', function (greeting) { + console.log(greeting.body) + $('.response').append('
'+greeting.body+'
'); + }); + }); +} +connect(); + + +$( "#form" ).submit(function( event ) { + + event.preventDefault(); + var data = { orderName: $("#Name").val(), orderMessage: $("#Order").val() }; + $.ajax({ + method: "POST", + contentType:"application/json; charset=utf-8", + dataType:"json", + url: "/localOrderUp", + data: JSON.stringify(data) + }) + .done(function( msg ) { + $('.response').append('

'+msg+'

'); + + }).fail(function( jqXHR, textStatus ) { + $('.response').append('

'+jqXHR.responseText+'

'); + }); +}); \ No newline at end of file diff --git a/pizza-e-vino-showcase/cooking/pom.xml b/pizza-e-vino-showcase/cooking/pom.xml new file mode 100644 index 0000000..c39f268 --- /dev/null +++ b/pizza-e-vino-showcase/cooking/pom.xml @@ -0,0 +1,24 @@ + + + + cooking + cooking + 4.0.0 + jar + + + io.miragon.miranum.consulting + pizza-e-vino-showcase + 0.1.0-SNAPSHOT + + + + + org.springframework.boot + spring-boot-starter-web + + + + diff --git a/pizza-e-vino-showcase/cooking/src/main/java/Cooking/CookingApplication.java b/pizza-e-vino-showcase/cooking/src/main/java/Cooking/CookingApplication.java new file mode 100644 index 0000000..48161a5 --- /dev/null +++ b/pizza-e-vino-showcase/cooking/src/main/java/Cooking/CookingApplication.java @@ -0,0 +1,11 @@ +package Cooking; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class CookingApplication { + public static void main(String[] args) { + SpringApplication.run(CookingApplication.class, args); + } +} diff --git a/pizza-e-vino-showcase/cooking/src/main/java/Cooking/CookingService.java b/pizza-e-vino-showcase/cooking/src/main/java/Cooking/CookingService.java new file mode 100644 index 0000000..fe8db01 --- /dev/null +++ b/pizza-e-vino-showcase/cooking/src/main/java/Cooking/CookingService.java @@ -0,0 +1,35 @@ +package Cooking; + +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 CookingService { + + long waitTimeMillis = 1000; + public static final String GREEN = "\033[0;32m"; // GREEN + public static final String RED_BACKGROUND = "\033[41m"; // RED + public static final String PURPLE_BRIGHT = "\033[0;95m"; // PURPLE + public static final String BLUE_BOLD_BRIGHT = "\033[1;94m"; // BLUE + public static final String GREEN_BACKGROUND_BRIGHT = "\033[0;102m";// GREEN + public static final String RESET = "\033[0m"; // Text Reset + + @RequestMapping(value = "/WorkIt", method = RequestMethod.PUT) + public String index(@RequestBody OrderMessageRequest orderRequest) throws InterruptedException { + int loops = 10; + System.out.println(); + System.out.println("We're Working on it! -- "+ orderRequest.orderMessage); + while(loops >= 0) { + System.out.print(GREEN_BACKGROUND_BRIGHT + ".!." + RESET); + Thread.sleep(waitTimeMillis); + loops--; + } + System.out.println(); + System.out.println("We've done it! -- "+ orderRequest.orderMessage); + + return "You have said "+ orderRequest.orderMessage + ""; + } +} diff --git a/pizza-e-vino-showcase/cooking/src/main/java/Cooking/OrderMessageRequest.java b/pizza-e-vino-showcase/cooking/src/main/java/Cooking/OrderMessageRequest.java new file mode 100644 index 0000000..53e7ef1 --- /dev/null +++ b/pizza-e-vino-showcase/cooking/src/main/java/Cooking/OrderMessageRequest.java @@ -0,0 +1,6 @@ +package Cooking; + +public class OrderMessageRequest { + public String orderMessage; + public String orderName; +} diff --git a/pizza-e-vino-showcase/cooking/src/main/resources/application.yaml b/pizza-e-vino-showcase/cooking/src/main/resources/application.yaml new file mode 100644 index 0000000..41d525d --- /dev/null +++ b/pizza-e-vino-showcase/cooking/src/main/resources/application.yaml @@ -0,0 +1,2 @@ +server: + port : 8081 \ No newline at end of file diff --git a/pizza-e-vino-showcase/img/Kafka.png b/pizza-e-vino-showcase/img/Kafka.png new file mode 100644 index 0000000..e3e9750 Binary files /dev/null and b/pizza-e-vino-showcase/img/Kafka.png differ diff --git a/pizza-e-vino-showcase/img/pizza-e-vino.png b/pizza-e-vino-showcase/img/pizza-e-vino.png new file mode 100644 index 0000000..5d0840a Binary files /dev/null and b/pizza-e-vino-showcase/img/pizza-e-vino.png differ diff --git a/pizza-e-vino-showcase/img/process.png b/pizza-e-vino-showcase/img/process.png new file mode 100644 index 0000000..6cf5368 Binary files /dev/null and b/pizza-e-vino-showcase/img/process.png differ diff --git a/pizza-e-vino-showcase/pom.xml b/pizza-e-vino-showcase/pom.xml new file mode 100644 index 0000000..3af424f --- /dev/null +++ b/pizza-e-vino-showcase/pom.xml @@ -0,0 +1,117 @@ + + + 4.0.0 + io.miragon.miranum.consulting + pizza-e-vino-showcase + pizza-e-vino-showcase + 0.1.0-SNAPSHOT + pom + + + 17 + 17 + 17 + UTF-8 + 2.7.8 + 7.18.0 + 8.1.4 + 3.8.1 + 1.18.26 + + + + checkout + cooking + service-sync + service-async + + + + + + org.springframework.boot + spring-boot-dependencies + ${spring.boot.version} + pom + import + + + + + + + + org.springframework.boot + spring-boot-starter + + + org.springframework.boot + spring-boot-starter-web + + + io.miragon.miranum + json-api + ${project.version} + + + org.projectlombok + lombok + ${lombok.version} + provided + + + + + + + + org.apache.maven.plugins + maven-clean-plugin + 3.2.0 + + + org.apache.maven.plugins + maven-jar-plugin + 3.3.0 + + + org.apache.maven.plugins + maven-resources-plugin + 3.3.0 + + UTF-8 + + + + org.apache.maven.plugins + maven-install-plugin + 3.1.0 + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.1.0 + + + enforce-maven + + enforce + + + + + 11 + + + 3.6.0 + + + + + + + + + + diff --git a/pizza-e-vino-showcase/service-async/pom.xml b/pizza-e-vino-showcase/service-async/pom.xml new file mode 100644 index 0000000..b4b5081 --- /dev/null +++ b/pizza-e-vino-showcase/service-async/pom.xml @@ -0,0 +1,34 @@ + + + + service-async + service-async + 4.0.0 + jar + + + io.miragon.miranum.consulting + pizza-e-vino-showcase + 0.1.0-SNAPSHOT + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-test + test + + + io.camunda + spring-zeebe-starter + 8.1.13 + + + + diff --git a/pizza-e-vino-showcase/service-async/src/main/java/hello/Application.java b/pizza-e-vino-showcase/service-async/src/main/java/hello/Application.java new file mode 100644 index 0000000..f7b32a9 --- /dev/null +++ b/pizza-e-vino-showcase/service-async/src/main/java/hello/Application.java @@ -0,0 +1,16 @@ +package hello; + +import io.camunda.zeebe.spring.client.EnableZeebeClient; +import io.camunda.zeebe.spring.client.annotation.Deployment; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +@EnableZeebeClient +@Deployment(resources = {"classpath:/howAreYou.bpmn"}) +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } +} diff --git a/pizza-e-vino-showcase/service-async/src/main/java/hello/ServiceController.java b/pizza-e-vino-showcase/service-async/src/main/java/hello/ServiceController.java new file mode 100644 index 0000000..fc2fd38 --- /dev/null +++ b/pizza-e-vino-showcase/service-async/src/main/java/hello/ServiceController.java @@ -0,0 +1,37 @@ +package hello; + +import hello.service.OrderMessageRequest; +import io.camunda.zeebe.spring.client.lifecycle.ZeebeClientLifecycle; +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; + +import java.util.HashMap; +import java.util.Map; + +@RestController +public class ServiceController { + @Autowired + private ZeebeClientLifecycle zeebeClient; + + @RequestMapping(value = "/orderUp", method = RequestMethod.POST) + public String index(@RequestBody OrderMessageRequest orderMessageRequest){ + + System.out.println("Got this message for Mike: " + orderMessageRequest.orderMessage); + Map vars = new HashMap(); + + vars.put("orderMessage", orderMessageRequest.orderMessage.toLowerCase()); + vars.put("businessKey", orderMessageRequest.orderName); + + + zeebeClient.newCreateInstanceCommand() + .bpmnProcessId("ProcessOrder") + .latestVersion() + .variables(vars) + .send(); + + return "Your Order is being Taken Care of"; + } +} diff --git a/pizza-e-vino-showcase/service-async/src/main/java/hello/service/OrderMessageRequest.java b/pizza-e-vino-showcase/service-async/src/main/java/hello/service/OrderMessageRequest.java new file mode 100644 index 0000000..e701078 --- /dev/null +++ b/pizza-e-vino-showcase/service-async/src/main/java/hello/service/OrderMessageRequest.java @@ -0,0 +1,6 @@ +package hello.service; + +public class OrderMessageRequest { + public String orderMessage; + public String orderName; +} diff --git a/pizza-e-vino-showcase/service-async/src/main/java/hello/service/SortPizzaOrderService.java b/pizza-e-vino-showcase/service-async/src/main/java/hello/service/SortPizzaOrderService.java new file mode 100644 index 0000000..0c7e685 --- /dev/null +++ b/pizza-e-vino-showcase/service-async/src/main/java/hello/service/SortPizzaOrderService.java @@ -0,0 +1,38 @@ +package hello.service; + +import io.camunda.zeebe.spring.client.annotation.JobWorker; +import io.camunda.zeebe.spring.client.annotation.Variable; +import io.camunda.zeebe.spring.client.exception.ZeebeBpmnError; +import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.stereotype.Component; +import org.springframework.web.client.RestTemplate; + +import java.net.URI; +import java.util.Random; + +@Component(value = "sortPizzaOrder") +public class SortPizzaOrderService { + private final RestTemplate restTemplate; + + public SortPizzaOrderService(RestTemplateBuilder restTemplateBuilder) { + this.restTemplate = restTemplateBuilder.build(); + } + + @JobWorker(type = "sortPizzaOrder", fetchAllVariables = true) + public void sortPizzaOrder(@Variable String orderMessage) throws Exception { + Random random = new Random(); + + if(orderMessage.contains("hawaii") && random.nextBoolean()){ + Thread.sleep(10000); + throw new ZeebeBpmnError("DOESNT_WORK", "We do not have any pineapples"); + } else { + if (orderMessage.toLowerCase().contains("pizza")) { + URI uri = URI.create("http://localhost:8081/WorkIt/"); + OrderMessageRequest request = new OrderMessageRequest(); + request.orderMessage = orderMessage; + restTemplate.put(uri, request); + System.out.println("I've sent an order for Pizza"); + } + } + } +} diff --git a/pizza-e-vino-showcase/service-async/src/main/java/hello/service/SortVinoOrderService.java b/pizza-e-vino-showcase/service-async/src/main/java/hello/service/SortVinoOrderService.java new file mode 100644 index 0000000..19d6fe5 --- /dev/null +++ b/pizza-e-vino-showcase/service-async/src/main/java/hello/service/SortVinoOrderService.java @@ -0,0 +1,27 @@ +package hello.service; + +import io.camunda.zeebe.spring.client.annotation.JobWorker; +import io.camunda.zeebe.spring.client.annotation.Variable; +import org.springframework.stereotype.Component; + +@Component(value = "sortVinoOrder") +public class SortVinoOrderService { + + long waitTimeMillis = 1000; + + @JobWorker(type = "sortVinoOrder", fetchAllVariables = true) + public void sortVinoOrder(@Variable String orderMessage) throws Exception { + if(orderMessage.toLowerCase().contains("vino")){ + int loops = 3; + System.out.println("We're Working on getting you Vino! -- "+ orderMessage ); + while(loops >= 0) { + System.out.print(".."); + Thread.sleep(waitTimeMillis); + loops--; + } + System.out.println(); + System.out.println("Vino is up -- "+ orderMessage ); + } + System.out.println("All good - order is complete"); + } +} diff --git a/pizza-e-vino-showcase/service-async/src/main/java/hello/service/TellCeckoutSomething.java b/pizza-e-vino-showcase/service-async/src/main/java/hello/service/TellCeckoutSomething.java new file mode 100644 index 0000000..93dee51 --- /dev/null +++ b/pizza-e-vino-showcase/service-async/src/main/java/hello/service/TellCeckoutSomething.java @@ -0,0 +1,28 @@ +package hello.service; + +import io.camunda.zeebe.spring.client.annotation.JobWorker; +import io.camunda.zeebe.spring.client.annotation.Variable; +import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.stereotype.Component; +import org.springframework.web.client.RestTemplate; + +import java.net.URI; + +@Component(value = "tellCheckoutAboutOrder") +public class TellCeckoutSomething { + private final RestTemplate restTemplate; + + public TellCeckoutSomething(RestTemplateBuilder restTemplateBuilder) { + this.restTemplate = restTemplateBuilder.build(); + } + + @JobWorker(type = "tellCheckout") + public void tellCheckoutAboutOrder(@Variable String message, @Variable String orderMessage, @Variable String businessKey) throws Exception { + URI uri = URI.create("http://localhost:8082/messageForCheckout/"); + OrderMessageRequest request = new OrderMessageRequest(); + request.orderMessage = message + " from order " +orderMessage; + request.orderName = businessKey; + restTemplate.put(uri, request); + System.out.println(businessKey + " Ready!"); + } +} diff --git a/pizza-e-vino-showcase/service-async/src/main/resources/META-INF/processes.xml b/pizza-e-vino-showcase/service-async/src/main/resources/META-INF/processes.xml new file mode 100644 index 0000000..e69de29 diff --git a/pizza-e-vino-showcase/service-async/src/main/resources/application.yaml b/pizza-e-vino-showcase/service-async/src/main/resources/application.yaml new file mode 100644 index 0000000..26f64d5 --- /dev/null +++ b/pizza-e-vino-showcase/service-async/src/main/resources/application.yaml @@ -0,0 +1,9 @@ +server: + port : 8080 +zeebe: + client: + cloud: + region: dsm-1 + clusterId: 706801a4-f288-4cbe-ba94-4626af466953 + clientId: A_9JjyOngYp-v-9tYdmbogCT7UHw_1ur + clientSecret: _NjczgYy5Y3FLUhEtb24BkIXvmWHlQ2Bna7ZWFBiofvEP1wlDZiW1Bi~GYvNaLnp \ No newline at end of file diff --git a/pizza-e-vino-showcase/service-async/src/main/resources/howAreYou.bpmn b/pizza-e-vino-showcase/service-async/src/main/resources/howAreYou.bpmn new file mode 100644 index 0000000..466ec81 --- /dev/null +++ b/pizza-e-vino-showcase/service-async/src/main/resources/howAreYou.bpmn @@ -0,0 +1,283 @@ + + + + + SequenceFlow_0x4prne + + + + + + + + + + SequenceFlow_1qfb9qb + SequenceFlow_1h66828 + + + SequenceFlow_0nhi2ol + + + + + + + + + SequenceFlow_0mpy8jg + SequenceFlow_0kmu169 + + + =contains(orderMessage, "vino") + + + =contains(orderMessage,"pizza") + + + + + + Pick Up Your Coffee + + + + + + + + + + SequenceFlow_0kmu169 + SequenceFlow_03xrlbw + + + + SequenceFlow_03xrlbw + + + + + + + Pick Up Your Cake + + + + + + + + + + SequenceFlow_1h66828 + SequenceFlow_0nhi2ol + + + SequenceFlow_0x4prne + SequenceFlow_1qfb9qb + SequenceFlow_0mpy8jg + SequenceFlow_1fyttf0 + + + SequenceFlow_05ezm3n + + + + + + + OUT OF STOCK! + + + + + + + SequenceFlow_1fyttf0 + SequenceFlow_05ezm3n + + + SequenceFlow_1f09yfs + + + + + + + + No Soya and so No Coffee + + + + + + + SequenceFlow_1f09yfs + SequenceFlow_1w55jm1 + + + + SequenceFlow_1pfyin1 + + PT30S + + + + + SequenceFlow_0rpjv91 + + + + + + Your order is taking a little longer + + + + + + + + + + SequenceFlow_1pfyin1 + SequenceFlow_0rpjv91 + + + + SequenceFlow_1w55jm1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pizza-e-vino-showcase/service-sync/pom.xml b/pizza-e-vino-showcase/service-sync/pom.xml new file mode 100644 index 0000000..981e66c --- /dev/null +++ b/pizza-e-vino-showcase/service-sync/pom.xml @@ -0,0 +1,29 @@ + + + + service-sync + service-sync + 4.0.0 + jar + + + io.miragon.miranum.consulting + pizza-e-vino-showcase + 0.1.0-SNAPSHOT + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-test + test + + + + diff --git a/pizza-e-vino-showcase/service-sync/src/main/java/hello/Application.java b/pizza-e-vino-showcase/service-sync/src/main/java/hello/Application.java new file mode 100644 index 0000000..2eaac3d --- /dev/null +++ b/pizza-e-vino-showcase/service-sync/src/main/java/hello/Application.java @@ -0,0 +1,11 @@ +package hello; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } +} diff --git a/pizza-e-vino-showcase/service-sync/src/main/java/hello/ServiceController.java b/pizza-e-vino-showcase/service-sync/src/main/java/hello/ServiceController.java new file mode 100644 index 0000000..76bf31d --- /dev/null +++ b/pizza-e-vino-showcase/service-sync/src/main/java/hello/ServiceController.java @@ -0,0 +1,39 @@ +package hello; + +import hello.service.OrderMessageRequest; +import hello.service.SortPizzaOrderService; +import hello.service.SortVinoOrderService; +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 ServiceController { + + @Autowired + SortVinoOrderService sortVinoOrder; + + @Autowired + SortPizzaOrderService sortPizzaOrder; + + @RequestMapping(value = "/orderUp", method = RequestMethod.POST) + public String index(@RequestBody OrderMessageRequest orderMessageRequest) throws Exception { + + System.out.println("Got this message for Mike: " + orderMessageRequest.orderMessage); + // Map vars = new HashMap(); + String orderMessage = ""; + + if(orderMessageRequest.orderMessage.toLowerCase().contains("vino")){ + orderMessage = orderMessage + " Vino "; + sortVinoOrder.execute(); + } + if(orderMessageRequest.orderMessage.toLowerCase().contains("pizza")){ + orderMessage = orderMessage + " Pizza "; + sortPizzaOrder.execute(); + } + + return "Order of " + orderMessage + " Is Ready"; + } +} diff --git a/pizza-e-vino-showcase/service-sync/src/main/java/hello/service/OrderMessageRequest.java b/pizza-e-vino-showcase/service-sync/src/main/java/hello/service/OrderMessageRequest.java new file mode 100644 index 0000000..e701078 --- /dev/null +++ b/pizza-e-vino-showcase/service-sync/src/main/java/hello/service/OrderMessageRequest.java @@ -0,0 +1,6 @@ +package hello.service; + +public class OrderMessageRequest { + public String orderMessage; + public String orderName; +} diff --git a/pizza-e-vino-showcase/service-sync/src/main/java/hello/service/SortPizzaOrderService.java b/pizza-e-vino-showcase/service-sync/src/main/java/hello/service/SortPizzaOrderService.java new file mode 100644 index 0000000..8d43add --- /dev/null +++ b/pizza-e-vino-showcase/service-sync/src/main/java/hello/service/SortPizzaOrderService.java @@ -0,0 +1,26 @@ +package hello.service; + +import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.stereotype.Component; +import org.springframework.web.client.RestTemplate; + +import java.net.URI; + +@Component(value = "sortPizzaOrder") +public class SortPizzaOrderService { + private final RestTemplate restTemplate; + + public SortPizzaOrderService(RestTemplateBuilder restTemplateBuilder) { + this.restTemplate = restTemplateBuilder.build(); + } + + public void execute(){ + String message = "Pizza Needed"; + + URI uri = URI.create("http://localhost:8081/WorkIt/"); + OrderMessageRequest request = new OrderMessageRequest(); + request.orderMessage = message; + restTemplate.put(uri, request); + System.out.println("I've sent an order for Pizza"); + } +} diff --git a/pizza-e-vino-showcase/service-sync/src/main/java/hello/service/SortVinoOrderService.java b/pizza-e-vino-showcase/service-sync/src/main/java/hello/service/SortVinoOrderService.java new file mode 100644 index 0000000..8b9be8a --- /dev/null +++ b/pizza-e-vino-showcase/service-sync/src/main/java/hello/service/SortVinoOrderService.java @@ -0,0 +1,32 @@ +package hello.service; + +import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.stereotype.Component; +import org.springframework.web.client.RestTemplate; + +@Component(value = "sortVinoOrder") +public class SortVinoOrderService { + private final RestTemplate restTemplate; + + public SortVinoOrderService(RestTemplateBuilder restTemplateBuilder) { + this.restTemplate = restTemplateBuilder.build(); + } + + long waitTimeMillis = 1000; + + public void execute() throws InterruptedException { + + int loops = 3; + System.out.println("We're Working on getting you Vino! -- " ); + while(loops >= 0) { + System.out.print(".."); + Thread.sleep(waitTimeMillis); + loops--; + } + System.out.println(); + System.out.println("Vino is up -- " ); + + System.out.println("All good - order is complete"); + } +} + diff --git a/pizza-e-vino-showcase/service-sync/src/main/resources/application.yaml b/pizza-e-vino-showcase/service-sync/src/main/resources/application.yaml new file mode 100644 index 0000000..26f64d5 --- /dev/null +++ b/pizza-e-vino-showcase/service-sync/src/main/resources/application.yaml @@ -0,0 +1,9 @@ +server: + port : 8080 +zeebe: + client: + cloud: + region: dsm-1 + clusterId: 706801a4-f288-4cbe-ba94-4626af466953 + clientId: A_9JjyOngYp-v-9tYdmbogCT7UHw_1ur + clientSecret: _NjczgYy5Y3FLUhEtb24BkIXvmWHlQ2Bna7ZWFBiofvEP1wlDZiW1Bi~GYvNaLnp \ No newline at end of file diff --git a/pizza-e-vino-showcase/service-sync/src/main/resources/orderProcess.bpmn b/pizza-e-vino-showcase/service-sync/src/main/resources/orderProcess.bpmn new file mode 100644 index 0000000..bdc71eb --- /dev/null +++ b/pizza-e-vino-showcase/service-sync/src/main/resources/orderProcess.bpmn @@ -0,0 +1,215 @@ + + + + + SequenceFlow_1vnwn5v + + + + =contains(message, "vino") + + + =contains(message, "pizza") + + + SequenceFlow_1vnwn5v + SequenceFlow_11iviyz + SequenceFlow_1s1ulcw + SequenceFlow_0s4a5m7 + + + SequenceFlow_0l5ijsy + + + + SequenceFlow_1pp61vh + + + + + + + + + + SequenceFlow_11iviyz + SequenceFlow_0iknyyp + + + + R4/PT1M + + + + + + SequenceFlow_1s1ulcw + SequenceFlow_19gzhs3 + + + SequenceFlow_0s4a5m7 + + + + + + + Cake is Ready + + + + + + + SequenceFlow_0iknyyp + SequenceFlow_0l5ijsy + + + + + + Coffee Is Ready + + + + + + + SequenceFlow_19gzhs3 + SequenceFlow_1pp61vh + + + + SequenceFlow_1y6735k + + PT30S + + + + + SequenceFlow_0zpw7u4 + + + + + + The order is taking longer than we thought + + + + + + + SequenceFlow_1y6735k + SequenceFlow_0zpw7u4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pizza-order-showcase/kitchen/kitchen-core/pom.xml b/pizza-order-showcase/kitchen/kitchen-core/pom.xml index a2f8b2c..44596f5 100644 --- a/pizza-order-showcase/kitchen/kitchen-core/pom.xml +++ b/pizza-order-showcase/kitchen/kitchen-core/pom.xml @@ -18,12 +18,12 @@ org.springframework.boot spring-boot-starter - org.springframework.boot spring-boot-starter-test test + io.miragon.miranum worker-api diff --git a/pizza-order-showcase/waiter/waiter-core/pom.xml b/pizza-order-showcase/waiter/waiter-core/pom.xml index c3cfc3e..b1e93e9 100644 --- a/pizza-order-showcase/waiter/waiter-core/pom.xml +++ b/pizza-order-showcase/waiter/waiter-core/pom.xml @@ -32,7 +32,7 @@ io.miragon.miranum process-api - 0.1.0-SNAPSHOT + ${project.version} compile diff --git a/pom.xml b/pom.xml index 4e7708a..8df09c8 100644 --- a/pom.xml +++ b/pom.xml @@ -12,6 +12,7 @@ pizza-order-showcase + pizza-e-vino-showcase process-example schema-client-example