β οΈ Difficulty:Intermediate
, we expect you to already know Java and Spring.
Learn how to build an app end-to-end application with Spring ecosystem (boot, mvc, security, data, test, thymeleaf) and Apache Cassandraβ’.
HOUSEKEEPING
LAB1 - Database Initialization
- 1.1 - Create Astra Account
- 1.2 - Create Astra Token
- 1.3 - Open your environment
- 1.4 - Setup Astra CLI
- 1.5 - Create Database
- 1.6 - Create Schema
- 1.7 - Load Data
LAB2 - Application Implementation
- 2.1 - Configuration
- 2.2 - Start application and first use
- 2.3 - Setup authentication for Google
- 2.4 - Setup authentication for Github
- 2.5 - Authentication with OAuth 2
- Discover how to use the following technologies:
- Spring Data: the Object Mapping layer of Spring
- Spring Data Cassandra: what traps to avoid
- Spring Security: how to handle authentication with OAuth2
- Spring MVC: how to expose REST API and controllers
- Spring Webflux: how to use the new
WebClient
- Thymeleaf: how to build a user interface with Spring
- Spring Test: How to run tests
- Astra DB (a Database-as-a-service built on Apache Cassandra)
- Han fun with an interactive session
This application has been built based on the work of Java Brains, a famous youtuber (500k+ subscribers). On his channel you can find the full Code with me Series, 16 episodes for building this application step-by-step. The link to each episode is provided at the end of this readme.
1οΈβ£ Can I run this workshop on my computer?
There is nothing preventing you from running the workshop on your own machine, If you do so, you will need the following
- git installed on your local system
- JDK 8+ installed on your local system
- Maven 3.6+ installed on your local system
2οΈβ£ What other prerequisites are required?
- You will need an enough *real estate* on screen, we will ask you to open a few windows and it does not file mobiles (tablets should be OK)
- You will need a GitHub account eventually a google account for the Google Authentication (optional)
- You will need an Astra account: don't worry, we'll work through that in the following
- As Intermediate level we expect you to know what java and Spring are.
3οΈβ£ Do I need to pay for anything for this workshop?
No. All tools and services we provide here are FREE. FREE not only during the session but also after.
4οΈβ£ Will I get a certificate if I attend this workshop?
Attending the session is not enough. You need to complete the homeworks detailed below and you will get a nice badge that you can share on linkedin or anywhere else *(open api badge)*
It doesn't matter if you join our workshop live or you prefer to work at your own pace, we have you covered. In this repository, you'll find everything you need for this workshop:
Note: Datastax Astra is a cloud-native, fully managed database-as-a-service (DBaaS) based on Apache Cassandra. It provides a scalable, performant and highly available database solution without the operational overhead of managing Cassandra clusters. Astra supports both SQL and NoSQL APIs, and includes features like backup and restore, monitoring and alerting, and access control. It enables developers to focus on application development while the database infrastructure is managed by Datastax.
β 1.1.a
- Access https://astra.datastax.com and register withGoogle
orGithub
account
-
β 1.2.a
LocateSettings
(#1) in the menu on the left, thenToken Management
(#2) -
β 1.2.b
Select the roleOrganization Administrator
before clicking[Generate Token]
β 1.2.c
- Copy your token in the clipboard. With this token we will now create what is needed for the training.
Note: Gitpod is a cloud-based integrated development environment (IDE) that allows developers to build, test and run applications directly in their web browser. It provides preconfigured dev environments for GitHub projects, so developers can start coding immediately without setting up local environment. Gitpod saves time and streamlines the development process.
β 1.3.a
βοΈ Right Click and select open as a new Tab...
Note: The Astra CLI is a command-line interface (CLI) tool for managing Apache Cassandra databases hosted on Datastax Astra. It allows developers to perform tasks like creating and managing databases, executing Cassandra queries, and managing security and access control. The Astra CLI simplifies database management and provides an alternative to the Astra web interface, enabling automation and integration with other tools and workflows.
β 1.4.a
Locate the terminal calledsetup
and check that the CLI is available
astra --version
π₯οΈ
output
$ astra --version 0.2.1
β 1.4.b
Trigger the setup command
astra setup
π₯οΈ
output
_____ __ / _ \ _______/ |_____________ / /_\ \ / ___/\ __\_ __ \__ \ / | \\___ \ | | | | \// __ \_ \____|__ /____ > |__| |__| (____ / \/ \/ \/ Version: 0.2.1 ----------------------- --- SETUP --- ----------------------- $ Enter an Astra token:
β 1.4.c
Provide your token as asked (starting witg AstraCS:..)
π₯οΈ
output
[OK] Configuration has been saved. [OK] Enter 'astra help' to list available commands.
β 1.4.d
List your existing Users.
astra user list
π₯οΈ
output
+--------------------------------------+-----------------------------+---------------------+ | User Id | User Email | Status | +--------------------------------------+-----------------------------+---------------------+ | b665658a-ae6a-4f30-a740-2342a7fb469c | [email protected] | active | +--------------------------------------+-----------------------------+---------------------+
β 1.5.a
Create databaseworkshops
with keyspacebetter_reads
astra db create workshops -k better_reads --if-not-exist
π₯οΈ
Output
[ INFO ] - Database 'workshops' already exist. Connecting to database. [ INFO ] - Database 'workshops' has status 'MAINTENANCE' waiting to be 'ACTIVE' ... [ INFO ] - Database 'workshops' has status 'ACTIVE' (took 7983 millis)
Chunk | Description |
---|---|
db create |
Operation executed create in group db |
workshops |
Name of the database, our argument |
-k better_reads |
Name of the keyspace, a db can contains multiple keyspaces |
--if-not-exist |
Flag for itempotency creating only what if needed |
Note: If the database already exist but has not been used for while the status will be
HIBERNATED
. The previous command will resume the db an create the new keyspace but it can take about a minute to execute.[OK] Resuming Database 'com.dtsx.astra.sdk.db.domain.Database@406005b3' ... [INFO] Database 'workshops' has status 'RESUMING' waiting to be 'ACTIVE' ... [INFO] Database 'workshops' has status 'ACTIVE' (took 41466 millis) [INFO] Keyspace 'workshops' already exists. Connecting to keyspace. [OK] Database 'workshops' is ready.
β 1.5.b
Check the status of databaseworkshops
astra db status workshops
π₯οΈ
output
[ INFO ] - Database 'workshops' has status 'ACTIVE'
β 1.5.c
Get the informations for your database including the keyspace list
astra db get workshops
π₯οΈ
output
+------------------------+-----------------------------------------+ | Attribute | Value | +------------------------+-----------------------------------------+ | Name | workshops | | id | 906ef2f2-07d0-472c-add6-fe719cf61d02 | | Status | ACTIVE | | Default Cloud Provider | GCP | | Default Region | us-east1 | | Default Keyspace | better_reads | | Creation Time | 2023-02-20T12:06:21Z | | | | | Keyspaces | [0] better_reads | | | | | Regions | [0] us-east1 | +------------------------+-----------------------------------------+
β 1.6.a
Check tables list leveragingcqlsh
astra db cqlsh workshops -k better_reads -e "describe tables;"
π₯οΈ
output
[INFO] Downloading Cqlshell, please wait... [INFO] Installing archive, please wait... [INFO] Secure connect bundles have been downloaded. [INFO] Cqlsh is starting, please wait for connection establishment... <empty>
β 1.6.b
Create tables
astra db cqlsh workshops \
-k better_reads \
-f /workspace/workshop-betterreads/dataset/schema-ddl.cql
π₯οΈ
output
[INFO] Secure connect bundles have been downloaded. [INFO] Cqlsh is starting, please wait for connection establishment...
β 1.6.c
List tables
astra db cqlsh workshops -k better_reads -e "describe tables;"
π₯οΈ
output
[INFO] Secure connect bundles have been downloaded. [INFO] Cqlsh is starting, please wait for connection establishment... author_by_id book_by_id book_by_user_and_bookid books_by_user
β 1.7.a
Show content of the CSV File
head -n 10 /workspace/workshop-betterreads/dataset/book_by_id_0.csv
π₯οΈ
output
id,author_id,author_names,book_description,book_name,cover_ids,published_date OL10000049W,"[\"OL3964979A\"]","[]",,"Le crime organise/quatre films exemplaires","[\"3140091\"]",2009-12-11 OL10000394W,"[\"OL3965434A\"]","[]",,"Portraits of Illusions","[\"3140733\"]",2009-12-11 OL10000415W,"[\"OL3965461A\"]","[]",,"Le Berceau du monde","[\"3140790\"]",2009-12-11 OL10000427W,"[\"OL3965478A\"]","[]",,"La fracture identitaire","[]",2009-12-11 OL10000471W,"[\"OL3965508A\"]","[]",,"JamiroquaΓ― de A Γ Z","[\"3140910\"]",2009-12-11 OL10001081W,"[\"OL3966201A\"]","[]",,"Contes soufis, tome 1","[\"3142335\"]",2009-12-11 OL10001150W,"[\"OL3966289A\"]","[]",,"Le prix de la terre","[\"3142514\"]",2009-12-11 OL10001271W,"[\"OL3966392A\"]","[]",,"Balzac","[\"3142712\"]",2009-12-11 OL10001538W,"[\"OL3966709A\"]","[]",,"D'affectueuses rΓ©vΓ©rences","[]",2009-12-11
β 1.7.b
Check how many rows. It should have more than 250k
wc -l /workspace/workshop-betterreads/dataset/book_by_id_0.csv
π₯οΈ
output
250437 ./dataset/book_by_id_0.csv
β 1.7.c
Populate tablebook_by_id
from the csvbook_by_id_0
astra db load workshops \
-k better_reads \
-t book_by_id \
-maxErrors -1 \
-url /workspace/workshop-betterreads/dataset/book_by_id_0.csv
- The batch is running and should be able to see the throughput at ~3k records per second.
π₯οΈ
output
[INFO] Downloading Dsbulk, please wait... [INFO] Installing archive, please wait... [INFO] Secure connect bundles have been downloaded. [INFO] RUNNING: dsbulk load -u token -p xxxxb -b /yyy1.zip -k better_reads -t book_by_id -logDir ./logs --log.verbosity normal --schema.allowMissingFields true -maxConcurrentQueries AUTO -delim , -url ./dataset/book_by_id_0.csv -header true -encoding UTF-8 -skipRecords 0 -maxErrors -1 [INFO] DSBulk is starting please wait ... Username and password provided but auth provider not specified, inferring PlainTextAuthProvider A cloud secure connect bundle was provided: ignoring all explicit contact points. A cloud secure connect bundle was provided and selected operation performs writes: changing default consistency level to LOCAL_QUORUM. ... total | failed | rows/s | p50ms | p99ms | p999ms | batches 18,944 | 0 | 1,706 | 107.08 | 134.22 | 182.45 | 1.00 ...
- The operation should take about 1 minute to complete. The file can have some errors like invalid title with special characters. IT IS NOT A PROBLEM the dataset is not perfect we will have some failed rows.
π₯οΈ
output
total | failed | rows/s | p50ms | p99ms | p999ms | batches 250,000 | 183 | 3,684 | 21.44 | 56.10 | 66.32 | 1.00 Operation LOAD_20220214-185449-001328 completed with 183 > errors in 1 minute and 7 seconds.
β 1.7.d
Populate tablebook_by_id
from the csvbook_by_id_1
astra db load workshops \
-k better_reads \
-t book_by_id \
-maxErrors -1 \
-url /workspace/workshop-betterreads/dataset/book_by_id_1.csv
π₯οΈ
output
total | failed | rows/s | p50ms | p99ms | p999ms | batches 250,000 | 138 | 1,787 | 106.92 | 136.31 | 398.46 | 1.00 Operation LOAD_20230220-153154-071483 completed with 138 errors in 2 minutes and 19 seconds.
β 1.7.e
Count Records in the tablebook_by_id
astra db count workshops \
-k better_reads \
-t book_by_id
π₯οΈ
output
Picked up JAVA_TOOL_OPTIONS: -Xmx2576m total | failed | rows/s | p50ms | p99ms | p999ms 499,679 | 0 | 57,806 | 210.15 | 6,207.57 | 6,207.57
β 2.1.a
Generate.env
file
cd /workspace/workshop-betterreads/better-reads-webapp
astra db create-dotenv workshops -k better_reads
cat .env
π₯οΈ
output
Values have been omitted in this guide for security reason
ASTRA_DB_APPLICATION_TOKEN=... ASTRA_DB_GRAPHQL_URL=... ASTRA_DB_GRAPHQL_URL_ADMIN=... ASTRA_DB_GRAPHQL_URL_PLAYGROUND=... ASTRA_DB_GRAPHQL_URL_SCHEMA=... ASTRA_DB_ID=... ASTRA_DB_KEYSPACE="better_reads" ASTRA_DB_REGION="us-east1" ASTRA_DB_REST_URL=... ASTRA_DB_REST_URL_SWAGGER=... ASTRA_DB_SECURE_BUNDLE_PATH=... ASTRA_DB_SECURE_BUNDLE_URL=... ASTRA_ORG_ID=... ASTRA_ORG_NAME=... ASTRA_ORG_TOKEN=...
β 2.1.b
Load.env
as environment variables
set -a
source .env
set +a
env | grep ASTRA_DB_
π₯οΈ
output
Values have been omitted in this guide for security reason
ASTRA_DB_APPLICATION_TOKEN=... ASTRA_DB_GRAPHQL_URL=... ASTRA_DB_GRAPHQL_URL_ADMIN=... ASTRA_DB_GRAPHQL_URL_PLAYGROUND=... ASTRA_DB_GRAPHQL_URL_SCHEMA=... ASTRA_DB_ID=... ASTRA_DB_KEYSPACE="better_reads" ASTRA_DB_REGION="us-east1" ASTRA_DB_REST_URL=... ASTRA_DB_REST_URL_SWAGGER=... ASTRA_DB_SECURE_BUNDLE_PATH=... ASTRA_DB_SECURE_BUNDLE_URL=...
-
β 2.1.c
Open configuration file -
Open project configuration
gp open /workspace/workshop-betterreads/better-reads-webapp/pom.xml
- Locate the declaration of the
spring-boot-starter
<dependency>
<groupId>com.datastax.astra</groupId>
<artifactId>astra-spring-boot-starter</artifactId>
<version>${astra-sdk.version}</version>
</dependency>
β 2.1.d
Studyapplication.yaml
file
gp open /workspace/workshop-betterreads/better-reads-webapp/src/main/resources/application.yml
- Notice how the variables are used
astra:
api:
application-token: ${ASTRA_ORG_TOKEN}
database-id: ${ASTRA_DB_ID}
database-region: ${ASTRA_DB_REGION}
- We could have let Spring Data generate the tables for us based on the entities but it is a bad practice
spring:
application:
name: betterreads
data:
cassandra:
schema-action: create-if-not-exists
-
β 2.2.a
Known the URL of the application -
It would be handy to know the URL of the application
gp url 8080
β 2.2.b
Start the Application
cd /workspace/workshop-betterreads/better-reads-webapp
mvn spring-boot:run
π₯οΈ
output
BetterReads with Spring Boot, String Data, Spring NVC, Spring security An application by JabaBrains. The application will start at http://localhost:8080 13:37:20.276 INFO com.datastax.astra.sdk.AstraClient : Setup of AstraClient from application.yml 13:37:20.280 INFO com.datastax.astra.sdk.config.AstraClientConfig : Initializing [AstraClient] 13:37:20.459 INFO com.datastax.astra.sdk.AstraClient : + API(s) Devops [ENABLED] 13:37:20.459 INFO com.datastax.astra.sdk.AstraClient : + Db: id > [3ed83de7-d97f-4fb6-bf9f-82e9f7eafa23] and region [eu-west-1] 13:37:20.460 INFO com.datastax.astra.sdk.AstraClient : + Downloading bundles in: [/home/gitpod/.astra] 13:37:21.124 INFO com.datastax.astra.sdk.databases.DatabaseClient : + SecureBundle found : scb_3ed83de7-d97f-4fb6-bf9f-82e9f7eafa23_eu-west-1.zip 13:37:21.124 INFO com.datastax.astra.sdk.databases.DatabaseClient : + SecureBundle found : scb_3ed83de7-d97f-4fb6-bf9f-82e9f7eafa23_eu-central-1.zip 13:37:23.041 INFO com.datastax.astra.sdk.AstraClient : [AstraClient] has been initialized.
A new tab should have opened in your browser. You can also open a new terminal and enter the command.
gp preview $(gp url 8080)
β 2.2.c
- Show Book details
In the search item look for Glimpses of ancient Sowams
you can search to whatever you want it will request open library ut during this workshop you only imported a subset of books, let us pick one you imported.
Select the first item, if you select the second you will hit the page book not found as this book is not in the DB.
This is only what we can do at this point. To mark the book as read we will need to authenticate with Google
or Github
.
-
β 2.3.a
- Connect to Google Cloud Platform -
β 2.3.b
- Create a new project if needed, on the screens i putBetterReadsDemoApps
and click[CREATE]]
β 2.3.c
- SelectApi and Services
on the project home page
β 2.3.c
- Select[ENABLE APIS AND SERVICES]
in menu
β 2.3.d
- Search forGmail Apis
and add them to your project.
Look For API
Select API
Output
β 2.3.e
- Search forGoogle Analytics Apis
and add them to your project.
Look For API
Select API
Output
β 2.3.f
- CheckExternal
(or internal as you prefer to limit scope). Then selectCREATE
β 2.3.g
- Select[OAuth consent screen]
in the menu on the left. Provide your application name, a support email and the application logo. Go to the bottom of the page and also provide an email. You can then[Save and continue]
.
β 2.3.h
- On menu in the left select Credentials and use the button on top[CREATE CREDENTIALS]
/ OAuth ClientID.
β 2.3.i
- SelectWeb Application
and provide it a name
β 2.3.j
- ForAuthorized JavaScript origins
use the output of :
gp url 8080
β 2.3.k
- ForAuthorized redirect URIs
use the output and then[Create]
echo $(gp url 8080)/login/oauth2/code/google | sed -r "s/https/http/"
β 2.3.l
- A new page will open with yourclientId
andclient Secret
. Make sure you copy them locally you will need to setup your application with it.
You are now doomed we will now mine cryptos with your google account.
Just kidding ^_^
β 2.3.m
- Open filesrc/main/resources/application.yml
in your project
gp open /workspace/workshop-betterreads/better-reads-webapp/src/main/resources/application.yml
β 2.3.n
- Changes keysclient-id
andclient-secret
with your values for the providerGoogle
.
security:
oauth2:
client:
registration:
google:
client-id: change
client-secret: change
As each attendee has a different URL in gitpod, you will have to create your own github `OAuth Apps - Let's do this together. For github settings we will have to enter a callback URL. To know which one enter use the following command
clear
echo $(gp url 8080)/login/oauth2/code/github | sed -r "s/https/http/"
β 2.4.a
- Login to your github account and go toOrganizations
β 2.4.b
- There scroll down to locate the last item of the menuDeveloper Settings
(hopefully you have not as many organizations as me), There pickOAuth Apps
(we are using OAuth)
β 2.4.c
- Click button[New OAuth Apps]
on the page
β 2.4.d
- You will be asked to login again for security reasons, then fill the form to register a new Github App. Thre Register your application
Name | Value |
---|---|
Application name |
The application name shown to user |
Homepage URL |
Can be anything, just the app (gp url 8080) |
Authorization Callback URL |
Call back url the one listed above ${homepage}/login/oauth2/code/github |
β 2.4.e
- Click[Register Application]
β 2.4.f
- The application is created. You got your clientId. You will have to generate a clientSecret now. Once you get both save them on a text file in your machine we will need them later
β 2.4.h
- When everything is set you can upload am image for your application and save the change with[Update Application]
.
β 2.4.i
- Open filesrc/main/resources/application.yml
in your project
gp open /workspace/workshop-betterreads/better-reads-webapp/src/main/resources/application.yml
β 2.4.j
- Changes keysclient-id
andclient-secret
with your values for the providerGithub
.
security:
oauth2:
client:
registration:
github:
client-id: change
client-secret: change
β 2.5.a
- After setting up the connection you can now start the application again :
cd /workspace/workshop-betterreads/better-reads-webapp
mvn spring-boot:run
- On homepage click on
Authenticate with Github
- Eventually you get the SSO screen for you organization
- Then you authorize the application again
HAHAHA EVIL LAUGH
YOU ARE DOOMED AGAIN WE ALSO HAVE YOUR GITHUB ACCOUNT NOW
WE WILL FEED OUR TROLLS AND CODEX.AI WITH IT.
- More seriously, Your are in !
- Use the button
[Login via Google]
- Validate with the familiar Google Screen
- You are in !
Don't forget to complete your assignment and get your verified skill badge! Finish and submit your homework!
-
Complete the practice steps as described below until you have your own app running in Gitpod. (up to step 11)
-
Answer the technical questions in the form (We promise, it is NOT difficult if you follow the workshop).
-
Take a screenshot of you authenticated in the app with a few books
-
Submit your homework here
-
(totally optional) Watch the full course on Javabrains.io
- 01 - Introduction to the series
- 02 - About the app
- 03 - System Design
- 04 - Cassandra Schema
- 05 - Setting up hosted
- 06 - Creating the Data Loader
- 07 - Connecting Spring Boot app to DataStax Astra
- 08 - Using Repository pattern with Spring Data
- 09 - Saving all the authors in the world to Cassandra
- 10 - Setting up books by ID
- 11 - Starting with Spring boot and security
- 12 - Implementing the Book view flow
- 13 - Building book search feature
- 14 - Tracking user interactions with books
- 15 - Building the My Books feature
- 16 - Wrapping Up