Skip to content
Spring Boot/Kafka/Mongo Microservice, part of a set of microservices for this project
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
.idea
Docker
gradle/wrapper
src/main
.DS_Store
.gitignore
LICENSE
README.md
build.gradle
gradlew
gradlew.bat
settings.gradle

README.md

Kafka Traveler Microservices Demo: Fulfillment

Fulfillment Service

Spring Boot/Kafka/Mongo Microservice, one of a set of microservices for this project. Services use Spring Kafka 2.1.6 to maintain eventually consistent data between their different Customer domain objects.

Originally code based on the post, Spring Kafka - JSON Serializer Deserializer Example, from the CodeNotFound.com Blog.

Development

For Kakfa, use garystafford/kafka-docker project, a clone of the wurstmeister/kafka-docker project. The garystafford/kafka-docker local docker-compose file builds a Kafka, Kafka Manager, ZooKeeper, MongoDB, Eureka Server, and Zuul.

Commands

I develop and debug directly from JetBrains IntelliJ. The default Spring profile will start the three services on different ports.

./gradlew clean build bootRun

Creating Sample Data

Create sample data for each service. Requires Kafka is running. Endpoints for Zuul, when using Docker Swarm/Stack, are different. See this Python script for Zuul endpoints.

# accounts - create sample customer accounts
http http://localhost:8085/customers/sample

# orders - add sample orders to each customer
http http://localhost:8090/customers/sample/orders

# orders - send approved orders to fulfillment service
http http://localhost:8090/customers/sample/fulfill

# fulfillment - change fulfillment requests from approved to processing
http http://localhost:8095/fulfillment/sample/process

# fulfillment - change fulfillment requests from processing to shipping
http http://localhost:8095/fulfillment/sample/ship

# fulfillment - change fulfillment requests from processing to in transit
http http://localhost:8095/fulfillment/sample/in-transit

# fulfillment - change fulfillment requests from in transit to in received
http http://localhost:8095/fulfillment/sample/receive

Container Infrastructure

$ docker container ls

CONTAINER ID        IMAGE                                        COMMAND                  CREATED             STATUS              PORTS                                  NAMES
ccf0e9a0637d        garystafford/storefront-fulfillment:latest   "java -jar -Djava.se…"   11 minutes ago      Up 11 minutes       8080/tcp                               storefront_fulfillment.1.0mht01m6nk461q7mt1ey4zsjb
f8a4654183cb        hlebalbau/kafka-manager:latest               "/kafka-manager/bin/…"   11 minutes ago      Up 11 minutes                                              storefront_kafka_manager.1.so9h6c8veemrwlznj5zdk3sdw
fe6579d68846        garystafford/storefront-accounts:latest      "java -jar -Djava.se…"   11 minutes ago      Up 11 minutes       8080/tcp                               storefront_accounts.1.nafdn02w68nixyvmz7l46kzcq
2495802b640b        garystafford/storefront-eureka:latest        "java -jar -Djava.se…"   11 minutes ago      Up 11 minutes       8761/tcp                               storefront_eureka.1.x2tu8vg1dnizx61lwnudrnsml
5afe1e94162f        wurstmeister/kafka:latest                    "start-kafka.sh"         12 minutes ago      Up 11 minutes                                              storefront_kafka.1.n55qrkbqfueg1sgz0fb9h47qu
44a9d4dbdc4b        mongo:latest                                 "docker-entrypoint.s…"   12 minutes ago      Up 11 minutes       27017/tcp                              storefront_mongo.1.tfy3u2zi4bpcmb7372ihdjmbc
23be66801ebc        garystafford/storefront-orders:latest        "java -jar -Djava.se…"   12 minutes ago      Up 11 minutes       8080/tcp                               storefront_orders.1.bo5hfnqb9ijbfd7vp88hcs3vn
bbe4dbe00048        wurstmeister/zookeeper:latest                "/bin/sh -c '/usr/sb…"   12 minutes ago      Up 12 minutes       22/tcp, 2181/tcp, 2888/tcp, 3888/tcp   storefront_zookeeper.1.ipfwro51ob6fpls26bk14lvkt
98b8084f0162        garystafford/storefront-zuul:latest          "java -jar -Djava.se…"   12 minutes ago      Up 12 minutes       8761/tcp                               storefront_zuul.1.u4h4bxp01mcwetyoezk19ljzt

Orders Customer Object in MongoDB

