It doesn't matter if you join our workshop live or you prefer to do at your own pace, we have you covered. In this repository, you'll find everything you need for this workshop:
- Slide deck - week 1
- Slide deck - week 2
- Slide deck - week 3
- Slide deck - week 4
- Questions and Answers
- [Worskhop code] (https://github.com/datastaxdevs/workshop-ecommerce-app)
If you cannot attend this workshop live, recordings of this workshop and many more is available on Youtube.
Complete the homework to earn the badge for this workshop (awarded only at the end of the series).
- Implement Google login and take SCREENSHOT(s).
- Don't worry about submitting it just yet. We'll have instructions on how to do that at the end of the series!
- Introduction
- Create your Database
- Create your schema
- Populate the dataset
- Create a token
- Setup your application
- Enable Social Login
- Run Unit Tests
- Start the Application
Are you building or do you support an e-commerce website? If so, then this content is for you!
Worldwide digital sales in 2020 eclipsed four trillion dollars (USD). Businesses that want to compete, need a high performing e-commerce website. Here, we will demonstrate how to build a high performing persistence layer with DataStax ASTRA DB
.
Why does an e-commerce site need to be fast? Because most consumers will leave a web page or a mobile app if it takes longer than a few seconds to load. In the content below, we will cover how to build high-performing data models and services, helping you to build a e-commerce site with high throughput and low latency.
You can skip to step 2c if you have already created a keyspace ecommerce
in database demos
. Otherwise (if you did not attend the previous installment of the e-commerce worksop):
ASTRA DB
is the simplest way to run Cassandra with zero operations - just push the button and get your cluster. No credit card required, $25.00 USD credit every month, roughly 20M read/write operations, 80GB storage monthly - sufficient to run small production workloads.
If you do not have an account yet, register and sign in to Astra DB: This is FREE and NO CREDIT CARD is required. https://astra.datastax.com: You can use your Github
, Google
accounts or register with an email
.
Make sure to chose a password with minimum 8 characters, containing upper and lowercase letters, at least one number and special character
Follow this guide, to set up a pay as you go database with a free $25 monthly credit. You will find below recommended values to enter:
-
For the database name -
demos
-
For the keyspace name -
ecommerce
You can technically use whatever name(s) you want and update the code to reflect the keyspace. This is really to get you on a happy path for the first run.
-
For provider and region: For Astra DB, select GCP as a provider and then the related region is where your database will reside physically (choose one close to you or your users).
-
Create the database. Review all the fields to make sure they are as shown, and click the
Create Database
button.
👁️ Walkthrough
The Walkthrough mentions a different keyspace, make sure to use ecommerce
You will see your new database pending
in the Dashboard.
To connect to the database programmatically, you need to make sure the status will change to Active
. This happens when the database is ready, and will only take 2-3 minutes. You will also receive an email when it is ready.
👁️ Expected Output
If it's in a standby
state you can hit Connect
and CQL Console
on top.
You should see a message something like below.
👁️ Expected Output
{"message":"Resuming your database, please try again shortly."}
Here we will walk through how to create an Astra Streaming Tenant. Start by clicking the "Create Stream" button in the left navigation pane.
On the next page, provide a name for your tenant and select a provider/region. Click the blue "Create Tenant" button when complete.
Note that Tenant Names must be unique across providers. To ensure uniqueness, name it "ecommerce-" followed by your name or company.
Now we need to create topics within our tenant. Click on the link or on the "Topics" tab. You should see the "default" namespace with an "Add Topic" button (on the right). Click the "Add Topic" button.
Name the topic "pending-orders" and make sure that the "Persistent" switch is selected. Don't worry about the "Partitioned" switch for now. Click the "Add Topic" button when ready.
Repeat this process to add 3 more topics:
- picked-orders
- shipped-orders
- completed-orders
When you are done, your "Topics" tab should look similar to this:
Introduction This section will provide DDL to create three tables inside the "ecommerce" keyspace: category, price, and product.
The product
table supports all product data queries, and uses product_id
as a single key. It has a few columns for specific product data, but any ad-hoc or non-standard properties can be added to the specifications
map.
The category
table will support all product navigation service calls. It is designed to provide recursive, hierarchical navigation without a pre-set limit on the number of levels. The top-most level only exists as a parent_id
, and the bottom-most level contains products.
The price
table was intentionally split-off from product. There are several reasons for this. Price data is much more likely to change than pure product data (different read/write patterns). Also, large enterprises typically have separate teams for product and price, meaning they will usually have different micro-service layers and data stores.
The featured_product_groups
table was a late-add, to be able to provide some extra "atmosphere" of an e-commerce website. This way, the UI has a means by which to highlight a few, select products.
The user_carts
table supports cart metadata. Carts are not expected to be long-lived, so they have a default TTL (time to live) of 60 days (5,184,000 seconds). Carts also have a name
as a part of the key, so that the user can have multiple carts (think "wish lists").
The cart_products
table holds data on the products added to the cart. The cart uses product_timestamp
as the first clustering key in descending order; this way products in the cart will be listed with the most-recently-added products at the top. Like user_carts
, each entry has a 60 day TTL.
The user
table holds all data on the user, keyed by a single PRIMARY KEY on user_id
. It's main features contain TEXT (string) data for common user properties, as well as a collection of addresses
. This is because users (especially B-to-B) may have multiple addresses (mail-to, ship-to, bill-to, etc). The addresses
collection is built on a special user defined type (UDT) and FROZEN
to treat the collection as a Binary Large OBject (BLOB) to reduce tombstones (required by CQL).
As mentioned above, the address
UDT contains properties used for postal contacts. All properties are of the TEXT datatype.
The user_by_email
table is intended to be used as a "manual index" on email address. Essentially, it is a lookup table returning the user_id
associated with an email address. This is necessary as user_email
is nigh-unique (in terms of cardinality of values), and thus a CQL secondary index would perform quite poorly.
The order_by_id
table holds detail on each order. It partitions on order_id
for optimal data distribution, and clusters on product_name
and product_id
for sort order. The columns specific to the order itself (and not a product) are STATIC
so that they are only stored once (with the partition key).
The order_by_user
table holds a reference to each order by user_id
. The idea, is that this table is queried by user_id
and the results are shown on an "order history" page for that user. Then, each order can be clicked-on, revealing the detail contained in the order_by_id
table. order_id
is a TimeUUID (version 1 UUID) type, which is converted into a human-readable timestamp in the service layer.
The order_status_history
table maintains a history of each status for an order. It is meant to be used with queries to the order_by_id
table, so that a user may see the status progression of their order.
use ecommerce;
/* Session 1 - Product data model */
/* category table */
CREATE TABLE IF NOT EXISTS category (
parent_id UUID,
category_id UUID,
name TEXT,
image TEXT,
products LIST<TEXT>,
PRIMARY KEY (parent_id,category_id));
/* price table */
CREATE TABLE IF NOT EXISTS price (
product_id TEXT,
store_id TEXT,
value DECIMAL,
PRIMARY KEY(product_id,store_id));
/* product table */
CREATE TABLE IF NOT EXISTS product (
product_id TEXT,
product_group TEXT,
name TEXT,
brand TEXT,
model_number TEXT,
short_desc TEXT,
long_desc TEXT,
specifications MAP<TEXT,TEXT>,
linked_documents MAP<TEXT,TEXT>,
images SET<TEXT>,
PRIMARY KEY(product_id));
/* featured product groups table */
CREATE TABLE IF NOT EXISTS featured_product_groups (
feature_id INT,
category_id UUID,
name TEXT,
image TEXT,
parent_id UUID,
price DECIMAL,
PRIMARY KEY (feature_id,category_id));
/* Session 2 - Shopping Cart data model */
CREATE TABLE IF NOT EXISTS user_carts (
user_id uuid,
cart_name text,
cart_id uuid,
cart_is_active boolean,
user_email text,
PRIMARY KEY (user_id, cart_name, cart_id)
) WITH default_time_to_live = 5184000;
CREATE TABLE IF NOT EXISTS cart_products (
cart_id uuid,
product_timestamp timestamp,
product_id text,
product_description text,
product_name text,
quantity int,
PRIMARY KEY (cart_id, product_timestamp, product_id)
) WITH CLUSTERING ORDER BY (product_timestamp DESC, product_id ASC)
AND default_time_to_live = 5184000;
/* Session 3 - User Profile data model */
CREATE TYPE IF NOT EXISTS address (
type TEXT,
mailto_name TEXT,
street TEXT,
street2 TEXT,
city TEXT,
state_province TEXT,
postal_code TEXT,
country TEXT
);
CREATE TABLE IF NOT EXISTS user (
user_id UUID,
user_email TEXT,
picture_url TEXT,
first_name TEXT,
last_name TEXT,
locale TEXT,
addresses LIST<FROZEN<address>>,
session_id TEXT,
password TEXT,
password_timestamp TIMESTAMP,
PRIMARY KEY (user_id)
);
CREATE TABLE IF NOT EXISTS user_by_email (
user_email TEXT PRIMARY KEY,
user_id UUID
);
/* Session 4 - Order Processing System data model */
CREATE TABLE IF NOT EXISTS order_by_id (
order_id timeuuid,
product_name text,
product_id text,
order_shipping_handling decimal static,
order_status text static,
order_subtotal decimal static,
order_tax decimal static,
order_total decimal static,
payment_method text static,
product_price decimal,
product_qty int,
shipping_address address static,
PRIMARY KEY (order_id, product_name, product_id)
) WITH CLUSTERING ORDER BY (product_name ASC, product_id ASC);
CREATE TABLE IF NOT EXISTS order_by_user (
user_id uuid,
order_id timeuuid,
order_status text,
order_total decimal,
PRIMARY KEY (user_id, order_id)
) WITH CLUSTERING ORDER BY (order_id DESC);
CREATE TABLE IF NOT EXISTS order_status_history (
order_id timeuuid,
status_timestamp timestamp,
order_status text,
PRIMARY KEY (order_id, status_timestamp)
) WITH CLUSTERING ORDER BY (status_timestamp DESC);
INSERT INTO category (name,category_id,image,parent_id) VALUES ('Clothing',18105592-77aa-4469-8556-833b419dacf4,'ls534.png',ffdac25a-0244-4894-bb31-a0884bc82aa9);
INSERT INTO category (name,category_id,image,parent_id) VALUES ('Tech Accessories',5929e846-53e8-473e-8525-80b666c46a83,'',ffdac25a-0244-4894-bb31-a0884bc82aa9);
INSERT INTO category (name,category_id,image,parent_id) VALUES ('Cups and Mugs',675cf3a2-2752-4de7-ae2e-849471c29f51,'',ffdac25a-0244-4894-bb31-a0884bc82aa9);
INSERT INTO category (name,category_id,image,parent_id) VALUES ('Wall Decor',591bf485-de09-4b46-8fd2-5d9dc7ca101e,'bh001.png',ffdac25a-0244-4894-bb31-a0884bc82aa9);
INSERT INTO category (name,category_id,image,parent_id) VALUES ('T-Shirts',91455473-212e-4c6e-8bec-1da06779ae10,'ls534.png',18105592-77aa-4469-8556-833b419dacf4);
INSERT INTO category (name,category_id,image,parent_id) VALUES ('Hoodies',6a4d86aa-ceb5-4c6f-b9b9-80e9a8c58ad1,'',18105592-77aa-4469-8556-833b419dacf4);
INSERT INTO category (name,category_id,image,parent_id) VALUES ('Jackets',d887b049-d16c-46e1-8c94-0a1280dedc30,'',18105592-77aa-4469-8556-833b419dacf4);
INSERT INTO category (name,category_id,image,parent_id) VALUES ('Mousepads',d04dfb5b-69c6-4e97-b572-e9e390165a84,'',5929e846-53e8-473e-8525-80b666c46a83);
INSERT INTO category (name,category_id,image,parent_id) VALUES ('Wrist Rests',aa161129-d456-45ba-b1f0-fac7898b6d06,'',5929e846-53e8-473e-8525-80b666c46a83);
INSERT INTO category (name,category_id,image,parent_id) VALUES ('Laptop Covers',1c4b8599-78df-4f93-9c52-578bd959a3a5,'',5929e846-53e8-473e-8525-80b666c46a83);
INSERT INTO category (name,category_id,image,parent_id) VALUES ('Cups',7536fdef-fcd9-44a3-9360-0bffd2904408,'',675cf3a2-2752-4de7-ae2e-849471c29f51);
INSERT INTO category (name,category_id,image,parent_id) VALUES ('Coffee Mugs',20374300-185c-4ee5-b0bc-77fbdc3a21ed,'',675cf3a2-2752-4de7-ae2e-849471c29f51);
INSERT INTO category (name,category_id,image,parent_id) VALUES ('Travel Mugs',0660483e-2fad-447b-b19a-63ab4935e482,'',675cf3a2-2752-4de7-ae2e-849471c29f51);
INSERT INTO category (name,category_id,image,parent_id) VALUES ('Posters',fdbe9dcb-6878-4216-a64d-27c094b1b075,'',591bf485-de09-4b46-8fd2-5d9dc7ca101e);
INSERT INTO category (name,category_id,image,parent_id) VALUES ('Wall Art',943482f9-070c-4390-bb30-2107b6fe653a,'bh001.png',591bf485-de09-4b46-8fd2-5d9dc7ca101e);
INSERT INTO category (name,category_id,image,parent_id,products) VALUES ('Men''s "Go Away...Annotation" T-Shirt',99c4d825-d262-4a95-a04e-cc72e7e273c1,'ls534.png',91455473-212e-4c6e-8bec-1da06779ae10,['LS534S','LS534M','LS534L','LS534XL','LS5342XL','LS5343XL']);
INSERT INTO category (name,category_id,image,parent_id,products) VALUES ('Men''s "Your Face...Autowired" T-Shirt',3fa13eee-d057-48d0-b0ae-2d83af9e3e3e,'ln355.png',91455473-212e-4c6e-8bec-1da06779ae10,['LN355S','LN355M','LN355L','LN355XL','LN3552XL','LN3553XL']);
INSERT INTO category (name,category_id,image,parent_id,products) VALUES ('Bigheads',2f25a732-0744-406d-baee-3e8131cbe500,'bh001.png',943482f9-070c-4390-bb30-2107b6fe653a,['bh001','bh002','bh003']);
INSERT INTO category (name,category_id,image,parent_id,products) VALUES ('DataStax Gray Track Jacket',f629e107-b219-4563-a852-6909fd246949,'dss821.jpg',d887b049-d16c-46e1-8c94-0a1280dedc30,['DSS821S','DSS821M','DSS821L','DSS821XL']);
INSERT INTO category (name,category_id,image,parent_id,products) VALUES ('DataStax Vintage 2015 MVP Hoodie',86d234a4-6b97-476c-ada8-efb344d39743,'dsh915.jpg',6a4d86aa-ceb5-4c6f-b9b9-80e9a8c58ad1,['DSH915S','DSH915M','DSH915L','DSH915XL']);
INSERT INTO category (name,category_id,image,parent_id,products) VALUES ('DataStax Black Hoodie',b9bed3c0-0a76-44ea-bce6-f5f21611a3f1,'dsh916.jpg',6a4d86aa-ceb5-4c6f-b9b9-80e9a8c58ad1,['DSH916S','DSH916M','DSH916L','DSH916XL']);
INSERT INTO category (name,category_id,image,parent_id,products) VALUES ('Apache Cassandra 3.0 Contributor T-Shirt',95ae4613-0184-46ee-b4b0-adfe882754a8,'apc30a.jpg',91455473-212e-4c6e-8bec-1da06779ae10,['APC30S','APC30M','APC30L','APC30XL','APC302XL','APC303XL']);
INSERT INTO category (name,category_id,image,parent_id,products) VALUES ('DataStax Astra "One Team" Long Sleeve Tee',775be203-1a84-4822-9645-4da98ca2b2d8,'dsa1121.jpg',91455473-212e-4c6e-8bec-1da06779ae10,['DSA1121S','DSA1121M','DSA1121L','DSA1121XL','DSA11212XL','DSA11213XL']);
INSERT INTO price(product_id,store_id,value) VALUES ('LS534S','web',14.99);
INSERT INTO price(product_id,store_id,value) VALUES ('LS534M','web',14.99);
INSERT INTO price(product_id,store_id,value) VALUES ('LS534L','web',14.99);
INSERT INTO price(product_id,store_id,value) VALUES ('LS534XL','web',14.99);
INSERT INTO price(product_id,store_id,value) VALUES ('LS5342XL','web',16.99);
INSERT INTO price(product_id,store_id,value) VALUES ('LS5343XL','web',16.99);
INSERT INTO price(product_id,store_id,value) VALUES ('LN355S','web',14.99);
INSERT INTO price(product_id,store_id,value) VALUES ('LN355M','web',14.99);
INSERT INTO price(product_id,store_id,value) VALUES ('LN355L','web',14.99);
INSERT INTO price(product_id,store_id,value) VALUES ('LN355XL','web',14.99);
INSERT INTO price(product_id,store_id,value) VALUES ('LN3552XL','web',16.99);
INSERT INTO price(product_id,store_id,value) VALUES ('LN3553XL','web',16.99);
INSERT INTO price(product_id,store_id,value) VALUES ('DSA1121S','web',21.99);
INSERT INTO price(product_id,store_id,value) VALUES ('DSA1121M','web',21.99);
INSERT INTO price(product_id,store_id,value) VALUES ('DSA1121L','web',21.99);
INSERT INTO price(product_id,store_id,value) VALUES ('DSA1121XL','web',21.99);
INSERT INTO price(product_id,store_id,value) VALUES ('DSA11212XL','web',23.99);
INSERT INTO price(product_id,store_id,value) VALUES ('DSA11213XL','web',23.99);
INSERT INTO price(product_id,store_id,value) VALUES ('DSS821S','web',44.99);
INSERT INTO price(product_id,store_id,value) VALUES ('DSS821M','web',44.99);
INSERT INTO price(product_id,store_id,value) VALUES ('DSS821L','web',44.99);
INSERT INTO price(product_id,store_id,value) VALUES ('DSS821XL','web',44.99);
INSERT INTO price(product_id,store_id,value) VALUES ('DSH915S','web',35.99);
INSERT INTO price(product_id,store_id,value) VALUES ('DSH915M','web',35.99);
INSERT INTO price(product_id,store_id,value) VALUES ('DSH915L','web',35.99);
INSERT INTO price(product_id,store_id,value) VALUES ('DSH915XL','web',35.99);
INSERT INTO price(product_id,store_id,value) VALUES ('DSH916S','web',35.99);
INSERT INTO price(product_id,store_id,value) VALUES ('DSH916M','web',35.99);
INSERT INTO price(product_id,store_id,value) VALUES ('DSH916L','web',35.99);
INSERT INTO price(product_id,store_id,value) VALUES ('DSH916XL','web',35.99);
INSERT INTO price(product_id,store_id,value) VALUES ('APC30S','web',15.99);
INSERT INTO price(product_id,store_id,value) VALUES ('APC30M','web',15.99);
INSERT INTO price(product_id,store_id,value) VALUES ('APC30L','web',15.99);
INSERT INTO price(product_id,store_id,value) VALUES ('APC30XL','web',15.99);
INSERT INTO price(product_id,store_id,value) VALUES ('APC302XL','web',17.99);
INSERT INTO price(product_id,store_id,value) VALUES ('APC303XL','web',17.99);
INSERT INTO product(product_id,product_group,name,brand,model_number,short_desc,long_desc,specifications,images)
VALUES ('LS534S','LS534','Go Away Annotation T-Shirt','NerdShirts','NS101','Men''s Small "Go Away...Annotation" T-Shirt','Having to answer support questions when you really want to get back to coding? Wear this to work, and let there be no question as to what you''d rather be doing.',{'size':'Small','material':'cotton, polyester','cut':'men''s','color':'black'},{'ls534.png'});
INSERT INTO product(product_id,product_group,name,brand,model_number,short_desc,long_desc,specifications,images)
VALUES ('LS534M','LS534','Go Away Annotation T-Shirt','NerdShirts','NS101','Men''s Medium "Go Away...Annotation" T-Shirt','Having to answer support questions when you really want to get back to coding? Wear this to work, and let there be no question as to what you''d rather be doing.',{'size':'Medium','material':'cotton, polyester','cut':'men''s','color':'black'},{'ls534.png'});
INSERT INTO product(product_id,product_group,name,brand,model_number,short_desc,long_desc,specifications,images)
VALUES ('LS534L','LS534','Go Away Annotation T-Shirt','NerdShirts','NS101','Men''s Large "Go Away...Annotation" T-Shirt','Having to answer support questions when you really want to get back to coding? Wear this to work, and let there be no question as to what you''d rather be doing.',{'size':'Large','material':'cotton, polyester','cut':'men''s','color':'black'},{'ls534.png'});
INSERT INTO product(product_id,product_group,name,brand,model_number,short_desc,long_desc,specifications,images)
VALUES ('LS534XL','LS534','Go Away Annotation T-Shirt','NerdShirts','NS101','Men''s Extra Large "Go Away...Annotation" T-Shirt','Having to answer support questions when you really want to get back to coding? Wear this to work, and let there be no question as to what you''d rather be doing.',{'size':'Extra Large','material':'cotton, polyester','cut':'men''s','color':'black'},{'ls534.png'});
INSERT INTO product(product_id,product_group,name,brand,model_number,short_desc,long_desc,specifications,images)
VALUES ('LS5342XL','LS534','Go Away Annotation T-Shirt','NerdShirts','NS101','Men''s 2x Large "Go Away...Annotation" T-Shirt','Having to answer support questions when you really want to get back to coding? Wear this to work, and let there be no question as to what you''d rather be doing.',{'size':'2x Large','material':'cotton, polyester','cut':'men''s','color':'black'},{'ls534.png'});
INSERT INTO product(product_id,product_group,name,brand,model_number,short_desc,long_desc,specifications,images)
VALUES ('LS5343XL','LS534','Go Away Annotation T-Shirt','NerdShirts','NS101','Men''s 3x Large "Go Away...Annotation" T-Shirt','Having to answer support questions when you really want to get back to coding? Wear this to work, and let there be no question as to what you''d rather be doing.',{'size':'3x Large','material':'cotton, polyester','cut':'men''s','color':'black'},{'ls534.png'});
INSERT INTO product(product_id,product_group,name,brand,model_number,short_desc,long_desc,specifications,images)
VALUES ('LN355S','LN355','Your Face is an @Autowired @Bean T-Shirt','NerdShirts','NS102','Men''s Small "Your Face...Autowired" T-Shirt','Everyone knows that one person who overuses the "your face" jokes.',{'size':'Small','material':'cotton, polyester','cut':'men''s','color':'black'},{'ln355.png'});
INSERT INTO product(product_id,product_group,name,brand,model_number,short_desc,long_desc,specifications,images)
VALUES ('LN355M','LN355','Your Face is an @Autowired @Bean T-Shirt','NerdShirts','NS102','Men''s Medium "Your Face...Autowired" T-Shirt','Everyone knows that one person who overuses the "your face" jokes.',{'size':'Medium','material':'cotton, polyester','cut':'men''s','color':'black'},{'ln355.png'});
INSERT INTO product(product_id,product_group,name,brand,model_number,short_desc,long_desc,specifications,images)
VALUES ('LN355L','LN355','Your Face is an @Autowired @Bean T-Shirt','NerdShirts','NS102','Men''s Large "Your Face...Autowired" T-Shirt','Everyone knows that one person who overuses the "your face" jokes.',{'size':'Large','material':'cotton, polyester','cut':'men''s','color':'black'},{'ln355.png'});
INSERT INTO product(product_id,product_group,name,brand,model_number,short_desc,long_desc,specifications,images)
VALUES ('LN355XL','LN355','Your Face is an @Autowired @Bean T-Shirt','NerdShirts','NS102','Men''s Extra Large "Your Face...Autowired" T-Shirt','Everyone knows that one person who overuses the "your face" jokes.',{'size':'Extra Large','material':'cotton, polyester','cut':'men''s','color':'black'},{'ln355.png'});
INSERT INTO product(product_id,product_group,name,brand,model_number,short_desc,long_desc,specifications,images)
VALUES ('LN3552XL','LN355','Your Face is an @Autowired @Bean T-Shirt','NerdShirts','NS102','Men''s 2x Large "Your Face...Autowired" T-Shirt','Everyone knows that one person who overuses the "your face" jokes.',{'size':'2x Large','material':'cotton, polyester','cut':'men''s','color':'black'},{'ln355.png'});
INSERT INTO product(product_id,product_group,name,brand,model_number,short_desc,long_desc,specifications,images)
VALUES ('LN355XL','LN355','Your Face is an @Autowired @Bean T-Shirt','NerdShirts','NS102','Men''s 3x Large "Your Face...Autowired" T-Shirt','Everyone knows that one person who overuses the "your face" jokes.',{'size':'3x Large','material':'cotton, polyester','cut':'men''s','color':'black'},{'ln355.png'});
INSERT INTO product(product_id,product_group,name,brand,model_number,short_desc,long_desc,specifications,images)
VALUES ('DSA1121S','DSA1121','DataStax Astra "One Team" Long Sleeve Tee','DataStax','DSA1121','DataStax Astra "One Team" Long Sleeve Tee - Small','Given out at the internal summit, show how proud you are to talk about the world''s best multi-region, multi-cloud, serverless database!',{'size':'Small','material':'cotton, polyester','color':'black'},{'dsa1121.jpg'});
INSERT INTO product(product_id,product_group,name,brand,model_number,short_desc,long_desc,specifications,images)
VALUES ('DSA1121M','DSA1121','DataStax Astra "One Team" Long Sleeve Tee','DataStax','DSA1121','DataStax Astra "One Team" Long Sleeve Tee - Medium','Given out at the internal summit, show how proud you are to talk about the world''s best multi-region, multi-cloud, serverless database!',{'size':'Medium','material':'cotton, polyester','color':'black'},{'dsa1121.jpg'});
INSERT INTO product(product_id,product_group,name,brand,model_number,short_desc,long_desc,specifications,images)
VALUES ('DSA1121L','DSA1121','DataStax Astra "One Team" Long Sleeve Tee','DataStax','DSA1121','DataStax Astra "One Team" Long Sleeve Tee - Large','Given out at the internal summit, show how proud you are to talk about the world''s best multi-region, multi-cloud, serverless database!',{'size':'Large','material':'cotton, polyester','color':'black'},{'dsa1121.jpg'});
INSERT INTO product(product_id,product_group,name,brand,model_number,short_desc,long_desc,specifications,images)
VALUES ('DSA1121XL','DSA1121','DataStax Astra "One Team" Long Sleeve Tee','DataStax','DSA1121','DataStax Astra "One Team" Long Sleeve Tee - Extra Large','Given out at the internal summit, show how proud you are to talk about the world''s best multi-region, multi-cloud, serverless database!',{'size':'Extra Large','material':'cotton, polyester','color':'black'},{'dsa1121.jpg'});
INSERT INTO product(product_id,product_group,name,brand,model_number,short_desc,long_desc,specifications,images)
VALUES ('DSA11212XL','DSA1121','DataStax Astra "One Team" Long Sleeve Tee','DataStax','DSA1121','DataStax Astra "One Team" Long Sleeve Tee - 2X Large','Given out at the internal summit, show how proud you are to talk about the world''s best multi-region, multi-cloud, serverless database!',{'size':'2X Large','material':'cotton, polyester','color':'black'},{'dsa1121.jpg'});
INSERT INTO product(product_id,product_group,name,brand,model_number,short_desc,long_desc,specifications,images)
VALUES ('DSA11213XL','DSA1121','DataStax Astra "One Team" Long Sleeve Tee','DataStax','DSA1121','DataStax Astra "One Team" Long Sleeve Tee - 3X Large','Given out at the internal summit, show how proud you are to talk about the world''s best multi-region, multi-cloud, serverless database!',{'size':'3X Large','material':'cotton, polyester','color':'black'},{'dsa1121.jpg'});
INSERT INTO product(product_id,product_group,name,brand,model_number,short_desc,long_desc,specifications,images)
VALUES ('APC30S','APC30','Apache Cassandra 3.0 Contributor T-Shirt','Apache Foundation','APC30','Apache Cassandra 3.0 Contributor T-Shirt - Small','Own a piece of Cassandra history with this Apache Cassandra 3.0 "Contributor" shirt. Given out to all of the contributors to the project in 2016, shows the unmistakable Cassandra Eye on the front, with the
engine rebuild" on the back.',{'size':'Small','material':'cotton, polyester','color':'black'},{'apc30.jpg'});
INSERT INTO product(product_id,product_group,name,brand,model_number,short_desc,long_desc,specifications,images)
VALUES ('APC30M','APC30','Apache Cassandra 3.0 Contributor T-Shirt','Apache Foundation','APC30','Apache Cassandra 3.0 Contributor T-Shirt - Medium','Own a piece of Cassandra history with this Apache Cassandra 3.0 "Contributor" shirt. Given out to all of the contributors to the project in 2016, shows the unmistakable Cassandra Eye on the front, with the
engine rebuild" on the back.',{'size':'Medium','material':'cotton, polyester','color':'black'},{'apc30.jpg'});
INSERT INTO product(product_id,product_group,name,brand,model_number,short_desc,long_desc,specifications,images)
VALUES ('APC30L','APC30','Apache Cassandra 3.0 Contributor T-Shirt','Apache Foundation','APC30','Apache Cassandra 3.0 Contributor T-Shirt - Large','Own a piece of Cassandra history with this Apache Cassandra 3.0 "Contributor" shirt. Given out to all of the contributors to the project in 2016, shows the unmistakable Cassandra Eye on the front, with the
engine rebuild" on the back.',{'size':'Large','material':'cotton, polyester','color':'black'},{'apc30.jpg'});
INSERT INTO product(product_id,product_group,name,brand,model_number,short_desc,long_desc,specifications,images)
VALUES ('APC30XL','APC30','Apache Cassandra 3.0 Contributor T-Shirt','Apache Foundation','APC30','Apache Cassandra 3.0 Contributor T-Shirt - Extra Large','Own a piece of Cassandra history with this Apache Cassandra 3.0 "Contributor" shirt. Given out to all of the contributors to the project in 2016, shows the unmistakable Cassandra Eye on the front, with the
engine rebuild" on the back.',{'size':'Extra Large','material':'cotton, polyester','color':'black'},{'apc30.jpg'});
INSERT INTO product(product_id,product_group,name,brand,model_number,short_desc,long_desc,specifications,images)
VALUES ('APC302XL','APC30','Apache Cassandra 3.0 Contributor T-Shirt','Apache Foundation','APC30','Apache Cassandra 3.0 Contributor T-Shirt - 2X Large','Own a piece of Cassandra history with this Apache Cassandra 3.0 "Contributor" shirt. Given out to all of the contributors to the project in 2016, shows the unmistakable Cassandra Eye on the front, with the
engine rebuild" on the back.',{'size':'2X Large','material':'cotton, polyester','color':'black'},{'apc30.jpg'});
INSERT INTO product(product_id,product_group,name,brand,model_number,short_desc,long_desc,specifications,images)
VALUES ('APC303XL','APC30','Apache Cassandra 3.0 Contributor T-Shirt','Apache Foundation','APC30','Apache Cassandra 3.0 Contributor T-Shirt - 3X Large','Own a piece of Cassandra history with this Apache Cassandra 3.0 "Contributor" shirt. Given out to all of the contributors to the project in 2016, shows the unmistakable Cassandra Eye on the front, with the
engine rebuild" on the back.',{'size':'3X Large','material':'cotton, polyester','color':'black'},{'apc30.jpg'});
INSERT INTO product(product_id,product_group,name,brand,model_number,short_desc,long_desc,specifications,images)
VALUES ('DSS821S','DSS821','DataStax Gray Track Jacket','DataStax','DSS821','DataStax Gray Track Jacket - Small','This lightweight polyester jacket will be your favorite while hiking the trails or teeing off.',{'size':'Small','material':'polyester','color':'gray'},{'dss821.jpg'});
INSERT INTO product(product_id,product_group,name,brand,model_number,short_desc,long_desc,specifications,images)
VALUES ('DSS821M','DSS821','DataStax Gray Track Jacket','DataStax','DSS821','DataStax Gray Track Jacket - Medium','This lightweight polyester jacket will be your favorite while hiking the trails or teeing off.',{'size':'Medium','material':'polyester','color':'gray'},{'dss821.jpg'});
INSERT INTO product(product_id,product_group,name,brand,model_number,short_desc,long_desc,specifications,images)
VALUES ('DSS821L','DSS821','DataStax Gray Track Jacket','DataStax','DSS821','DataStax Gray Track Jacket - Large','This lightweight polyester jacket will be your favorite while hiking the trails or teeing off.',{'size':'Large','material':'polyester','color':'gray'},{'dss821.jpg'});
INSERT INTO product(product_id,product_group,name,brand,model_number,short_desc,long_desc,specifications,images)
VALUES ('DSS821XL','DSS821','DataStax Gray Track Jacket','DataStax','DSS821','DataStax Gray Track Jacket - Extra Large','This lightweight polyester jacket will be your favorite while hiking the trails or teeing off.',{'size':'Extra Large','material':'polyester','color':'gray'},{'dss821.jpg'});
INSERT INTO product(product_id,product_group,name,brand,model_number,short_desc,long_desc,specifications,images)
VALUES ('DSH915S','DSH915','DataStax Vintage 2015 MVP Hoodie','DataStax','DSS915','DataStax Vintage 2015 MVP Hoodie - Small','Given out to MVPs at the 2015 DataStax Cassandra Summit. Warm! You will underestimate how many times you will fall asleep wearing this!',{'size':'Small','color':'black'},{'dsh915.jpg'});
INSERT INTO product(product_id,product_group,name,brand,model_number,short_desc,long_desc,specifications,images)
VALUES ('DSH915M','DSH915','DataStax Vintage 2015 MVP Hoodie','DataStax','DSS915','DataStax Vintage 2015 MVP Hoodie - Medium','Given out to MVPs at the 2015 DataStax Cassandra Summit. Warm! You will underestimate how many times you will fall asleep wearing this!',{'size':'Medium','color':'black'},{'dsh915.jpg'});
INSERT INTO product(product_id,product_group,name,brand,model_number,short_desc,long_desc,specifications,images)
VALUES ('DSH915L','DSH915','DataStax Vintage 2015 MVP Hoodie','DataStax','DSS915','DataStax Vintage 2015 MVP Hoodie - Large','Given out to MVPs at the 2015 DataStax Cassandra Summit. Warm! You will underestimate how many times you will fall asleep wearing this!',{'size':'Large','color':'black'},{'dsh915.jpg'});
INSERT INTO product(product_id,product_group,name,brand,model_number,short_desc,long_desc,specifications,images)
VALUES ('DSH915XL','DSH915','DataStax Vintage 2015 MVP Hoodie','DataStax','DSS915','DataStax Vintage 2015 MVP Hoodie - Extra Large','Given out to MVPs at the 2015 DataStax Cassandra Summit. Warm! You will underestimate how many times you will fall asleep wearing this!',{'size':'Extra Large','color':'black'},{'dsh915.jpg'});
INSERT INTO product(product_id,product_group,name,brand,model_number,short_desc,long_desc,specifications,images)
VALUES ('DSH916S','DSH916','DataStax Black Hoodie','DataStax','DSS916','DataStax Black Hoodie - Small','Super warm! You will underestimate how many times you will fall asleep wearing this!',{'size':'Small','color':'black'},{'dsh916.jpg'});
INSERT INTO product(product_id,product_group,name,brand,model_number,short_desc,long_desc,specifications,images)
VALUES ('DSH916M','DSH916','DataStax Black Hoodie','DataStax','DSS916','DataStax Black Hoodie - Medium','Super warm! You will underestimate how many times you will fall asleep wearing this!',{'size':'Medium','color':'black'},{'dsh916.jpg'});
INSERT INTO product(product_id,product_group,name,brand,model_number,short_desc,long_desc,specifications,images)
VALUES ('DSH916L','DSH916','DataStax Black Hoodie','DataStax','DSS916','DataStax Black Hoodie - Large','Super warm! You will underestimate how many times you will fall asleep wearing this!',{'size':'Large','color':'black'},{'dsh916.jpg'});
INSERT INTO product(product_id,product_group,name,brand,model_number,short_desc,long_desc,specifications,images)
VALUES ('DSH916XL','DSH916','DataStax Black Hoodie','DataStax','DSS916','DataStax Black Hoodie - Extra Large','Super warm! You will underestimate how many times you will fall asleep wearing this!',{'size':'Extra Large','color':'black'},{'dsh916.jpg'});
INSERT INTO featured_product_groups (feature_id,name,category_id,image,price,parent_id) VALUES (202112,'DataStax Gray Track Jacket',f629e107-b219-4563-a852-6909fd246949,'dss821.jpg',44.99,d887b049-d16c-46e1-8c94-0a1280dedc30);
INSERT INTO featured_product_groups (feature_id,name,category_id,image,price,parent_id) VALUES (202112,'DataStax Black Hoodie',b9bed3c0-0a76-44ea-bce6-f5f21611a3f1,'dsh916.jpg',35.99,6a4d86aa-ceb5-4c6f-b9b9-80e9a8c58ad1);
INSERT INTO featured_product_groups (feature_id,name,category_id,image,price,parent_id) VALUES (202112,'Apache Cassandra 3.0 Contributor T-Shirt',95ae4613-0184-46ee-b4b0-adfe882754a8,'apc30a.jpg',15.99,91455473-212e-4c6e-8bec-1da06779ae10);
INSERT INTO featured_product_groups (feature_id,name,category_id,image,price,parent_id) VALUES (202112,'DataStax Astra "One Team" Long Sleeve Tee',775be203-1a84-4822-9645-4da98ca2b2d8,'dsa1121.jpg',21.99,91455473-212e-4c6e-8bec-1da06779ae10);
Although it's not advised to use wildcards as below, you can verify the data has been created with the following command.
select * from CATEGORY;
Notes:
- The "top" categories of the product hierarchy can be retrieved using a
parent_id
of "ffdac25a-0244-4894-bb31-a0884bc82aa9". - Without specifying a
category_id
, all categories for theparent_id
are returned. - When a category from the "bottom" of the hierarchy is queried, a populated
products
ArrayList will be returned. From there, the returnedproduct_id
s can be used with the/product
service. - Category navigation is achieved by using the
parent_id
andcategory_id
properties returned for each category (to build the "next level" category links). /category/ffdac25a-0244-4894-bb31-a0884bc82aa9
=> Category[Clothing, Cups and Mugs, Tech Accessories, Wall Decor]/category/ffdac25a-0244-4894-bb31-a0884bc82aa9/18105592-77aa-4469-8556-833b419dacf4
=> Category[Clothing]/category/18105592-77aa-4469-8556-833b419dacf4
=> Category[T-Shirts, Hoodies, Jackets]/category/91455473-212e-4c6e-8bec-1da06779ae10
=> Category[Men's "Your Face...Autowired" T-Shirt, Men's "Go Away...Annotation" T-Shirt]- The featured products table is a simple way for web marketers to promote small numbers of products, and have them appear in an organized fashion on the main page. The
feature_id
key is simply an integer, with the default being202112
(for December, 2021). You can (of course) use other numeric naming schemes.
Following the Manage Application Tokens docs create a token with Database Admnistrator
roles.
-
Go the
Organization Settings
-
Go to
Token Management
-
Pick the role
Database Administrator
on the select box -
Click Generate token
👁️ Walkthrough
This is what the token page looks like. You can now download the values as a CSV. We will need those values but you can also keep this window open for use later.
appToken:
We will use it as a api token Key to interact with APIs.
To know more about roles of each token you can have a look to this video.
Note: Make sure you don't close the window accidentally or otherwise - if you close this window before you copy the values, the application token is lost forever. They won't be available later for security reasons.
⚠️ ImportantThe instructor will show you on screen how to create a token but will have to destroy to token immediately for security reasons.
We are now set with the database and credentials and will incorporate them into the application as we will see below.
Click on the "Connect" tab. Take note of your tenant name and broker service URL. It's a good idea to copy/paste those into a text editor for now. When you're ready, click on the "Token Manager" link.
You should have one token created by default. Click on the copy icon on the right. Paste your token into a text editor for now.
Later on, we will use this information to populate environment variables, allowing us to connect to our Astra Streaming tenant. It will be similar to the example below:
export ASTRA_STREAM_TENANT=ecommerce-aaron
export ASTRA_STREAM_URL="pulsar+ssl://pulsar-gcp-uscentral1.streaming.datastax.com:6651"
export ASTRA_STREAM_TOKEN="eyJhMBhGYBlahBlahBlahNotARealToken37hOAv9t1fHIhJLAHw"
Take a moment to read this entire section since it'll help you with the rest of the workshop as you'll be spending most of your time in Gitpod. If you're familiar with Gitpod, you can easily skip this entire section.
The extreme left side has the explorer view(1). The top left, middle to right is where you'll be editing files(2), etc. and the bottom left, middle to right is what we will refer to as the Gitpod terminal window(3) as shown below.
👁️ Expected output
You can always get back to the file explorer view whenever by clicking on the hamburger menu on the top left followed by View
and Explorer
as shown below.
You can allow cutting and pasting into the window by clicking on Allow
as shown below.
✅ 6a: Enter the token
To run the application you need to provide the credentials and identifier to the application. you will have to provide 4 values in total as shown below
Copy the environment sample file as below.
cp .env.example .env
Open the .env
file as below.
gp open .env
-
In Astra DB go back to home page by clicking the logo
-
Select you database
demos
in the left panel and then copy values forcloud-region
anddatabase-id
(clusterID) from the details page as shown below. -
The DatabaseID is located on the home page
- The Database region (and keyspace) are located in the details page
-
Replace
application-token
with values shown on the Astra token screen or picking the values from the CSV token file your dowloaded before including the AstraCS: part of the token. -
Make sure the Token looks something like (with AstraCS: preceeding
AstraCS:xxxxxxxxxxx:yyyyyyyyyyy
# Copy this file to .env and fill in the appropriate values. Refer to README.md
# for instructions on where to find them.
export ASTRA_DB_ID=
export ASTRA_DB_REGION=
export ASTRA_DB_APP_TOKEN=
export ASTRA_DB_KEYSPACE=ecommerce
export ASTRA_STREAM_TENANT=
export ASTRA_STREAM_URL=
export ASTRA_STREAM_TOKEN=
export GOOGLE_CLIENT_ID=
export GOOGLE_CLIENT_SECRET=
Make sure to inject the environment variables by running the following command
source .env
Verify that the environment variables are properly setup with the following command
env | grep -i astra
You should see four environment variables (not shown here).
Now that we're done with tests, let's cd
to the top directory.
/workspace/workshop-ecommerce-app/
On a tab in a browser navigate to https://console.cloud.google.com/apis/credentials.
Consent to using APIs and services and you should finally be presented a screen that looks like below and pick values as shown.
Pick the appropriate values as shown below and complete the consent.
Make sure the project is setup for internal testing (and not for production) as shown below with the "MAKE INTERNAL".
Now click on the credentials
tab, + CREATE CREDENTIALS
tab and finally the OAuth Client ID
dropdown as shown in the following screen.
You will be presented with a screen for entering the Authorized JavaScript Origins
and Authorized redirect URIs
as shown below.
You'll need the following URIs. Make a note of this. We will use http
instead of https
as illustrated below.
For the Authorized JavaScript Origins
use the following value from the Gitpod terminal window,
echo $(gp url 8080 | sed 's/https/http/')
For the Authorized redirect URIs
use the following from the GitPod terminal window.
echo $(gp url 8080 | sed 's/https/http/')/login/oauth2/code/google
Enter the respective values as shown below which enables URI redirection and SSO for the app.
Make sure you enter the above values correctly as shown and hit CREATE
on bottom as shown.
Now you're ready to fetch the credentials by using the copy 'n paste icons on right as shown below.
You can copy and paste them in the .env
file as entries for Google GOOGLE_CLIENT_ID
and GOOGLE_CLIENT_SECRET
.
The application is now set you should be able to interact with your DB. Let's demonstrate some capabilities.
✅ 8a: Use CqlSession
Interaction with Cassandra are implemented in Java through drivers and the main Class is CqlSession
.
Higher level frameworks like Spring, Spring Data, or even quarkus will rely on this object so let's make sure it is part of your Spring context with a @SpringBootTest
.
Let's change to the sub-directory from the terminal window as shown below.
cd backend
Let's run the first test with the following command.
mvn test -Dtest=com.datastax.tutorials.Test01_Connectivity
👁️ Expected output
[..init...]
Execute some Cql (CqlSession)
+ Your Keyspace: sag_ecommerce
+ Product Categories:
Clothing
Cups and Mugs
Tech Accessories
Wall Decor
List Databases available in your Organization (AstraClient)
+ Your OrganizationID: e195fbea-79b6-4d60-9291-063d8c9e6364
+ Your Databases:
workshops : id=8c98b922-aeb0-4435-a0d5-a2788e23dff8, region=eu-central-1
sample_apps : id=c2d6bd3d-6112-47f6-9b66-b033e6174f0e, region=us-east-1
sdk_tests : id=a52f5879-3476-42d2-b5c9-81b18fc6d103, region=us-east-1
metrics : id=d7ded041-3cfb-4dd4-9957-e20003c3ebe2, region=us-east-1
✅ 8b: Working With Spring Data
Spring Data allows Mapping Object <=> Table
based on annotation at the java bean level. Then by convention CQL query will be executed under the hood.
mvn test -Dtest=com.datastax.tutorials.Test02_SpringData
👁️ Expected output
Categories:
- Clothing with children:[T-Shirts, Hoodies, Jackets]
- Cups and Mugs with children:[Cups, Coffee Mugs, Travel Mugs]
- Tech Accessories with children:[Mousepads, Wrist Rests, Laptop Covers]
- Wall Decor with children:[Posters, Wall Art]
✅ 8c: Working With Rest Controller
TestRestTemplate
is a neat way to test a web controller. The application will start on a random port with @SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)
mvn test -Dtest=com.datastax.tutorials.Test03_RestController
👁️ Expected output
List Categories:
Clothing
Cups and Mugs
Tech Accessories
Wall Decor
You can install the backend with the credentials using the following command
cd /workspace/workshop-ecommerce-app
mvn install -f backend/pom.xml -DskipTests
✅ 9a: Know your public URL
The workshop application has opened with an ephemeral URL. To know the URL where your application endpoint will be exposed you can run the following command in the terminal after the build has completed. **Please note this URL and we will open this up in a new browser window if required later **.
gp url 8080
👁️ Expected output
✅ 9b: Check APIs are not available (yet)
Run the following command in the Gitpod terminal window
curl localhost:8080/api/v1/products/product/LS534S
👁️ Expected output
curl: (7) Failed to connect to localhost port 8080: Connection refused
Not to be overly concerned as we're going to be starting the application that will be served from the port.
✅ 9c: Start the application
To start the application, we've provided a very simple convenience script that can be run as below.
./start.sh
Pay attention to popups being blocked as shown below and allow the popups.
You may encounter the following at different steps and although this may not be applicable right away, the steps are included in advance and summarized here so that you can keep an eye out for it. Different paths and different environments might be slightly different although Gitpod levels the playing field a bit.
Your e-commerce application should be up and running.
✅ 9d: Check APIs are now available
Get back to Gitpod tab/window.
Leave the application running and open up another shell
in the Gitpod terminal window by clicking on +
and clicking on bash
dropdown as shown below.
This will bring up a new bash
shell as shown below.
Issue the following command in that shell as you did earlier.
curl localhost:8080/api/v1/products/product/LS534S
and you should see some output indicating that the API server is serving our ecommerce APIs.
👁️ Expected output
Try a few other APIs (Hint: Look for the RestController
java files in the respective sub-directories.).
✅ 9e: OPTIONAL - Open in Gitpod preview window
This might be useful for troubleshooting if your application does not automatically open up a browser tab.
If you want, you can run the following command to open your application in the preview window of Gitpod (it's much easier to use the app running in browser, though).
gp preview $(gp url 8080)
As indicated in the output below it's a very Simple Browser
.
👁️ Expected output
If your application is running in the preview window but you have difficulty accessing it from the browser pay attention to popups being blocked by the browser as explained before.
✅ 9f: Get the Open API specification
In the new shell window open the specification in the preview or browser with the following command
gp preview $(gp url 8080)/swagger-ui/index.html
The preview window looks like below. It might help to close all the tabs or open this URL in a browser by clicking on the open in browser
tab on the top right as shown.
👁️ Expected output
Here's how it looks in the browser tab.
This is the docs for the open APIs that enables the frontend or any other program to obtain the data and manipulate it with REST-based CRUD operations.
The complete app is running in the browser as shown below.
✅ 9g: Use your social login
Hit login as shown below
You should be presented with the Google SSO Login option. Click on the icon as shown below.
Pick the Google user account and proceed to login as you would with Google.
If all the values are wired properly you should see the following screen with the icon above showing that the authentication worked as below and the Logout
button now available.
and voila, just like that we are done setting up user profile with Google. We can implement Github and other social logins similarly.
✅ 9h: Process your order(s)
Did you put items in your cart and check out? You will likely have an order waiting in your "pending-orders" topic. To simulate moving the orders between topics, a small Order Processor was created. To build and run:
source .env
cd orderProcessor
mvn clean install
Once that process completes, have a look at the target/
directory. You should see a JAR named ecom-0.0.1-SNAPSHOT-spring-boot.jar
. To process an order on the "pending-orders" topic, you need to have it "picked." To simulate a picking process, try this:
java -jar target/ecom-0.0.1-SNAPSHOT-spring-boot.jar pick
If an order is present, you should see the order JSON get processed and moved to the next topic:
{"cartId":"b8a5bd07-2337-44de-8890-582e88e29754","cartName":"b8a5bd07-2337-44de-8890-582e88e29754","orderId":"e8ecd3b0-498b-11ed-b5a7-fbd1f5143654","userId":"f1dbd2c0-bda4-4ccc-93dd-4aecd78758f5","productList":[{"productId":"DSS821XL","productName":"DataStax Gray Track Jacket","productQty":1,"productPrice":44.99},{"productId":"APC30XL","productName":"Apache Cassandra 3.0 Contributor T-Shirt","productQty":1,"productPrice":15.99}],"orderStatus":"PENDING","orderTimestamp":"Oct 11, 2022, 5:41:17 PM","orderSubtotal":60.98,"orderShippingHandling":4,"orderTax":3.05,"orderTotal":68.03,"shippingAddress":{"street":"123 Limon Gala Rd.","city":"Maple Grove","stateProvince":"Minnesota","postalCode":"55369","country":"United States"}}
Pushed order e8ecd3b0-498b-11ed-b5a7-fbd1f5143654 to ecommerce-aaron/default/picked-orders
Congratulations: you made it to the end of today's workshop. You will notice that the application is still incomplete as we're evolving it. More building to follow!!!
... and see you at our next workshop!
Sincerely yours, The DataStax Developers