Skip to content

datastaxdevs/workshop-betterreads

Β 
Β 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Workshops πŸ“˜ Better Reads πŸ“˜ !

Gitpod ready-to-code License Apache2 Discord

⚠️ 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β„’.

πŸ“‹ Table of content

HOUSEKEEPING

LAB1 - Database Initialization

LAB2 - Application Implementation

Homeworks

HouseKeeping

Objectives

  • 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

Acknowledgements

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.

Frequently asked questions

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

  1. git installed on your local system
  2. JDK 8+ installed on your local system
  3. Maven 3.6+ installed on your local system

In this readme, we try to provide instructions for local development as well - but keep in mind that the main focus is development on Gitpod, hence We can't guarantee live support about local development in order to keep on track with the schedule. However, we will do our best to give you the info you need to succeed.

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)*

🏠 Back to Table of Contents

Materials for the Session

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:


1. Database Initialization

1.1 - Create an Astra Account

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.2 - Create an Astra Token

  • βœ… 1.2.a Locate Settings (#1) in the menu on the left, then Token Management (#2)

  • βœ… 1.2.bSelect the role Organization 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.

1.3 - Open your Environment

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...

Open in Gitpod

1.4 - Setup Astra CLI

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 called setup 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 - Create database

  • βœ… 1.5.a Create database workshops with keyspace better_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 database workshops
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                            |
+------------------------+-----------------------------------------+

🏠 Back to Table of Contents

1.6 - Create Schema

  • βœ… 1.6.a Check tables list leveraging cqlsh
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

🏠 Back to Table of Contents

1.7 - Load Data

  • βœ… 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 table book_by_id from the csv book_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 table book_by_id from the csv book_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 table book_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

🏠 Back to Table of Contents

2. Application Implementation

2.1 - Configuration

  • βœ… 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 Study application.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 - Start Application and first use

  • βœ… 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.

new_terminal

gp preview $(gp url 8080)

new_terminal

  • βœ… 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.

new_terminal

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.

new_terminal

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.

🏠 Back to Table of Contents

2.3 - Setup Authentication for Google

  • βœ… 2.3.a - Connect to Google Cloud Platform

  • βœ… 2.3.b - Create a new project if needed, on the screens i put BetterReadsDemoApps and click [CREATE]]

new_terminal

  • βœ… 2.3.c - Select Api and Services on the project home page

new_terminal

  • βœ… 2.3.c - Select [ENABLE APIS AND SERVICES] in menu

new_terminal

  • βœ… 2.3.d - Search for Gmail Apis and add them to your project.

Look For API

new_terminal

Select API

new_terminal

Output

new_terminal

  • βœ… 2.3.e - Search for Google Analytics Apis and add them to your project.

Look For API

new_terminal

Select API

new_terminal

Output

new_terminal

  • βœ… 2.3.f - Check External (or internal as you prefer to limit scope). Then select CREATE

new_terminal

  • βœ… 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].

new_terminal

  • βœ… 2.3.h - On menu in the left select Credentials and use the button on top [CREATE CREDENTIALS]/ OAuth ClientID.

new_terminal

  • βœ… 2.3.i - Select Web Application and provide it a name

new_terminal

  • βœ… 2.3.j - For Authorized JavaScript origins use the output of :
gp url 8080
  • βœ… 2.3.k - For Authorized redirect URIs use the output and then [Create]
echo $(gp url 8080)/login/oauth2/code/google | sed -r  "s/https/http/"

new_terminal

  • βœ… 2.3.l - A new page will open with your clientId and client Secret. Make sure you copy them locally you will need to setup your application with it.

new_terminal

You are now doomed we will now mine cryptos with your google account.

Just kidding ^_^

new_terminal

  • βœ… 2.3.m - Open file src/main/resources/application.yml in your project
gp open /workspace/workshop-betterreads/better-reads-webapp/src/main/resources/application.yml
  • βœ… 2.3.n - Changes keys client-id and client-secret with your values for the provider Google.
  security:
    oauth2:
      client:
        registration:
          google:
            client-id: change
            client-secret: change

2.4 - Setup Authentication for Github

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 to Organizations

new_terminal

  • βœ… 2.4.b - There scroll down to locate the last item of the menu Developer Settings (hopefully you have not as many organizations as me), There pick OAuth Apps (we are using OAuth)

new_terminal

  • βœ… 2.4.c - Click button [New OAuth Apps] on the page

new_terminal

  • βœ… 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]

new_terminal

  • βœ… 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

new_terminal

  • βœ… 2.4.h - When everything is set you can upload am image for your application and save the change with [Update Application].

new_terminal

  • βœ… 2.4.i - Open file src/main/resources/application.yml in your project
gp open /workspace/workshop-betterreads/better-reads-webapp/src/main/resources/application.yml
  • βœ… 2.4.j - Changes keys client-id and client-secret with your values for the provider Github.
  security:
    oauth2:
      client:
        registration:
          github:
            client-id: change
            client-secret: change

🏠 Back to Table of Contents

2.5 - Authenticate with Oauth2

  • βœ… 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

βœ… 2.5.b - Authenticate with Github

  • On homepage click on Authenticate with Github

new_terminal

  • Eventually you get the SSO screen for you organization

new_terminal

  • Then you authorize the application again

new_terminal

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 !

new_terminal

βœ… 2.5.c Authenticate with Github

  • Use the button [Login via Google]

new_terminal

  • Validate with the familiar Google Screen

new_terminal

  • You are in !

new_terminal

🏠 Back to Table of Contents

Homeworks

Don't forget to complete your assignment and get your verified skill badge! Finish and submit your homework!

  1. Complete the practice steps as described below until you have your own app running in Gitpod. (up to step 11)

  2. Answer the technical questions in the form (We promise, it is NOT difficult if you follow the workshop).

  3. Take a screenshot of you authenticated in the app with a few books

  4. Submit your homework here

  5. (totally optional) Watch the full course on Javabrains.io


Releases

No releases published

Packages

No packages published

Languages

  • Java 71.0%
  • HTML 25.7%
  • Shell 3.3%