docker exec -it $(docker ps | grep storefront_mongo | awk '{print $NF}') sh
mongo
use fulfillment
db.fulfillment.requests.find().pretty()
db.fulfillment.requests.remove({})
{
	"_id" : ObjectId("5b18878ca8d05609e6ff1851"),
	"timestamp" : NumberLong("1528334218838"),
	"name" : {
		"title" : "Ms.",
		"firstName" : "Susan",
		"lastName" : "Blackstone"
	},
	"contact" : {
		"primaryPhone" : "433-544-6555",
		"secondaryPhone" : "223-445-6767",
		"email" : "susan.m.blackstone@emailisus.com"
	},
	"address" : {
		"type" : "SHIPPING",
		"description" : "Home Sweet Home",
		"address1" : "33 Oak Avenue",
		"city" : "Nowhere",
		"state" : "VT",
		"postalCode" : "444556-9090"
	},
	"order" : {
		"guid" : "f52e2930-ef31-44db-a53c-b7ba4ae3f5cf",
		"orderStatusEvents" : [
			{
				"timestamp" : NumberLong("1528334457603"),
				"orderStatusType" : "COMPLETED"
			}
		],
		"orderItems" : [
			{
				"product" : {
					"guid" : "d01fde07-7c24-49c5-a5f1-bc2ce1f14c48",
					"title" : "Red Widget"
				},
				"quantity" : 2
			},
			{
				"product" : {
					"guid" : "4efe33a1-722d-48c8-af8e-7879edcad2fa",
					"title" : "Purple Widget"
				},
				"quantity" : 5
			}
		]
	},
	"shippingMethod" : "FedEx",
	"shippingStatusEvents" : [
		{
			"timestamp" : NumberLong("1528334457603"),
			"shippingStatusType" : "SHIPPED"
		},
		{
			"timestamp" : NumberLong("1528334457603"),
			"shippingStatusType" : "IN_TRANSIT"
		},
		{
			"timestamp" : NumberLong("1528334457603"),
			"shippingStatusType" : "RECEIVED"
		}
	],
	"_class" : "com.storefront.model.FulfillmentRequestEvent"
}

Current Results

Output from application, on the orders.order.fulfill topic

