diff --git a/scs-101/.gitignore b/scs-100-2/.gitignore similarity index 100% rename from scs-101/.gitignore rename to scs-100-2/.gitignore diff --git a/scs-100-2/README.md b/scs-100-2/README.md new file mode 100644 index 0000000..5f8a65f --- /dev/null +++ b/scs-100-2/README.md @@ -0,0 +1,58 @@ +# SCS-100-2 + +## Functional Programming (For Alternative of SCS-100 Project) + +A simple Example of an Event Driven Flow by the help of **SPRING CLOUD STREAM KAFKA** + +##### properties + +* java.version: `11` +* spring-cloud.version: `2020.0.3` +* spring-boot.version: `2.5.2` + +![General Flow Diagram](material/kafka-events-intro-100.svg) + +The Docker-compose file contains: single kafka and zookeeper. just simply run the following command + +```shell +docker-compose up -d +``` + +_Note: I assume you already have docker setup in your machine._ + +### Make the project + +run the following command line to create you jar file in `target` directory + +```shell +mvn clean package +``` + +Then run the generated jar file in `target` folder, (so make sure you are in the same directory when you run the jar file +or give the full path) + +```shell +java -jar scs-100-0.0.1-SNAPSHOT.jar +``` + +the application starts to listen on port 8080. make sure that port not being occupied by any other app already, if is try +to pass the following parameter before `-jar` by adding `-Dserver.port=8081` as: + +```shell +java -Dserver.port=8081 -jar scs-100-0.0.1-SNAPSHOT.jar +``` + +_Note: you can also modify the application.yml and set the same properties based on your app profile_ + +At this point you should have already seen the information about your topics. + +### Check Application + +#### Create Order or Place your Order +you should now be able to place your order by calling the following `curl` command + +```shell +# assuming your app is listening on 8080 +ORDER_UUID=$(curl --silent -H 'Content-Type: application/json' -d "{\"itemName\":\"book\"}" http://localhost:8080/order | jq -r '.orderUuid') && for i in `seq 1 15`; do echo $(curl --silent "http://localhost:8080/order/status/"$ORDER_UUID); sleep 1; done; +``` +Note: make sure you have already installed the `jq` diff --git a/scs-100-2/docker-compose.yml b/scs-100-2/docker-compose.yml new file mode 100644 index 0000000..347e011 --- /dev/null +++ b/scs-100-2/docker-compose.yml @@ -0,0 +1,19 @@ +version: '3' +services: + kafka: + image: wurstmeister/kafka + container_name: kafka-mc + ports: + - "9092:9092" + environment: + - KAFKA_ADVERTISED_HOST_NAME=127.0.0.1 + - KAFKA_ADVERTISED_PORT=9092 + - KAFKA_ZOOKEEPER_CONNECT=zookeeper:2181 + depends_on: + - zookeeper + zookeeper: + image: wurstmeister/zookeeper + ports: + - "2181:2181" + environment: + - KAFKA_ADVERTISED_HOST_NAME=zookeeper diff --git a/scs-101/pom.xml b/scs-100-2/pom.xml similarity index 59% rename from scs-101/pom.xml rename to scs-100-2/pom.xml index 6bf4286..a5e9f0d 100644 --- a/scs-101/pom.xml +++ b/scs-100-2/pom.xml @@ -6,39 +6,37 @@ org.springframework.boot spring-boot-starter-parent - 2.4.5 + 2.5.2 + - com.example - scs-101 + com.ehsaniara.scs_kafka_intro + scs-100-2 0.0.1-SNAPSHOT - scs-101 - pom + scs-100-2 Demo project for Spring Boot - - scs-101-commons - scs-101-producer - scs-101-consumer - - 11 - 2020.0.2 + 2020.0.3 ${project.parent.version} - + - org.springframework.cloud - spring-cloud-stream + org.springframework.boot + spring-boot-starter org.springframework.boot - spring-boot-configuration-processor - true + spring-boot-starter-web + + + + org.springframework.cloud + spring-cloud-stream-binder-kafka-streams @@ -47,19 +45,6 @@ true - - org.springframework.boot - spring-boot-starter-test - test - - - - org.springframework.cloud - spring-cloud-stream - test - test-binder - test-jar - @@ -74,4 +59,23 @@ + + + + org.springframework.boot + spring-boot-maven-plugin + ${spring-boot.version} + + + + org.projectlombok + lombok + + + + + + + + diff --git a/scs-100-2/src/main/java/com/ehsaniara/scs_kafka_intro/scs1002/Application.java b/scs-100-2/src/main/java/com/ehsaniara/scs_kafka_intro/scs1002/Application.java new file mode 100644 index 0000000..edcc2f1 --- /dev/null +++ b/scs-100-2/src/main/java/com/ehsaniara/scs_kafka_intro/scs1002/Application.java @@ -0,0 +1,24 @@ +package com.ehsaniara.scs_kafka_intro.scs1002; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.kafka.common.serialization.Serde; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.kafka.support.serializer.JsonSerde; + +@SpringBootApplication +public class Application { + + final static String STATE_STORE_NAME = "scs-100-2-order-events"; + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + + @Bean + public Serde orderJsonSerde() { + return new JsonSerde<>(Order.class, new ObjectMapper()); + } + +} diff --git a/scs-100-2/src/main/java/com/ehsaniara/scs_kafka_intro/scs1002/Order.java b/scs-100-2/src/main/java/com/ehsaniara/scs_kafka_intro/scs1002/Order.java new file mode 100644 index 0000000..973ef1c --- /dev/null +++ b/scs-100-2/src/main/java/com/ehsaniara/scs_kafka_intro/scs1002/Order.java @@ -0,0 +1,23 @@ +package com.ehsaniara.scs_kafka_intro.scs1002; + +import lombok.*; + +import javax.validation.constraints.NotBlank; +import java.io.Serializable; +import java.util.UUID; + +@ToString +@Builder +@Setter +@Getter +@AllArgsConstructor +@NoArgsConstructor +public class Order implements Serializable { + + private UUID orderUuid; + + @NotBlank + private String itemName; + + private OrderStatus orderStatus; +} diff --git a/scs-100-2/src/main/java/com/ehsaniara/scs_kafka_intro/scs1002/OrderNotFoundException.java b/scs-100-2/src/main/java/com/ehsaniara/scs_kafka_intro/scs1002/OrderNotFoundException.java new file mode 100644 index 0000000..7b81461 --- /dev/null +++ b/scs-100-2/src/main/java/com/ehsaniara/scs_kafka_intro/scs1002/OrderNotFoundException.java @@ -0,0 +1,11 @@ +package com.ehsaniara.scs_kafka_intro.scs1002; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(value = HttpStatus.NOT_FOUND) +public class OrderNotFoundException extends RuntimeException { + public OrderNotFoundException(String msg) { + super(msg); + } +} diff --git a/scs-100-2/src/main/java/com/ehsaniara/scs_kafka_intro/scs1002/OrderStatus.java b/scs-100-2/src/main/java/com/ehsaniara/scs_kafka_intro/scs1002/OrderStatus.java new file mode 100644 index 0000000..bf14290 --- /dev/null +++ b/scs-100-2/src/main/java/com/ehsaniara/scs_kafka_intro/scs1002/OrderStatus.java @@ -0,0 +1,18 @@ +package com.ehsaniara.scs_kafka_intro.scs1002; + +import lombok.AllArgsConstructor; + +@AllArgsConstructor +public enum OrderStatus { + PENDING("PENDING"), + INVENTORY_CHECKING("INVENTORY_CHECKING"), + OUT_OF_STOCK("OUT_OF_STOCK"), + SHIPPED("SHIPPED"), + CANCELED("CANCELED"); + + private final String name; + + public String toString() { + return this.name; + } +}