├── .gitignore ├── .gitpod.yml ├── .vscode └── settings.json ├── README.md ├── astra.json ├── img └── splash.png ├── week1-intro-to-cassandra ├── LICENSE ├── README.MD ├── images │ ├── astra-cql-console.gif │ ├── astra-create-2.png │ ├── astra-create-3.png │ ├── astra-create-4.png │ ├── astra-create-5.png │ ├── astra-create-6.png │ ├── astra-create-7.png │ ├── astra-create-launch-now.png │ ├── astra-create-login.png │ ├── astra-create-register.png │ ├── astra-login-cql-console.png │ ├── astra-use-cql-console-create-tables.png │ ├── astra-use-cql-console-create-users-by-city.png │ ├── astra-use-cql-console-delete-from-comments-by-video.png │ ├── astra-use-cql-console-delete-from-cred.png │ ├── astra-use-cql-console-desc-keyspace.png │ ├── astra-use-cql-console-describe-tables.png │ ├── astra-use-cql-console-insert-into-cred.png │ ├── astra-use-cql-console-select-from-tables.png │ ├── astra-use-cql-console-update-comments-by-video.png │ ├── astra-use-cql-console-use-killrvideo.png │ ├── astra-use-cql-console.png │ ├── astra-view-cql-console.png │ ├── badge │ │ └── intro-to-cassandra.png │ ├── cluster_basics.png │ ├── cql │ │ ├── 01_desc_keyspaces.png │ │ ├── 02_use_chatsandra.png │ │ ├── 03_user_table_created.png │ │ ├── 04_post_tables_created.png │ │ ├── 05_selects.png │ │ ├── 06_updated.png │ │ └── 07_deleting.png │ ├── getting-started-with-cassandra.png │ ├── intro.png │ └── tutorials │ │ ├── astra-create-db.gif │ │ └── astra_signup.gif └── slides │ ├── Presentation.pdf │ └── WEEK1 - Introduction to Apache Cassandra.pdf ├── week2-data-modelling ├── README.md ├── images │ ├── astra-cql-console.gif │ ├── create_keyspace_todos.gif │ ├── data_model_methodology_badge.png │ ├── datamodel.png │ ├── killrvideo_users_by_city.png │ ├── resuming.png │ ├── resuming2.png │ ├── sensors-1-er.png │ ├── sensors-2-aw.png │ ├── sensors-3-ld.png │ ├── sensors-4-pd.png │ ├── shopping-cart-data-access-patterns.png │ ├── todoapp.png │ └── todoitems_table_created.png ├── model.cql └── slides │ ├── Presentation.pdf │ └── test ├── week3-app-development ├── .env.sample ├── README.MD ├── images │ ├── AppDevSplash.png │ ├── Filexplorer0.png │ ├── OpenPorts.png │ ├── Verifytodos.png │ ├── allow.png │ ├── api_badge.png │ ├── appdev_badge.png │ ├── astra-create-token.gif │ ├── astra-token.png │ ├── bootcamp_badge.png │ ├── dotenv1.png │ ├── dotenv2.png │ ├── dotenv3.png │ ├── dotenv4.png │ ├── dotenv5.png │ ├── gitpod-01-home-annotated.png │ ├── gitpod-01-home-plain.png │ ├── gitpod-02-url.png │ ├── gitpod-bootcampappdev-1.jpg │ ├── gitpodpreferences1.png │ ├── secureconnectbundle1.png │ ├── secureconnectbundle2.png │ ├── secureconnectbundle3.png │ └── shells.png ├── java │ ├── README.MD │ ├── pom.xml │ └── src │ │ ├── main │ │ └── java │ │ │ └── com │ │ │ └── datastax │ │ │ └── workshop │ │ │ ├── DBConnection.java │ │ │ └── DBConnection.java.init │ │ └── test │ │ ├── java │ │ └── com │ │ │ └── datastax │ │ │ └── workshop │ │ │ ├── Ex06_Connect_to_Astra.java │ │ │ ├── Ex6a_Create_Table.java │ │ │ ├── Ex6b_Insert_Todos.java │ │ │ ├── Ex6c_Get_All_Todos.java │ │ │ ├── Ex6d_Update_A_Todo.java │ │ │ ├── Ex6e_Remove_A_Todo.java │ │ │ ├── Ex6f_Remove_All_Todos.java │ │ │ └── TestUtils.java │ │ └── resources │ │ └── logback-test.xml ├── javascript │ ├── Ex06_Connect_to_Astra.js │ ├── Ex6a_Create_Table.js │ ├── Ex6b_Insert_Todos.js │ ├── Ex6c_Get_All_Todos.js │ ├── Ex6d_Update_A_Todo.js │ ├── Ex6e_Remove_A_Todo.js │ ├── Ex6f_Remove_All_Todos.js │ ├── README.MD │ ├── connection.js │ └── connection.js.init ├── plugastracreds ├── python │ ├── Ex06_Connect_to_Astra.py │ ├── Ex6a_Create_Table.py │ ├── Ex6b_Insert_Todos.py │ ├── Ex6c_Get_All_Todos.py │ ├── Ex6d_Update_A_Todo.py │ ├── Ex6e_Remove_A_Todo.py │ ├── Ex6f_Remove_All_Todos.py │ ├── README.MD │ ├── connection.py │ └── connection.py.init └── slides │ └── WEEK3 - App Development with Cassandra.pdf └── week4-api-microservices ├── .env.sample ├── README.MD ├── images ├── Filexplorer0.png ├── OpenPorts.png ├── Verifytodos.png ├── allow.png ├── astra-create-token.gif ├── astra-token.png ├── bootcamp_badge.png ├── dotenv1.png ├── dotenv2.png ├── dotenv3.png ├── dotenv4.png ├── dotenv5.png ├── gitpod-01-home-annotated.png ├── gitpod-01-home-plain.png ├── gitpod-02-url.png ├── gitpod-bootcampappdev-1.jpg ├── gitpod-client-error.png ├── gitpod-client-success.png ├── gitpod-home-error.png ├── gitpod-john-task.png ├── gitpod-openport.png ├── gitpod-spec-error.png ├── gitpod-spec-success.png ├── gitpodpreferences1.png ├── public9191.png ├── resume-db.png ├── secureconnectbundle1.png ├── secureconnectbundle2.png ├── secureconnectbundle3.png ├── shells.png ├── splash.png ├── todobackend-output-client.png ├── todobackend-output-host.png ├── todobackend-runclient.png ├── todobackend-runtest.png ├── todobackend.png ├── todobackend2-1.png ├── todomvc.png └── week4_badge.png ├── java ├── README.MD ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── datastaxdev │ │ │ ├── TodoApplication.java │ │ │ ├── conf │ │ │ └── CassandraDriverConguration.java │ │ │ └── todo │ │ │ ├── Todo.java │ │ │ ├── TodoItem.java │ │ │ ├── TodoItemKey.java │ │ │ ├── TodoItemRepository.java │ │ │ └── TodoRestController.java │ └── resources │ │ ├── META-INF │ │ └── additional-spring-configuration-metadata.json │ │ ├── application.conf │ │ ├── application.properties │ │ ├── application.properties.init │ │ ├── banner.txt │ │ └── logback.xml │ └── test │ └── java │ └── com │ └── datastaxdev │ ├── Test01_Connect.java │ ├── Test02_CreateSchema.java │ ├── Test03_SaveTask.java │ └── Test04_Controller.java ├── javascript ├── .env.example ├── README.MD ├── Test01_Connect.js ├── Test02_CreateSchema.js ├── Test03_SaveTask.js ├── api.js ├── connection.js ├── connection.js.init ├── package-lock.json ├── package.json ├── todos.js └── todos.test.js ├── plugastracreds ├── python ├── .env.example ├── README.MD ├── Test01_Connect.py ├── Test02_CreateSchema.py ├── Test03_SaveTask.py ├── api.py ├── connection.py ├── connection.py.init ├── pytest.ini ├── requirements.txt ├── test_api.py ├── test_todos.py └── todos.py └── slides └── slides.pdf /.gitignore: -------------------------------------------------------------------------------- 1 | bundle.zip 2 | 3 | ############################ 4 | # JAVA 5 | ############################ 6 | 7 | # eclipse conf file 8 | .settings 9 | .classpath 10 | .project 11 | .cache 12 | .factorypath 13 | 14 | # idea conf files 15 | .idea 16 | *.ipr 17 | *.iws 18 | *.iml 19 | 20 | # building 21 | target 22 | # build 23 | tmp 24 | dist 25 | 26 | 27 | ############################ 28 | # PYTHON 29 | ############################ 30 | 31 | # Byte-compiled / optimized / DLL files 32 | __pycache__/ 33 | *.py[cod] 34 | *$py.class 35 | 36 | # C extensions 37 | *.so 38 | 39 | # Distribution / packaging 40 | .Python 41 | # build/ 42 | develop-eggs/ 43 | dist/ 44 | downloads/ 45 | eggs/ 46 | .eggs/ 47 | lib/ 48 | lib64/ 49 | parts/ 50 | sdist/ 51 | var/ 52 | wheels/ 53 | pip-wheel-metadata/ 54 | share/python-wheels/ 55 | *.egg-info/ 56 | .installed.cfg 57 | *.egg 58 | MANIFEST 59 | 60 | # PyInstaller 61 | # Usually these files are written by a python script from a template 62 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 63 | *.manifest 64 | *.spec 65 | 66 | # Installer logs 67 | pip-log.txt 68 | pip-delete-this-directory.txt 69 | 70 | # Unit test / coverage reports 71 | htmlcov/ 72 | .tox/ 73 | .nox/ 74 | .coverage 75 | .coverage.* 76 | .cache 77 | nosetests.xml 78 | coverage.xml 79 | *.cover 80 | .hypothesis/ 81 | .pytest_cache/ 82 | 83 | # Translations 84 | *.mo 85 | *.pot 86 | 87 | # Django stuff: 88 | *.log 89 | local_settings.py 90 | db.sqlite3 91 | db.sqlite3-journal 92 | 93 | # Flask stuff: 94 | instance/ 95 | .webassets-cache 96 | 97 | # Scrapy stuff: 98 | .scrapy 99 | 100 | # Sphinx documentation 101 | docs/_build/ 102 | 103 | # PyBuilder 104 | target/ 105 | 106 | # Jupyter Notebook 107 | .ipynb_checkpoints 108 | 109 | # IPython 110 | profile_default/ 111 | ipython_config.py 112 | 113 | # pyenv 114 | .python-version 115 | 116 | # pipenv 117 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 118 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 119 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 120 | # install all needed dependencies. 121 | #Pipfile.lock 122 | 123 | # celery beat schedule file 124 | celerybeat-schedule 125 | 126 | # SageMath parsed files 127 | *.sage.py 128 | 129 | # Environments 130 | .env 131 | .venv 132 | env/ 133 | venv/ 134 | ENV/ 135 | env.bak/ 136 | venv.bak/ 137 | 138 | # Spyder project settings 139 | .spyderproject 140 | .spyproject 141 | 142 | # Rope project settings 143 | .ropeproject 144 | 145 | # mkdocs documentation 146 | /site 147 | 148 | # mypy 149 | .mypy_cache/ 150 | .dmypy.json 151 | dmypy.json 152 | 153 | # Pyre type checker 154 | .pyre/ 155 | 156 | 157 | ############################ 158 | # NODEJS 159 | ############################ 160 | 161 | # Logs 162 | logs 163 | *.log 164 | npm-debug.log* 165 | yarn-debug.log* 166 | yarn-error.log* 167 | lerna-debug.log* 168 | 169 | # Diagnostic reports (https://nodejs.org/api/report.html) 170 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 171 | 172 | # Runtime data 173 | pids 174 | *.pid 175 | *.seed 176 | *.pid.lock 177 | 178 | # Directory for instrumented libs generated by jscoverage/JSCover 179 | lib-cov 180 | 181 | # Coverage directory used by tools like istanbul 182 | coverage 183 | *.lcov 184 | 185 | # nyc test coverage 186 | .nyc_output 187 | 188 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 189 | .grunt 190 | 191 | # Bower dependency directory (https://bower.io/) 192 | bower_components 193 | 194 | # node-waf configuration 195 | .lock-wscript 196 | 197 | # Compiled binary addons (https://nodejs.org/api/addons.html) 198 | build/Release 199 | 200 | # Dependency directories 201 | node_modules/ 202 | jspm_packages/ 203 | 204 | # TypeScript v1 declaration files 205 | typings/ 206 | 207 | # TypeScript cache 208 | *.tsbuildinfo 209 | 210 | # Optional npm cache directory 211 | .npm 212 | 213 | # Optional eslint cache 214 | .eslintcache 215 | 216 | # Optional REPL history 217 | .node_repl_history 218 | 219 | # Output of 'npm pack' 220 | *.tgz 221 | 222 | # Yarn Integrity file 223 | .yarn-integrity 224 | 225 | # dotenv environment variables file 226 | .env 227 | .env.test 228 | 229 | # parcel-bundler cache (https://parceljs.org/) 230 | .cache 231 | 232 | # next.js build output 233 | .next 234 | 235 | # nuxt.js build output 236 | .nuxt 237 | 238 | # vuepress build output 239 | .vuepress/dist 240 | 241 | # Serverless directories 242 | .serverless/ 243 | 244 | # FuseBox cache 245 | .fusebox/ 246 | 247 | # DynamoDB Local files 248 | .dynamodb/ 249 | 250 | 251 | ## Ignore Visual Studio temporary files, build results, and 252 | ## files generated by popular Visual Studio add-ons. 253 | ## 254 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 255 | 256 | # User-specific files 257 | *.rsuser 258 | *.suo 259 | *.user 260 | *.userosscache 261 | *.sln.docstates 262 | 263 | # User-specific files (MonoDevelop/Xamarin Studio) 264 | *.userprefs 265 | 266 | # Mono auto generated files 267 | mono_crash.* 268 | 269 | # Build results 270 | [Dd]ebug/ 271 | [Dd]ebugPublic/ 272 | [Rr]elease/ 273 | [Rr]eleases/ 274 | x64/ 275 | x86/ 276 | [Aa][Rr][Mm]/ 277 | [Aa][Rr][Mm]64/ 278 | bld/ 279 | [Bb]in/ 280 | [Oo]bj/ 281 | [Ll]og/ 282 | 283 | # Visual Studio 2015/2017 cache/options directory 284 | .vs/ 285 | # Uncomment if you have tasks that create the project's static files in wwwroot 286 | #wwwroot/ 287 | 288 | # Visual Studio 2017 auto generated files 289 | Generated\ Files/ 290 | 291 | # MSTest test Results 292 | [Tt]est[Rr]esult*/ 293 | [Bb]uild[Ll]og.* 294 | 295 | # NUnit 296 | *.VisualState.xml 297 | TestResult.xml 298 | nunit-*.xml 299 | 300 | # Build Results of an ATL Project 301 | [Dd]ebugPS/ 302 | [Rr]eleasePS/ 303 | dlldata.c 304 | 305 | # Benchmark Results 306 | BenchmarkDotNet.Artifacts/ 307 | 308 | # .NET Core 309 | project.lock.json 310 | project.fragment.lock.json 311 | artifacts/ 312 | 313 | # StyleCop 314 | StyleCopReport.xml 315 | 316 | # Files built by Visual Studio 317 | *_i.c 318 | *_p.c 319 | *_h.h 320 | *.ilk 321 | *.meta 322 | *.obj 323 | *.iobj 324 | *.pch 325 | *.pdb 326 | *.ipdb 327 | *.pgc 328 | *.pgd 329 | *.rsp 330 | *.sbr 331 | *.tlb 332 | *.tli 333 | *.tlh 334 | *.tmp 335 | *.tmp_proj 336 | *_wpftmp.csproj 337 | *.log 338 | *.vspscc 339 | *.vssscc 340 | .builds 341 | *.pidb 342 | *.svclog 343 | *.scc 344 | 345 | # Chutzpah Test files 346 | _Chutzpah* 347 | 348 | # Visual C++ cache files 349 | ipch/ 350 | *.aps 351 | *.ncb 352 | *.opendb 353 | *.opensdf 354 | *.sdf 355 | *.cachefile 356 | *.VC.db 357 | *.VC.VC.opendb 358 | 359 | # Visual Studio profiler 360 | *.psess 361 | *.vsp 362 | *.vspx 363 | *.sap 364 | 365 | # Visual Studio Trace Files 366 | *.e2e 367 | 368 | # TFS 2012 Local Workspace 369 | $tf/ 370 | 371 | # Guidance Automation Toolkit 372 | *.gpState 373 | 374 | # ReSharper is a .NET coding add-in 375 | _ReSharper*/ 376 | *.[Rr]e[Ss]harper 377 | *.DotSettings.user 378 | 379 | # JustCode is a .NET coding add-in 380 | .JustCode 381 | 382 | # TeamCity is a build add-in 383 | _TeamCity* 384 | 385 | # DotCover is a Code Coverage Tool 386 | *.dotCover 387 | 388 | # AxoCover is a Code Coverage Tool 389 | .axoCover/* 390 | !.axoCover/settings.json 391 | 392 | # Visual Studio code coverage results 393 | *.coverage 394 | *.coveragexml 395 | 396 | # NCrunch 397 | _NCrunch_* 398 | .*crunch*.local.xml 399 | nCrunchTemp_* 400 | 401 | # MightyMoose 402 | *.mm.* 403 | AutoTest.Net/ 404 | 405 | # Web workbench (sass) 406 | .sass-cache/ 407 | 408 | # Installshield output folder 409 | [Ee]xpress/ 410 | 411 | # DocProject is a documentation generator add-in 412 | DocProject/buildhelp/ 413 | DocProject/Help/*.HxT 414 | DocProject/Help/*.HxC 415 | DocProject/Help/*.hhc 416 | DocProject/Help/*.hhk 417 | DocProject/Help/*.hhp 418 | DocProject/Help/Html2 419 | DocProject/Help/html 420 | 421 | # Click-Once directory 422 | publish/ 423 | 424 | # Publish Web Output 425 | *.[Pp]ublish.xml 426 | *.azurePubxml 427 | # Note: Comment the next line if you want to checkin your web deploy settings, 428 | # but database connection strings (with potential passwords) will be unencrypted 429 | *.pubxml 430 | *.publishproj 431 | 432 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 433 | # checkin your Azure Web App publish settings, but sensitive information contained 434 | # in these scripts will be unencrypted 435 | PublishScripts/ 436 | 437 | # NuGet Packages 438 | *.nupkg 439 | # NuGet Symbol Packages 440 | *.snupkg 441 | # The packages folder can be ignored because of Package Restore 442 | **/[Pp]ackages/* 443 | # except build/, which is used as an MSBuild target. 444 | !**/[Pp]ackages/build/ 445 | # Uncomment if necessary however generally it will be regenerated when needed 446 | #!**/[Pp]ackages/repositories.config 447 | # NuGet v3's project.json files produces more ignorable files 448 | *.nuget.props 449 | *.nuget.targets 450 | 451 | # Microsoft Azure Build Output 452 | csx/ 453 | *.build.csdef 454 | 455 | # Microsoft Azure Emulator 456 | ecf/ 457 | rcf/ 458 | 459 | # Windows Store app package directories and files 460 | AppPackages/ 461 | BundleArtifacts/ 462 | Package.StoreAssociation.xml 463 | _pkginfo.txt 464 | *.appx 465 | *.appxbundle 466 | *.appxupload 467 | 468 | 469 | ############################ 470 | # CSHARP 471 | ############################ 472 | 473 | !?*.[Cc]ache/ 474 | 475 | # Others 476 | ClientBin/ 477 | ~$* 478 | *~ 479 | *.dbmdl 480 | *.dbproj.schemaview 481 | *.jfm 482 | *.pfx 483 | *.publishsettings 484 | orleans.codegen.cs 485 | 486 | # Including strong name files can present a security risk 487 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 488 | #*.snk 489 | 490 | # Since there are multiple workflows, uncomment next line to ignore bower_components 491 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 492 | #bower_components/ 493 | 494 | # RIA/Silverlight projects 495 | Generated_Code/ 496 | 497 | # Backup & report files from converting an old project file 498 | # to a newer Visual Studio version. Backup files are not needed, 499 | # because we have git ;-) 500 | _UpgradeReport_Files/ 501 | Backup*/ 502 | UpgradeLog*.XML 503 | UpgradeLog*.htm 504 | ServiceFabricBackup/ 505 | *.rptproj.bak 506 | 507 | # SQL Server files 508 | *.mdf 509 | *.ldf 510 | *.ndf 511 | 512 | # Business Intelligence projects 513 | *.rdl.data 514 | *.bim.layout 515 | *.bim_*.settings 516 | *.rptproj.rsuser 517 | *- [Bb]ackup.rdl 518 | *- [Bb]ackup ([0-9]).rdl 519 | *- [Bb]ackup ([0-9][0-9]).rdl 520 | 521 | # Microsoft Fakes 522 | FakesAssemblies/ 523 | 524 | # GhostDoc plugin setting file 525 | *.GhostDoc.xml 526 | 527 | # Node.js Tools for Visual Studio 528 | .ntvs_analysis.dat 529 | node_modules/ 530 | 531 | # Visual Studio 6 build log 532 | *.plg 533 | 534 | # Visual Studio 6 workspace options file 535 | *.opt 536 | 537 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 538 | *.vbw 539 | 540 | # Visual Studio LightSwitch build output 541 | **/*.HTMLClient/GeneratedArtifacts 542 | **/*.DesktopClient/GeneratedArtifacts 543 | **/*.DesktopClient/ModelManifest.xml 544 | **/*.Server/GeneratedArtifacts 545 | **/*.Server/ModelManifest.xml 546 | _Pvt_Extensions 547 | 548 | # Paket dependency manager 549 | .paket/paket.exe 550 | paket-files/ 551 | 552 | # FAKE - F# Make 553 | .fake/ 554 | 555 | # CodeRush personal settings 556 | .cr/personal 557 | 558 | # Python Tools for Visual Studio (PTVS) 559 | __pycache__/ 560 | *.pyc 561 | 562 | # Cake - Uncomment if you are using it 563 | # tools/** 564 | # !tools/packages.config 565 | 566 | # Tabs Studio 567 | *.tss 568 | 569 | # Telerik's JustMock configuration file 570 | *.jmconfig 571 | 572 | # BizTalk build output 573 | *.btp.cs 574 | *.btm.cs 575 | *.odx.cs 576 | *.xsd.cs 577 | 578 | # OpenCover UI analysis results 579 | OpenCover/ 580 | 581 | # Azure Stream Analytics local run output 582 | ASALocalRun/ 583 | 584 | # MSBuild Binary and Structured Log 585 | *.binlog 586 | 587 | # NVidia Nsight GPU debugger configuration file 588 | *.nvuser 589 | 590 | # MFractors (Xamarin productivity tool) working folder 591 | .mfractor/ 592 | 593 | # Local History for Visual Studio 594 | .localhistory/ 595 | 596 | # BeatPulse healthcheck temp database 597 | healthchecksdb 598 | 599 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 600 | MigrationBackup/ 601 | 602 | 603 | ############################ 604 | # MAC 605 | ############################ 606 | 607 | .DS_Store 608 | 609 | 610 | 611 | 612 | 613 | -------------------------------------------------------------------------------- /.gitpod.yml: -------------------------------------------------------------------------------- 1 | tasks: 2 | - name: setup 3 | env: 4 | CQLENG_ALLOW_SCHEMA_MANAGEMENT: 1 5 | FLASK_APP: api 6 | before: | 7 | echo "Setting up, please wait!" 8 | cd /workspace/bootcamp-fullstack-apps-with-cassandra 9 | sed -i '1,$s/sdkman_auto_answer=false/sdkman_auto_answer=true/' /home/gitpod/.sdkman/etc/config 10 | sed -i '1,$s/sdkman_selfupdate_enable=true/sdkman_selfupdate_enable=false/' /home/gitpod/.sdkman/etc/config 11 | sdk install java 21.2.0.r11-grl -y 12 | pip3 install cassandra-driver 13 | npm install cassandra-driver 14 | wget https://downloads.datastax.com/enterprise/cqlsh-astra.tar.gz \ 15 | && tar xvzf cqlsh-astra.tar.gz \ 16 | && rm -f cqlsh-astra.tar.gz 17 | cp ~/.zshrc ~/.zshrc.init 18 | if [ -f /workspace/bootcamp-fullstack-apps-with-cassandra/zshrcinit ]; then 19 | cp /workspace/bootcamp-fullstack-apps-with-cassandra/zshrcinit ~/.zshrc 20 | fi 21 | pip3 install -r week4-api-microservices/python/requirements.txt 22 | npm i --prefix week4-api-microservices/javascript 23 | ports: 24 | - port: 5005 25 | - port: 8080 26 | visibility: public 27 | - port: 8081 28 | onOpen: open-browser 29 | - port: 9191 30 | visibility: public 31 | onOpen: open-browser 32 | 33 | github: 34 | prebuilds: 35 | master: true 36 | branches: true 37 | pullRequests: true 38 | pullRequestsFromForks: false 39 | addCheck: true 40 | addComment: false 41 | addBadge: true 42 | addLabel: false 43 | 44 | vscode: 45 | extensions: 46 | - datastax.astra-for-vs-code 47 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "workbench.editor.enablePreviewFromCodeNavigation": true, 3 | "workbench.editor.enablePreviewFromQuickOpen": true, 4 | "workbench.editor.enablePreview": true, 5 | "workbench.editorAssociations": { 6 | "*.md": "vscode.markdown.preview.editor" 7 | }, 8 | "terminal.integrated.profiles.linux": { 9 | "cqlsh": { 10 | "path": "zsh", 11 | "args": ["-l"], 12 | "overrideName": true 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Build FullStack Applications with Apache Cassandra 2 | 3 | ## 🎓🔥 Introduction to NotOnly SQL Databases 4 | 5 | [![License Apache2](https://img.shields.io/hexpm/l/plug.svg)](http://www.apache.org/licenses/LICENSE-2.0) 6 | [![Discord](https://img.shields.io/discord/685554030159593522)](https://discord.com/widget?id=685554030159593522&theme=dark) 7 | 8 | 9 | 10 | * [Week I: Intro to Cassandra](https://github.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/tree/main/week1-intro-to-cassandra) 11 | * [Week II: Building Efficient Data Model with Apache Cassandra](https://github.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/tree/main/week2-data-modelling) 12 | * [Week III: Back End App Dev with Cassandra](week3-app-development) 13 | * [Week IV: APIs and Microservices with Cassandra](week4-api-microservices) 14 | 15 | 16 | -------------------------------------------------------------------------------- /astra.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Build Microservice and API", 3 | "description": "Learn how to build a backend for Cassandra, from data model to drivers to API exposition", 4 | "duration": "120 minutes", 5 | "skillLevel": "Intermediate", 6 | "language":["java", "python", "javascript"], 7 | "stack": ["spring", "fastAPI", "express"], 8 | "githubUrl": "https://github.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra", 9 | "badge": "https://media.badgr.com/uploads/badges/ca43050e-5e6e-4edc-8218-3c12e66de4af.png", 10 | "youTubeUrl": [ "https://www.youtube.com/watch?v=4djnV5wZSeg", 11 | "https://www.youtube.com/watch?v=8KmSN3KEspE", 12 | "https://www.youtube.com/watch?v=sGBFNDvk0pA", 13 | "https://www.youtube.com/watch?v=h7BEsnMk1_E" 14 | ], 15 | "tags": [ 16 | { "name": "java" }, 17 | { "name": "javascript" }, 18 | { "name": "python" }, 19 | { "name": "api" }, 20 | { "name":"astradb" }, 21 | { "name":"cassandra" } 22 | ], 23 | "category": "workshop", 24 | "usecases": [] 25 | } 26 | -------------------------------------------------------------------------------- /img/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/img/splash.png -------------------------------------------------------------------------------- /week1-intro-to-cassandra/LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /week1-intro-to-cassandra/images/astra-cql-console.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week1-intro-to-cassandra/images/astra-cql-console.gif -------------------------------------------------------------------------------- /week1-intro-to-cassandra/images/astra-create-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week1-intro-to-cassandra/images/astra-create-2.png -------------------------------------------------------------------------------- /week1-intro-to-cassandra/images/astra-create-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week1-intro-to-cassandra/images/astra-create-3.png -------------------------------------------------------------------------------- /week1-intro-to-cassandra/images/astra-create-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week1-intro-to-cassandra/images/astra-create-4.png -------------------------------------------------------------------------------- /week1-intro-to-cassandra/images/astra-create-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week1-intro-to-cassandra/images/astra-create-5.png -------------------------------------------------------------------------------- /week1-intro-to-cassandra/images/astra-create-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week1-intro-to-cassandra/images/astra-create-6.png -------------------------------------------------------------------------------- /week1-intro-to-cassandra/images/astra-create-7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week1-intro-to-cassandra/images/astra-create-7.png -------------------------------------------------------------------------------- /week1-intro-to-cassandra/images/astra-create-launch-now.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week1-intro-to-cassandra/images/astra-create-launch-now.png -------------------------------------------------------------------------------- /week1-intro-to-cassandra/images/astra-create-login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week1-intro-to-cassandra/images/astra-create-login.png -------------------------------------------------------------------------------- /week1-intro-to-cassandra/images/astra-create-register.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week1-intro-to-cassandra/images/astra-create-register.png -------------------------------------------------------------------------------- /week1-intro-to-cassandra/images/astra-login-cql-console.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week1-intro-to-cassandra/images/astra-login-cql-console.png -------------------------------------------------------------------------------- /week1-intro-to-cassandra/images/astra-use-cql-console-create-tables.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week1-intro-to-cassandra/images/astra-use-cql-console-create-tables.png -------------------------------------------------------------------------------- /week1-intro-to-cassandra/images/astra-use-cql-console-create-users-by-city.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week1-intro-to-cassandra/images/astra-use-cql-console-create-users-by-city.png -------------------------------------------------------------------------------- /week1-intro-to-cassandra/images/astra-use-cql-console-delete-from-comments-by-video.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week1-intro-to-cassandra/images/astra-use-cql-console-delete-from-comments-by-video.png -------------------------------------------------------------------------------- /week1-intro-to-cassandra/images/astra-use-cql-console-delete-from-cred.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week1-intro-to-cassandra/images/astra-use-cql-console-delete-from-cred.png -------------------------------------------------------------------------------- /week1-intro-to-cassandra/images/astra-use-cql-console-desc-keyspace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week1-intro-to-cassandra/images/astra-use-cql-console-desc-keyspace.png -------------------------------------------------------------------------------- /week1-intro-to-cassandra/images/astra-use-cql-console-describe-tables.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week1-intro-to-cassandra/images/astra-use-cql-console-describe-tables.png -------------------------------------------------------------------------------- /week1-intro-to-cassandra/images/astra-use-cql-console-insert-into-cred.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week1-intro-to-cassandra/images/astra-use-cql-console-insert-into-cred.png -------------------------------------------------------------------------------- /week1-intro-to-cassandra/images/astra-use-cql-console-select-from-tables.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week1-intro-to-cassandra/images/astra-use-cql-console-select-from-tables.png -------------------------------------------------------------------------------- /week1-intro-to-cassandra/images/astra-use-cql-console-update-comments-by-video.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week1-intro-to-cassandra/images/astra-use-cql-console-update-comments-by-video.png -------------------------------------------------------------------------------- /week1-intro-to-cassandra/images/astra-use-cql-console-use-killrvideo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week1-intro-to-cassandra/images/astra-use-cql-console-use-killrvideo.png -------------------------------------------------------------------------------- /week1-intro-to-cassandra/images/astra-use-cql-console.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week1-intro-to-cassandra/images/astra-use-cql-console.png -------------------------------------------------------------------------------- /week1-intro-to-cassandra/images/astra-view-cql-console.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week1-intro-to-cassandra/images/astra-view-cql-console.png -------------------------------------------------------------------------------- /week1-intro-to-cassandra/images/badge/intro-to-cassandra.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week1-intro-to-cassandra/images/badge/intro-to-cassandra.png -------------------------------------------------------------------------------- /week1-intro-to-cassandra/images/cluster_basics.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week1-intro-to-cassandra/images/cluster_basics.png -------------------------------------------------------------------------------- /week1-intro-to-cassandra/images/cql/01_desc_keyspaces.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week1-intro-to-cassandra/images/cql/01_desc_keyspaces.png -------------------------------------------------------------------------------- /week1-intro-to-cassandra/images/cql/02_use_chatsandra.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week1-intro-to-cassandra/images/cql/02_use_chatsandra.png -------------------------------------------------------------------------------- /week1-intro-to-cassandra/images/cql/03_user_table_created.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week1-intro-to-cassandra/images/cql/03_user_table_created.png -------------------------------------------------------------------------------- /week1-intro-to-cassandra/images/cql/04_post_tables_created.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week1-intro-to-cassandra/images/cql/04_post_tables_created.png -------------------------------------------------------------------------------- /week1-intro-to-cassandra/images/cql/05_selects.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week1-intro-to-cassandra/images/cql/05_selects.png -------------------------------------------------------------------------------- /week1-intro-to-cassandra/images/cql/06_updated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week1-intro-to-cassandra/images/cql/06_updated.png -------------------------------------------------------------------------------- /week1-intro-to-cassandra/images/cql/07_deleting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week1-intro-to-cassandra/images/cql/07_deleting.png -------------------------------------------------------------------------------- /week1-intro-to-cassandra/images/getting-started-with-cassandra.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week1-intro-to-cassandra/images/getting-started-with-cassandra.png -------------------------------------------------------------------------------- /week1-intro-to-cassandra/images/intro.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week1-intro-to-cassandra/images/intro.png -------------------------------------------------------------------------------- /week1-intro-to-cassandra/images/tutorials/astra-create-db.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week1-intro-to-cassandra/images/tutorials/astra-create-db.gif -------------------------------------------------------------------------------- /week1-intro-to-cassandra/images/tutorials/astra_signup.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week1-intro-to-cassandra/images/tutorials/astra_signup.gif -------------------------------------------------------------------------------- /week1-intro-to-cassandra/slides/Presentation.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week1-intro-to-cassandra/slides/Presentation.pdf -------------------------------------------------------------------------------- /week1-intro-to-cassandra/slides/WEEK1 - Introduction to Apache Cassandra.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week1-intro-to-cassandra/slides/WEEK1 - Introduction to Apache Cassandra.pdf -------------------------------------------------------------------------------- /week2-data-modelling/images/astra-cql-console.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week2-data-modelling/images/astra-cql-console.gif -------------------------------------------------------------------------------- /week2-data-modelling/images/create_keyspace_todos.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week2-data-modelling/images/create_keyspace_todos.gif -------------------------------------------------------------------------------- /week2-data-modelling/images/data_model_methodology_badge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week2-data-modelling/images/data_model_methodology_badge.png -------------------------------------------------------------------------------- /week2-data-modelling/images/datamodel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week2-data-modelling/images/datamodel.png -------------------------------------------------------------------------------- /week2-data-modelling/images/killrvideo_users_by_city.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week2-data-modelling/images/killrvideo_users_by_city.png -------------------------------------------------------------------------------- /week2-data-modelling/images/resuming.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week2-data-modelling/images/resuming.png -------------------------------------------------------------------------------- /week2-data-modelling/images/resuming2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week2-data-modelling/images/resuming2.png -------------------------------------------------------------------------------- /week2-data-modelling/images/sensors-1-er.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week2-data-modelling/images/sensors-1-er.png -------------------------------------------------------------------------------- /week2-data-modelling/images/sensors-2-aw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week2-data-modelling/images/sensors-2-aw.png -------------------------------------------------------------------------------- /week2-data-modelling/images/sensors-3-ld.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week2-data-modelling/images/sensors-3-ld.png -------------------------------------------------------------------------------- /week2-data-modelling/images/sensors-4-pd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week2-data-modelling/images/sensors-4-pd.png -------------------------------------------------------------------------------- /week2-data-modelling/images/shopping-cart-data-access-patterns.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week2-data-modelling/images/shopping-cart-data-access-patterns.png -------------------------------------------------------------------------------- /week2-data-modelling/images/todoapp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week2-data-modelling/images/todoapp.png -------------------------------------------------------------------------------- /week2-data-modelling/images/todoitems_table_created.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week2-data-modelling/images/todoitems_table_created.png -------------------------------------------------------------------------------- /week2-data-modelling/model.cql: -------------------------------------------------------------------------------- 1 | CREATE TABLE todoitems ( 2 | user_id TEXT, 3 | item_id TIMEUUID, 4 | title TEXT, 5 | completed BOOLEAN, 6 | PRIMARY KEY ((user_id), item_id) 7 | ) WITH CLUSTERING ORDER BY (item_id ASC); 8 | -------------------------------------------------------------------------------- /week2-data-modelling/slides/Presentation.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week2-data-modelling/slides/Presentation.pdf -------------------------------------------------------------------------------- /week2-data-modelling/slides/test: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /week3-app-development/.env.sample: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #TODO: REPLACE_ME with Astra Client Id and Secret 3 | 4 | export ASTRA_USERNAME= 5 | export ASTRA_PASSWORD= 6 | -------------------------------------------------------------------------------- /week3-app-development/images/AppDevSplash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week3-app-development/images/AppDevSplash.png -------------------------------------------------------------------------------- /week3-app-development/images/Filexplorer0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week3-app-development/images/Filexplorer0.png -------------------------------------------------------------------------------- /week3-app-development/images/OpenPorts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week3-app-development/images/OpenPorts.png -------------------------------------------------------------------------------- /week3-app-development/images/Verifytodos.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week3-app-development/images/Verifytodos.png -------------------------------------------------------------------------------- /week3-app-development/images/allow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week3-app-development/images/allow.png -------------------------------------------------------------------------------- /week3-app-development/images/api_badge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week3-app-development/images/api_badge.png -------------------------------------------------------------------------------- /week3-app-development/images/appdev_badge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week3-app-development/images/appdev_badge.png -------------------------------------------------------------------------------- /week3-app-development/images/astra-create-token.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week3-app-development/images/astra-create-token.gif -------------------------------------------------------------------------------- /week3-app-development/images/astra-token.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week3-app-development/images/astra-token.png -------------------------------------------------------------------------------- /week3-app-development/images/bootcamp_badge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week3-app-development/images/bootcamp_badge.png -------------------------------------------------------------------------------- /week3-app-development/images/dotenv1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week3-app-development/images/dotenv1.png -------------------------------------------------------------------------------- /week3-app-development/images/dotenv2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week3-app-development/images/dotenv2.png -------------------------------------------------------------------------------- /week3-app-development/images/dotenv3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week3-app-development/images/dotenv3.png -------------------------------------------------------------------------------- /week3-app-development/images/dotenv4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week3-app-development/images/dotenv4.png -------------------------------------------------------------------------------- /week3-app-development/images/dotenv5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week3-app-development/images/dotenv5.png -------------------------------------------------------------------------------- /week3-app-development/images/gitpod-01-home-annotated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week3-app-development/images/gitpod-01-home-annotated.png -------------------------------------------------------------------------------- /week3-app-development/images/gitpod-01-home-plain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week3-app-development/images/gitpod-01-home-plain.png -------------------------------------------------------------------------------- /week3-app-development/images/gitpod-02-url.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week3-app-development/images/gitpod-02-url.png -------------------------------------------------------------------------------- /week3-app-development/images/gitpod-bootcampappdev-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week3-app-development/images/gitpod-bootcampappdev-1.jpg -------------------------------------------------------------------------------- /week3-app-development/images/gitpodpreferences1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week3-app-development/images/gitpodpreferences1.png -------------------------------------------------------------------------------- /week3-app-development/images/secureconnectbundle1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week3-app-development/images/secureconnectbundle1.png -------------------------------------------------------------------------------- /week3-app-development/images/secureconnectbundle2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week3-app-development/images/secureconnectbundle2.png -------------------------------------------------------------------------------- /week3-app-development/images/secureconnectbundle3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week3-app-development/images/secureconnectbundle3.png -------------------------------------------------------------------------------- /week3-app-development/images/shells.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week3-app-development/images/shells.png -------------------------------------------------------------------------------- /week3-app-development/java/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | com.datastax.workshop 7 | crud 8 | 1.0-SNAPSHOT 9 | jar 10 | 11 | 12 | UTF-8 13 | 11 14 | 15 | 4.13.0 16 | 17 | 5.6.2 18 | 1.6.2 19 | 1.2.3 20 | 21 | 22 | 23 | 24 | com.datastax.oss 25 | java-driver-core 26 | ${cassandra-java-driver.version} 27 | 28 | 29 | com.datastax.oss 30 | java-driver-query-builder 31 | ${cassandra-java-driver.version} 32 | 33 | 34 | com.datastax.oss 35 | java-driver-mapper-runtime 36 | ${cassandra-java-driver.version} 37 | 38 | 39 | com.datastax.oss 40 | java-driver-mapper-processor 41 | ${cassandra-java-driver.version} 42 | 43 | 44 | 45 | 46 | org.junit.jupiter 47 | junit-jupiter-api 48 | ${junit.jupiter.version} 49 | test 50 | 51 | 52 | org.junit.jupiter 53 | junit-jupiter-engine 54 | ${junit.jupiter.version} 55 | test 56 | 57 | 58 | org.junit.platform 59 | junit-platform-runner 60 | ${junit.platform.version} 61 | test 62 | 63 | 64 | ch.qos.logback 65 | logback-classic 66 | ${logback.version} 67 | 68 | 69 | 70 | 71 | 72 | 73 | org.apache.maven.plugins 74 | maven-compiler-plugin 75 | 3.8.1 76 | 77 | ${java.version} 78 | ${java.version} 79 | ${java.version} 80 | false 81 | 82 | 83 | com.datastax.oss 84 | java-driver-mapper-processor 85 | ${cassandra-java-driver.version} 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /week3-app-development/java/src/main/java/com/datastax/workshop/DBConnection.java: -------------------------------------------------------------------------------- 1 | package com.datastax.workshop; 2 | 3 | /* 4 | * WARNING: THIS FILE IS GOING TO BE OVERWRITTEN 5 | * you used when you created the ASTRA instance. 6 | */ 7 | public interface DBConnection { 8 | 9 | // This is the Zip file you downloaded 10 | String SECURE_CONNECT_BUNDLE = "/workspace/bootcamp-fullstack-apps-with-cassandra/secure-connect-workshops.zip"; 11 | 12 | // This is the "Client Id" value you obtained earlier 13 | String USERNAME = "$ASTRA_USERNAME"; 14 | 15 | // This is the "Client Secret" value you obtained earlier 16 | String PASSWORD = "$ASTRA_PASSWORD"; 17 | 18 | // This is the keyspace name, recommended value was killrvideo 19 | String KEYSPACE = "todos"; 20 | 21 | } 22 | -------------------------------------------------------------------------------- /week3-app-development/java/src/main/java/com/datastax/workshop/DBConnection.java.init: -------------------------------------------------------------------------------- 1 | package com.datastax.workshop; 2 | 3 | /* 4 | * 5 | * THIS FILE WILL BE OVERWRITTEN. DO NOT MAKE ANY CHANGES HERE. 6 | */ 7 | public interface DBConnection { 8 | 9 | // This is the Zip file you downloaded 10 | String SECURE_CONNECT_BUNDLE = "/workspace/bootcamp-fullstack-apps-with-cassandra/secure-connect-workshops.zip"; 11 | 12 | // This is the "Client Id" value you obtained earlier 13 | String USERNAME = "$ASTRA_USERNAME"; 14 | 15 | // This is the "Client Secret" value you obtained earlier 16 | String PASSWORD = "$ASTRA_PASSWORD"; 17 | 18 | // This is the keyspace name, recommended value was killrvideo 19 | String KEYSPACE = "todos"; 20 | 21 | } 22 | -------------------------------------------------------------------------------- /week3-app-development/java/src/test/java/com/datastax/workshop/Ex06_Connect_to_Astra.java: -------------------------------------------------------------------------------- 1 | package com.datastax.workshop; 2 | 3 | import java.io.File; 4 | import java.nio.file.Paths; 5 | 6 | import org.junit.jupiter.api.Assertions; 7 | import org.junit.jupiter.api.Test; 8 | import org.junit.platform.runner.JUnitPlatform; 9 | import org.junit.runner.RunWith; 10 | 11 | import com.datastax.oss.driver.api.core.CqlSession; 12 | 13 | @RunWith(JUnitPlatform.class) 14 | public class Ex06_Connect_to_Astra { 15 | 16 | @Test 17 | public void should_connect_to_astra() { 18 | System.out.println("[should_connect_to_astra] ========================================"); 19 | System.out.println("[should_connect_to_astra] Start Exercise"); 20 | // Given 21 | Assertions.assertFalse( 22 | DBConnection.SECURE_CONNECT_BUNDLE.equals(""), 23 | "Please fill DBConnection class constants" 24 | ); 25 | Assertions.assertFalse( 26 | DBConnection.KEYSPACE.equals(""), 27 | "Please fill DBConnection class constants" 28 | ); 29 | Assertions.assertFalse( 30 | DBConnection.USERNAME.equals(""), 31 | "Please fill DBConnection class constants" 32 | ); 33 | Assertions.assertFalse( 34 | DBConnection.PASSWORD.equals(""), 35 | "Please fill DBConnection class constants" 36 | ); 37 | Assertions.assertTrue( 38 | new File(DBConnection.SECURE_CONNECT_BUNDLE).exists(), 39 | "File '" + 40 | DBConnection.SECURE_CONNECT_BUNDLE + 41 | "' has not been found\n" + 42 | "To run this sample you need to download the secure bundle file from ASTRA WebPage\n" + 43 | "More info here:" 44 | ); 45 | System.out.println("[should_connect_to_astra] File '" + DBConnection.SECURE_CONNECT_BUNDLE + "' located"); 46 | 47 | // When 48 | try ( 49 | CqlSession cqlSession = CqlSession 50 | .builder() 51 | .withCloudSecureConnectBundle( 52 | Paths.get(DBConnection.SECURE_CONNECT_BUNDLE) 53 | ) 54 | .withAuthCredentials(DBConnection.USERNAME, DBConnection.PASSWORD) 55 | .withKeyspace(DBConnection.KEYSPACE) 56 | .build() 57 | ) { 58 | // Then 59 | System.out.println("[should_connect_to_astra] Connected with Keyspace " + cqlSession.getKeyspace().get()); 60 | } 61 | System.out.println("[should_connect_to_astra] [OK]"); 62 | System.out.println("[should_connect_to_astra] ========================================"); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /week3-app-development/java/src/test/java/com/datastax/workshop/Ex6a_Create_Table.java: -------------------------------------------------------------------------------- 1 | package com.datastax.workshop; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.junit.platform.runner.JUnitPlatform; 5 | import org.junit.runner.RunWith; 6 | 7 | import com.datastax.oss.driver.api.core.CqlSession; 8 | 9 | @RunWith(JUnitPlatform.class) 10 | public class Ex6a_Create_Table implements DBConnection { 11 | 12 | @Test 13 | public void should_create_a_table_1() { 14 | System.out.println("[should_create_a_table_1] ========================================"); 15 | System.out.println("[should_create_a_table_1] Start exercise"); 16 | 17 | try (CqlSession cqlSession = TestUtils.createCqlSession()) { 18 | String query = 19 | "CREATE TABLE IF NOT EXISTS todoitems (" + 20 | "user_id TEXT," + 21 | "item_id TIMEUUID," + 22 | "title TEXT," + 23 | "completed BOOLEAN," + 24 | "PRIMARY KEY ((user_id), item_id)" + 25 | ") WITH CLUSTERING ORDER BY (item_id ASC);"; 26 | cqlSession.execute(query); 27 | } 28 | 29 | System.out.println("[should_create_a_table_1] [OK]"); 30 | System.out.println("[should_create_a_table_1] ========================================"); 31 | System.out.println(); 32 | } 33 | 34 | @Test 35 | public void should_create_a_table_2() { 36 | System.out.println("[should_create_a_table_2] ========================================"); 37 | System.out.println("[should_create_a_table_2] Start exercise"); 38 | try (CqlSession cqlSession = TestUtils.createCqlSession()) { 39 | TestUtils.createTableTodoItem(cqlSession); 40 | } 41 | System.out.println("[should_create_a_table_2] [OK]"); 42 | System.out.println("[should_create_a_table_2] ========================================"); 43 | } 44 | 45 | 46 | } 47 | -------------------------------------------------------------------------------- /week3-app-development/java/src/test/java/com/datastax/workshop/Ex6b_Insert_Todos.java: -------------------------------------------------------------------------------- 1 | package com.datastax.workshop; 2 | 3 | import java.util.UUID; 4 | 5 | import org.junit.jupiter.api.MethodOrderer.OrderAnnotation; 6 | import org.junit.jupiter.api.Order; 7 | import org.junit.jupiter.api.Test; 8 | import org.junit.jupiter.api.TestMethodOrder; 9 | import org.junit.platform.runner.JUnitPlatform; 10 | import org.junit.runner.RunWith; 11 | 12 | import com.datastax.oss.driver.api.core.CqlSession; 13 | import com.datastax.oss.driver.api.core.cql.PreparedStatement; 14 | import com.datastax.oss.driver.api.core.cql.SimpleStatement; 15 | import com.datastax.oss.driver.api.core.uuid.Uuids; 16 | 17 | @RunWith(JUnitPlatform.class) 18 | @TestMethodOrder(OrderAnnotation.class) 19 | public class Ex6b_Insert_Todos implements DBConnection { 20 | 21 | @Test 22 | @Order(1) 23 | public void should_insert_todos_1() { 24 | System.out.println("[should_insert_todos_1] ========================================"); 25 | System.out.println("[should_insert_todos_1] Start with static CQL"); 26 | try (CqlSession cqlSession = TestUtils.createCqlSession()) { 27 | cqlSession.execute( 28 | "INSERT INTO todoitems (user_id, item_id, completed, title) " + 29 | "VALUES ( 'john', 11111111-5cff-11ec-be16-1fedb0dfd057, true, 'Walk the dog');" 30 | ); 31 | 32 | System.out.println("[should_insert_todos_1] Task '11111111-5cff-11ec-be16-1fedb0dfd057' has been inserted"); 33 | cqlSession.execute( 34 | "INSERT INTO todoitems (user_id, item_id, completed, title) " + 35 | "VALUES ( 'john', 22222222-5cff-11ec-be16-1fedb0dfd057, false, 'Have lunch tomorrow');" 36 | ); 37 | System.out.println("[should_insert_todos_1] Task '22222222-5cff-11ec-be16-1fedb0dfd057' has been inserted"); 38 | cqlSession.execute( 39 | "INSERT INTO todoitems (user_id, item_id, completed, title) " + 40 | "VALUES ( 'mary', 33333333-5cff-11ec-be16-1fedb0dfd057, true, 'Attend the workshop');" 41 | ); 42 | System.out.println("[should_insert_todos_1] Task '33333333-5cff-11ec-be16-1fedb0dfd057' has been inserted"); 43 | } 44 | System.out.println("[should_insert_todos_1] [OK]"); 45 | System.out.println("[should_insert_todos_1] ========================================\n"); 46 | } 47 | 48 | @Test 49 | @Order(2) 50 | public void should_create_task_cql() { 51 | System.out.println("[should_create_task_cql] ========================================"); 52 | System.out.println("[should_create_task_cql] Start Exercise"); 53 | try (CqlSession cqlSession = TestUtils.createCqlSession()) { 54 | cqlSession.execute("" 55 | + "INSERT INTO todoitems (user_id, item_id, title, completed) " 56 | + "VALUES('createTask'," + Uuids.timeBased() + ",'Task CQL',FALSE)"); 57 | } 58 | System.out.println("[should_create_task_cql] [OK]"); 59 | System.out.println("[should_create_task_cql] ========================================\n"); 60 | } 61 | 62 | @Test 63 | @Order(3) 64 | public void should_insert_task_simple_position() { 65 | System.out.println("[should_insert_task_simple_position] ========================================"); 66 | System.out.println("[should_insert_task_simple_position] Start Exercise"); 67 | try (CqlSession cqlSession = TestUtils.createCqlSession()) { 68 | UUID itemId = Uuids.timeBased(); 69 | cqlSession.execute(SimpleStatement.builder("" 70 | + "INSERT INTO todoitems (user_id, item_id, title, completed) " 71 | + "VALUES(?,?,?,?)") 72 | .addPositionalValue("createTask") 73 | .addPositionalValue(itemId) 74 | .addPositionalValue("Task Simple Statement position") 75 | .addPositionalValue(Boolean.FALSE) 76 | .build()); 77 | System.out.println("[should_insert_task_simple_position] Task " + itemId + " has been inserted"); 78 | } 79 | System.out.println("[should_insert_task_simple_position] [OK]"); 80 | System.out.println("[should_insert_task_simple_position] ========================================\n"); 81 | } 82 | 83 | @Test 84 | @Order(4) 85 | public void should_insert_task_simple_label() { 86 | System.out.println("[should_insert_task_simple_label] ========================================"); 87 | System.out.println("[should_insert_task_simple_label] Start Exercise"); 88 | try (CqlSession cqlSession = TestUtils.createCqlSession()) { 89 | UUID itemId = Uuids.timeBased(); 90 | cqlSession.execute(SimpleStatement.builder("" 91 | + "INSERT INTO todoitems (user_id, item_id, title, completed) " 92 | + "VALUES(:userid,:itemid,:title,:completed)") 93 | .addNamedValue("userid","createTask") 94 | .addNamedValue("itemid",itemId) 95 | .addNamedValue("title","Task Simple Statement name") 96 | .addNamedValue("completed", Boolean.FALSE) 97 | .build()); 98 | System.out.println("[should_insert_task_simple_label] Task " + itemId + " has been inserted"); 99 | } 100 | System.out.println("[should_insert_task_simple_label] [OK]"); 101 | System.out.println("[should_insert_task_simple_label] ========================================\n"); 102 | } 103 | 104 | @Test 105 | @Order(5) 106 | public void should_insert_task_prepared() { 107 | System.out.println("[should_insert_task_prepared] ========================================"); 108 | System.out.println("[should_insert_task_prepared] Start Exercise"); 109 | // When 110 | try (CqlSession cqlSession = TestUtils.createCqlSession()) { 111 | PreparedStatement ps = cqlSession.prepare( 112 | "INSERT INTO todoitems (user_id, item_id, title, completed) " 113 | + "VALUES(?,?,?,?)"); 114 | UUID itemId = Uuids.timeBased(); 115 | cqlSession.execute(ps.bind("createTask", itemId, "Prepared Task", Boolean.FALSE)); 116 | System.out.println("[should_insert_task_prepared] Task " + itemId + " has been inserted"); 117 | } 118 | System.out.println("[should_insert_task_prepared] [OK]"); 119 | System.out.println("[should_insert_task_prepared] ========================================\n"); 120 | } 121 | 122 | } 123 | -------------------------------------------------------------------------------- /week3-app-development/java/src/test/java/com/datastax/workshop/Ex6c_Get_All_Todos.java: -------------------------------------------------------------------------------- 1 | package com.datastax.workshop; 2 | 3 | import org.junit.jupiter.api.MethodOrderer.OrderAnnotation; 4 | import org.junit.jupiter.api.Order; 5 | import org.junit.jupiter.api.Test; 6 | import org.junit.jupiter.api.TestMethodOrder; 7 | import org.junit.platform.runner.JUnitPlatform; 8 | import org.junit.runner.RunWith; 9 | 10 | import com.datastax.oss.driver.api.core.CqlSession; 11 | import com.datastax.oss.driver.api.core.cql.ResultSet; 12 | import com.datastax.oss.driver.api.core.cql.Row; 13 | import com.datastax.oss.driver.api.core.cql.SimpleStatement; 14 | 15 | import java.util.ArrayList; 16 | import java.util.List; 17 | import java.util.UUID; 18 | 19 | @RunWith(JUnitPlatform.class) 20 | @TestMethodOrder(OrderAnnotation.class) 21 | public class Ex6c_Get_All_Todos implements DBConnection { 22 | 23 | @Test 24 | @Order(1) 25 | public void should_get_todos_1() { 26 | System.out.println("[should_get_todos_1] ========================================"); 27 | System.out.println("[should_get_todos_1] Looking for John's Tasks"); 28 | try (CqlSession cqlSession = TestUtils.createCqlSession()) { 29 | ResultSet rs = cqlSession.execute( 30 | "SELECT * FROM todoitems WHERE user_id = 'john';" 31 | ); 32 | for (Row row : rs) { 33 | System.out.println("[should_get_todos_1] " + 34 | row.getUuid("item_id") + ": " + 35 | row.getString("title")); 36 | } 37 | } 38 | System.out.println("[should_get_todos_1] [OK]"); 39 | System.out.println("[should_get_todos_1] ========================================\n"); 40 | } 41 | 42 | @Test 43 | @Order(2) 44 | public void should_get_todos_2() { 45 | System.out.println("[should_get_todos_2] ========================================"); 46 | System.out.println("[should_get_todos_2] Looking for 'createTask' Tasks"); 47 | try (CqlSession cqlSession = TestUtils.createCqlSession()) { 48 | SimpleStatement query = SimpleStatement.builder("" 49 | + "SELECT item_id,title,completed " 50 | + "FROM todoitems WHERE user_id=?") 51 | .addPositionalValue("createTask") 52 | .build(); 53 | cqlSession.execute(query).forEach(row -> 54 | System.out.println("[should_get_todos_2] " + 55 | row.getUuid("item_id") + ": " + 56 | row.getString("title"))); 57 | } 58 | System.out.println("[should_get_todos_2] [OK]"); 59 | System.out.println("[should_get_todos_2] ========================================\n"); 60 | } 61 | @Test 62 | @Order(3) 63 | public void should_get_todos_3() { 64 | class TodoItem { 65 | public String user_id; 66 | public UUID item_id; 67 | public String title; 68 | public Boolean completed; 69 | 70 | TodoItem(String u, UUID i, String t, Boolean c) { 71 | this.user_id = u; 72 | this.item_id = i; 73 | this.title = t; 74 | this.completed = c; 75 | } 76 | } 77 | System.out.println("[should_get_todos_3 with simple object mapper]================="); 78 | System.out.println("[should_get_todos_3] Looking for 'createTask' Tasks"); 79 | try (CqlSession cqlSession = TestUtils.createCqlSession()) { 80 | ResultSet rs = cqlSession.execute( 81 | "SELECT * FROM todoitems WHERE user_id='createTask';" 82 | ); 83 | 84 | List result = new ArrayList<>(); 85 | 86 | // Simple Object Mapper 87 | 88 | rs.forEach(item -> result.add( 89 | new TodoItem(item.getString("user_id"), 90 | item.getUuid("item_id"), 91 | item.getString("title"), 92 | item.getBoolean("completed")) 93 | )); 94 | 95 | for (TodoItem item: result) { 96 | System.out.println("Todoitem title = " + item.title); 97 | } 98 | } 99 | System.out.println("[should_get_todos_3 with simple object mapper] [OK]"); 100 | System.out.println("[should_get_todos_3] ========================================\n"); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /week3-app-development/java/src/test/java/com/datastax/workshop/Ex6d_Update_A_Todo.java: -------------------------------------------------------------------------------- 1 | package com.datastax.workshop; 2 | 3 | import java.util.UUID; 4 | 5 | import org.junit.jupiter.api.MethodOrderer.OrderAnnotation; 6 | import org.junit.jupiter.api.Order; 7 | import org.junit.jupiter.api.Test; 8 | import org.junit.jupiter.api.TestMethodOrder; 9 | import org.junit.platform.runner.JUnitPlatform; 10 | import org.junit.runner.RunWith; 11 | 12 | import com.datastax.oss.driver.api.core.CqlSession; 13 | import com.datastax.oss.driver.api.core.cql.SimpleStatement; 14 | 15 | @RunWith(JUnitPlatform.class) 16 | @TestMethodOrder(OrderAnnotation.class) 17 | public class Ex6d_Update_A_Todo implements DBConnection { 18 | 19 | @Test 20 | @Order(1) 21 | public void should_update_todos() { 22 | System.out.println("[should_update_todos] ========================================"); 23 | System.out.println("[should_update_todos] Start Exercise"); 24 | // When 25 | try (CqlSession cqlSession = TestUtils.createCqlSession()) { 26 | System.out.println("[should_update_todos] Before:"); 27 | TestUtils.showTasks(cqlSession, "john"); 28 | cqlSession.execute("" 29 | + "UPDATE todoitems " 30 | + "SET completed = true " 31 | + "WHERE user_id = 'john' " 32 | + "AND item_id = 22222222-5cff-11ec-be16-1fedb0dfd057;" 33 | ); 34 | System.out.println("[should_update_todos] After:"); 35 | TestUtils.showTasks(cqlSession, "john"); 36 | } 37 | System.out.println("[should_update_todos] [OK]"); 38 | System.out.println("[should_update_todos] ========================================\n"); 39 | } 40 | 41 | @Test 42 | @Order(2) 43 | public void should_update_todos_2() { 44 | System.out.println("[should_update_todos_2] ========================================"); 45 | System.out.println("[should_update_todos_2] Start Exercise"); 46 | try (CqlSession cqlSession = TestUtils.createCqlSession()) { 47 | cqlSession.execute(SimpleStatement.builder("" 48 | + "UPDATE todoitems " 49 | + "SET completed=:flag " 50 | + "WHERE user_id=:userId AND item_id=:itemId") 51 | .addNamedValue("flag", false) 52 | .addNamedValue("userId", "john") 53 | .addNamedValue("itemId", UUID.fromString("11111111-5cff-11ec-be16-1fedb0dfd057")) 54 | .build()); 55 | TestUtils.showTasks(cqlSession, "john"); 56 | } 57 | System.out.println("[should_update_todos_2] [OK]"); 58 | System.out.println("[should_update_todos_2] ========================================\n"); 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /week3-app-development/java/src/test/java/com/datastax/workshop/Ex6e_Remove_A_Todo.java: -------------------------------------------------------------------------------- 1 | package com.datastax.workshop; 2 | 3 | import java.util.UUID; 4 | 5 | import org.junit.jupiter.api.Test; 6 | import org.junit.platform.runner.JUnitPlatform; 7 | import org.junit.runner.RunWith; 8 | 9 | import com.datastax.oss.driver.api.core.CqlSession; 10 | import com.datastax.oss.driver.api.core.cql.SimpleStatement; 11 | 12 | @RunWith(JUnitPlatform.class) 13 | public class Ex6e_Remove_A_Todo implements DBConnection { 14 | 15 | @Test 16 | public void should_remove_todos() { 17 | System.out.println("[should_remove_todos] ========================================"); 18 | System.out.println("[should_remove_todos] Start Exercise"); 19 | try (CqlSession cqlSession = TestUtils.createCqlSession()) { 20 | deleteTask(cqlSession, "john", UUID.fromString("11111111-5cff-11ec-be16-1fedb0dfd057")); 21 | TestUtils.showTasks(cqlSession, "john"); 22 | } 23 | System.out.println("[should_remove_todos] [OK]"); 24 | System.out.println("[should_remove_todos] ========================================\n"); 25 | } 26 | 27 | private void deleteTask(CqlSession cqlSession, String user, UUID taskId) { 28 | cqlSession.execute(SimpleStatement.builder("" 29 | + "DELETE FROM todoitems " 30 | + "WHERE user_id=? " 31 | + "AND item_id=?") 32 | .addPositionalValue(user) 33 | .addPositionalValue(taskId) 34 | .build()); 35 | } 36 | 37 | 38 | } 39 | -------------------------------------------------------------------------------- /week3-app-development/java/src/test/java/com/datastax/workshop/Ex6f_Remove_All_Todos.java: -------------------------------------------------------------------------------- 1 | package com.datastax.workshop; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.junit.platform.runner.JUnitPlatform; 5 | import org.junit.runner.RunWith; 6 | 7 | import com.datastax.oss.driver.api.core.CqlSession; 8 | 9 | @RunWith(JUnitPlatform.class) 10 | public class Ex6f_Remove_All_Todos implements DBConnection { 11 | 12 | @Test 13 | public void should_remote_all_todos() { 14 | System.out.println("[should_remove_all_todos] ========================================"); 15 | System.out.println("[should_remove_all_todos] Start Exercise"); 16 | try (CqlSession cqlSession = TestUtils.createCqlSession()) { 17 | cqlSession.execute("TRUNCATE TABLE todoitems;"); 18 | TestUtils.showTasks(cqlSession, "john"); 19 | } 20 | System.out.println("[should_remove_all_todos] [OK]"); 21 | System.out.println("[should_remove_all_todos] ========================================\n"); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /week3-app-development/java/src/test/java/com/datastax/workshop/TestUtils.java: -------------------------------------------------------------------------------- 1 | package com.datastax.workshop; 2 | 3 | import static com.datastax.oss.driver.api.core.type.DataTypes.BOOLEAN; 4 | import static com.datastax.oss.driver.api.core.type.DataTypes.TEXT; 5 | import static com.datastax.oss.driver.api.core.type.DataTypes.TIMEUUID; 6 | import static com.datastax.oss.driver.api.querybuilder.SchemaBuilder.createTable; 7 | 8 | import java.nio.file.Paths; 9 | 10 | import com.datastax.oss.driver.api.core.CqlSession; 11 | import com.datastax.oss.driver.api.core.cql.SimpleStatement; 12 | import com.datastax.oss.driver.api.core.metadata.schema.ClusteringOrder; 13 | 14 | public class TestUtils { 15 | 16 | public static final String TABLE_TODOITEMS = "todoitems"; 17 | public static final String TODO_USER_ID = "user_id"; 18 | public static final String TODO_ITEM_ID = "item_id"; 19 | public static final String TODO_TITLE = "title"; 20 | public static final String TODO_COMPLETED = "completed"; 21 | public static final String TODO_OFFSET = "offset"; 22 | 23 | public static CqlSession createCqlSession() { 24 | return CqlSession 25 | .builder() 26 | .withCloudSecureConnectBundle(Paths.get(DBConnection.SECURE_CONNECT_BUNDLE)) 27 | .withAuthCredentials(DBConnection.USERNAME, DBConnection.PASSWORD) 28 | .withKeyspace(DBConnection.KEYSPACE) 29 | .build(); 30 | } 31 | 32 | /** 33 | * CREATE TABLE todoitems IF NOT EXISTS ( 34 | * user_id text, 35 | * item_id timeuuid, 36 | * completed boolean, 37 | * title text, 38 | * PRIMARY KEY ((user_id), item_id) 39 | * ) WITH CLUSTERING ORDER BY (item_id ASC); 40 | */ 41 | public static void createTableTodoItem(CqlSession cqlSession) { 42 | cqlSession.execute( 43 | createTable(TABLE_TODOITEMS).ifNotExists() 44 | .withPartitionKey(TODO_USER_ID, TEXT) 45 | .withClusteringColumn(TODO_ITEM_ID, TIMEUUID) 46 | .withColumn(TODO_COMPLETED, BOOLEAN) 47 | .withColumn(TODO_TITLE, TEXT) 48 | .withClusteringOrder(TODO_ITEM_ID, ClusteringOrder.ASC) 49 | .build()); 50 | } 51 | 52 | 53 | public static void showTasks(CqlSession cqlSession, String user) { 54 | cqlSession.execute(SimpleStatement 55 | .builder("SELECT item_id, completed, title FROM todoitems WHERE user_id=?") 56 | .addPositionalValue(user).build()) 57 | .forEach(row -> { 58 | System.out.println("+" + row.getUuid("item_id") + ": " + 59 | row.getBoolean("completed") + ":" + 60 | row.getString("title")); 61 | }); 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /week3-app-development/java/src/test/resources/logback-test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | %d{HH:mm:ss.SSS} %magenta(%-5level) %cyan(%-10logger) : %msg%n 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /week3-app-development/javascript/Ex06_Connect_to_Astra.js: -------------------------------------------------------------------------------- 1 | const { client } = require("./connection"); 2 | 3 | console.log("========================================"); 4 | console.log("Start exercise"); 5 | 6 | (async () => { 7 | try { 8 | const result = await client.execute("SELECT * FROM system.local"); 9 | result.rows.forEach((row) => { 10 | console.log( 11 | "Your are now connected to Astra '%s' at '%s'", 12 | row.cluster_name, 13 | row.data_center 14 | ); 15 | }); 16 | console.log("SUCCESS"); 17 | } catch (e) { 18 | console.log(e); 19 | } 20 | console.log("========================================"); 21 | process.exit(); 22 | })(); 23 | -------------------------------------------------------------------------------- /week3-app-development/javascript/Ex6a_Create_Table.js: -------------------------------------------------------------------------------- 1 | const { client } = require("./connection"); 2 | 3 | console.log("========================================"); 4 | console.log("Start exercise"); 5 | 6 | (async () => { 7 | try { 8 | await client.execute(` 9 | CREATE TABLE IF NOT EXISTS todoitems ( 10 | user_id TEXT, 11 | item_id TIMEUUID, 12 | title TEXT, 13 | completed BOOLEAN, 14 | PRIMARY KEY ((user_id), item_id) 15 | ) WITH CLUSTERING ORDER BY (item_id ASC);`); 16 | console.log("SUCCESS"); 17 | } catch (e) { 18 | console.log(e); 19 | } 20 | console.log("========================================"); 21 | process.exit(); 22 | })(); 23 | -------------------------------------------------------------------------------- /week3-app-development/javascript/Ex6b_Insert_Todos.js: -------------------------------------------------------------------------------- 1 | const { client } = require("./connection"); 2 | 3 | console.log("========================================"); 4 | console.log("Start exercise"); 5 | 6 | (async () => { 7 | try { 8 | await client.execute( 9 | "INSERT INTO todoitems (user_id, item_id, completed, title) VALUES ( 'john', 11111111-5cff-11ec-be16-1fedb0dfd057, true, 'Walk the dog');" 10 | ); 11 | await client.execute( 12 | "INSERT INTO todoitems (user_id, item_id, completed, title) VALUES ( 'john', 22222222-5cff-11ec-be16-1fedb0dfd057, false, 'Have lunch tomorrow');" 13 | ); 14 | await client.execute( 15 | "INSERT INTO todoitems (user_id, item_id, completed, title) VALUES ( 'mary', 33333333-5cff-11ec-be16-1fedb0dfd057, true, 'Attend the workshop');" 16 | ); 17 | console.log("SUCCESS"); 18 | } catch (e) { 19 | console.log(e); 20 | } 21 | console.log("========================================"); 22 | process.exit(); 23 | })(); 24 | -------------------------------------------------------------------------------- /week3-app-development/javascript/Ex6c_Get_All_Todos.js: -------------------------------------------------------------------------------- 1 | const { client } = require("./connection"); 2 | 3 | console.log("========================================"); 4 | console.log("Start exercise"); 5 | 6 | (async () => { 7 | try { 8 | const result = await client.execute( 9 | "SELECT * FROM todoitems WHERE user_id = 'john';" 10 | ); 11 | result.rows.forEach((row) => { 12 | console.log(row); 13 | }); 14 | console.log("SUCCESS"); 15 | } catch (e) { 16 | console.log(e); 17 | } 18 | console.log("========================================"); 19 | process.exit(); 20 | })(); 21 | -------------------------------------------------------------------------------- /week3-app-development/javascript/Ex6d_Update_A_Todo.js: -------------------------------------------------------------------------------- 1 | const { client } = require("./connection"); 2 | 3 | console.log("========================================"); 4 | console.log("Start exercise"); 5 | 6 | (async () => { 7 | try { 8 | await client.execute( 9 | "UPDATE todoitems SET completed = true WHERE user_id = 'john' AND item_id = 22222222-5cff-11ec-be16-1fedb0dfd057;" 10 | ); 11 | const result = await client.execute( 12 | "SELECT toTimestamp(item_id), completed, title FROM todoitems WHERE user_id = 'john';" 13 | ); 14 | result.rows.forEach((row) => { 15 | console.log(row); 16 | }); 17 | console.log("SUCCESS"); 18 | } catch (e) { 19 | console.log(e); 20 | } 21 | console.log("========================================"); 22 | process.exit(); 23 | })(); 24 | -------------------------------------------------------------------------------- /week3-app-development/javascript/Ex6e_Remove_A_Todo.js: -------------------------------------------------------------------------------- 1 | const { client } = require("./connection"); 2 | 3 | console.log("========================================"); 4 | console.log("Start exercise"); 5 | 6 | (async () => { 7 | try { 8 | await client.execute( 9 | "DELETE FROM todoitems WHERE user_id='john' AND item_id=11111111-5cff-11ec-be16-1fedb0dfd057;" 10 | ); 11 | const result = await client.execute( 12 | "SELECT toTimestamp(item_id), completed, title FROM todoitems WHERE user_id = 'john';" 13 | ); 14 | result.rows.forEach((row) => { 15 | console.log(row); 16 | }); 17 | console.log("SUCCESS"); 18 | } catch (e) { 19 | console.log(e); 20 | } 21 | console.log("========================================"); 22 | process.exit(); 23 | })(); 24 | -------------------------------------------------------------------------------- /week3-app-development/javascript/Ex6f_Remove_All_Todos.js: -------------------------------------------------------------------------------- 1 | const { client } = require("./connection"); 2 | 3 | console.log("========================================"); 4 | console.log("Start exercise"); 5 | 6 | (async () => { 7 | try { 8 | await client.execute("TRUNCATE TABLE todoitems;"); 9 | console.log("SUCCESS"); 10 | } catch (e) { 11 | console.log(e); 12 | } 13 | console.log("========================================"); 14 | process.exit(); 15 | })(); 16 | -------------------------------------------------------------------------------- /week3-app-development/javascript/README.MD: -------------------------------------------------------------------------------- 1 | # 🎓🔥 NodeJS - Back End App Dev with Cassandra 🔥🎓 2 | 3 | ![datamodel](../images/AppDevSplash.png?raw=true) 4 | 5 | ## NodeJS - Back End App Dev with Cassandra 6 | 7 | ![Javascript](https://raw.githubusercontent.com/DataStax-Academy/cassandra-workshop-series/master/materials/images/logo-javascript.png) 8 | 9 | ## Table of contents 10 | 11 | We will be walking through code that establishes a connection to the Astra database and does CRUD (Create, Read, Update, Delete commands). 12 | 13 | - 6.[Connect to Astra](#-step-6-run-unit-test-ex06_connect_to_astrajs) 14 | - 6a. [Create the todoitems Table](#-step-6a-run-unit-test-ex6a_create_tablejs) 15 | - 6b. [Insert values](#-step-6b-run-unit-test-ex6b_insert_todosjs) 16 | - 6c. [Retrieve all rows](#-step-6c-run-unit-test-ex6c_get_all_todosjs) 17 | - 6d. [Update a todo](#-step-6d-run-unit-test-ex6d_update_a_todojs) 18 | - 6e. [Remove a todo](#-step-6e-run-unit-test-ex6e_remove_a_todojs) 19 | - 6f. [Remove all todos](#-step-6f-run-unit-test-ex6f_remove_all_todosjs) 20 | 21 | 22 | Make sure you're in the right sub-directory (`javascript`) by issuing the following command in the GitPod terminal window. 23 | 24 | ```bash 25 | cd /workspace/bootcamp-fullstack-apps-with-cassandra/week3-app-development/javascript 26 | ``` 27 | 28 | Verify again you're in the `javascript` sub-directory using the following command 29 | 30 | ```bash 31 | pwd 32 | ``` 33 | **👁️ Expected output** 34 | 35 | ``` 36 | /workspace/bootcamp-fullstack-apps-with-cassandra/week3-app-development/javascript 37 | ``` 38 | 39 | #### ✅ Step 6a. Run unit test `Ex06_Connect_to_Astra.js`** 40 | 41 | From the GitPod terminal window issue the following command 42 | 43 | ```bash 44 | open connection.js 45 | ``` 46 | 47 | and notice the following lines have been updated with the appropriate values. 48 | 49 | 50 | ```javascript 51 | // This is the "Client Id" value you obtained earlier 52 | const USERNAME = "FXXXXXXXXXXl"; 53 | // This is the "Client Secret" value you obtained earlier 54 | const PASSWORD = "FXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXdeOE.kio_.L981NQ.xq5HqXDB7s_FIJC.ssbLgbdz+G1IC0BCwIA_ZrwPrQNJWUiv26uZf2f4wo"; 55 | ``` 56 | 57 | You can optionally issue the following command or notice the changes in the Gitpod explorer window. Hit space bar to proceed through the changes or hit or `q` to exit the command. 58 | 59 | 60 | ```bash 61 | git diff connection.js 62 | ``` 63 | 64 | You are ready and can now test the connection to Astra with the following command 65 | 66 | ```bash 67 | node Ex07a_Connect_to_Astra.js 68 | ``` 69 | **👁️ Expected output** 70 | 71 | ``` 72 | ======================================== 73 | Start exercise 74 | ======================================== 75 | Your are now connected to Astra 'cndb' at 'us-east1' 76 | SUCCESS 77 | ``` 78 | Now that we're successfully able to establish the connection, take a moment to walk through how the connection has been established by opening the source code using the following command 79 | 80 | ``` 81 | gp open Ex06_Connect_to_Astra.js 82 | ``` 83 | 84 | #### ✅ Step 6a. Run unit test `Ex6a_Create_Table.js` 85 | 86 | Let's create the table. 87 | 88 | Take a moment to review the code with the following command 89 | 90 | ```bash 91 | gp open Ex6a_Create_Table.js 92 | ``` 93 | After reviewing the code, run the following command in the GitPod terminal window which runs the code after making the connection. 94 | 95 | 96 | ```bash 97 | node Ex6a_Create_Table.js 98 | ``` 99 | 100 | **6a. Test output** 101 | 102 | ```bash 103 | ======================================== 104 | Start exercise 105 | SUCCESS 106 | ======================================== 107 | ``` 108 | 109 | **6a. CQL Console** 110 | 111 | From either the CQL shell window or the CQL console in the Astra console issue the following command to notice the items that have been created. 112 | 113 | ```cql 114 | use todos; 115 | DESCRIBE TABLE todoitems; 116 | ``` 117 | 118 | **6a. CQL output** 119 | 120 | **👁️ Expected output** 121 | 122 | ```bash 123 | CREATE TABLE todos.todoitems ( 124 | user_id text, 125 | item_id timeuuid, 126 | completed boolean, 127 | title text, 128 | PRIMARY KEY (user_id, item_id) 129 | ) WITH CLUSTERING ORDER BY (item_id ASC) 130 | AND additional_write_policy = '99PERCENTILE' 131 | AND bloom_filter_fp_chance = 0.01 132 | AND caching = {'keys': 'ALL', 'rows_per_partition': 'NONE'} 133 | AND comment = '' 134 | AND compaction = {'class': 'org.apache.cassandra.db.compaction.UnifiedCompactionStrategy'} 135 | AND compression = {'chunk_length_in_kb': '64', 'class': 'org.apache.cassandra.io.compress.LZ4Compressor'} 136 | AND crc_check_chance = 1.0 137 | AND default_time_to_live = 0 138 | AND gc_grace_seconds = 864000 139 | AND max_index_interval = 2048 140 | AND memtable_flush_period_in_ms = 0 141 | AND min_index_interval = 128 142 | AND read_repair = 'BLOCKING' 143 | AND speculative_retry = '99PERCENTILE'; 144 | ``` 145 | 146 | #### ✅ Step 6b. Run unit test `Ex6b_Insert_Todos.js` 147 | 148 | Let's insert some items. 149 | 150 | Take a moment to review the code with the following command 151 | 152 | ```bash 153 | gp open Ex6b_Insert_Todos.js 154 | ``` 155 | After reviewing the code, run the following command in the GitPod terminal window which runs the code after making the connection. 156 | 157 | ```bash 158 | node Ex6b_Insert_Todos.js 159 | ``` 160 | 161 | **6b. Test output** 162 | 163 | **👁️ Expected output** 164 | 165 | ```bash 166 | ======================================== 167 | Start exercise 168 | SUCCESS 169 | ======================================== 170 | ``` 171 | 172 | **6b. CQL Console** 173 | 174 | From either the CQL shell window or the CQL console in the Astra console issue the following command to notice the items that have been created. 175 | 176 | ```cql 177 | select * from todoitems; 178 | ``` 179 | 180 | **6b. CQL Output** 181 | 182 | **👁️ Expected output** 183 | 184 | ```cql 185 | 186 | user_id | item_id | completed | title 187 | ---------+--------------------------------------+-----------+--------------------- 188 | mary | 33333333-5cff-11ec-be16-1fedb0dfd057 | True | Attend the workshop 189 | john | 11111111-5cff-11ec-be16-1fedb0dfd057 | True | Walk the dog 190 | john | 22222222-5cff-11ec-be16-1fedb0dfd057 | False | Have lunch tomorrow 191 | 192 | (3 rows) 193 | 194 | ``` 195 | 196 | #### ✅ Step 6c. Run unit test `Ex6c_Get_All_Todos.js` 197 | 198 | Let's get all the todos associated with an user. 199 | 200 | Take a moment to review the code with the following command 201 | 202 | ```bash 203 | gp open Ex6c_Get_All_Todos.js 204 | ``` 205 | 206 | After reviewing the code, run the following command in the GitPod terminal window which runs the code after making the connection. 207 | 208 | ```bash 209 | node Ex6c_Get_All_Todos.js 210 | ``` 211 | 212 | **6c. Test output** 213 | 214 | **👁️ Expected output** 215 | 216 | ```bash 217 | ======================================== 218 | Start exercise 219 | Row { 220 | user_id: 'john', 221 | item_id: TimeUuid { 222 | buffer: 223 | }, 224 | completed: false, 225 | title: 'Have lunch tomorrow' 226 | } 227 | SUCCESS 228 | ======================================== 229 | ``` 230 | 231 | You can verify via the CQL shell or via the console as well as you did in previous step(s). 232 | 233 | #### ✅ Step 6d. Run unit test `Ex6d_Update_A_Todo.js` 234 | 235 | Let's update an item. 236 | 237 | Take a moment to review the code with the following command 238 | 239 | ```bash 240 | gp open Ex6d_Update_A_Todo.js 241 | ``` 242 | 243 | After reviewing the code, run the following command in the GitPod terminal window which runs the code after making the connection. 244 | 245 | ```bash 246 | node Ex6d_Update_A_Todo.js 247 | ``` 248 | 249 | **6d. Test output** 250 | 251 | **👁️ Expected output** 252 | 253 | ```bash 254 | ======================================== 255 | Start exercise 256 | Row { 257 | 'system.totimestamp(item_id)': 2021-12-14T16:59:00.072Z, 258 | completed: true, 259 | title: 'Have lunch tomorrow' 260 | } 261 | SUCCESS 262 | ======================================== 263 | ``` 264 | 265 | **6d. CQL Console** 266 | 267 | From either the CQL shell window or the CQL console in the Astra console issue the following command to notice the items that have been created. 268 | 269 | ```cql 270 | select * from todoitems; 271 | ``` 272 | 273 | **6d. CQL Output** 274 | 275 | **👁️ Expected output** 276 | 277 | ```cql 278 | 279 | user_id | item_id | completed | title 280 | ---------+--------------------------------------+-----------+--------------------- 281 | mary | 33333333-5cff-11ec-be16-1fedb0dfd057 | True | Attend the workshop 282 | john | 11111111-5cff-11ec-be16-1fedb0dfd057 | True | Walk the dog 283 | john | 22222222-5cff-11ec-be16-1fedb0dfd057 | True | Have lunch tomorrow 284 | 285 | (3 rows) 286 | ``` 287 | 288 | #### ✅ Step 6e. Run unit test `Ex6e_Remove_A_Todo.js` 289 | 290 | Let's remove an item. 291 | 292 | Take a moment to review the code with the following command 293 | 294 | ```bash 295 | gp open Ex6e_Remove_A_Todo.js 296 | ``` 297 | 298 | After reviewing the code, run the following command in the GitPod terminal window which runs the code after making the connection. 299 | 300 | ```bash 301 | node Ex6e_Remove_A_Todo.js 302 | ``` 303 | 304 | **6e. Test output** 305 | 306 | ```bash 307 | ======================================== 308 | Start exercise 309 | Row { 310 | 'system.totimestamp(item_id)': 2021-12-14T16:59:00.072Z, 311 | completed: true, 312 | title: 'Have lunch tomorrow' 313 | } 314 | SUCCESS 315 | ======================================== 316 | ``` 317 | 318 | **6e. CQL Console** 319 | 320 | From either the CQL shell window or the CQL console in the Astra console issue the following command to notice the items that have been removed. 321 | 322 | ```cql 323 | select * from todoitems; 324 | ``` 325 | 326 | **6e. CQL Output** 327 | 328 | **👁️ Expected output** 329 | 330 | ```cql 331 | user_id | item_id | completed | title 332 | ---------+--------------------------------------+-----------+--------------------- 333 | mary | 33333333-5cff-11ec-be16-1fedb0dfd057 | True | Attend the workshop 334 | john | 22222222-5cff-11ec-be16-1fedb0dfd057 | True | Have lunch tomorrow 335 | 336 | (2 rows) 337 | ``` 338 | 339 | #### ✅ Step 6f. Run unit test `Ex6f_Remove_All_Todos.js` 340 | 341 | Finally, let's remove all todos associated with an user. 342 | 343 | Take a moment to review the code with the following command 344 | 345 | ```bash 346 | gp open Ex6f_Remove_All_Todos.js 347 | ``` 348 | 349 | After reviewing the code, run the following command in the GitPod terminal window which runs the code after making the connection. 350 | 351 | ```bash 352 | node Ex6f_Remove_All_Todos.js 353 | ``` 354 | 355 | **6f. Test output** 356 | 357 | **👁️ Expected output** 358 | 359 | ```bash 360 | ======================================== 361 | Start exercise 362 | SUCCESS 363 | ======================================== 364 | ``` 365 | 366 | **6f. CQL Console** 367 | 368 | From either the CQL shell window or the CQL console in the Astra console issue the following command to notice the items that have been created. 369 | 370 | **👁️ Expected output** 371 | 372 | ```cql 373 | select * from todoitems; 374 | ``` 375 | 376 | **6f. CQL Output** 377 | 378 | ```cql 379 | user_id | item_id | completed | title 380 | ---------+---------+-----------+------- 381 | 382 | (0 rows) 383 | ``` 384 | 385 | 386 | **Cleanup** 387 | 388 | **Caution: You will lose all the data** if you run the following command in the CQL Console 389 | 390 | ```cql 391 | DROP TABLE IF EXISTS todos.todoitems; 392 | ``` 393 | 394 | [🏠 Go back](../README.MD) -------------------------------------------------------------------------------- /week3-app-development/javascript/connection.js: -------------------------------------------------------------------------------- 1 | // WARNING: THIS FILE IS GOING TO BE OVERWRITTEN 2 | const cassandra = require("cassandra-driver"); 3 | 4 | // This is the Zip file you downloaded 5 | const SECURE_CONNECT_BUNDLE = 6 | "/workspace/bootcamp-fullstack-apps-with-cassandra/secure-connect-workshops.zip"; 7 | // This is the "Client Id" value you obtained earlier 8 | const USERNAME = ""; 9 | // This is the "Client Secret" value you obtained earlier 10 | const PASSWORD = ""; 11 | // This is the keyspace name 12 | const KEYSPACE = "todos"; 13 | 14 | const client = new cassandra.Client({ 15 | cloud: { secureConnectBundle: SECURE_CONNECT_BUNDLE }, 16 | keyspace: KEYSPACE, 17 | credentials: { username: USERNAME, password: PASSWORD }, 18 | }); 19 | 20 | process.on("exit", () => client.shutdown()); 21 | 22 | module.exports = { 23 | client, 24 | }; 25 | -------------------------------------------------------------------------------- /week3-app-development/javascript/connection.js.init: -------------------------------------------------------------------------------- 1 | // THIS FILE WILL BE OVERWRITTEN. DO NOT MAKE ANY CHANGES 2 | const cassandra = require("cassandra-driver"); 3 | 4 | // This is the Zip file you downloaded 5 | const SECURE_CONNECT_BUNDLE = 6 | "/workspace/bootcamp-fullstack-apps-with-cassandra/secure-connect-workshops.zip"; 7 | // This is the "Client Id" value you obtained earlier 8 | const USERNAME = "$ASTRA_USERNAME"; 9 | // This is the "Client Secret" value you obtained earlier 10 | const PASSWORD = "$ASTRA_PASSWORD"; 11 | // This is the keyspace name 12 | const KEYSPACE = "todos"; 13 | 14 | const client = new cassandra.Client({ 15 | cloud: { secureConnectBundle: SECURE_CONNECT_BUNDLE }, 16 | keyspace: KEYSPACE, 17 | credentials: { username: USERNAME, password: PASSWORD }, 18 | }); 19 | 20 | process.on("exit", () => client.shutdown()); 21 | 22 | module.exports = { 23 | client, 24 | }; 25 | -------------------------------------------------------------------------------- /week3-app-development/plugastracreds: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ ! -f .env ]; then 4 | echo "File .env needs to exist." 5 | exit -1 6 | fi 7 | 8 | source .env 9 | 10 | if [ ! "$ASTRA_USERNAME" ]; then 11 | echo "env variable ASTRA_USERNAME needs to be set" 12 | exit -1 13 | fi 14 | 15 | if [ ! "$ASTRA_PASSWORD" ]; then 16 | echo "env variable ASTRA_PASSWORD needs to be set" 17 | exit -1 18 | fi 19 | 20 | if [ ! -f /workspace/bootcamp-fullstack-apps-with-cassandra/secure-connect-workshops.zip ]; then 21 | echo "Secure connect bundle to connect to Astra does not exist." 22 | exit -1 23 | fi 24 | 25 | cat ./java/src/main/java/com/datastax/workshop/DBConnection.java.init | \ 26 | sed "s/\$ASTRA_USERNAME/$ASTRA_USERNAME/" | \ 27 | sed "s/\$ASTRA_PASSWORD/$ASTRA_PASSWORD/" > \ 28 | ./java/src/main/java/com/datastax/workshop/DBConnection.java 29 | 30 | cat ./javascript/connection.js.init | \ 31 | sed "s/\$ASTRA_USERNAME/$ASTRA_USERNAME/" | \ 32 | sed "s/\$ASTRA_PASSWORD/$ASTRA_PASSWORD/" > \ 33 | ./javascript/connection.js 34 | 35 | cat ./python/connection.py.init | \ 36 | sed "s/\$ASTRA_USERNAME/$ASTRA_USERNAME/" | \ 37 | sed "s/\$ASTRA_PASSWORD/$ASTRA_PASSWORD/" > \ 38 | ./python/connection.py 39 | 40 | echo "Astra credentials plugged into all language environments. Please verify!" 41 | 42 | 43 | if [ ! -f /workspace/bootcamp-fullstack-apps-with-cassandra/zshrcinit ]; then 44 | cp ~/.zshrc /workspace/bootcamp-fullstack-apps-with-cassandra/zshrcinit 45 | echo "/workspace/bootcamp-fullstack-apps-with-cassandra/cqlsh-astra/bin/cqlsh \\ 46 | --secure-connect-bundle=/workspace/bootcamp-fullstack-apps-with-cassandra/secure-connect-workshops.zip \\ 47 | --color \\ 48 | -u $ASTRA_USERNAME \\ 49 | -p $ASTRA_PASSWORD" >> /workspace/bootcamp-fullstack-apps-with-cassandra/zshrcinit 50 | cp /workspace/bootcamp-fullstack-apps-with-cassandra/zshrcinit ~/.zshrc 51 | else 52 | cp /workspace/bootcamp-fullstack-apps-with-cassandra/zshrcinit ~/.zshrc 53 | fi 54 | 55 | touch /workspace/bootcamp-fullstack-apps-with-cassandra/zshrcinit 56 | -------------------------------------------------------------------------------- /week3-app-development/python/Ex06_Connect_to_Astra.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | from connection import session 3 | 4 | print('========================================') 5 | print('Start exercise') 6 | try: 7 | output = session.execute("SELECT * FROM system.local") 8 | for row in output: 9 | print('You are now connected to cluster %s at %s' % 10 | (row.cluster_name, row.data_center)) 11 | except Exception as e: 12 | print(e) 13 | print('Failure') 14 | else: 15 | print('Success') 16 | print('========================================') 17 | -------------------------------------------------------------------------------- /week3-app-development/python/Ex6a_Create_Table.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | from connection import session 3 | 4 | print('========================================') 5 | print('Start exercise') 6 | try: 7 | session.execute("""CREATE TABLE IF NOT EXISTS todoitems ( 8 | user_id TEXT, 9 | item_id TIMEUUID, 10 | title TEXT, 11 | completed BOOLEAN, 12 | PRIMARY KEY ((user_id), item_id) 13 | ) WITH CLUSTERING ORDER BY (item_id ASC); 14 | """) 15 | except Exception as e: 16 | print(e) 17 | print('Failure') 18 | else: 19 | print('Success') 20 | print('========================================') 21 | -------------------------------------------------------------------------------- /week3-app-development/python/Ex6b_Insert_Todos.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import uuid 3 | from connection import session 4 | 5 | print('========================================') 6 | print('Start exercise') 7 | try: 8 | session.execute( 9 | "INSERT INTO todoitems (user_id, item_id, completed, title) VALUES ( 'john', 11111111-5cff-11ec-be16-1fedb0dfd057, true, 'Walk the dog');") 10 | session.execute( 11 | "INSERT INTO todoitems (user_id, item_id, completed, title) VALUES ( 'john', 22222222-5cff-11ec-be16-1fedb0dfd057, false, 'Have lunch tomorrow');") 12 | session.execute( 13 | "INSERT INTO todoitems (user_id, item_id, completed, title) VALUES ( 'mary', 33333333-5cff-11ec-be16-1fedb0dfd057, true, 'Attend the workshop');") 14 | except Exception as e: 15 | print(e) 16 | print('Failure') 17 | else: 18 | print('Success') 19 | print('========================================') 20 | -------------------------------------------------------------------------------- /week3-app-development/python/Ex6c_Get_All_Todos.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | from connection import session 3 | 4 | print('========================================') 5 | print('Start exercise') 6 | try: 7 | output = session.execute("SELECT * FROM todoitems WHERE user_id = 'john';") 8 | for row in output: 9 | print(str(row)) 10 | except Exception as e: 11 | print(e) 12 | print('Failure') 13 | else: 14 | print('Success') 15 | print('========================================') 16 | -------------------------------------------------------------------------------- /week3-app-development/python/Ex6d_Update_A_Todo.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | from connection import session 3 | 4 | print('========================================') 5 | print('Start exercise') 6 | try: 7 | session.execute( 8 | "UPDATE todoitems SET completed = true WHERE user_id = 'john' AND item_id = 22222222-5cff-11ec-be16-1fedb0dfd057;") 9 | output = session.execute( 10 | "SELECT toTimestamp(item_id), completed, title FROM todoitems WHERE user_id = 'john';") 11 | for row in output: 12 | print(row) 13 | except Exception as e: 14 | print(e) 15 | print('Failure') 16 | else: 17 | print('Success') 18 | print('========================================') 19 | -------------------------------------------------------------------------------- /week3-app-development/python/Ex6e_Remove_A_Todo.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | from connection import session 3 | 4 | print('========================================') 5 | print('Start exercise') 6 | try: 7 | session.execute( 8 | "DELETE FROM todoitems WHERE user_id='john' AND item_id=11111111-5cff-11ec-be16-1fedb0dfd057;") 9 | output = session.execute( 10 | "SELECT toTimestamp(item_id), completed, title FROM todoitems WHERE user_id = 'john';") 11 | for row in output: 12 | print(row) 13 | except Exception as e: 14 | print(e) 15 | print('Failure') 16 | else: 17 | print('Success') 18 | print('========================================') 19 | -------------------------------------------------------------------------------- /week3-app-development/python/Ex6f_Remove_All_Todos.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | from connection import session 3 | 4 | print('========================================') 5 | print('Start exercise') 6 | try: 7 | session.execute("TRUNCATE TABLE todoitems;") 8 | except Exception as e: 9 | print(e) 10 | print('Failure') 11 | else: 12 | print('Success') 13 | print('========================================') 14 | -------------------------------------------------------------------------------- /week3-app-development/python/README.MD: -------------------------------------------------------------------------------- 1 | # 🎓🔥 Python - Back End App Dev with Cassandra 🔥🎓 2 | 3 | ![datamodel](../images/AppDevSplash.png?raw=true) 4 | 5 | ## Python - Back End App Dev with Cassandra 6 | 7 | ![Python](https://raw.githubusercontent.com/DataStax-Academy/cassandra-workshop-series/master/materials/images/logo-python.png) 8 | 9 | ## Table of contents 10 | 11 | We will be walking through code that establishes a connection to the Astra database and does CRUD (Create, Read, Update, Delete commands). 12 | 13 | - 6.[Connect to Astra](#-step-6-run-unit-test-ex06_connect_to_astrapy) 14 | - 6a. [Create the todoitems Table](#-step-6a-run-unit-test-ex6a_create_tablepy) 15 | - 6b. [Insert values](#-step-6b-run-unit-test-ex6b_insert_todospy) 16 | - 6c. [Retrieve all rows](#-step-6c-run-unit-test-ex6c_get_all_todospy) 17 | - 6d. [Update a todo](#-step-6d-run-unit-test-ex6d_update_a_todopy) 18 | - 6e. [Remove a todo](#-step-6e-run-unit-test-ex6e_remove_a_todopy) 19 | - 6f. [Remove all todos](#-step-6f-run-unit-test-ex6f_remove_all_todospy) 20 | 21 | 22 | Make sure you're in the right sub-directory (`python`) by issuing the following command in the GitPod terminal window. 23 | 24 | ```bash 25 | cd /workspace/bootcamp-fullstack-apps-with-cassandra/week3-app-development/python 26 | ``` 27 | 28 | Verify again you're in the `python` sub-directory using the following command 29 | 30 | ```bash 31 | pwd 32 | ``` 33 | **👁️ Expected output** 34 | 35 | ``` 36 | /workspace/bootcamp-fullstack-apps-with-cassandra/week3-app-development/python 37 | ``` 38 | 39 | #### ✅ Step 6a. Run unit test `Ex06_Connect_to_Astra.py` 40 | 41 | From the GitPod terminal window issue the following command 42 | 43 | ```bash 44 | open connection.py 45 | ``` 46 | 47 | and notice the following lines have been updated with the appropriate values. 48 | 49 | 50 | ```javascript 51 | // This is the "Client Id" value you obtained earlier 52 | const USERNAME = "FXXXXXXXXXXl"; 53 | // This is the "Client Secret" value you obtained earlier 54 | const PASSWORD = "FXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXdeOE.kio_.L981NQ.xq5HqXDB7s_FIJC.ssbLgbdz+G1IC0BCwIA_ZrwPrQNJWUiv26uZf2f4wo"; 55 | ``` 56 | 57 | You can optionally issue the following command or notice the changes in the Gitpod explorer window. Hit space bar to proceed through the changes or hit or `q` to exit the command. 58 | 59 | 60 | ```bash 61 | git diff connection.py 62 | ``` 63 | 64 | You are ready and can now test the connection to Astra with the following command 65 | 66 | ```bash 67 | python Ex06_Connect_to_Astra.py 68 | ``` 69 | **👁️ Expected output** 70 | 71 | ``` 72 | ======================================== 73 | Start exercise 74 | You are now connected to cluster cndb at us-east1 75 | Success 76 | ======================================== 77 | ``` 78 | 79 | Now that we're successfully able to establish the connection, take a moment to walk through how the connection has been established by opening the source code using the following command 80 | 81 | ``` 82 | gp open Ex06_Connect_to_Astra.py 83 | ``` 84 | 85 | #### ✅ Step 6a. Run unit test `Ex6a_Create_Table.py` 86 | 87 | Let's create the table. 88 | 89 | Take a moment to review the code with the following command 90 | 91 | ```bash 92 | gp open Ex6a_Create_Table.py 93 | ``` 94 | After reviewing the code, run the following command in the GitPod terminal window which runs the code after making the connection. 95 | 96 | 97 | ```bash 98 | python Ex6a_Create_Table.py 99 | ``` 100 | 101 | **6a. Test output** 102 | 103 | ```bash 104 | ======================================== 105 | Start exercise 106 | Success 107 | ======================================== 108 | ``` 109 | 110 | **6a. CQL Console** 111 | 112 | From either the CQL shell window or the CQL console in the Astra console issue the following command to notice the items that have been created. 113 | 114 | ```cql 115 | use todos; 116 | DESCRIBE TABLE todoitems; 117 | ``` 118 | 119 | **6a. CQL output** 120 | 121 | **👁️ Expected output** 122 | 123 | ```bash 124 | CREATE TABLE todos.todoitems ( 125 | user_id text, 126 | item_id timeuuid, 127 | completed boolean, 128 | title text, 129 | PRIMARY KEY (user_id, item_id) 130 | ) WITH CLUSTERING ORDER BY (item_id ASC) 131 | AND additional_write_policy = '99PERCENTILE' 132 | AND bloom_filter_fp_chance = 0.01 133 | AND caching = {'keys': 'ALL', 'rows_per_partition': 'NONE'} 134 | AND comment = '' 135 | AND compaction = {'class': 'org.apache.cassandra.db.compaction.UnifiedCompactionStrategy'} 136 | AND compression = {'chunk_length_in_kb': '64', 'class': 'org.apache.cassandra.io.compress.LZ4Compressor'} 137 | AND crc_check_chance = 1.0 138 | AND default_time_to_live = 0 139 | AND gc_grace_seconds = 864000 140 | AND max_index_interval = 2048 141 | AND memtable_flush_period_in_ms = 0 142 | AND min_index_interval = 128 143 | AND read_repair = 'BLOCKING' 144 | AND speculative_retry = '99PERCENTILE'; 145 | ``` 146 | 147 | #### ✅ Step 6b. Run unit test `Ex6b_Insert_Todos.py` 148 | 149 | Let's insert some items. 150 | 151 | Take a moment to review the code with the following command 152 | 153 | ```bash 154 | gp open Ex6b_Insert_Todos.py 155 | ``` 156 | After reviewing the code, run the following command in the GitPod terminal window which runs the code after making the connection. 157 | 158 | ```bash 159 | python Ex6b_Insert_Todos.py 160 | ``` 161 | 162 | **6b. Test output** 163 | 164 | **👁️ Expected output** 165 | 166 | ```bash 167 | ======================================== 168 | Start exercise 169 | Success 170 | ======================================== 171 | ``` 172 | 173 | **6b. CQL Console** 174 | 175 | From either the CQL shell window or the CQL console in the Astra console issue the following command to notice the items that have been created. 176 | 177 | ```cql 178 | select * from todoitems; 179 | ``` 180 | 181 | **6b. CQL Output** 182 | 183 | **👁️ Expected output** 184 | 185 | ```bash 186 | 187 | user_id | item_id | completed | title 188 | ---------+--------------------------------------+-----------+--------------------- 189 | mary | 33333333-5cff-11ec-be16-1fedb0dfd057 | True | Attend the workshop 190 | john | 11111111-5cff-11ec-be16-1fedb0dfd057 | True | Walk the dog 191 | john | 22222222-5cff-11ec-be16-1fedb0dfd057 | False | Have lunch tomorrow 192 | 193 | (3 rows) 194 | 195 | ``` 196 | 197 | #### ✅ Step 6c. Run unit test `Ex6c_Get_All_Todos.py` 198 | 199 | Let's get all the todos associated with an user. 200 | 201 | Take a moment to review the code with the following command 202 | 203 | ```bash 204 | gp open Ex6c_Get_All_Todos.py 205 | ``` 206 | 207 | After reviewing the code, run the following command in the GitPod terminal window which runs the code after making the connection. 208 | 209 | ```bash 210 | python Ex6c_Get_All_Todos.py 211 | ``` 212 | 213 | **6c. Test output** 214 | 215 | **👁️ Expected output** 216 | 217 | ```bash 218 | ======================================== 219 | Start exercise 220 | Row(user_id='john', item_id=UUID('11111111-5cff-11ec-be16-1fedb0dfd057'), completed=True, title='Walk the dog') 221 | Row(user_id='john', item_id=UUID('22222222-5cff-11ec-be16-1fedb0dfd057'), completed=False, title='Have lunch tomorrow') 222 | Success 223 | ======================================== 224 | ``` 225 | 226 | You can verify via the CQL shell or via the console as well as you did in previous step(s). 227 | 228 | #### ✅ Step 6d. Run unit test `Ex6d_Update_A_Todo.py` 229 | 230 | Let's update an item. 231 | 232 | Take a moment to review the code with the following command 233 | 234 | ```bash 235 | gp open Ex6d_Update_A_Todo.py 236 | ``` 237 | 238 | After reviewing the code, run the following command in the GitPod terminal window which runs the code after making the connection. 239 | 240 | ```bash 241 | python Ex6d_Update_A_Todo.py 242 | ``` 243 | 244 | **6d. Test output** 245 | 246 | **👁️ Expected output** 247 | 248 | ```bash 249 | ======================================== 250 | Start exercise 251 | Row(system_totimestamp_item_id=datetime.datetime(2021, 12, 14, 16, 58, 31, 438000), completed=True, title='Walk the dog') 252 | Row(system_totimestamp_item_id=datetime.datetime(2021, 12, 14, 16, 59, 0, 72000), completed=True, title='Have lunch tomorrow') 253 | Success 254 | ======================================== 255 | ``` 256 | 257 | **6d. CQL Console** 258 | 259 | From either the CQL shell window or the CQL console in the Astra console issue the following command to notice the items that have been created. 260 | 261 | ```cql 262 | select * from todoitems; 263 | ``` 264 | 265 | **6d. CQL Output** 266 | 267 | **👁️ Expected output** 268 | 269 | ```cql 270 | 271 | user_id | item_id | completed | title 272 | ---------+--------------------------------------+-----------+--------------------- 273 | mary | 33333333-5cff-11ec-be16-1fedb0dfd057 | True | Attend the workshop 274 | john | 11111111-5cff-11ec-be16-1fedb0dfd057 | True | Walk the dog 275 | john | 22222222-5cff-11ec-be16-1fedb0dfd057 | True | Have lunch tomorrow 276 | 277 | (3 rows) 278 | ``` 279 | 280 | #### ✅ Step 6e. Run unit test `Ex6e_Remove_A_Todo.py` 281 | 282 | Let's remove an item. 283 | 284 | Take a moment to review the code with the following command 285 | 286 | ```bash 287 | gp open Ex6e_Remove_A_Todo.py 288 | ``` 289 | 290 | After reviewing the code, run the following command in the GitPod terminal window which runs the code after making the connection. 291 | 292 | ```bash 293 | python Ex6e_Remove_A_Todo.py 294 | ``` 295 | 296 | **6e. Test output** 297 | 298 | ```bash 299 | ======================================== 300 | Start exercise 301 | Row(system_totimestamp_item_id=datetime.datetime(2021, 12, 14, 16, 59, 0, 72000), completed=True, title='Have lunch tomorrow') 302 | Success 303 | ======================================== 304 | ``` 305 | 306 | **6e. CQL Console** 307 | 308 | From either the CQL shell window or the CQL console in the Astra console issue the following command to notice the items that have been removed. 309 | 310 | ```cql 311 | select * from todoitems; 312 | ``` 313 | 314 | **6e. CQL Output** 315 | 316 | **👁️ Expected output** 317 | 318 | ```cql 319 | user_id | item_id | completed | title 320 | ---------+--------------------------------------+-----------+--------------------- 321 | mary | 33333333-5cff-11ec-be16-1fedb0dfd057 | True | Attend the workshop 322 | john | 22222222-5cff-11ec-be16-1fedb0dfd057 | True | Have lunch tomorrow 323 | 324 | (2 rows) 325 | ``` 326 | 327 | #### ✅ Step 6f. Run unit test `Ex6f_Remove_All_Todos.py` 328 | 329 | Finally, let's remove all todos associated with an user. 330 | 331 | Take a moment to review the code with the following command 332 | 333 | ```bash 334 | gp open Ex6f_Remove_All_Todos.py 335 | ``` 336 | 337 | After reviewing the code, run the following command in the GitPod terminal window which runs the code after making the connection. 338 | 339 | ```bash 340 | python Ex6f_Remove_All_Todos.py 341 | ``` 342 | 343 | **6f. Test output** 344 | 345 | **👁️ Expected output** 346 | 347 | ```bash 348 | ======================================== 349 | Start exercise 350 | Success 351 | ======================================== 352 | ``` 353 | 354 | **6f. CQL Console** 355 | 356 | From either the CQL shell window or the CQL console in the Astra console issue the following command to notice the items that have been created. 357 | 358 | **👁️ Expected output** 359 | 360 | ```cql 361 | select * from todoitems; 362 | ``` 363 | 364 | **6f. CQL Output** 365 | 366 | ```cql 367 | user_id | item_id | completed | title 368 | ---------+---------+-----------+------- 369 | 370 | (0 rows) 371 | ``` 372 | 373 | 374 | **Cleanup** 375 | 376 | **Caution: You will lose all the data** if you run the following command in the CQL Console 377 | 378 | ```cql 379 | DROP TABLE IF EXISTS todos.todoitems; 380 | ``` 381 | 382 | [🏠 Go back](../README.MD) -------------------------------------------------------------------------------- /week3-app-development/python/connection.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | #WARNING: THIS FILE IS GOING TO BE OVERWRITTEN 3 | 4 | import atexit 5 | from cassandra.cluster import Cluster 6 | from cassandra.auth import PlainTextAuthProvider 7 | 8 | # This is the Zip file you downloaded 9 | SECURE_CONNECT_BUNDLE = '/workspace/bootcamp-fullstack-apps-with-cassandra/secure-connect-workshops.zip' 10 | # This is the "Client Id" value you obtained earlier 11 | USERNAME = "" 12 | # This is the "Client Secret" value you obtained earlier 13 | PASSWORD = "" 14 | # This is the keyspace name 15 | KEYSPACE = "todos" 16 | 17 | 18 | secure_connect_bundle = SECURE_CONNECT_BUNDLE 19 | path_to_creds = '' 20 | cluster = Cluster( 21 | cloud={ 22 | 'secure_connect_bundle': SECURE_CONNECT_BUNDLE 23 | }, 24 | auth_provider=PlainTextAuthProvider(USERNAME, PASSWORD) 25 | ) 26 | session = cluster.connect(KEYSPACE) 27 | 28 | 29 | @atexit.register 30 | def shutdown_driver(): 31 | cluster.shutdown() 32 | session.shutdown() 33 | -------------------------------------------------------------------------------- /week3-app-development/python/connection.py.init: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # THIS FILE WILL BE OVERWRITTEN. DO NOT MAKE ANY CHANGES HERE 3 | 4 | import atexit 5 | from cassandra.cluster import Cluster 6 | from cassandra.auth import PlainTextAuthProvider 7 | 8 | # This is the Zip file you downloaded 9 | SECURE_CONNECT_BUNDLE = '/workspace/bootcamp-fullstack-apps-with-cassandra/secure-connect-workshops.zip' 10 | # This is the "Client Id" value you obtained earlier 11 | USERNAME = "$ASTRA_USERNAME" 12 | # This is the "Client Secret" value you obtained earlier 13 | PASSWORD = "$ASTRA_PASSWORD" 14 | # This is the keyspace name 15 | KEYSPACE = "todos" 16 | 17 | 18 | secure_connect_bundle = SECURE_CONNECT_BUNDLE 19 | path_to_creds = '' 20 | cluster = Cluster( 21 | cloud={ 22 | 'secure_connect_bundle': SECURE_CONNECT_BUNDLE 23 | }, 24 | auth_provider=PlainTextAuthProvider(USERNAME, PASSWORD) 25 | ) 26 | session = cluster.connect(KEYSPACE) 27 | 28 | 29 | @atexit.register 30 | def shutdown_driver(): 31 | cluster.shutdown() 32 | session.shutdown() 33 | -------------------------------------------------------------------------------- /week3-app-development/slides/WEEK3 - App Development with Cassandra.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week3-app-development/slides/WEEK3 - App Development with Cassandra.pdf -------------------------------------------------------------------------------- /week4-api-microservices/.env.sample: -------------------------------------------------------------------------------- 1 | #TODO: REPLACE_ME with Astra Client Id and Secret 2 | 3 | export ASTRA_USERNAME= 4 | export ASTRA_PASSWORD= -------------------------------------------------------------------------------- /week4-api-microservices/images/Filexplorer0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week4-api-microservices/images/Filexplorer0.png -------------------------------------------------------------------------------- /week4-api-microservices/images/OpenPorts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week4-api-microservices/images/OpenPorts.png -------------------------------------------------------------------------------- /week4-api-microservices/images/Verifytodos.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week4-api-microservices/images/Verifytodos.png -------------------------------------------------------------------------------- /week4-api-microservices/images/allow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week4-api-microservices/images/allow.png -------------------------------------------------------------------------------- /week4-api-microservices/images/astra-create-token.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week4-api-microservices/images/astra-create-token.gif -------------------------------------------------------------------------------- /week4-api-microservices/images/astra-token.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week4-api-microservices/images/astra-token.png -------------------------------------------------------------------------------- /week4-api-microservices/images/bootcamp_badge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week4-api-microservices/images/bootcamp_badge.png -------------------------------------------------------------------------------- /week4-api-microservices/images/dotenv1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week4-api-microservices/images/dotenv1.png -------------------------------------------------------------------------------- /week4-api-microservices/images/dotenv2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week4-api-microservices/images/dotenv2.png -------------------------------------------------------------------------------- /week4-api-microservices/images/dotenv3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week4-api-microservices/images/dotenv3.png -------------------------------------------------------------------------------- /week4-api-microservices/images/dotenv4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week4-api-microservices/images/dotenv4.png -------------------------------------------------------------------------------- /week4-api-microservices/images/dotenv5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week4-api-microservices/images/dotenv5.png -------------------------------------------------------------------------------- /week4-api-microservices/images/gitpod-01-home-annotated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week4-api-microservices/images/gitpod-01-home-annotated.png -------------------------------------------------------------------------------- /week4-api-microservices/images/gitpod-01-home-plain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week4-api-microservices/images/gitpod-01-home-plain.png -------------------------------------------------------------------------------- /week4-api-microservices/images/gitpod-02-url.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week4-api-microservices/images/gitpod-02-url.png -------------------------------------------------------------------------------- /week4-api-microservices/images/gitpod-bootcampappdev-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week4-api-microservices/images/gitpod-bootcampappdev-1.jpg -------------------------------------------------------------------------------- /week4-api-microservices/images/gitpod-client-error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week4-api-microservices/images/gitpod-client-error.png -------------------------------------------------------------------------------- /week4-api-microservices/images/gitpod-client-success.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week4-api-microservices/images/gitpod-client-success.png -------------------------------------------------------------------------------- /week4-api-microservices/images/gitpod-home-error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week4-api-microservices/images/gitpod-home-error.png -------------------------------------------------------------------------------- /week4-api-microservices/images/gitpod-john-task.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week4-api-microservices/images/gitpod-john-task.png -------------------------------------------------------------------------------- /week4-api-microservices/images/gitpod-openport.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week4-api-microservices/images/gitpod-openport.png -------------------------------------------------------------------------------- /week4-api-microservices/images/gitpod-spec-error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week4-api-microservices/images/gitpod-spec-error.png -------------------------------------------------------------------------------- /week4-api-microservices/images/gitpod-spec-success.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week4-api-microservices/images/gitpod-spec-success.png -------------------------------------------------------------------------------- /week4-api-microservices/images/gitpodpreferences1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week4-api-microservices/images/gitpodpreferences1.png -------------------------------------------------------------------------------- /week4-api-microservices/images/public9191.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week4-api-microservices/images/public9191.png -------------------------------------------------------------------------------- /week4-api-microservices/images/resume-db.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week4-api-microservices/images/resume-db.png -------------------------------------------------------------------------------- /week4-api-microservices/images/secureconnectbundle1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week4-api-microservices/images/secureconnectbundle1.png -------------------------------------------------------------------------------- /week4-api-microservices/images/secureconnectbundle2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week4-api-microservices/images/secureconnectbundle2.png -------------------------------------------------------------------------------- /week4-api-microservices/images/secureconnectbundle3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week4-api-microservices/images/secureconnectbundle3.png -------------------------------------------------------------------------------- /week4-api-microservices/images/shells.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week4-api-microservices/images/shells.png -------------------------------------------------------------------------------- /week4-api-microservices/images/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week4-api-microservices/images/splash.png -------------------------------------------------------------------------------- /week4-api-microservices/images/todobackend-output-client.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week4-api-microservices/images/todobackend-output-client.png -------------------------------------------------------------------------------- /week4-api-microservices/images/todobackend-output-host.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week4-api-microservices/images/todobackend-output-host.png -------------------------------------------------------------------------------- /week4-api-microservices/images/todobackend-runclient.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week4-api-microservices/images/todobackend-runclient.png -------------------------------------------------------------------------------- /week4-api-microservices/images/todobackend-runtest.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week4-api-microservices/images/todobackend-runtest.png -------------------------------------------------------------------------------- /week4-api-microservices/images/todobackend.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week4-api-microservices/images/todobackend.png -------------------------------------------------------------------------------- /week4-api-microservices/images/todobackend2-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week4-api-microservices/images/todobackend2-1.png -------------------------------------------------------------------------------- /week4-api-microservices/images/todomvc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week4-api-microservices/images/todomvc.png -------------------------------------------------------------------------------- /week4-api-microservices/images/week4_badge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week4-api-microservices/images/week4_badge.png -------------------------------------------------------------------------------- /week4-api-microservices/java/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | com.datastaxdev 6 | week4-todo-springboot 7 | 1.0.0-SNAPSHOT 8 | 9 | 10 | org.springframework.boot 11 | spring-boot-starter-parent 12 | 2.6.2 13 | 14 | 15 | 16 | 17 | 11 18 | 19 | 20 | 21 | 22 | 23 | org.springframework.boot 24 | spring-boot-starter-web 25 | 26 | 27 | 28 | org.springframework.boot 29 | spring-boot-starter-data-cassandra 30 | 31 | 32 | 33 | 34 | org.springframework.boot 35 | spring-boot-starter-test 36 | test 37 | 38 | 39 | org.junit.vintage 40 | junit-vintage-engine 41 | 42 | 43 | com.vaadin.external.google 44 | android-json 45 | 46 | 47 | 48 | 49 | org.junit.platform 50 | junit-platform-runner 51 | test 52 | 53 | 54 | 55 | 56 | 57 | 58 | org.springframework.boot 59 | spring-boot-maven-plugin 60 | 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /week4-api-microservices/java/src/main/java/com/datastaxdev/TodoApplication.java: -------------------------------------------------------------------------------- 1 | package com.datastaxdev; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class TodoApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(TodoApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /week4-api-microservices/java/src/main/java/com/datastaxdev/conf/CassandraDriverConguration.java: -------------------------------------------------------------------------------- 1 | package com.datastaxdev.conf; 2 | 3 | import java.io.File; 4 | 5 | import org.springframework.beans.factory.annotation.Value; 6 | import org.springframework.boot.autoconfigure.cassandra.CqlSessionBuilderCustomizer; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | 10 | @Configuration 11 | public class CassandraDriverConguration { 12 | 13 | @Value("${datastax.astra.secure-connect-bundle}") 14 | private File cloudSecureBundle; 15 | 16 | @Bean 17 | public CqlSessionBuilderCustomizer sessionBuilderCustomizer() { 18 | return builder -> builder.withCloudSecureConnectBundle(cloudSecureBundle.toPath()); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /week4-api-microservices/java/src/main/java/com/datastaxdev/todo/Todo.java: -------------------------------------------------------------------------------- 1 | package com.datastaxdev.todo; 2 | 3 | import java.util.UUID; 4 | 5 | import javax.servlet.http.HttpServletRequest; 6 | 7 | /** 8 | * Class to TODO 9 | * 10 | * @author Cedrick LUNVEN (@clunven) 11 | */ 12 | public class Todo { 13 | 14 | private String url; 15 | private UUID uuid; 16 | private String title; 17 | private boolean completed = false; 18 | private Integer order = 0; 19 | 20 | public Todo() {} 21 | 22 | public Todo(String title, Integer order) { 23 | this.uuid = UUID.randomUUID(); 24 | this.title = title; 25 | this.order = order; 26 | } 27 | 28 | public Todo(String title, int order, boolean completed) { 29 | this(title, order); 30 | this.completed = completed; 31 | } 32 | 33 | public Todo setUrl(HttpServletRequest req) { 34 | if (url == null) { 35 | String reqUrl = req.getRequestURL().toString(); 36 | url = reqUrl.contains("gitpod") ? reqUrl.replaceAll("http", "https") : reqUrl; 37 | url += uuid; 38 | } 39 | return this; 40 | } 41 | 42 | public Todo setUrl(String myUrl) { 43 | if (url == null) { 44 | url = myUrl.contains("gitpod") ? myUrl.replaceAll("http", "https") : myUrl; 45 | } 46 | return this; 47 | } 48 | 49 | /** 50 | * Getter accessor for attribute 'uuid'. 51 | * 52 | * @return 53 | * current value of 'uuid' 54 | */ 55 | public UUID getUuid() { 56 | return uuid; 57 | } 58 | 59 | /** 60 | * Setter accessor for attribute 'uuid'. 61 | * @param uuid 62 | * new value for 'uuid ' 63 | */ 64 | public void setUuid(UUID uuid) { 65 | this.uuid = uuid; 66 | } 67 | 68 | /** 69 | * Getter accessor for attribute 'title'. 70 | * 71 | * @return 72 | * current value of 'title' 73 | */ 74 | public String getTitle() { 75 | return title; 76 | } 77 | 78 | /** 79 | * Setter accessor for attribute 'title'. 80 | * @param title 81 | * new value for 'title ' 82 | */ 83 | public void setTitle(String title) { 84 | this.title = title; 85 | } 86 | 87 | /** 88 | * Getter accessor for attribute 'completed'. 89 | * 90 | * @return 91 | * current value of 'completed' 92 | */ 93 | public boolean isCompleted() { 94 | return completed; 95 | } 96 | 97 | /** 98 | * Setter accessor for attribute 'completed'. 99 | * @param completed 100 | * new value for 'completed ' 101 | */ 102 | public void setCompleted(boolean completed) { 103 | this.completed = completed; 104 | } 105 | 106 | /** 107 | * Getter accessor for attribute 'order'. 108 | * 109 | * @return 110 | * current value of 'order' 111 | */ 112 | public Integer getOrder() { 113 | return order; 114 | } 115 | 116 | /** 117 | * Setter accessor for attribute 'order'. 118 | * @param order 119 | * new value for 'order ' 120 | */ 121 | public void setOrder(Integer order) { 122 | this.order = order; 123 | } 124 | 125 | /** 126 | * Getter accessor for attribute 'url'. 127 | * 128 | * @return 129 | * current value of 'url' 130 | */ 131 | public String getUrl() { 132 | return url; 133 | } 134 | 135 | /** {@inheritDoc} */ 136 | @Override 137 | public String toString() { 138 | return "Todo [url=" + url + ", uuid=" + uuid + ", title=" + title + ", completed=" + completed + ", order=" + order + "]"; 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /week4-api-microservices/java/src/main/java/com/datastaxdev/todo/TodoItem.java: -------------------------------------------------------------------------------- 1 | package com.datastaxdev.todo; 2 | 3 | import org.springframework.data.cassandra.core.mapping.Column; 4 | import org.springframework.data.cassandra.core.mapping.PrimaryKey; 5 | import org.springframework.data.cassandra.core.mapping.Table; 6 | 7 | import com.datastax.oss.driver.api.core.uuid.Uuids; 8 | 9 | @Table("todoitems") 10 | public class TodoItem { 11 | 12 | @PrimaryKey 13 | private TodoItemKey key = new TodoItemKey("default", Uuids.timeBased()); 14 | 15 | @Column("title") 16 | private String title; 17 | 18 | @Column("completed") 19 | private boolean completed = false; 20 | 21 | @Column("offset") 22 | private Integer offset = 0; 23 | 24 | /** 25 | * Default Constructor. 26 | */ 27 | public TodoItem() {} 28 | 29 | /** 30 | * Simple constructor. 31 | * 32 | * @param userid 33 | * user id 34 | * @param title 35 | * title 36 | */ 37 | public TodoItem(String userid, String title) { 38 | this.title = title; 39 | this.key.setUserId(userid); 40 | } 41 | 42 | /** 43 | * Getter accessor for attribute 'key'. 44 | * 45 | * @return 46 | * current value of 'key' 47 | */ 48 | public TodoItemKey getKey() { 49 | return key; 50 | } 51 | 52 | /** 53 | * Setter accessor for attribute 'key'. 54 | * @param key 55 | * new value for 'key ' 56 | */ 57 | public void setKey(TodoItemKey key) { 58 | this.key = key; 59 | } 60 | 61 | /** 62 | * Getter accessor for attribute 'title'. 63 | * 64 | * @return 65 | * current value of 'title' 66 | */ 67 | public String getTitle() { 68 | return title; 69 | } 70 | 71 | /** 72 | * Setter accessor for attribute 'title'. 73 | * @param title 74 | * new value for 'title ' 75 | */ 76 | public void setTitle(String title) { 77 | this.title = title; 78 | } 79 | 80 | /** 81 | * Getter accessor for attribute 'completed'. 82 | * 83 | * @return 84 | * current value of 'completed' 85 | */ 86 | public boolean isCompleted() { 87 | return completed; 88 | } 89 | 90 | /** 91 | * Setter accessor for attribute 'completed'. 92 | * @param completed 93 | * new value for 'completed ' 94 | */ 95 | public void setCompleted(boolean completed) { 96 | this.completed = completed; 97 | } 98 | 99 | /** 100 | * Getter accessor for attribute 'offset'. 101 | * 102 | * @return 103 | * current value of 'offset' 104 | */ 105 | public Integer getOffset() { 106 | return offset; 107 | } 108 | 109 | /** 110 | * Setter accessor for attribute 'offset'. 111 | * @param offset 112 | * new value for 'offset ' 113 | */ 114 | public void setOffset(int offset) { 115 | this.offset = offset; 116 | } 117 | 118 | } 119 | -------------------------------------------------------------------------------- /week4-api-microservices/java/src/main/java/com/datastaxdev/todo/TodoItemKey.java: -------------------------------------------------------------------------------- 1 | package com.datastaxdev.todo; 2 | 3 | import java.util.UUID; 4 | 5 | import org.springframework.data.cassandra.core.cql.Ordering; 6 | import org.springframework.data.cassandra.core.cql.PrimaryKeyType; 7 | import org.springframework.data.cassandra.core.mapping.CassandraType; 8 | import org.springframework.data.cassandra.core.mapping.CassandraType.Name; 9 | import org.springframework.data.cassandra.core.mapping.PrimaryKeyClass; 10 | import org.springframework.data.cassandra.core.mapping.PrimaryKeyColumn; 11 | 12 | @PrimaryKeyClass 13 | public class TodoItemKey { 14 | 15 | @PrimaryKeyColumn(name = "user_id",type = PrimaryKeyType.PARTITIONED, ordinal = 0) 16 | private String userId; 17 | 18 | @PrimaryKeyColumn(name = "item_id", type = PrimaryKeyType.CLUSTERED, ordinal = 1, ordering = Ordering.ASCENDING) 19 | @CassandraType(type = Name.TIMEUUID) 20 | private UUID itemId; 21 | 22 | public TodoItemKey() {} 23 | 24 | public TodoItemKey(String userId, UUID itemId) { 25 | super(); 26 | this.userId = userId; 27 | this.itemId = itemId; 28 | } 29 | 30 | /** 31 | * Getter accessor for attribute 'userId'. 32 | * 33 | * @return 34 | * current value of 'userId' 35 | */ 36 | public String getUserId() { 37 | return userId; 38 | } 39 | 40 | /** 41 | * Setter accessor for attribute 'userId'. 42 | * @param userId 43 | * new value for 'userId ' 44 | */ 45 | public void setUserId(String userId) { 46 | this.userId = userId; 47 | } 48 | 49 | /** 50 | * Getter accessor for attribute 'itemId'. 51 | * 52 | * @return 53 | * current value of 'itemId' 54 | */ 55 | public UUID getItemId() { 56 | return itemId; 57 | } 58 | 59 | /** 60 | * Setter accessor for attribute 'itemId'. 61 | * @param itemId 62 | * new value for 'itemId ' 63 | */ 64 | public void setItemId(UUID itemId) { 65 | this.itemId = itemId; 66 | } 67 | 68 | 69 | 70 | } 71 | -------------------------------------------------------------------------------- /week4-api-microservices/java/src/main/java/com/datastaxdev/todo/TodoItemRepository.java: -------------------------------------------------------------------------------- 1 | package com.datastaxdev.todo; 2 | 3 | import java.util.List; 4 | 5 | import org.springframework.data.cassandra.repository.CassandraRepository; 6 | import org.springframework.stereotype.Repository; 7 | 8 | /** 9 | * For Basic operations you can leverage on Interface only repository 10 | */ 11 | @Repository 12 | public interface TodoItemRepository extends CassandraRepository { 13 | 14 | /** 15 | * Retrieve all todos for a user as the userId is the partition key. 16 | * 17 | * @param userid 18 | * unique identifier for a user 19 | * @return 20 | */ 21 | List findByKeyUserId(String userid); 22 | 23 | /** 24 | * Delete all tasks for a todolist. 25 | * 26 | * @param userid 27 | * current userid. 28 | */ 29 | void deleteByKeyUserId(String userid); 30 | 31 | } 32 | -------------------------------------------------------------------------------- /week4-api-microservices/java/src/main/java/com/datastaxdev/todo/TodoRestController.java: -------------------------------------------------------------------------------- 1 | package com.datastaxdev.todo; 2 | 3 | import static org.springframework.web.bind.annotation.RequestMethod.DELETE; 4 | import static org.springframework.web.bind.annotation.RequestMethod.GET; 5 | import static org.springframework.web.bind.annotation.RequestMethod.OPTIONS; 6 | import static org.springframework.web.bind.annotation.RequestMethod.PATCH; 7 | import static org.springframework.web.bind.annotation.RequestMethod.POST; 8 | import static org.springframework.web.bind.annotation.RequestMethod.PUT; 9 | 10 | import java.net.URI; 11 | import java.net.URISyntaxException; 12 | import java.util.Optional; 13 | import java.util.UUID; 14 | import java.util.stream.Stream; 15 | 16 | import javax.servlet.http.HttpServletRequest; 17 | 18 | import org.springframework.http.HttpStatus; 19 | import org.springframework.http.ResponseEntity; 20 | import org.springframework.web.bind.annotation.CrossOrigin; 21 | import org.springframework.web.bind.annotation.DeleteMapping; 22 | import org.springframework.web.bind.annotation.GetMapping; 23 | import org.springframework.web.bind.annotation.PatchMapping; 24 | import org.springframework.web.bind.annotation.PathVariable; 25 | import org.springframework.web.bind.annotation.PostMapping; 26 | import org.springframework.web.bind.annotation.RequestBody; 27 | import org.springframework.web.bind.annotation.RequestMapping; 28 | import org.springframework.web.bind.annotation.RestController; 29 | 30 | @RestController 31 | @CrossOrigin( 32 | methods = {POST, GET, OPTIONS, PUT, DELETE, PATCH}, 33 | maxAge = 3600, 34 | allowedHeaders = {"x-requested-with", "origin", "content-type", "accept"}, 35 | origins = "*" 36 | ) 37 | @RequestMapping("/api/v1") 38 | public class TodoRestController { 39 | 40 | private TodoItemRepository repo; 41 | 42 | public TodoRestController(TodoItemRepository todoRepo) { 43 | this.repo = todoRepo; 44 | } 45 | 46 | @GetMapping("/{user}/todos/") 47 | public Stream findAllByUser(HttpServletRequest req, 48 | @PathVariable(value = "user") String user) { 49 | return repo.findByKeyUserId(user).stream() 50 | .map(TodoRestController::mapAsTodo) 51 | .map(t -> t.setUrl(req)); 52 | } 53 | 54 | @GetMapping("/{user}/todos/{uid}") 55 | public ResponseEntity findById(HttpServletRequest req, 56 | @PathVariable(value = "user") String user, 57 | @PathVariable(value = "uid") String itemId) { 58 | Optional e = repo.findById(new TodoItemKey(user, UUID.fromString(itemId))); 59 | if (e.isEmpty()) { 60 | return ResponseEntity.notFound().build(); 61 | } 62 | return ResponseEntity.ok(mapAsTodo(e.get()).setUrl(req.getRequestURL().toString())); 63 | } 64 | 65 | @PostMapping("/{user}/todos/") 66 | public ResponseEntity create(HttpServletRequest req, 67 | @PathVariable(value = "user") String user, 68 | @RequestBody Todo todoReq) 69 | throws URISyntaxException { 70 | TodoItem te = mapAsTodoEntity(todoReq, user); 71 | repo.save(te); 72 | todoReq.setUuid(te.getKey().getItemId()); 73 | todoReq.setUrl(req); 74 | return ResponseEntity.created(new URI(todoReq.getUrl())).body(todoReq); 75 | } 76 | 77 | @PatchMapping("/{user}/todos/{uid}") 78 | public ResponseEntity update(HttpServletRequest req, 79 | @PathVariable(value = "user") String user, 80 | @PathVariable(value = "uid") String uid, 81 | @RequestBody Todo todoReq) 82 | throws URISyntaxException { 83 | 84 | // Retrieve existing task 85 | Optional todo = repo.findById(new TodoItemKey(user, UUID.fromString(uid))); 86 | if (todo.isEmpty()) return ResponseEntity.notFound().build(); 87 | 88 | // Update based on provided information 89 | TodoItem item = todo.get(); 90 | if (null != todoReq.getTitle() && !"".equals(todoReq.getTitle())) { 91 | item.setTitle(todoReq.getTitle()); 92 | } 93 | if (null != todoReq.getOrder()) { 94 | item.setOffset(todoReq.getOrder()); 95 | } 96 | item.setCompleted(todoReq.isCompleted()); 97 | 98 | // Save 99 | repo.save(item); 100 | todoReq.setTitle(item.getTitle()); 101 | todoReq.setUrl(req.getRequestURL().toString()); 102 | todoReq.setUuid(UUID.fromString(uid)); 103 | return ResponseEntity.accepted().body(todoReq); 104 | } 105 | 106 | @DeleteMapping("/{user}/todos/{uid}") 107 | public ResponseEntity deleteById( 108 | @PathVariable(value = "user") String user, 109 | @PathVariable(value = "uid") String uid) { 110 | if (!repo.existsById(new TodoItemKey(user, UUID.fromString(uid)))) { 111 | return ResponseEntity.notFound().build(); 112 | } 113 | repo.deleteById(new TodoItemKey(user, UUID.fromString(uid))); 114 | return new ResponseEntity<>(HttpStatus.NO_CONTENT); 115 | } 116 | 117 | @DeleteMapping("/{user}/todos/") 118 | public ResponseEntity deleteAllByUser(@PathVariable(value = "user") String user) { 119 | repo.deleteByKeyUserId(user); 120 | return new ResponseEntity<>(HttpStatus.NO_CONTENT); 121 | } 122 | 123 | private static Todo mapAsTodo(TodoItem te) { 124 | Todo todo = new Todo(); 125 | todo.setTitle(te.getTitle()); 126 | todo.setOrder(te.getOffset()); 127 | todo.setUuid(te.getKey().getItemId()); 128 | todo.setCompleted(te.isCompleted()); 129 | return todo; 130 | } 131 | 132 | private TodoItem mapAsTodoEntity(Todo te, String user) { 133 | TodoItem todo = new TodoItem(); 134 | if (null != te.getUuid()) { 135 | todo.getKey().setItemId(te.getUuid()); 136 | } 137 | todo.getKey().setUserId(user); 138 | todo.setTitle(te.getTitle()); 139 | todo.setOffset(te.getOrder()); 140 | todo.setCompleted(te.isCompleted()); 141 | return todo; 142 | } 143 | } -------------------------------------------------------------------------------- /week4-api-microservices/java/src/main/resources/META-INF/additional-spring-configuration-metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "properties": [ 3 | { 4 | "name": "datastax.astra.secure-connect-bundle", 5 | "type": "java.lang.String", 6 | "description": "An absolute path to the Astra secure connect bundle to use." 7 | } 8 | ] 9 | } -------------------------------------------------------------------------------- /week4-api-microservices/java/src/main/resources/application.conf: -------------------------------------------------------------------------------- 1 | datastax-java-driver { 2 | basic { 3 | request { 4 | timeout = 8 seconds 5 | consistency = LOCAL_QUORUM 6 | page-size = 5000 7 | } 8 | } 9 | advanced { 10 | connection { 11 | init-query-timeout = 10 seconds 12 | set-keyspace-timeout = 10 seconds 13 | } 14 | control-connection.timeout = 10 seconds 15 | } 16 | } -------------------------------------------------------------------------------- /week4-api-microservices/java/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | server.port=9191 2 | 3 | spring.data.cassandra.schema-action=CREATE_IF_NOT_EXISTS 4 | spring.data.cassandra.request.timeout=10s 5 | spring.data.cassandra.connection.connect-timeout=10s 6 | spring.data.cassandra.connection.init-query-timeout=10s 7 | spring.data.cassandra.keyspace-name=todos 8 | spring.data.cassandra.username=$ASTRA_USERNAME 9 | spring.data.cassandra.password=$ASTRA_PASSWORD 10 | datastax.astra.secure-connect-bundle=/workspace/bootcamp-fullstack-apps-with-cassandra/secure-connect-workshops.zip 11 | -------------------------------------------------------------------------------- /week4-api-microservices/java/src/main/resources/application.properties.init: -------------------------------------------------------------------------------- 1 | server.port=9191 2 | 3 | spring.data.cassandra.schema-action=CREATE_IF_NOT_EXISTS 4 | spring.data.cassandra.request.timeout=10s 5 | spring.data.cassandra.connection.connect-timeout=10s 6 | spring.data.cassandra.connection.init-query-timeout=10s 7 | spring.data.cassandra.keyspace-name=todos 8 | spring.data.cassandra.username=$ASTRA_USERNAME 9 | spring.data.cassandra.password=$ASTRA_PASSWORD 10 | datastax.astra.secure-connect-bundle=/workspace/bootcamp-fullstack-apps-with-cassandra/secure-connect-workshops.zip 11 | -------------------------------------------------------------------------------- /week4-api-microservices/java/src/main/resources/banner.txt: -------------------------------------------------------------------------------- 1 | ${AnsiColor.BLUE} ________ __ __ ________ .__ 2 | ${AnsiColor.BLUE} \______ \ _____ _/ |______ _______/ |______ ___ ___ \______ \ _______ __ ____ | | ____ ______ ___________ ______ 3 | ${AnsiColor.BLUE} | | \\__ \\ __\__ \ / ___/\ __\__ \ \ \/ / | | \_/ __ \ \/ // __ \| | / _ \\____ \_/ __ \_ __ \/ ___/ 4 | ${AnsiColor.BLUE} | ` \/ __ \| | / __ \_\___ \ | | / __ \_> < | ` \ ___/\ /\ ___/| |_( <_> ) |_> > ___/| | \/\___ \ 5 | ${AnsiColor.BLUE} /_______ (____ /__| (____ /____ > |__| (____ /__/\_ \ /_______ /\___ >\_/ \___ >____/\____/| __/ \___ >__| /____ > 6 | ${AnsiColor.BLUE} \/ \/ \/ \/ \/ \/ \/ \/ \/ |__| \/ \/ 7 | 8 | ${AnsiColor.CYAN} Todobackend with Spring Boot, String Data and Astra 9 | ${AnsiColor.GREEN} The application will start at ${AnsiColor.RED}http://localhost:${server.port}${AnsiColor.BLACK} 10 | -------------------------------------------------------------------------------- /week4-api-microservices/java/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | %d{HH:mm:ss.SSS} %magenta(%-5level) %cyan(%-45logger) : %msg%n 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /week4-api-microservices/java/src/test/java/com/datastaxdev/Test01_Connect.java: -------------------------------------------------------------------------------- 1 | package com.datastaxdev; 2 | 3 | import java.io.File; 4 | import java.nio.file.Paths; 5 | 6 | import org.junit.jupiter.api.Assertions; 7 | import org.junit.jupiter.api.DisplayName; 8 | import org.junit.jupiter.api.Test; 9 | import org.junit.platform.runner.JUnitPlatform; 10 | import org.junit.runner.RunWith; 11 | import org.slf4j.Logger; 12 | import org.slf4j.LoggerFactory; 13 | import org.springframework.beans.factory.annotation.Value; 14 | import org.springframework.test.context.TestPropertySource; 15 | import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; 16 | 17 | import com.datastax.oss.driver.api.core.CqlSession; 18 | 19 | // --> Eclipse Support 20 | @SuppressWarnings("deprecation") 21 | @RunWith(JUnitPlatform.class) 22 | // <-- 23 | 24 | @SpringJUnitConfig 25 | @TestPropertySource(locations="/application.properties") 26 | public class Test01_Connect { 27 | 28 | /** Logger for the class. */ 29 | private static Logger LOGGER = LoggerFactory.getLogger(Test01_Connect.class); 30 | 31 | @Value("${spring.data.cassandra.username}") 32 | private String username; 33 | 34 | @Value("${spring.data.cassandra.password}") 35 | private String password; 36 | 37 | @Value("${spring.data.cassandra.keyspace-name}") 38 | private String keyspace; 39 | 40 | @Value("${datastax.astra.secure-connect-bundle}") 41 | private String cloudSecureBundle; 42 | 43 | @Test 44 | @DisplayName("Test connectivity to Astra explicit values") 45 | public void should_connect_to_Astra() { 46 | 47 | // Given interface is properly populated 48 | Assertions.assertTrue(new File(cloudSecureBundle).exists(), 49 | "File '" + cloudSecureBundle + "' has not been found\n" 50 | + "To run this sample you need to download the secure bundle file from ASTRA WebPage\n" 51 | + "More info here:"); 52 | 53 | // When connecting to ASTRA 54 | try (CqlSession cqlSession = CqlSession.builder() 55 | .withCloudSecureConnectBundle(Paths.get(cloudSecureBundle)) 56 | .withAuthCredentials(username, password) 57 | .withKeyspace(keyspace) 58 | .build()) { 59 | 60 | // Then connection is successfull 61 | LOGGER.info(" + [OK] - Connection Established to Astra with Keyspace {}", 62 | cqlSession.getKeyspace().get()); 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /week4-api-microservices/java/src/test/java/com/datastaxdev/Test02_CreateSchema.java: -------------------------------------------------------------------------------- 1 | package com.datastaxdev; 2 | 3 | import java.io.File; 4 | import java.nio.file.Paths; 5 | 6 | import org.junit.jupiter.api.Assertions; 7 | import org.junit.jupiter.api.DisplayName; 8 | import org.junit.jupiter.api.Test; 9 | import org.junit.platform.runner.JUnitPlatform; 10 | import org.junit.runner.RunWith; 11 | import org.slf4j.Logger; 12 | import org.slf4j.LoggerFactory; 13 | import org.springframework.beans.factory.annotation.Value; 14 | import org.springframework.test.context.TestPropertySource; 15 | import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; 16 | 17 | import com.datastax.oss.driver.api.core.CqlSession; 18 | import com.datastax.oss.driver.api.core.cql.SimpleStatement; 19 | import com.datastax.oss.driver.api.core.type.DataTypes; 20 | import com.datastax.oss.driver.api.querybuilder.SchemaBuilder; 21 | 22 | //--> Eclipse Support 23 | @SuppressWarnings("deprecation") 24 | @RunWith(JUnitPlatform.class) 25 | //<-- 26 | 27 | @SpringJUnitConfig 28 | @TestPropertySource(locations="/application.properties") 29 | public class Test02_CreateSchema { 30 | 31 | /** Logger for the class. */ 32 | private static Logger LOGGER = LoggerFactory.getLogger(Test02_CreateSchema.class); 33 | 34 | @Value("${spring.data.cassandra.username}") 35 | private String username; 36 | 37 | @Value("${spring.data.cassandra.password}") 38 | private String password; 39 | 40 | @Value("${spring.data.cassandra.keyspace-name}") 41 | private String keyspace; 42 | 43 | @Value("${datastax.astra.secure-connect-bundle}") 44 | private String cloudSecureBundle; 45 | 46 | @Test 47 | @DisplayName("Test to create a table in ASTRA") 48 | public void should_create_expected_table() { 49 | // Given interface is properly populated 50 | Assertions.assertTrue(new File(cloudSecureBundle).exists(), 51 | "File '" + cloudSecureBundle + "' has not been found\n" 52 | + "To run this sample you need to download the secure bundle file from ASTRA WebPage\n" 53 | + "More info here:"); 54 | 55 | // When connecting to ASTRA 56 | try (CqlSession cqlSession = CqlSession.builder() 57 | .withCloudSecureConnectBundle(Paths.get(cloudSecureBundle)) 58 | .withAuthCredentials(username, password) 59 | .withKeyspace(keyspace) 60 | .build()) { 61 | LOGGER.info("Connection Established to Astra with Keyspace '{}'", 62 | cqlSession.getKeyspace().get()); 63 | 64 | SimpleStatement stmtDropTable = SchemaBuilder 65 | .dropTable("todoitems") 66 | .ifExists().build(); 67 | // When creating the table 68 | cqlSession.execute(stmtDropTable); 69 | 70 | SimpleStatement stmtCreateTable = SchemaBuilder 71 | .createTable("todoitems") 72 | .ifNotExists() 73 | .withPartitionKey("user_id", DataTypes.TEXT) 74 | .withClusteringColumn("item_id", DataTypes.TIMEUUID) 75 | .withColumn("title", DataTypes.TEXT) 76 | .withColumn("completed", DataTypes.BOOLEAN) 77 | .withColumn("offset", DataTypes.INT) 78 | .build(); 79 | 80 | // When creating the table 81 | cqlSession.execute(stmtCreateTable); 82 | 83 | // Then table is created 84 | LOGGER.info("Table '{}' has been created (if needed).", "todoitems"); 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /week4-api-microservices/java/src/test/java/com/datastaxdev/Test03_SaveTask.java: -------------------------------------------------------------------------------- 1 | package com.datastaxdev; 2 | 3 | import org.junit.jupiter.api.Assertions; 4 | import org.junit.jupiter.api.Test; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.boot.test.context.SpringBootTest; 7 | 8 | import com.datastaxdev.todo.TodoItem; 9 | import com.datastaxdev.todo.TodoItemKey; 10 | import com.datastaxdev.todo.TodoItemRepository; 11 | 12 | @SpringBootTest 13 | class Test03_SaveTask { 14 | 15 | @Autowired 16 | private TodoItemRepository repo; 17 | 18 | @Test 19 | void shoud_save_task_when_save() { 20 | // Given 21 | TodoItem te = new TodoItem("john", "Sample task1"); 22 | // When 23 | repo.save(te); 24 | // then 25 | Assertions.assertTrue(repo.existsById(new TodoItemKey("john", te.getKey().getItemId()))); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /week4-api-microservices/java/src/test/java/com/datastaxdev/Test04_Controller.java: -------------------------------------------------------------------------------- 1 | package com.datastaxdev; 2 | 3 | import org.junit.jupiter.api.Assertions; 4 | import org.junit.jupiter.api.Test; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.boot.test.web.client.TestRestTemplate; 7 | import org.springframework.boot.web.server.LocalServerPort; 8 | import org.springframework.http.HttpEntity; 9 | import org.springframework.http.HttpHeaders; 10 | import org.springframework.http.HttpMethod; 11 | import org.springframework.http.HttpStatus; 12 | import org.springframework.http.ResponseEntity; 13 | 14 | import com.datastaxdev.todo.Todo; 15 | 16 | @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) 17 | public class Test04_Controller { 18 | 19 | @LocalServerPort 20 | private int port; 21 | 22 | TestRestTemplate restTemplate = new TestRestTemplate(); 23 | 24 | @Test 25 | public void should_retrieve_todolist_v1() { 26 | HttpHeaders headers = new HttpHeaders(); 27 | HttpEntity entity = new HttpEntity(null, headers); 28 | ResponseEntity response = restTemplate.exchange( 29 | createURLWithPort("/api/v1/john/todos/"), HttpMethod.GET, entity, Todo[].class); 30 | Assertions.assertEquals(HttpStatus.OK, response.getStatusCode()); 31 | } 32 | 33 | private String createURLWithPort(String uri) { 34 | return "http://localhost:" + port + uri; 35 | } 36 | 37 | 38 | 39 | } 40 | 41 | -------------------------------------------------------------------------------- /week4-api-microservices/javascript/.env.example: -------------------------------------------------------------------------------- 1 | # Copy this file to .env and fill in the appropriate values. Refer to README.md 2 | # for instructions on where to find them. 3 | CQLENG_ALLOW_SCHEMA_MANAGEMENT=1 4 | ASTRA_DB_BUNDLE_PATH=bundle.zip 5 | ASTRA_DB_KEYSPACE=sag_todos 6 | ASTRA_DB_CLIENT_ID= 7 | ASTRA_DB_CLIENT_SECRET= 8 | -------------------------------------------------------------------------------- /week4-api-microservices/javascript/README.MD: -------------------------------------------------------------------------------- 1 | # 🎓🔥 API and MicroServices with Apache Cassandra - Javascript 🔥🎓 2 | 3 | ![pic](../images/splash.png) 4 | 5 | ![JAVA](https://raw.githubusercontent.com/DataStax-Academy/cassandra-workshop-series/master/materials/images/logo-javascript.png) 6 | 7 | ## Javascript Todos 8 | 9 | ## 7a - Connect to Astra 10 | 11 | ### ✅ Check connectivity parameters 12 | 13 | - Make sure you're in the right sub-directory (`javascript`) by issuing the following command in the GitPod terminal window. 14 | 15 | ```bash 16 | cd /workspace/bootcamp-fullstack-apps-with-cassandra/week4-api-microservices/javascript 17 | ``` 18 | 19 | - Verify again you're in the `javascript` sub-directory using the following command 20 | 21 | ```bash 22 | pwd 23 | ``` 24 | 25 | **👁️ Expected output** 26 | 27 | ``` 28 | /workspace/bootcamp-fullstack-apps-with-cassandra/week4-api-microservices/javascript 29 | ``` 30 | 31 | - From the GitPod terminal window issue the following command 32 | 33 | ```bash 34 | open connection.js 35 | ``` 36 | 37 | and notice the following lines have been updated with the appropriate values. 38 | 39 | ```javascript 40 | // This is the "Client Id" value you obtained earlier 41 | const USERNAME = "FXXXXXXXXXXl"; 42 | // This is the "Client Secret" value you obtained earlier 43 | const PASSWORD = 44 | "FXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXdeOE.kio_.L981NQ.xq5HqXDB7s_FIJC.ssbLgbdz+G1IC0BCwIA_ZrwPrQNJWUiv26uZf2f4wo"; 45 | ``` 46 | 47 | ### ✅ Run the test 48 | 49 | You are ready and can now test the connection to Astra with the following command 50 | 51 | ```bash 52 | node Test01_Connect.js 53 | ``` 54 | 55 | **👁️ Expected output** 56 | 57 | ``` 58 | ======================================== 59 | Start exercise 60 | ======================================== 61 | Your are now connected to Astra 'cndb' at 'us-east1' 62 | SUCCESS 63 | ``` 64 | 65 | Now that we're successfully able to establish the connection, take a moment to walk through how the connection has been established by opening the source code using the following command 66 | 67 | ``` 68 | gp open Test01_Connect.js 69 | ``` 70 | 71 | ## 7b - Create the schema 72 | 73 | ### ✅ Run Test 74 | 75 | Let's create the table. We will **drop** a table if it already exists with the same name. 76 | 77 | - Take a moment to review the code with the following command 78 | 79 | ```bash 80 | gp open Test02_CreateSchema.js 81 | ``` 82 | 83 | - After reviewing the code, run the following command in the GitPod terminal window which runs the code after making the connection. 84 | 85 | ```bash 86 | node Test02_CreateSchema.js 87 | ``` 88 | 89 | **👁️ Expected output** 90 | 91 | ```bash 92 | ======================================== 93 | Start exercise 94 | SUCCESS 95 | ======================================== 96 | ``` 97 | 98 | If you run into a timeout error rerun this command and confirm that the table is dropped (we changed the data model slightly so its imperative the table is dropped). 99 | 100 | ### ✅ Validate Schema with CqlSH 101 | 102 | - Open a terminal `zsh` to open a cqlsh shell (we overrided .zshrc to give you that feature) 103 | 104 | ```cql 105 | DESCRIBE KEYSPACE todos; 106 | ``` 107 | 108 | **👁️ Expected output** 109 | 110 | ```cql 111 | Connected to cndb at 127.0.0.1:9042. 112 | [cqlsh 6.8.0 | Cassandra 4.0.0.6816 | CQL spec 3.4.5 | Native protocol v4] 113 | Use HELP for help. 114 | token@cqlsh> describe keyspace todos; 115 | 116 | CREATE KEYSPACE todos WITH replication = {'class': 'NetworkTopologyStrategy', 'eu-west-1': '3'} AND durable_writes = true; 117 | 118 | CREATE TABLE native_java.todoitems ( 119 | user_id text, 120 | item_id timeuuid, 121 | completed boolean, 122 | offset int, 123 | title text, 124 | PRIMARY KEY (user_id, item_id) 125 | ) WITH CLUSTERING ORDER BY (item_id ASC) 126 | AND additional_write_policy = '99PERCENTILE' 127 | AND bloom_filter_fp_chance = 0.01 128 | AND caching = {'keys': 'ALL', 'rows_per_partition': 'NONE'} 129 | AND comment = '' 130 | AND compaction = {'class': 'org.apache.cassandra.db.compaction.UnifiedCompactionStrategy'} 131 | AND compression = {'chunk_length_in_kb': '64', 'class': 'org.apache.cassandra.io.compress.LZ4Compressor'} 132 | AND crc_check_chance = 1.0 133 | AND default_time_to_live = 0 134 | AND gc_grace_seconds = 864000 135 | AND max_index_interval = 2048 136 | AND memtable_flush_period_in_ms = 0 137 | AND min_index_interval = 128 138 | AND read_repair = 'BLOCKING' 139 | AND speculative_retry = '99PERCENTILE'; 140 | 141 | token@cqlsh> 142 | ``` 143 | 144 | ## 7c - Save a Task 145 | 146 | ### ✅ Run Test 147 | 148 | Let's insert some item(s). 149 | 150 | - Take a moment to review the code with the following command 151 | 152 | ```bash 153 | gp open Test03_SaveTask.js 154 | ``` 155 | 156 | - After reviewing the code, run the following command in the GitPod terminal window which runs the code after making the connection. 157 | 158 | ```bash 159 | node Test03_SaveTask.js 160 | ``` 161 | 162 | **👁️ Expected output** 163 | 164 | ```bash 165 | ======================================== 166 | Start exercise 167 | SUCCESS 168 | ======================================== 169 | ``` 170 | 171 | ### ✅ Validate with Cqlsh 172 | 173 | - Open a terminal `cqlsh` to open a cqlsh shell (we overrided .zshrc to give you that feature) 174 | 175 | ```cql 176 | select * from todos.todoitems; 177 | ``` 178 | 179 | **👁️ Expected output** 180 | 181 | ```bash 182 | token@cqlshs> select * from todos.todoitems; 183 | 184 | user_id | item_id | completed | offset | title 185 | ---------+--------------------------------------+-----------+--------+-------------- 186 | john | 1793e4e0-7d65-11ec-b3f6-15c8273bc04a | False | 0 | Sample task1 187 | ``` 188 | 189 | ## 7d - Test REST Endpoint 190 | 191 | ### ✅ Run Test 192 | 193 | ```bash 194 | npm test 195 | ``` 196 | 197 | **👁️ Expected output** 198 | 199 | ```bash 200 | Todos 201 | ✔ it should initialize (761ms) 202 | ✔ it should create a todo (172ms) 203 | ✔ it should get todos (86ms) 204 | ✔ it should update todos (200ms) 205 | ✔ it should delete a todo (133ms) 206 | ✔ it should delete todos (615ms) 207 | 208 | 209 | 6 passing (2s) 210 | ``` 211 | 212 | ## 7e - Start the application 213 | 214 | Now that we know the application is working we can go ahead and start it 215 | 216 | ### ✅ Start the application 217 | 218 | ```bash 219 | npm start 220 | ``` 221 | 222 | **👁️ Expected output** 223 | 224 | ```bash 225 | > todos@0.0.1 start 226 | > node api.js 227 | 228 | Example app listening on port 8080 229 | ``` 230 | 231 | ## 7f - Run the integration tests 232 | 233 | ### ✅ Open the Api in the preview 234 | 235 | Spawn a new shell (Bash is fine) while the app is running, and use it to get the full URL the API will be available at: 236 | 237 | ```bash 238 | gp preview $(gp url 8080)/api/v1/john/todos/ 239 | ``` 240 | 241 | You should see an empty list of todos 242 | 243 | - You might tempted to run the unit test suite now (as well you should) 244 | 245 | ```bash 246 | gp preview https://todobackend.com/specs/index.html?$(gp url 8080)/api/v1/test/todos 247 | ``` 248 | 249 | You will get an error this is expected, it is a limitation of the preview in gitpod. 250 | 251 | ![pic](../images/gitpod-spec-error.png) 252 | 253 | - Open the same link in a new tabs in your browser 254 | 255 | ![pic](../images/gitpod-spec-success.png) 256 | 257 | ## 7g - Run the client 258 | 259 | ### ✅ Open the Client in the preview 260 | 261 | Change in the url the `specs` path by `client` 262 | 263 | ```bash 264 | gp preview https://todobackend.com/client/index.html?$(gp url 8080)/api/v1/test/todos 265 | ``` 266 | 267 | ![pic](../images/gitpod-client-error.png) 268 | 269 | If running into the gitpod preview limitations, open the link in a new TAB. 270 | 271 | ![pic](../images/gitpod-client-success.png) 272 | 273 | ### ✅ Validate with cqlsh 274 | 275 | ```cql 276 | select * from todoitems; 277 | ``` 278 | 279 | **👁️ Expected output** 280 | 281 | ``` 282 | user_id | item_id | completed | offset | title 283 | ----------+--------------------------------------+-----------+--------+--------------------------------- 284 | test | 4828ffc0-7d68-11ec-8c88-2913db53e434 | False | 523 | blah 285 | test | 483ada10-7d68-11ec-8c88-2913db53e434 | False | 95 | null 286 | test | 48625f40-7d68-11ec-8c88-2913db53e434 | False | 95 | null 287 | bootcamp | 9e6e2760-7d69-11ec-8c88-2913db53e434 | False | 1 | Week 1 - Todo 288 | bootcamp | a2fb77b0-7d69-11ec-8c88-2913db53e434 | False | 2 | Week 2 - data modelling 289 | bootcamp | a5b3b9e0-7d69-11ec-8c88-2913db53e434 | False | 3 | Week 3 - App developerment 290 | ``` 291 | 292 | Congratulations! You can now head back! 293 | 294 | [BACK](../README.MD) 295 | -------------------------------------------------------------------------------- /week4-api-microservices/javascript/Test01_Connect.js: -------------------------------------------------------------------------------- 1 | const { client } = require("./connection"); 2 | 3 | console.log("========================================"); 4 | console.log("Start exercise"); 5 | 6 | (async () => { 7 | try { 8 | const result = await client.execute("SELECT * FROM system.local"); 9 | result.rows.forEach((row) => { 10 | console.log( 11 | "Your are now connected to Astra '%s' at '%s'", 12 | row.cluster_name, 13 | row.data_center 14 | ); 15 | }); 16 | console.log("SUCCESS"); 17 | } catch (e) { 18 | console.log(e); 19 | } 20 | console.log("========================================"); 21 | process.exit(); 22 | })(); 23 | -------------------------------------------------------------------------------- /week4-api-microservices/javascript/Test02_CreateSchema.js: -------------------------------------------------------------------------------- 1 | const { client } = require("./connection"); 2 | 3 | console.log("========================================"); 4 | console.log("Start exercise"); 5 | 6 | (async () => { 7 | try { 8 | await client.execute(`DROP TABLE IF EXISTS todoitems ;`); 9 | await client.execute(` 10 | CREATE TABLE IF NOT EXISTS todoitems ( 11 | user_id TEXT, 12 | item_id TIMEUUID, 13 | title TEXT, 14 | url TEXT, 15 | completed BOOLEAN, 16 | offset INT, 17 | PRIMARY KEY ((user_id), item_id) 18 | ) WITH CLUSTERING ORDER BY (item_id ASC);`); 19 | console.log("SUCCESS"); 20 | } catch (e) { 21 | console.log(e); 22 | } 23 | console.log("========================================"); 24 | process.exit(); 25 | })(); 26 | -------------------------------------------------------------------------------- /week4-api-microservices/javascript/Test03_SaveTask.js: -------------------------------------------------------------------------------- 1 | const { client } = require("./connection"); 2 | 3 | console.log("========================================"); 4 | console.log("Start exercise"); 5 | 6 | (async () => { 7 | try { 8 | await client.execute( 9 | "INSERT INTO todoitems (user_id, item_id, completed, title, offset) VALUES ( 'john', 11111111-5cff-11ec-be16-1fedb0dfd057, true, 'Walk the dog', 0);" 10 | ); 11 | 12 | console.log("SUCCESS"); 13 | } catch (e) { 14 | console.log(e); 15 | } 16 | console.log("========================================"); 17 | process.exit(); 18 | })(); 19 | -------------------------------------------------------------------------------- /week4-api-microservices/javascript/api.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const app = express(); 3 | const cors = require("cors"); 4 | const morgan = require("morgan"); 5 | const todos = require("./todos"); 6 | 7 | const port = 8080; 8 | 9 | app.use(express.json()); 10 | app.use(cors()); 11 | app.use(morgan("dev")); 12 | 13 | app.get("/api/v1/:userId/todos", async (req, res) => { 14 | const todoRes = await todos.getTodos(req.params.userId); 15 | res.json(todoRes); 16 | }); 17 | 18 | app.get("/api/v1/:userId/todos/:itemId", async (req, res) => { 19 | const todoRes = await todos.getTodo(req.params.userId, req.params.itemId); 20 | res.json(todoRes); 21 | }); 22 | 23 | app.post("/api/v1/:userId/todos", async (req, res) => { 24 | const todoRes = await todos.createTodo({ 25 | ...req.body, 26 | url: `https://${req.hostname}${req.originalUrl}`, 27 | user_id: req.params.userId, 28 | }); 29 | res.json(todoRes); 30 | }); 31 | 32 | app.patch("/api/v1/:userId/todos/:itemId", async (req, res) => { 33 | const todoRes = await todos.updateTodo(req.params.userId, req.params.itemId, { 34 | ...req.body, 35 | }); 36 | res.json(todoRes); 37 | }); 38 | 39 | app.delete("/api/v1/:userId/todos/:itemId", async (req, res) => { 40 | const todoRes = await todos.deleteTodo(req.params.userId, req.params.itemId); 41 | res.json(todoRes); 42 | }); 43 | 44 | app.delete("/api/v1/:userId/todos", async (req, res) => { 45 | const todoRes = await todos.deleteTodos(); 46 | res.json(todoRes); 47 | }); 48 | 49 | app.listen(port, async () => { 50 | await todos.init(); 51 | console.log(`Example app listening on port ${port}`); 52 | }); 53 | 54 | module.exports = app; 55 | -------------------------------------------------------------------------------- /week4-api-microservices/javascript/connection.js: -------------------------------------------------------------------------------- 1 | // WARNING: THIS FILE IS GOING TO BE OVERWRITTEN 2 | const cassandra = require("cassandra-driver"); 3 | 4 | // This is the Zip file you downloaded 5 | const SECURE_CONNECT_BUNDLE = 6 | "/workspace/bootcamp-fullstack-apps-with-cassandra/secure-connect-workshops.zip"; 7 | // This is the "Client Id" value you obtained earlier 8 | const USERNAME = ""; 9 | // This is the "Client Secret" value you obtained earlier 10 | const PASSWORD = ""; 11 | // This is the keyspace name 12 | const KEYSPACE = "todos"; 13 | 14 | const client = new cassandra.Client({ 15 | cloud: { secureConnectBundle: SECURE_CONNECT_BUNDLE }, 16 | keyspace: KEYSPACE, 17 | credentials: { username: USERNAME, password: PASSWORD }, 18 | }); 19 | 20 | process.on("exit", () => client.shutdown()); 21 | 22 | module.exports = { 23 | client, 24 | }; 25 | -------------------------------------------------------------------------------- /week4-api-microservices/javascript/connection.js.init: -------------------------------------------------------------------------------- 1 | // THIS FILE WILL BE OVERWRITTEN. DO NOT MAKE ANY CHANGES 2 | const cassandra = require("cassandra-driver"); 3 | 4 | // This is the Zip file you downloaded 5 | const SECURE_CONNECT_BUNDLE = 6 | "/workspace/bootcamp-fullstack-apps-with-cassandra/secure-connect-workshops.zip"; 7 | // This is the "Client Id" value you obtained earlier 8 | const USERNAME = "$ASTRA_USERNAME"; 9 | // This is the "Client Secret" value you obtained earlier 10 | const PASSWORD = "$ASTRA_PASSWORD"; 11 | // This is the keyspace name 12 | const KEYSPACE = "todos"; 13 | 14 | const client = new cassandra.Client({ 15 | cloud: { secureConnectBundle: SECURE_CONNECT_BUNDLE }, 16 | keyspace: KEYSPACE, 17 | credentials: { username: USERNAME, password: PASSWORD }, 18 | }); 19 | 20 | process.on("exit", () => client.shutdown()); 21 | 22 | module.exports = { 23 | client, 24 | }; 25 | -------------------------------------------------------------------------------- /week4-api-microservices/javascript/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "todos", 3 | "version": "0.0.1", 4 | "main": "api.js", 5 | "scripts": { 6 | "start": "node api.js", 7 | "test": "mocha *.test.js --timeout 30000 --exit" 8 | }, 9 | "devDependencies": { 10 | "mocha": "^9.2.0" 11 | }, 12 | "dependencies": { 13 | "cassandra-driver": "^4.6.3", 14 | "cors": "^2.8.5", 15 | "dotenv": "^14.2.0", 16 | "express": "^4.17.2", 17 | "morgan": "^1.10.0" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /week4-api-microservices/javascript/todos.js: -------------------------------------------------------------------------------- 1 | require("dotenv").config(); 2 | const { client } = require("./connection"); 3 | const cassandra = require("cassandra-driver"); 4 | 5 | let todoMapper = null; 6 | 7 | process.on("exit", () => client.shutdown()); 8 | 9 | module.exports = { 10 | client, 11 | todoMapper, 12 | init: async () => { 13 | await client.connect(); 14 | await client.execute(`CREATE TABLE IF NOT EXISTS todoitems ( 15 | user_id TEXT, 16 | item_id TIMEUUID, 17 | title TEXT, 18 | url TEXT, 19 | completed BOOLEAN, 20 | offset INT, 21 | PRIMARY KEY ((user_id), item_id) 22 | ) WITH CLUSTERING ORDER BY (item_id ASC);`); 23 | 24 | const mapper = new cassandra.mapping.Mapper(client, { 25 | models: { 26 | Todos: { 27 | tables: ["todoitems"], 28 | keyspace: process.env.ASTRA_DB_KEYSPACE, 29 | columns: { 30 | offset: "order", 31 | }, 32 | }, 33 | }, 34 | }); 35 | todoMapper = mapper.forModel("Todos"); 36 | }, 37 | getTodos: async (userId) => { 38 | const res = await todoMapper.find({ user_id: userId }); 39 | if (res.length) { 40 | return res 41 | .toArray() 42 | .map((item) => ({ ...item, item_id: item.item_id.toString() })); 43 | } 44 | return []; 45 | }, 46 | deleteTodos: async () => { 47 | await client.execute("TRUNCATE TABLE todoitems"); 48 | return []; 49 | }, 50 | createTodo: async (todo) => { 51 | const item_id = cassandra.types.TimeUuid.now().toString(); 52 | const newTodo = { 53 | item_id, 54 | completed: false, 55 | ...todo, 56 | url: todo.url + "/" + item_id, 57 | }; 58 | await todoMapper.insert(newTodo); 59 | return newTodo; 60 | }, 61 | updateTodo: async (userId, itemId, todo) => { 62 | const updatedTodo = { 63 | user_id: userId, 64 | item_id: itemId, 65 | ...todo, 66 | }; 67 | await todoMapper.update(updatedTodo); 68 | return updatedTodo; 69 | }, 70 | deleteTodo: async (userId, itemId) => { 71 | await todoMapper.remove({ user_id: userId, item_id: itemId }); 72 | return { 73 | userId, 74 | itemId, 75 | }; 76 | }, 77 | getTodo: async (userId, itemId) => { 78 | const res = await todoMapper.get({ user_id: userId, item_id: itemId }); 79 | if (res) { 80 | return { ...res, item_id: res.item_id.toString() }; 81 | } 82 | return null; 83 | }, 84 | }; 85 | -------------------------------------------------------------------------------- /week4-api-microservices/javascript/todos.test.js: -------------------------------------------------------------------------------- 1 | const assert = require("assert"); 2 | const todos = require("./todos"); 3 | 4 | describe("Todos", () => { 5 | it("it should initialize", async () => { 6 | await todos.init(); 7 | assert.equal(true, true); 8 | }); 9 | 10 | it("it should create a todo", async () => { 11 | const todo = await todos.createTodo({ 12 | user_id: "jake", 13 | title: "hello world", 14 | }); 15 | assert.equal(todo.title, "hello world"); 16 | }); 17 | 18 | it("it should get todos", async () => { 19 | const res = await todos.getTodos("jake"); 20 | assert.equal(res.length, 1); 21 | }); 22 | 23 | it("it should update todos", async () => { 24 | const res = await todos.getTodos("jake"); 25 | const existingTodo = res[0]; 26 | await todos.updateTodo("jake", existingTodo.item_id, { 27 | title: "hello world 2", 28 | }); 29 | const todo = await todos.getTodo("jake", existingTodo.item_id); 30 | assert.equal(todo.title, "hello world 2"); 31 | }); 32 | 33 | it("it should delete a todo", async () => { 34 | const res = await todos.getTodos("jake"); 35 | const existingTodo = res[0]; 36 | await todos.deleteTodo("jake", existingTodo.item_id); 37 | const todo = await todos.getTodo("jake", existingTodo.item_id); 38 | assert.equal(todo, null); 39 | }); 40 | 41 | it("it should delete todos", async () => { 42 | await todos.deleteTodos(); 43 | assert.equal(true, true); 44 | }); 45 | }); 46 | -------------------------------------------------------------------------------- /week4-api-microservices/plugastracreds: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ ! -f .env ]; then 4 | echo "File .env needs to exist." 5 | exit -1 6 | fi 7 | 8 | source .env 9 | 10 | if [ ! "$ASTRA_USERNAME" ]; then 11 | echo "env variable ASTRA_USERNAME needs to be set" 12 | exit -1 13 | fi 14 | 15 | if [ ! "$ASTRA_PASSWORD" ]; then 16 | echo "env variable ASTRA_PASSWORD needs to be set" 17 | exit -1 18 | fi 19 | 20 | if [ ! -f /workspace/bootcamp-fullstack-apps-with-cassandra/secure-connect-workshops.zip ]; then 21 | echo "Secure connect bundle to connect to Astra does not exist." 22 | exit -1 23 | fi 24 | 25 | cat ./java/src/main/resources/application.properties.init | \ 26 | sed "s/\$ASTRA_USERNAME/$ASTRA_USERNAME/" | \ 27 | sed "s/\$ASTRA_PASSWORD/$ASTRA_PASSWORD/" > \ 28 | ./java/src/main/resources/application.properties 29 | 30 | cat ./javascript/connection.js.init | \ 31 | sed "s/\$ASTRA_USERNAME/$ASTRA_USERNAME/" | \ 32 | sed "s/\$ASTRA_PASSWORD/$ASTRA_PASSWORD/" > \ 33 | ./javascript/connection.js 34 | 35 | cat ./python/connection.py.init | \ 36 | sed "s/\$ASTRA_USERNAME/$ASTRA_USERNAME/" | \ 37 | sed "s/\$ASTRA_PASSWORD/$ASTRA_PASSWORD/" > \ 38 | ./python/connection.py 39 | 40 | echo "Astra credentials plugged into all language environments. Please verify!" 41 | 42 | if [ ! -f /workspace/bootcamp-fullstack-apps-with-cassandra/zshrcinit ]; then 43 | cp ~/.zshrc /workspace/bootcamp-fullstack-apps-with-cassandra/zshrcinit 44 | echo "/workspace/bootcamp-fullstack-apps-with-cassandra/cqlsh-astra/bin/cqlsh \\ 45 | --secure-connect-bundle=/workspace/bootcamp-fullstack-apps-with-cassandra/secure-connect-workshops.zip \\ 46 | --color \\ 47 | -u $ASTRA_USERNAME \\ 48 | -p $ASTRA_PASSWORD" >> /workspace/bootcamp-fullstack-apps-with-cassandra/zshrcinit 49 | cp /workspace/bootcamp-fullstack-apps-with-cassandra/zshrcinit ~/.zshrc 50 | else 51 | cp /workspace/bootcamp-fullstack-apps-with-cassandra/zshrcinit ~/.zshrc 52 | fi 53 | 54 | touch /workspace/bootcamp-fullstack-apps-with-cassandra/zshrcinit 55 | -------------------------------------------------------------------------------- /week4-api-microservices/python/.env.example: -------------------------------------------------------------------------------- 1 | # Copy this file to .env and fill in the appropriate values. Refer to README.md 2 | # for instructions on where to find them. 3 | FLASK_APP=api 4 | CQLENG_ALLOW_SCHEMA_MANAGEMENT=1 5 | ASTRA_DB_BUNDLE_PATH=bundle.zip 6 | ASTRA_DB_KEYSPACE=sag_todos 7 | ASTRA_DB_CLIENT_ID= 8 | ASTRA_DB_CLIENT_SECRET= -------------------------------------------------------------------------------- /week4-api-microservices/python/README.MD: -------------------------------------------------------------------------------- 1 | # 🎓🔥 API and MicroServices with Apache Cassandra - Python 🔥🎓 2 | 3 | ![pic](../images/splash.png) 4 | 5 | ![Python](https://raw.githubusercontent.com/DataStax-Academy/cassandra-workshop-series/master/materials/images/logo-python.png) 6 | 7 | ## Python Todos 8 | 9 | An implementation of a Todo's API using ExpressJS and the Cassandra Python driver. 10 | 11 | 12 | ## 7a - Connect to Astra 13 | 14 | ### ✅ Check connectivity parameters 15 | 16 | - Make sure you're in the right sub-directory (`python`) by issuing the following command in the GitPod terminal window. 17 | 18 | ```bash 19 | cd /workspace/bootcamp-fullstack-apps-with-cassandra/week4-api-microservices/python 20 | ``` 21 | 22 | - Verify again you're in the `python` sub-directory using the following command 23 | 24 | ```bash 25 | pwd 26 | ``` 27 | 28 | **👁️ Expected output** 29 | 30 | ``` 31 | /workspace/bootcamp-fullstack-apps-with-cassandra/week4-api-microservices/python 32 | ``` 33 | 34 | - From the GitPod terminal window issue the following command 35 | 36 | ```bash 37 | open connection.py 38 | ``` 39 | 40 | and notice the following lines have been updated with the appropriate values. 41 | 42 | ```python 43 | # This is the "Client Id" value you obtained earlier 44 | USERNAME = "FXXXXXXXXXXl"; 45 | # This is the "Client Secret" value you obtained earlier 46 | PASSWORD = 47 | "FXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXdeOE.kio_.L981NQ.xq5HqXDB7s_FIJC.ssbLgbdz+G1IC0BCwIA_ZrwPrQNJWUiv26uZf2f4wo"; 48 | ``` 49 | 50 | ### ✅ Run the test 51 | 52 | You are ready and can now test the connection to Astra with the following command 53 | 54 | ```bash 55 | python Test01_Connect.py 56 | ``` 57 | 58 | **👁️ Expected output** 59 | 60 | ``` 61 | ======================================== 62 | Start exercise 63 | ======================================== 64 | Your are now connected to Astra 'cndb' at 'us-east1' 65 | SUCCESS 66 | ``` 67 | 68 | Now that we're successfully able to establish the connection, take a moment to walk through how the connection has been established by opening the source code using the following command 69 | 70 | ``` 71 | gp open Test01_Connect.py 72 | ``` 73 | 74 | ## 7b - Create the schema 75 | 76 | ### ✅ Run Test 77 | 78 | Let's create the table. We will **drop** a table if it already exists with the same name. 79 | 80 | - Take a moment to review the code with the following command 81 | 82 | ```bash 83 | gp open Test02_CreateSchema.py 84 | ``` 85 | 86 | - After reviewing the code, run the following command in the GitPod terminal window which runs the code after making the connection. 87 | 88 | ```bash 89 | python Test02_CreateSchema.py 90 | ``` 91 | 92 | **👁️ Expected output** 93 | 94 | ```bash 95 | ======================================== 96 | Start exercise 97 | SUCCESS 98 | ======================================== 99 | ``` 100 | 101 | If you run into a timeout error rerun this command and confirm that the table is dropped (we changed the data model slightly so its imperative the table is dropped). 102 | 103 | ### ✅ Validate Schema with Cqlsh 104 | 105 | - Open a terminal `cqlsh` to open a cqlsh shell (we overrided .zshrc to give you that feature) 106 | 107 | ```cql 108 | DESCRIBE KEYSPACE todos; 109 | ``` 110 | 111 | **👁️ Expected output** 112 | 113 | ```cql 114 | Connected to cndb at 127.0.0.1:9042. 115 | [cqlsh 6.8.0 | Cassandra 4.0.0.6816 | CQL spec 3.4.5 | Native protocol v4] 116 | Use HELP for help. 117 | token@cqlsh> describe keyspace todos; 118 | 119 | CREATE KEYSPACE todos WITH replication = {'class': 'NetworkTopologyStrategy', 'eu-west-1': '3'} AND durable_writes = true; 120 | 121 | CREATE TABLE todos.todoitems ( 122 | user_id text, 123 | item_id timeuuid, 124 | completed boolean, 125 | offset int, 126 | title text, 127 | PRIMARY KEY (user_id, item_id) 128 | ) WITH CLUSTERING ORDER BY (item_id ASC) 129 | AND additional_write_policy = '99PERCENTILE' 130 | AND bloom_filter_fp_chance = 0.01 131 | AND caching = {'keys': 'ALL', 'rows_per_partition': 'NONE'} 132 | AND comment = '' 133 | AND compaction = {'class': 'org.apache.cassandra.db.compaction.UnifiedCompactionStrategy'} 134 | AND compression = {'chunk_length_in_kb': '64', 'class': 'org.apache.cassandra.io.compress.LZ4Compressor'} 135 | AND crc_check_chance = 1.0 136 | AND default_time_to_live = 0 137 | AND gc_grace_seconds = 864000 138 | AND max_index_interval = 2048 139 | AND memtable_flush_period_in_ms = 0 140 | AND min_index_interval = 128 141 | AND read_repair = 'BLOCKING' 142 | AND speculative_retry = '99PERCENTILE'; 143 | 144 | token@cqlsh> 145 | ``` 146 | 147 | ## 7c - Save a Task 148 | 149 | ### ✅ Run Test 150 | 151 | Let's insert some items. 152 | 153 | - Take a moment to review the code with the following command 154 | 155 | ```bash 156 | gp open Test03_SaveTask.py 157 | ``` 158 | 159 | - After reviewing the code, run the following command in the GitPod terminal window which runs the code after making the connection. 160 | 161 | ```bash 162 | python Test03_SaveTask.py 163 | ``` 164 | 165 | **👁️ Expected output** 166 | 167 | ```bash 168 | ======================================== 169 | Start exercise 170 | SUCCESS 171 | ======================================== 172 | ``` 173 | 174 | ### ✅ Validate with Cqlsh 175 | 176 | - Open a terminal `zsh` to open a cqlsh shell (we overrided .zshrc to give you that feature) 177 | 178 | ```cql 179 | select * from todos.todoitems; 180 | ``` 181 | 182 | **👁️ Expected output** 183 | 184 | ```bash 185 | token@cqlshs> select * from todos.todoitems; 186 | 187 | user_id | item_id | completed | offset | title 188 | ---------+--------------------------------------+-----------+--------+-------------- 189 | john | 1793e4e0-7d65-11ec-b3f6-15c8273bc04a | False | 0 | Sample task1 190 | ``` 191 | 192 | ## 7d - Test REST Endpoint 193 | 194 | ### ✅ Run Test 195 | 196 | ```bash 197 | pytest 198 | ``` 199 | 200 | **👁️ Expected output** 201 | 202 | ```bash 203 | collected 13 items 204 | 205 | test_api.py::test_get_empty_todos 206 | api 207 | ✓ it should get an empty list of todos 208 | 209 | test_api.py::test_create_todo ✓ it should create a todo 210 | 211 | test_api.py::test_not_create_todo ✓ it should not create a todo 212 | 213 | test_api.py::test_get_todo ✓ it should get a single todo 214 | 215 | test_api.py::test_not_get_todo ✓ it should not get a single todo 216 | 217 | test_api.py::test_get_todos ✓ it should get a list of todos 218 | 219 | test_api.py::test_delete_todo ✓ it should delete a single todo 220 | 221 | test_api.py::test_update_todo ✓ it should update a single todo 222 | 223 | test_api.py::test_delete_all_todos ✓ it should delete all todos 224 | 225 | test_todos.py::test_create_todo 226 | todos 227 | ✓ it should create a todo 228 | 229 | test_todos.py::test_delete_todo ✓ it should delete a single todo 230 | 231 | test_todos.py::test_update_todo ✓ it should update a single todo 232 | 233 | test_todos.py::test_delete_all_todos ✓ it should delete all todos 234 | 235 | 236 | ---------- coverage: platform darwin, python 3.9.4-final-0 ----------- 237 | Name Stmts Miss Cover Missing 238 | ------------------------------------------------------ 239 | Test01_Connect.py 12 12 0% 2-16 240 | Test02_CreateSchema.py 11 11 0% 2-22 241 | Test03_SaveTask.py 11 11 0% 2-15 242 | api.py 54 0 100% 243 | connection.py 15 2 87% 35-36 244 | test_api.py 67 0 100% 245 | test_todos.py 24 1 96% 18 246 | todos.py 20 0 100% 247 | ------------------------------------------------------ 248 | TOTAL 214 37 83% 249 | ``` 250 | 251 | ## 7e - Start the application 252 | 253 | Now that we know the application is working we can go ahead and start it 254 | 255 | ### ✅ Start the application 256 | 257 | ```bash 258 | FLASK_APP=api:app flask run --port 8080 259 | ``` 260 | 261 | **👁️ Expected output** 262 | 263 | ```bash 264 | * Serving Flask app 'api' (lazy loading) 265 | * Environment: production 266 | WARNING: This is a development server. Do not use it in a production deployment. 267 | Use a production WSGI server instead. 268 | * Debug mode: off 269 | * Running on http://127.0.0.1:8080/ (Press CTRL+C to quit) 270 | ``` 271 | 272 | ## 7f - Run the integrations tests 273 | 274 | ### ✅ Open the Api in the preview 275 | 276 | (while the API is running you should use another Gitpod terminal to run other commands) 277 | 278 | ```bash 279 | gp preview $(gp url 8080)/api/v1/john/todos/ 280 | ``` 281 | 282 | You should see an empty list of todos 283 | 284 | - You might tempted to run the unit test suite now (as well you should) 285 | 286 | ```bash 287 | gp preview https://todobackend.com/specs/index.html?$(gp url 8080)/api/v1/test/todos 288 | ``` 289 | 290 | You will get an error this is expected, it is a limitation of the preview in gitpod. 291 | 292 | ![pic](../images/gitpod-spec-error.png) 293 | 294 | - Open the same link in a new tabs in your browser 295 | 296 | ![pic](../images/gitpod-spec-success.png) 297 | 298 | ## 7g - Run the client 299 | 300 | ### ✅ Open the Client in the preview 301 | 302 | Change in the url the `specs` path by `client` 303 | 304 | ```bash 305 | gp preview https://todobackend.com/client/index.html?$(gp url 8080)/api/v1/test/todos 306 | ``` 307 | 308 | ![pic](../images/gitpod-client-error.png) 309 | 310 | If running into the gitpod preview limitations, open the link in a new TAB. 311 | 312 | ![pic](../images/gitpod-client-success.png) 313 | 314 | ### ✅ Validate with cqlsh 315 | 316 | ```cql 317 | select * from todoitems; 318 | ``` 319 | 320 | **👁️ Expected output** 321 | 322 | ``` 323 | user_id | item_id | completed | offset | title 324 | ----------+--------------------------------------+-----------+--------+--------------------------------- 325 | test | 4828ffc0-7d68-11ec-8c88-2913db53e434 | False | 523 | blah 326 | test | 483ada10-7d68-11ec-8c88-2913db53e434 | False | 95 | null 327 | test | 48625f40-7d68-11ec-8c88-2913db53e434 | False | 95 | null 328 | bootcamp | 9e6e2760-7d69-11ec-8c88-2913db53e434 | False | 1 | Week 1 - Todo 329 | bootcamp | a2fb77b0-7d69-11ec-8c88-2913db53e434 | False | 2 | Week 2 - data modelling 330 | bootcamp | a5b3b9e0-7d69-11ec-8c88-2913db53e434 | False | 3 | Week 3 - App developerment 331 | ``` 332 | 333 | Congratulations! You can now head back! 334 | 335 | [BACK](../README.MD) 336 | -------------------------------------------------------------------------------- /week4-api-microservices/python/Test01_Connect.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | from connection import session 3 | 4 | print('========================================') 5 | print('Start exercise') 6 | try: 7 | output = session.execute("SELECT * FROM system.local") 8 | for row in output: 9 | print('You are now connected to cluster %s at %s' % 10 | (row.cluster_name, row.data_center)) 11 | except Exception as e: 12 | print(e) 13 | print('Failure') 14 | else: 15 | print('Success') 16 | print('========================================') 17 | -------------------------------------------------------------------------------- /week4-api-microservices/python/Test02_CreateSchema.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | from connection import session 3 | 4 | print('========================================') 5 | print('Start exercise by dropping and creating table') 6 | try: 7 | session.execute("""DROP TABLE IF EXISTS todoitems;""") 8 | session.execute("""CREATE TABLE IF NOT EXISTS todoitems ( 9 | user_id TEXT, 10 | item_id TIMEUUID, 11 | title TEXT, 12 | url TEXT, 13 | completed BOOLEAN, 14 | offset INT, 15 | PRIMARY KEY ((user_id), item_id) 16 | ) WITH CLUSTERING ORDER BY (item_id ASC); 17 | """) 18 | except Exception as e: 19 | print(e) 20 | print('Failure') 21 | else: 22 | print('Success') 23 | print('========================================') 24 | -------------------------------------------------------------------------------- /week4-api-microservices/python/Test03_SaveTask.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import uuid 3 | from connection import session 4 | 5 | print('========================================') 6 | print('Start exercise') 7 | try: 8 | session.execute( 9 | "INSERT INTO todoitems (user_id, item_id, completed, title, offset) VALUES ( 'john', 11111111-5cff-11ec-be16-1fedb0dfd057, true, 'Walk the dog', 0);") 10 | except Exception as e: 11 | print(e) 12 | print('Failure') 13 | else: 14 | print('Success') 15 | print('========================================') 16 | -------------------------------------------------------------------------------- /week4-api-microservices/python/api.py: -------------------------------------------------------------------------------- 1 | import uuid 2 | from dotenv import load_dotenv 3 | from cassandra.cqlengine.management import sync_table 4 | from cassandra.cqlengine import ValidationError 5 | from cassandra.cqlengine.models import Model 6 | from flask import Flask, jsonify, request 7 | from todos import Todos, session, KEYSPACE 8 | from flask_cors import CORS 9 | 10 | load_dotenv() 11 | 12 | 13 | # setup flask 14 | app = Flask(__name__) 15 | CORS(app, resources={r"/api/*": {"origins": "*"}}) 16 | 17 | 18 | @app.route("/api/v1//todos", methods=["GET"]) 19 | def get_todos(user_id): 20 | res = [dict(x) for x in Todos.filter(user_id=user_id)] 21 | return jsonify(res) 22 | 23 | 24 | @app.route("/api/v1//todos", methods=["DELETE"]) 25 | def delete_todos(user_id): 26 | session.execute( 27 | f"TRUNCATE TABLE {KEYSPACE}.todoitems") 28 | sync_table(Todos) 29 | return jsonify({"success": True}) 30 | 31 | 32 | @app.route("/api/v1//todos", methods=["POST"]) 33 | def create_todo(user_id): 34 | try: 35 | request_json = request.get_json(force=True) 36 | item_id = uuid.uuid1() 37 | request_json["item_id"] = item_id 38 | request_json["url"] = f"https://{request.headers.get('X-Forwarded-Host', 'localhost')}/api/v1/{user_id}/todos/{item_id}" 39 | new_todo = Todos.create(user_id=user_id, **request_json) 40 | return jsonify(dict(new_todo)) 41 | except ValidationError as e: 42 | return jsonify({"error": str(e)}), 400 43 | 44 | 45 | @app.route("/api/v1//todos/", methods=["GET"]) 46 | def get_todo(user_id, item_id): 47 | try: 48 | todo = Todos.get(user_id=user_id, item_id=item_id) 49 | return jsonify(dict(todo)) 50 | except Model.DoesNotExist: 51 | return jsonify({"error": "not found"}), 404 52 | 53 | 54 | @app.route("/api/v1//todos/", methods=["DELETE"]) 55 | def delete_todo(user_id, item_id): 56 | try: 57 | todo = Todos.get(user_id=user_id, item_id=item_id) 58 | todo.delete() 59 | return jsonify(dict(todo)) 60 | except Model.DoesNotExist: 61 | return jsonify({"error": "not found"}), 404 62 | 63 | 64 | @app.route("/api/v1//todos/", methods=["PATCH"]) 65 | def update_todo(user_id, item_id): 66 | try: 67 | todo = Todos.get(user_id=user_id, item_id=item_id) 68 | request_json = request.get_json(force=True) 69 | todo.update(**request_json) 70 | return jsonify(dict(todo)) 71 | except Model.DoesNotExist: 72 | return jsonify({"error": "not found"}), 404 73 | except ValidationError as e: 74 | return jsonify({"error": str(e)}), 400 75 | -------------------------------------------------------------------------------- /week4-api-microservices/python/connection.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # THIS FILE WILL BE OVERWRITTEN. DO NOT MAKE ANY CHANGES HERE 3 | 4 | import atexit 5 | from cassandra.cluster import Cluster 6 | from cassandra.auth import PlainTextAuthProvider 7 | 8 | # This is the Zip file you downloaded 9 | SECURE_CONNECT_BUNDLE = '/workspace/bootcamp-fullstack-apps-with-cassandra/secure-connect-workshops.zip' 10 | # This is the "Client Id" value you obtained earlier 11 | USERNAME = "" 12 | # This is the "Client Secret" value you obtained earlier 13 | PASSWORD = "" 14 | # This is the keyspace name 15 | KEYSPACE = "todos" 16 | 17 | 18 | secure_connect_bundle = SECURE_CONNECT_BUNDLE 19 | path_to_creds = '' 20 | cluster = Cluster( 21 | cloud={ 22 | 'secure_connect_bundle': SECURE_CONNECT_BUNDLE 23 | }, 24 | auth_provider=PlainTextAuthProvider(USERNAME, PASSWORD) 25 | ) 26 | session = cluster.connect(KEYSPACE) 27 | 28 | 29 | @atexit.register 30 | def shutdown_driver(): 31 | cluster.shutdown() 32 | session.shutdown() 33 | -------------------------------------------------------------------------------- /week4-api-microservices/python/connection.py.init: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # THIS FILE WILL BE OVERWRITTEN. DO NOT MAKE ANY CHANGES HERE 3 | 4 | import atexit 5 | from cassandra.cluster import Cluster 6 | from cassandra.auth import PlainTextAuthProvider 7 | 8 | # This is the Zip file you downloaded 9 | SECURE_CONNECT_BUNDLE = '/workspace/bootcamp-fullstack-apps-with-cassandra/secure-connect-workshops.zip' 10 | # This is the "Client Id" value you obtained earlier 11 | USERNAME = "$ASTRA_USERNAME" 12 | # This is the "Client Secret" value you obtained earlier 13 | PASSWORD = "$ASTRA_PASSWORD" 14 | # This is the keyspace name 15 | KEYSPACE = "todos" 16 | 17 | 18 | secure_connect_bundle = SECURE_CONNECT_BUNDLE 19 | path_to_creds = '' 20 | cluster = Cluster( 21 | cloud={ 22 | 'secure_connect_bundle': SECURE_CONNECT_BUNDLE 23 | }, 24 | auth_provider=PlainTextAuthProvider(USERNAME, PASSWORD) 25 | ) 26 | session = cluster.connect(KEYSPACE) 27 | 28 | 29 | @atexit.register 30 | def shutdown_driver(): 31 | cluster.shutdown() 32 | session.shutdown() 33 | -------------------------------------------------------------------------------- /week4-api-microservices/python/pytest.ini: -------------------------------------------------------------------------------- 1 | [pytest] 2 | filterwarnings = ignore::DeprecationWarning 3 | addopts = -v --cov=. --cov-report term-missing --testdox 4 | log_cli = 1 5 | log_cli_level = INFO -------------------------------------------------------------------------------- /week4-api-microservices/python/requirements.txt: -------------------------------------------------------------------------------- 1 | flask==2.0.2 2 | python-dotenv==0.19.2 3 | cassandra-driver==3.25.0 4 | pytest==6.2.5 5 | pytest-cov==3.0.0 6 | pytest-testdox==3.0.0 7 | flask-cors==3.0.10 8 | -------------------------------------------------------------------------------- /week4-api-microservices/python/test_api.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | import uuid 3 | from api import app 4 | 5 | USER_ID = "jake" 6 | 7 | with app.test_client() as client: 8 | @pytest.mark.it("it should get an empty list of todos") 9 | def test_get_empty_todos(): 10 | get_res = client.get(f"/api/v1/{USER_ID}/todos") 11 | get_res_json = get_res.get_json() 12 | assert len(get_res_json) == 0 13 | 14 | @pytest.mark.it("it should create a todo") 15 | def test_create_todo(): 16 | res = client.post(f"/api/v1/{USER_ID}/todos", 17 | json={"title": "hello world"}) 18 | res_json = res.get_json() 19 | assert res_json["title"] == "hello world" 20 | 21 | @pytest.mark.it("it should not create a todo") 22 | def test_not_create_todo(): 23 | res = client.post(f"/api/v1/{USER_ID}/todos", json={"title": ""}) 24 | assert res.status_code == 400 25 | 26 | @pytest.mark.it("it should get a single todo") 27 | def test_get_todo(): 28 | res = client.post(f"/api/v1/{USER_ID}/todos", 29 | json={"title": "hello world 2"}) 30 | res_json = res.get_json() 31 | get_res = client.get(f"/api/v1/{USER_ID}/todos/{res_json['item_id']}") 32 | get_res_json = get_res.get_json() 33 | assert get_res_json["title"] == "hello world 2" 34 | 35 | @pytest.mark.it("it should not get a single todo") 36 | def test_not_get_todo(): 37 | get_res = client.get(f"/api/v1/{USER_ID}/todos/{uuid.uuid1()}") 38 | assert get_res.status_code == 404 39 | 40 | @pytest.mark.it("it should get a list of todos") 41 | def test_get_todos(): 42 | get_res = client.get(f"/api/v1/{USER_ID}/todos") 43 | get_res_json = get_res.get_json() 44 | assert len(get_res_json) == 2 45 | 46 | @pytest.mark.it("it should delete a single todo") 47 | def test_delete_todo(): 48 | res = client.post(f"/api/v1/{USER_ID}/todos", 49 | json={"title": "hello world 3"}) 50 | res_json = res.get_json() 51 | delete_res = client.delete( 52 | f"/api/v1/{USER_ID}/todos/{res_json['item_id']}") 53 | delete_res_json = delete_res.get_json() 54 | assert delete_res_json["title"] == "hello world 3" 55 | get_res = client.get(f"/api/v1/{USER_ID}/todos/{res_json['item_id']}") 56 | assert get_res.status_code == 404 57 | del_res = client.delete( 58 | f"/api/v1/{USER_ID}/todos/{res_json['item_id']}") 59 | assert del_res.status_code == 404 60 | 61 | @pytest.mark.it("it should update a single todo") 62 | def test_update_todo(): 63 | res = client.post(f"/api/v1/{USER_ID}/todos", 64 | json={"title": "hello world 4"}) 65 | res_json = res.get_json() 66 | patch_res = client.patch( 67 | f"/api/v1/{USER_ID}/todos/{res_json['item_id']}", json={"completed": True}) 68 | assert patch_res.status_code == 200 69 | get_res = client.get(f"/api/v1/{USER_ID}/todos/{res_json['item_id']}") 70 | get_res_json = get_res.get_json() 71 | assert get_res_json["completed"] == True 72 | bad_res = client.patch( 73 | f"/api/v1/{USER_ID}/todos/{res_json['item_id']}", json={"title": ""}) 74 | assert bad_res.status_code == 400 75 | missing_res = client.patch(f"/api/v1/{USER_ID}/todos/{uuid.uuid1()}") 76 | assert missing_res.status_code == 404 77 | 78 | @pytest.mark.it("it should delete all todos") 79 | def test_delete_all_todos(): 80 | delete_res = client.delete(f"/api/v1/{USER_ID}/todos") 81 | delete_res_json = delete_res.get_json() 82 | assert delete_res_json["success"] == True 83 | get_res = client.get(f"/api/v1/{USER_ID}/todos") 84 | get_res_json = get_res.get_json() 85 | assert get_res_json == [] 86 | -------------------------------------------------------------------------------- /week4-api-microservices/python/test_todos.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | import os 3 | from todos import Todos, session, KEYSPACE 4 | 5 | 6 | @pytest.mark.it("it should create a todo") 7 | def test_create_todo(): 8 | todo = Todos.create(user_id="jake", title="hello world") 9 | assert todo.title == "hello world" 10 | 11 | 12 | @pytest.mark.it("it should delete a single todo") 13 | def test_delete_todo(): 14 | todo = Todos.create(user_id="jake", title="hello world 2") 15 | todo.delete() 16 | try: 17 | todo = Todos.get(user_id="jake", item_id=todo.item_id) 18 | assert False 19 | except: 20 | assert True 21 | 22 | 23 | @pytest.mark.it("it should update a single todo") 24 | def test_update_todo(): 25 | todo = Todos.create(user_id="jake", title="hello world 3") 26 | todo.update(title="hello world 4") 27 | assert todo.title == "hello world 4" 28 | 29 | 30 | @pytest.mark.it("it should delete all todos") 31 | def test_delete_all_todos(): 32 | session.execute( 33 | f"TRUNCATE TABLE {KEYSPACE}.todoitems") 34 | -------------------------------------------------------------------------------- /week4-api-microservices/python/todos.py: -------------------------------------------------------------------------------- 1 | import os 2 | import uuid 3 | from dotenv import load_dotenv 4 | from cassandra.cqlengine import columns 5 | from cassandra.cqlengine.models import Model 6 | from cassandra.cqlengine.management import sync_table 7 | from cassandra.cqlengine import connection 8 | from connection import session, KEYSPACE 9 | 10 | load_dotenv() 11 | session.default_timeout = 60 12 | connection.register_connection("session", session=session, default=True) 13 | 14 | 15 | class Todos(Model): 16 | __keyspace__ = KEYSPACE 17 | __table_name__ = "todoitems" 18 | user_id = columns.Text(primary_key=True, required=True) 19 | item_id = columns.TimeUUID( 20 | primary_key=True, clustering_order="DESC", default=uuid.uuid1) 21 | url = columns.Text() 22 | title = columns.Text(required=True) 23 | completed = columns.Boolean(default=False) 24 | order = columns.Integer(db_field="offset") 25 | 26 | 27 | sync_table(Todos) 28 | -------------------------------------------------------------------------------- /week4-api-microservices/slides/slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/bootcamp-fullstack-apps-with-cassandra/737c17e0a618dd2b7bafb3700116a6b477203b01/week4-api-microservices/slides/slides.pdf --------------------------------------------------------------------------------