2018-06-06 21:20:57.519  INFO [-,46fcaf5802394709,46fcaf5802394709,false] 2534 --- [nio-8095-exec-2] c.storefront.handler.AfterSaveListener   : onAfterSave event='org.springframework.data.mongodb.core.mapping.event.AfterSaveEvent[source=FulfillmentRequest(id=5b18878ba8d05609e6ff1849, timestamp=1528334218543, name=Name(title=Mr., firstName=John, middleName=S., lastName=Doe, suffix=Jr.), contact=Contact(primaryPhone=555-666-7777, secondaryPhone=555-444-9898, email=john.doe@internet.com), address=Address(type=SHIPPING, description=My home address, address1=123 Oak Street, address2=null, city=Sunrise, state=CA, postalCode=12345-6789), order=Order(guid=ef8572ad-1e21-41ed-9f4d-7a908c0d0b9b, orderStatusEvents=[OrderStatusEvent(timestamp=1528334457507, orderStatusType=COMPLETED, note=null)], orderItems=[OrderItem(product=Product(guid=7f3c9c22-3c0a-47a5-9a92-2bd2e23f6e37, title=Green Widget), quantity=5), OrderItem(product=Product(guid=f3b9bdce-10d8-4c22-9861-27149879b3c1, title=Orange Widget), quantity=3), OrderItem(product=Product(guid=4efe33a1-722d-48c8-af8e-7879edcad2fa, title=Purple Widget), quantity=5)]), shippingMethod=FedEx, shippingStatusEvents=[ShippingStatusEvent(timestamp=1528334457507, shippingStatusType=SHIPPED, note=null), ShippingStatusEvent(timestamp=1528334457507, shippingStatusType=IN_TRANSIT, note=null), ShippingStatusEvent(timestamp=1528334457507, shippingStatusType=RECEIVED, note=null)])]'
2018-06-06 21:20:57.520  INFO [-,46fcaf5802394709,46fcaf5802394709,false] 2534 --- [nio-8095-exec-2] com.storefront.kafka.Sender              : sending payload='OrderStatusEventChange(guid=ef8572ad-1e21-41ed-9f4d-7a908c0d0b9b, orderStatusEvent=OrderStatusEvent(timestamp=1528334457507, orderStatusType=COMPLETED, note=null))' to topic='fulfillment.order.change'
2018-06-06 21:20:57.524  INFO [-,46fcaf5802394709,46fcaf5802394709,false] 2534 --- [nio-8095-exec-2] c.storefront.handler.AfterSaveListener   : onAfterSave event='org.springframework.data.mongodb.core.mapping.event.AfterSaveEvent[source=FulfillmentRequest(id=5b18878ba8d05609e6ff184a, timestamp=1528334218805, name=Name(title=Ms., firstName=Mary, middleName=null, lastName=Smith, suffix=null), contact=Contact(primaryPhone=456-789-0001, secondaryPhone=456-222-1111, email=marysmith@yougotmail.com), address=Address(type=SHIPPING, description=Home Sweet Home, address1=1234 Main Street, address2=null, city=Anywhere, state=NY, postalCode=45455-66677), order=Order(guid=6d8a81e5-23dc-4ec5-8488-c7519c890ae1, orderStatusEvents=[OrderStatusEvent(timestamp=1528334457521, orderStatusType=COMPLETED, note=null)], orderItems=[OrderItem(product=Product(guid=b506b962-fcfa-4ad6-a955-8859797edf16, title=Black Widget), quantity=2), OrderItem(product=Product(guid=f3b9bdce-10d8-4c22-9861-27149879b3c1, title=Orange Widget), quantity=4)]), shippingMethod=FedEx, shippingStatusEvents=[ShippingStatusEvent(timestamp=1528334457521, shippingStatusType=SHIPPED, note=null), ShippingStatusEvent(timestamp=1528334457521, shippingStatusType=IN_TRANSIT, note=null), ShippingStatusEvent(timestamp=1528334457521, shippingStatusType=RECEIVED, note=null)])]'
2018-06-06 21:20:57.525  INFO [-,46fcaf5802394709,46fcaf5802394709,false] 2534 --- [nio-8095-exec-2] com.storefront.kafka.Sender              : sending payload='OrderStatusEventChange(guid=6d8a81e5-23dc-4ec5-8488-c7519c890ae1, orderStatusEvent=OrderStatusEvent(timestamp=1528334457521, orderStatusType=COMPLETED, note=null))' to topic='fulfillment.order.change'
2018-06-06 21:20:57.534  INFO [-,46fcaf5802394709,46fcaf5802394709,false] 2534 --- [nio-8095-exec-2] c.storefront.handler.AfterSaveListener   : onAfterSave event='org.springframework.data.mongodb.core.mapping.event.AfterSaveEvent[source=FulfillmentRequest(id=5b18878ca8d05609e6ff184b, timestamp=1528334218806, name=Name(title=Ms., firstName=Susan, middleName=null, lastName=Blackstone, suffix=null), contact=Contact(primaryPhone=433-544-6555, secondaryPhone=223-445-6767, email=susan.m.blackstone@emailisus.com), address=Address(type=SHIPPING, description=Home Sweet Home, address1=33 Oak Avenue, address2=null, city=Nowhere, state=VT, postalCode=444556-9090), order=Order(guid=ffe75116-f72b-40c8-b819-b3cc0ad60b47, orderStatusEvents=[OrderStatusEvent(timestamp=1528334457525, orderStatusType=COMPLETED, note=null)], orderItems=[OrderItem(product=Product(guid=b506b962-fcfa-4ad6-a955-8859797edf16, title=Black Widget), quantity=2), OrderItem(product=Product(guid=f3b9bdce-10d8-4c22-9861-27149879b3c1, title=Orange Widget), quantity=2), OrderItem(product=Product(guid=d01fde07-7c24-49c5-a5f1-bc2ce1f14c48, title=Red Widget), quantity=5)]), shippingMethod=FedEx, shippingStatusEvents=[ShippingStatusEvent(timestamp=1528334457525, shippingStatusType=SHIPPED, note=null), ShippingStatusEvent(timestamp=1528334457525, shippingStatusType=IN_TRANSIT, note=null), ShippingStatusEvent(timestamp=1528334457525, shippingStatusType=RECEIVED, note=null)])]'

Output from Kafka container using the following command.

kafka-console-consumer.sh \
  --bootstrap-server localhost:9092 \
  --from-beginning --topic orders.order.fulfill

Kafka Consumer Output

{"timestamp":1528001014137,"name":{"title":"Mr.","firstName":"John","middleName":"S.","lastName":"Doe","suffix":"Jr."},"contact":{"primaryPhone":"555-666-7777","secondaryPhone":"555-444-9898","email":"john.doe@internet.com"},"address":{"type":"SHIPPING","description":"My home address","address1":"123 Oak Street","address2":null,"city":"Sunrise","state":"CA","postalCode":"12345-6789"},"order":{"guid":"617e9b8f-970c-487d-b4b7-faad870090c7","orderStatusEvents":[{"timestamp":1527996053859,"orderStatusType":"APPROVED","note":null}],"orderItems":[{"product":{"id":null,"guid":"f3b9bdce-10d8-4c22-9861-27149879b3c1","title":"Orange Widget","description":"Opulent Orange Widget","price":9.99},"quantity":3},{"product":{"id":null,"guid":"7f3c9c22-3c0a-47a5-9a92-2bd2e23f6e37","title":"Green Widget","description":"Gorgeous Green Widget","price":11.99},"quantity":4}]}}
{"timestamp":1528001014321,"name":{"title":"Ms.","firstName":"Mary","middleName":null,"lastName":"Smith","suffix":null},"contact":{"primaryPhone":"456-789-0001","secondaryPhone":"456-222-1111","email":"marysmith@yougotmail.com"},"address":{"type":"SHIPPING","description":"Home Sweet Home","address1":"1234 Main Street","address2":null,"city":"Anywhere","state":"NY","postalCode":"45455-66677"},"order":{"guid":"d51113cd-fbc1-45b3-b3e9-53b78d22b5bf","orderStatusEvents":[{"timestamp":1527996053859,"orderStatusType":"APPROVED","note":null}],"orderItems":[{"product":{"id":null,"guid":"a9d5a5c7-4245-4b4e-b1c3-1d3968f36b2d","title":"Yellow Widget","description":"Amazing Yellow Widget","price":5.99},"quantity":1},{"product":{"id":null,"guid":"4efe33a1-722d-48c8-af8e-7879edcad2fa","title":"Purple Widget","description":"Pretty Purple Widget","price":7.99},"quantity":4},{"product":{"id":null,"guid":"a9d5a5c7-4245-4b4e-b1c3-1d3968f36b2d","title":"Yellow Widget","description":"Amazing Yellow Widget","price":5.99},"quantity":4}]}}
{"timestamp":1528001014339,"name":{"title":"Ms.","firstName":"Susan","middleName":null,"lastName":"Blackstone","suffix":null},"contact":{"primaryPhone":"433-544-6555","secondaryPhone":"223-445-6767","email":"susan.m.blackstone@emailisus.com"},"address":{"type":"SHIPPING","description":"Home Sweet Home","address1":"33 Oak Avenue","address2":null,"city":"Nowhere","state":"VT","postalCode":"444556-9090"},"order":{"guid":"05f3d73c-df01-4b31-87b0-3b65065222bd","orderStatusEvents":[{"timestamp":1527996053859,"orderStatusType":"APPROVED","note":null}],"orderItems":[{"product":{"id":null,"guid":"d01fde07-7c24-49c5-a5f1-bc2ce1f14c48","title":"Red Widget","description":"Reliable Red Widget","price":3.99},"quantity":4}]}}

The fulfillment.order.change sends fulfilled order notifications back to orders, via topic

kafka-topics.sh --create \
  --zookeeper zookeeper:2181 \
  --replication-factor 1 --partitions 1 \
  --topic fulfillment.order.change

kafka-console-consumer.sh \
  --bootstrap-server localhost:9092 \
  --from-beginning --topic fulfillment.order.change

Output from application, on the fulfillment.order.change topic

{"guid":"5f900d92-e2a2-484f-8e9c-7e0a24b093fd","orderStatusEvent":{"timestamp":1528334452755,"orderStatusType":"PROCESSING","note":null}}
{"guid":"f52e2930-ef31-44db-a53c-b7ba4ae3f5cf","orderStatusEvent":{"timestamp":1528334452800,"orderStatusType":"PROCESSING","note":null}}
{"guid":"ef8572ad-1e21-41ed-9f4d-7a908c0d0b9b","orderStatusEvent":{"timestamp":1528334457507,"orderStatusType":"COMPLETED","note":null}}
{"guid":"6d8a81e5-23dc-4ec5-8488-c7519c890ae1","orderStatusEvent":{"timestamp":1528334457521,"orderStatusType":"COMPLETED","note":null}}
{"guid":"ffe75116-f72b-40c8-b819-b3cc0ad60b47","orderStatusEvent":{"timestamp":1528334457525,"orderStatusType":"COMPLETED","note":null}}

References

You can’t perform that action at this time.