{"id":27370210,"url":"https://github.com/datastaxdevs/workshop-intro-quarkus-cassandra","last_synced_at":"2025-04-13T08:48:20.187Z","repository":{"id":37814376,"uuid":"420580985","full_name":"datastaxdevs/workshop-intro-quarkus-cassandra","owner":"datastaxdevs","description":null,"archived":false,"fork":false,"pushed_at":"2023-03-11T14:50:32.000Z","size":45622,"stargazers_count":18,"open_issues_count":1,"forks_count":15,"subscribers_count":4,"default_branch":"master","last_synced_at":"2023-03-11T15:10:18.355Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/datastaxdevs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-10-24T03:52:01.000Z","updated_at":"2023-02-08T05:55:56.000Z","dependencies_parsed_at":"2023-01-19T14:01:42.749Z","dependency_job_id":null,"html_url":"https://github.com/datastaxdevs/workshop-intro-quarkus-cassandra","commit_stats":null,"previous_names":[],"tags_count":null,"template":null,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/datastaxdevs%2Fworkshop-intro-quarkus-cassandra","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/datastaxdevs%2Fworkshop-intro-quarkus-cassandra/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/datastaxdevs%2Fworkshop-intro-quarkus-cassandra/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/datastaxdevs%2Fworkshop-intro-quarkus-cassandra/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/datastaxdevs","download_url":"https://codeload.github.com/datastaxdevs/workshop-intro-quarkus-cassandra/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248688193,"owners_count":21145762,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-04-13T08:48:19.358Z","updated_at":"2025-04-13T08:48:20.171Z","avatar_url":"https://github.com/datastaxdevs.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# Intro to Quarkus and Cassandra with Kubernetes\n\n[![Gitpod ready-to-code](https://img.shields.io/badge/Gitpod-ready--to--code-blue?logo=gitpod)](https://gitpod.io/#https://github.com/datastaxdevs/quarkus-astra-intro-demo)\n[![License Apache2](https://img.shields.io/hexpm/l/plug.svg)](http://www.apache.org/licenses/LICENSE-2.0)\n[![Discord](https://img.shields.io/discord/685554030159593522)](https://discord.com/widget?id=685554030159593522\u0026theme=dark)\n\nToday we showcase an application using **Apache Cassandra™** as a backend implemented with **Quarkus**, and experience some developer joy with features that often have been an envy for Java programmers - hot reloading, debugging, containerizing and finally generating native code.\n\nThere are many other features of the Quarkus platform that we will not be looking into that are widely considered as unique strengths of the platform including testing.\n\nWe will deploy the app on containers in Kubernetes using Lens.\n\nThe application we will be using is based on [Jake's port](https://github.com/tjake/todo-astra-react-serverless/) of the [TodoMVC code](https://github.com/tastejs/todomvc/tree/master/examples/react) originally written by [Pete Hunt](https://github.com/petehunt). The example is modified from [https://github.com/huksley/todo-react-ssr-serverless](https://github.com/huksley/todo-react-ssr-serverless).\n\nA screenshot of this simple app is below.\n\n![AstraTodo](images/tutorials/AstraTodos.png?raw=true)\n\nℹ️ **Objective(s) of workshop**\n\nWhether you're a seasoned developer or relatively new to programming, you will be spending a lot of time in an Integrated Development Environment and the \"inner loop\" of development with a lightweight CI/CD cycle.\n\nOnce you have a stable environment after repeated iterations in the editor, testing environments, profiler, debugger, etc. you push it to the outer loop which has a more robust CI/CD cycle usually backed by gitops, Jenkins and other CI/CD tools.\n\nThe objective of today's workshop is to understand how the Quarkus platform simplifies the \"inner loop\" of development which results in huge developer productivity gains. You will see in today's workshop you can go from plain old Java to containers with relative ease and yet not make a significant change in devlopment.\n\nAlthough, the Quarkus platform leverages a reactive architecture, the developer tools are drawn from a list that they are familar with and complements them while making those same tools leaner and more performant. This means that Quarkus does not force developers to use reactive programming styles. Additionally, it helps to build better and more performant applications (which is always necessary) and also enhances the day-to-day life of a developer having to bridge the gap between their existing platforms and taking a plunge into microservices, service mesh and so on. Developers can use their current tools and methodologies and let Quarkus take care of being \"reactive\", or build new fully-reactive applications that take advantage of Quarkus' reactive core.\n\nℹ️ **Frequently asked questions**\n\n- _Can I run the workshop on my computer?_\n  \u003e There is nothing preventing you from running the workshop on your own machine. If you do so, you will need _java jdk11+_, _Graal VM_, _Maven_, an IDE like _VSCode, IntelliJ, Eclipse, Spring STS_. You will have to adapt commands and paths based on your environment and install the dependencies by yourself. **We won't provide support** to keep on track with schedule.\n\n##  Prerequisites\n\nWe strive to make our hands-on workshops prerequisites free -- who has the time to install prerequistes? :-)\n\nHowever, docker login credentials, some familiarity with an IDE like [Visual Studio Code](https://code.visualstudio.com) or [Gitpod](https://gitpod.io) (although not strictly necessary) might help.\n\n## Materials for the Session\n\nIt doesn't matter if you join our workshop live or you prefer to do at your own pace, we have you covered. In this repository, you'll find everything you need for this workshop:\n\n- [Slide deck](./slides.pdf)\n- [Discord chat](https://bit.ly/cassandra-workshop)\n- [Questions and Answers](https://community.datastax.com/)\n- [Workshop code](https://github.com/datastaxdevs/quarkus-astra-intro-demo)\n\n## Alternate Learning Path(s) in this workshop\n\nIf you're primarily interested in containerization (as in **Slay the complexity of Kubernetes Inner Loop Development**), you can skip most of the early steps and jump straight to [Containerizing](#10-containerizing). Summarizing\n\n|Focus| Step(s) | Verify connection | Step(s) skipped |\n| ----------- | --- | ---|----------- |\n|**Containers/Inner loop**| Do steps 1-6 and 10 onwards | [After steps 1-6, verify connection](#6-run-some-unit-tests) | Skip steps 7,8,9|\n\n## 0. Table of contents\n\n1. [Database Initialization](#1-create-astra-db-instance)\n3. [Launch Gitpod](#3-launch-gitpod)\n4. [Know your Gitpod](#4-know-your-gitpod)\n5. [Setup your Application](#5-setup-your-application)\n6. [Run Unit test(s)](#6-run-some-unit-tests)\n7. [Quarkus Dev Mode](#7-quarkus-dev-mode)\n8. [Debugging](#8-debugging)\n9. [Packaging](#9-packaging)\n10. [Containerizing](#10-containerizing)\n11. [Native Image](#11-native-image)\n12. [Homework](#12-homework)\n\n\n## 1. Database Initialization\n\n### 1.1 - Create an Astra Account\n\n\u003e **Note**: **Datastax Astra** is a cloud-native, fully managed database-as-a-service (DBaaS) based on Apache Cassandra. It provides a scalable, performant and highly available database solution without the operational overhead of managing Cassandra clusters. Astra supports both SQL and NoSQL APIs, and includes features like backup and restore, monitoring and alerting, and access control. It enables developers to focus on application development while the database infrastructure is managed by Datastax.\n\n- `✅ 1.1.a` - Access [https://astra.datastax.com](https://astra.datastax.com) and register with `Google` or `Github` account\n\n![](images/astra-login.png?raw=true\")\n\n\n### 1.2 - Create an Astra DB\n\n\u003e **Info** [Reference Documentation](https://awesome-astra.github.io/docs/pages/astra/create-instance/)\n\n| Parameter     | Value     |\n|---------------|-----------|\n| Database name | `workshops` |\n| Keyspace name | `todolist`  |\n| Cloud         | `GCP`  |\n| Region        | `us-east1`  |\n\n![](images/astra-create-db.png?raw=true\")\n\n\n[🏠 Back to Table of Contents](#0-table-of-contents)\n\n### 1.3 - Create an Astra Token\n\n- `✅ 1.2.a` Locate `Settings` (#1) in the menu on the left, then `Token Management` (#2) \n\n- `✅ 1.2.b`Select the role `Organization Administrator` before clicking `[Generate Token]`\n\n![](https://github.com/DataStax-Academy/cassandra-for-data-engineers/blob/main/images/setup-astra-2.png?raw=true)\n\n- `✅ 1.2.c` - Copy your token in the clipboard. With this token we will now create what is needed for the training.\n\n![](https://github.com/DataStax-Academy/cassandra-for-data-engineers/blob/main/images/setup-astra-3.png?raw=true)\n\n\n[🏠 Back to Table of Contents](#0-table-of-contents)\n\n## 2. Gitpod\n\n[Gitpod](https://www.gitpod.io/) is an IDE 100% online based on [VS Code](https://github.com/gitpod-io/vscode/blob/gp-code/LICENSE.txt?lang=en-US). To initialize your environment simply click on the button below\n_(CTRL + Click to open in new tab)_ You will be asked for you github account, as needed.\n\n[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/datastaxdevs/quarkus-astra-intro-demo)\n\n**👁️ Expected output**\n\n_The screenshot may be slightly different based on your default skin and a few edits in the read me._\n\n![gitpod](images/tutorials/gitpod-01-home-plain.png?raw=true)\n\n**That's it.** Gitpod provides all tools we will need today including `maven` and exposing port `8080`, ports `5005` which is used for debugging, etc. \n\n**You may safely ignore the error output at the end of the terminal window.**\n\n**👁️ Expected output**\n\n![image](images/tutorials/gitpod-quarkus-1.jpg?raw=true)\n\nAlthough GitPod terminal might seem to be available, the setup might still be ongoing. Wait for a few minutes before entering commands in the GitPod terminal window.\n\n[🏠 Back to Table of Contents](#table-of-contents)\n\n## 4. Know your gitpod\n\nTake a moment to read this entire section since it'll help you with the rest of the workshop as you'll be spending most of your time in Gitpod. If you're familiar with Gitpod, you can easily skip this entire section.\n\nThe extreme left side has the explorer view(1). The top left, middle to right is where you'll be editing files(2), etc. and the bottom left, middle to right is what we will refer to as the Gitpod terminal window(3) as shown below.\n\n**👁️ Expected output**\n\n![gitpod](images/tutorials/gitpod-01-home-annotated.png?raw=true)\n\n\nYou can always get back to the file explorer view whenever by clicking on the hamburger menu on the top left followed by `View` and `Explorer` as shown below.\n\n![gitpod](images/tutorials/Filexplorer0.png?raw=true)\n\n✅ **Step 4a: Know your public URL**\n\nThe workshop application has opened with an ephemeral URL. To know the URL where your application endpoint will be exposed you can run the following command in the terminal after the build has completed. **Please note this URL and open this up in a new browser window as shown below**.\n\n```bash\ngp url 8080\n```\n\n**👁️ Expected output**\n\n![gitpod](images/tutorials/gitpod-02-url.png?raw=true)\n\n\nAlthough the application is not running yet, \nlaunch a new browser window (**don't close it for the rest of the workshop since you'll continually keep using this**. If you accidentally close it, just come back to this step. The browser will generate an error (due to application not running yet) which is fine for now as shown below.\n\n**👁️ Expected output**\n\n![gitpod](images/tutorials/newbrowser1.png?raw=true)\n\nYou may encounter the following at different steps and although this may not be applicable right away, the steps are included **in advance** and summarized here so that you can keep an eye out for it. Different paths and different environments might be slightly different although Gipod levels the playing field a bit.\n\nYou can allow cutting and pasting into the window by clicking on `Allow` as shown below.\n\n![gitpod](images/tutorials/allow.png?raw=true)\n\nOr allow ports to be opened by just exiting windows that are informational messages about ports like below.\n\n![gitpod](images/tutorials/OpenPorts.png?raw=true)\n\n\n[🏠 Back to Table of Contents](#0-table-of-contents)\n\n## 5. Setup your application\n\nTo run the application you need to provide the credentials and identifier to the application.\n\nIssue the following command from the Gitpod terminal window.\n\n```\ngp open src/main/resources/application.properties\n```\n\n![gitpod](images/tutorials/editapplicationproperties1.png?raw=true)\n\n\n✅ **Step 5a: Enter 2 values from the token**\n\nEnter the values of `Client Id` and `Client Secret` from values noted earlier for `astra-username` and `astra-password` respectively. The two lines with a TBD in comments is shown below.\n\n![gitpod](images/tutorials/editapplicationproperties2.png?raw=true)\n\n\n✅ **Step 5b: Download the secure connect bundle**\n\n```\ncurl -Ls \"https://dtsx.io/get-astra-cli\" | bash\nsource /home/gitpod/.astra/cli/astra-init.sh\nastra\nastra setup --token \u003c\u003e\nastra db download-scb workshops -f /workspace/quarkus-astra-intro-demo/secure-connect-workshops.zip \nls -l secure-connect-workshops.zip\n```\n\nThe file size should be roughly 12K otherwise something may have gone wrong in the process.\n\n**👁️ Expected output**\n\n```\n-rw-r--r-- 1 gitpod gitpod 12231 Oct 26 00:15 secure-connect-workshops.zip\n```\n\nTADA your application is now configured we can finally play with some code.\n\n[🏠 Back to Table of Contents](#0-table-of-contents)\n\n## 6. Run some unit test(s)\n\nThe application is now set and you should be able to interact with your DB, although connecting to a \"real\" DB is not necessary in order to execute tests. The application's tests use the [Quarkus Cassandra Test Framework](https://github.com/datastax/cassandra-quarkus/tree/main/test-framework). Quarkus will automatically bootstrap a Cassandra Docker container and connect it to the application when the tests execute.\n\nUnder the covers, all interaction with Cassandra is implemented in Java through the `com.datastax.oss.driver.api.core.CqlSession`, part of the [DataStax Java Driver](https://docs.datastax.com/en/developer/java-driver/latest). Higher level frameworks like Quarkus, Spring, Spring Data, rely on this object. The [Quarkus Cassandra Test Framework](https://github.com/datastax/cassandra-quarkus/tree/main/test-framework) makes sure its available to the tests.\n\nLet's run this unit test in the Gitpod terminal window.\n\n```bash\n./mvnw test -Dtest=com.datastaxdev.todo.rest.TodoResourceTests\n```\n\n**👁️ Expected output**\n\n```\nPicked up JAVA_TOOL_OPTIONS:  -Xmx3435m\n[INFO] Scanning for projects...\n[INFO] \n[INFO] ---------\u003c quarkus-astra-intro-demo:quarkus-astra-intro-demo \u003e----------\n[INFO] Building quarkus-astra-intro-demo 0.01\n[INFO] --------------------------------[ jar ]---------------------------------\n[INFO] \n[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ quarkus-astra-intro-demo ---\n[INFO] Using 'UTF-8' encoding to copy filtered resources.\n[INFO] Copying 24 resources\n[INFO] \n[INFO] --- quarkus-maven-plugin:2.9.1.Final:generate-code (default) @ quarkus-astra-intro-demo ---\n[INFO] \n[INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) @ quarkus-astra-intro-demo ---\n[INFO] Nothing to compile - all classes are up to date\n[INFO] \n[INFO] --- quarkus-maven-plugin:2.9.1.Final:generate-code-tests (default) @ quarkus-astra-intro-demo ---\n[INFO] \n[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ quarkus-astra-intro-demo ---\n[INFO] Using 'UTF-8' encoding to copy filtered resources.\n[INFO] Copying 1 resource\n[INFO] \n[INFO] --- maven-compiler-plugin:3.8.1:testCompile (default-testCompile) @ quarkus-astra-intro-demo ---\n[INFO] Nothing to compile - all classes are up to date\n[INFO] \n[INFO] --- maven-surefire-plugin:3.0.0-M5:test (default-test) @ quarkus-astra-intro-demo ---\n[INFO] \n[INFO] -------------------------------------------------------\n[INFO]  T E S T S\n[INFO] -------------------------------------------------------\n[ERROR] Picked up JAVA_TOOL_OPTIONS:  -Xmx3435m\n[INFO] Running com.datastaxdev.todo.rest.TodoResourceTests\nINFO  [org.jbo.threads] (main) JBoss Threads version 3.4.2.Final\nINFO  [org.tes.uti.ImageNameSubstitutor] (main) Image name substitution will be performed by: DefaultImageNameSubstitutor (composite of 'ConfigurationFileImageNameSubstitutor' and 'PrefixingImageNameSubstitutor')\nINFO  [org.tes.doc.DockerClientProviderStrategy] (pool-4-thread-1) Loaded org.testcontainers.dockerclient.UnixSocketClientProviderStrategy from ~/.testcontainers.properties, will try it first\nINFO  [org.tes.doc.DockerClientProviderStrategy] (pool-4-thread-1) Found Docker environment with local Unix socket (unix:///var/run/docker.sock)\nINFO  [org.tes.DockerClientFactory] (pool-4-thread-1) Docker host IP address is localhost\nINFO  [org.tes.DockerClientFactory] (pool-4-thread-1) Connected to docker: \n  Server Version: 20.10.14\n  API Version: 1.41\n  Operating System: Ubuntu 20.04.4 LTS\n  Total Memory: 64312 MB\nINFO  [org.tes.uti.RegistryAuthLocator] (pool-4-thread-1) Failure when attempting to lookup auth config. Please ignore if you don't have images in an authenticated registry. Details: (dockerImageName: testcontainers/ryuk:0.3.3, configFile: /home/gitpod/.docker/config.json. Falling back to docker-java default behaviour. Exception message: /home/gitpod/.docker/config.json (No such file or directory)\nINFO  [org.tes.uti.RyukResourceReaper] (pool-4-thread-1) Ryuk started - will monitor and terminate Testcontainers containers on JVM exit\nINFO  [org.tes.DockerClientFactory] (pool-4-thread-1) Checking the system...\nINFO  [org.tes.DockerClientFactory] (pool-4-thread-1) ✔︎ Docker server version should be at least 1.6.0\nINFO  [org.tes.DockerClientFactory] (pool-4-thread-1) ✔︎ Docker environment should have more than 2GB free disk space\nINFO  [com.dat.oss.qua.tes.CassandraTestResource] (pool-4-thread-1) Container cassandra:latest starting...\nINFO  [🐳 [cassandra:latest]] (pool-4-thread-1) Creating container for image: cassandra:latest\nINFO  [🐳 [cassandra:latest]] (pool-4-thread-1) Container cassandra:latest is starting: 001d53b387a0a5861466621f6828e753036bec4d9958562ba24a934442c430e5\nINFO  [com.dat.dri.core] (ducttape-0) DataStax Java driver 3.7.1 for Apache Cassandra\nINFO  [com.dat.dri.cor.GuavaCompatibility] (ducttape-0) Detected Guava \u003e= 19 in the classpath, using modern compatibility layer\nINFO  [com.dat.dri.cor.ClockFactory] (ducttape-0) Using native clock to generate timestamps.\nINFO  [com.dat.dri.cor.NettyUtil] (ducttape-0) Did not find Netty's native epoll transport in the classpath, defaulting to NIO.\nINFO  [com.dat.dri.cor.ClockFactory] (ducttape-0) Using native clock to generate timestamps.\nINFO  [com.dat.dri.cor.ClockFactory] (ducttape-0) Using native clock to generate timestamps.\nWARN  [com.dat.dri.cor.Cluster] (ducttape-0) You listed localhost/127.0.0.1:49156 in your contact points, but it wasn't found in the control host's system.peers at startup\nINFO  [com.dat.dri.cor.pol.DCAwareRoundRobinPolicy] (ducttape-0) Using data-center name 'datacenter1' for DCAwareRoundRobinPolicy (if this is incorrect, please provide the correct datacenter name with DCAwareRoundRobinPolicy constructor)\nINFO  [com.dat.dri.cor.Cluster] (ducttape-0) New Cassandra host localhost/0:0:0:0:0:0:0:1:49156 added\nINFO  [🐳 [cassandra:latest]] (pool-4-thread-1) Container cassandra:latest started in PT9.049449S\nINFO  [org.tes.ext.ScriptUtils] (pool-4-thread-1) Executing database script from init_script.cql\nINFO  [com.dat.dri.cor.ClockFactory] (pool-4-thread-1) Using native clock to generate timestamps.\nWARN  [com.dat.dri.cor.Cluster] (pool-4-thread-1) You listed localhost/127.0.0.1:49156 in your contact points, but it wasn't found in the control host's system.peers at startup\nINFO  [com.dat.dri.cor.pol.DCAwareRoundRobinPolicy] (pool-4-thread-1) Using data-center name 'datacenter1' for DCAwareRoundRobinPolicy (if this is incorrect, please provide the correct datacenter name with DCAwareRoundRobinPolicy constructor)\nINFO  [com.dat.dri.cor.Cluster] (pool-4-thread-1) New Cassandra host localhost/0:0:0:0:0:0:0:1:49156 added\nINFO  [org.tes.ext.ScriptUtils] (pool-4-thread-1) Executed database script from init_script.cql in 2132 ms.\nINFO  [com.dat.dri.cor.ClockFactory] (pool-4-thread-1) Using native clock to generate timestamps.\nWARN  [com.dat.dri.cor.Cluster] (pool-4-thread-1) You listed localhost/0:0:0:0:0:0:0:1:49156 in your contact points, but it wasn't found in the control host's system.peers at startup\nINFO  [com.dat.dri.cor.pol.DCAwareRoundRobinPolicy] (pool-4-thread-1) Using data-center name 'datacenter1' for DCAwareRoundRobinPolicy (if this is incorrect, please provide the correct datacenter name with DCAwareRoundRobinPolicy constructor)\nINFO  [com.dat.dri.cor.Cluster] (pool-4-thread-1) New Cassandra host localhost/127.0.0.1:49156 added\nINFO  [com.dat.oss.qua.tes.CassandraTestResource] (pool-4-thread-1) Container cassandra:latest listening on 127.0.0.1:49156 (inferred local DC: datacenter1)\nWARN  [io.qua.config] (main) Unrecognized configuration key \"quarkus.kubernetes.service-type\" was provided; it will be ignored; verify that the dependency extension for this configuration is set or that you did not make a typo\nWARN  [io.qua.config] (main) Unrecognized configuration key \"quarkus.kubernetes.env.secrets\" was provided; it will be ignored; verify that the dependency extension for this configuration is set or that you did not make a typo\nINFO  [com.dat.oss.qua.run.int.qua.CassandraClientRecorder] (main) Enabling Cassandra metrics using Micrometer.\nINFO  [com.dat.oss.qua.run.int.qua.CassandraClientStarter] (main) Eagerly initializing Quarkus Cassandra client.\nINFO  [com.dat.oss.dri.int.cor.DefaultMavenCoordinates] (main) DataStax Java driver for Apache Cassandra(R) (com.datastax.oss:java-driver-core) version 4.14.0\nINFO  [com.dat.oss.dri.int.cor.tim.Clock] (vert.x-eventloop-thread-0) Using native clock for microsecond precision\nINFO  [com.dat.tod.res.TodoResource] (main) **** Table created true****\nINFO  [io.quarkus] (main) quarkus-astra-intro-demo 0.01 on JVM (powered by Quarkus 2.9.1.Final) started in 16.146s. Listening on: http://localhost:41159\nINFO  [io.quarkus] (main) Profile test activated. \nINFO  [io.quarkus] (main) Installed features: [cassandra-client, cdi, micrometer, resteasy-reactive, resteasy-reactive-jackson, smallrye-context-propagation, smallrye-health, smallrye-openapi, swagger-ui, vertx]\n[INFO] Tests run: 8, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 19.304 s - in com.datastaxdev.todo.rest.TodoResourceTests\nINFO  [com.dat.oss.qua.run.int.qua.CassandraClientRecorder] (main) Closing Quarkus Cassandra session.\nINFO  [io.quarkus] (main) quarkus-astra-intro-demo stopped in 0.039s\n[INFO] \n[INFO] Results:\n[INFO] \n[INFO] Tests run: 8, Failures: 0, Errors: 0, Skipped: 0\n[INFO] \n[INFO] ------------------------------------------------------------------------\n[INFO] BUILD SUCCESS\n[INFO] ------------------------------------------------------------------------\n[INFO] Total time:  25.096 s\n[INFO] Finished at: 2022-05-16T18:22:07Z\n[INFO] ------------------------------------------------------------------------\n```\n\nYou can see from the output that the `cassandra:latest` Docker container was started before the tests were executed.\n\nVerfiy that the table got created with the following command\n\n```bash\n./mvnw test -Dcom.datastaxdev.todo.rest.TodoResourceTests | grep -i table\n```\n\n**👁️ Expected output**\n\n```\nINFO  [com.dat.tod.res.TodoResource] (main) **** Table created true****\n```\n\n\u003e You will likely see that output repeated more than once.\n\nAlthough a significant strength of the Quarkus platform is it's [continuous testing](https://quarkus.io/guides/continuous-testing) capabilities, we will skip tests going foraward and focus on the other capabilities of the platform (perhaps, another workshop sometime focussed mainly on testing capabilities, assuming there is enough demand).\n\n[🏠 Back to Table of Contents](#0-table-of-contents)\n\n## 7. Quarkus Dev Mode\n\nBefore we get started let's check that the Graal VM is available.\n\n```\necho $GRAALVM_HOME\n```\n\n**👁️ Expected output**\n\n```\n/home/gitpod/.sdkman/candidates/java/current\n```\n\n✅ **Step 7a: Begin dev**\n\nIn the Gitpod terminal window, We will begin the inner loop journey in dev mode using the following command.\n\n\n```bash\n./mvnw quarkus:dev -DskipTests\n```\n**👁️ Expected output**\n\n```\n__  ____  __  _____   ___  __ ____  ______ \n --/ __ \\/ / / / _ | / _ \\/ //_/ / / / __/ \n -/ /_/ / /_/ / __ |/ , _/ ,\u003c / /_/ /\\ \\   \n--\\___\\_\\____/_/ |_/_/|_/_/|_|\\____/___/   \nWARN  [io.qua.config] (Quarkus Main Thread) Unrecognized configuration key \"quarkus.kubernetes.service-type\" was provided; it will be ignored; verify that the dependency extension for this configuration is set or that you did not make a typo\n\nWARN  [io.qua.config] (Quarkus Main Thread) Unrecognized configuration key \"quarkus.kubernetes.env.secrets\" was provided; it will be ignored; verify that the dependency extension for this configuration is set or that you did not make a typo\nINFO  [com.dat.oss.qua.run.int.qua.CassandraClientRecorder] (Quarkus Main Thread) Enabling Cassandra metrics using Micrometer.\nINFO  [com.dat.oss.qua.run.int.qua.CassandraClientStarter] (Quarkus Main Thread) Eagerly initializing Quarkus Cassandra client.\nINFO  [com.dat.oss.dri.int.cor.DefaultMavenCoordinates] (Quarkus Main Thread) DataStax Java driver for Apache Cassandra(R) (com.datastax.oss:java-driver-core) version 4.14.0\nINFO  [com.dat.oss.dri.int.cor.tim.Clock] (vert.x-eventloop-thread-0) Using native clock for microsecond precision\nINFO  [com.dat.oss.dri.int.cor.ses.DefaultSession] (vert.x-eventloop-thread-9) [s0] Negotiated protocol version V4 for the initial contact point, but cluster seems to support V5, keeping the negotiated version\nINFO  [com.dat.tod.res.TodoResource] (Quarkus Main Thread) **** Table created true****\nINFO  [io.quarkus] (Quarkus Main Thread) quarkus-astra-intro-demo 0.01 on JVM (powered by Quarkus 2.9.1.Final) started in 7.383s. Listening on: http://localhost:8080\nINFO  [io.quarkus] (Quarkus Main Thread) Profile dev activated. Live Coding activated.\nINFO  [io.quarkus] (Quarkus Main Thread) Installed features: [cassandra-client, cdi, micrometer, resteasy-reactive, resteasy-reactive-jackson, smallrye-context-propagation, smallrye-health, smallrye-openapi, swagger-ui, vertx]\n\n--\nTests paused\nPress [r] to resume testing, [o] Toggle test output, [:] for the terminal, [h] for more options\u003e\n```\n✅ **Step 7b: Explore Quarkus dev mode**\n\nTyping `h` in the terminal window should bring up the following\n\n**👁️ Expected output**\n\n```\nThe following commands are currently available:\n\n== Continuous Testing\n\n[r] - Resume testing\n[o] - Toggle test output (disabled)\n\n== Exceptions\n\n[x] - Opens last exception in IDE (None)\n\n== HTTP\n\n[w] - Open the application in a browser\n[d] - Open the Dev UI in a browser\n\n== System\n\n[s] - Force restart\n[i] - Toggle instrumentation based reload (disabled)\n[l] - Toggle live reload (enabled)\n[j] - Toggle log levels (INFO)\n[h] - Shows this help\n[:] - Enters terminal mode\n[q] - Quits the application\n\n--\nTests paused\nPress [r] to resume testing, [o] Toggle test output, [:] for the terminal, [h] for more options\u003e\n```\n\nYou can try the different options available.\n\nNote that you may have to allow popups from `gitpod.io` as shown below.\n\n![gitpod](images/tutorials/quarkus-dev-0.png?raw=true)\n\nTry connecting to the application in a browser by pressing the `w` key as indicated above. This should bring up the application as below.\n\n\u003e **NOTE:** This may not actually work in Gitpod because of the way Gitpod handles links. If the page doesn't open for you simply go to the browser tab you opened back in step 4a.\n\n**👁️ Expected output**\n\n![gitpod](images/tutorials/quarkus-dev-1.png?raw=true)\n\n✅ **Step 7c: Hot reload**\nNow, let's go ahead and make an illustrative change.\n\nNavigate to the file `src/main/java/resources/META-INF/resources/index.html` and change the `data-ribbon` entry from \"Fork me on Github\" to \"Fork me today on Github.\"\n\nNext, refresh the browser page. You should immediately see the update. This hot reloading feature of Quarkus works for more than just static content too!\n\n**👁️ Expected output**\n\n![gitpod](images/tutorials/quarkus-dev-2.png?raw=true)\n\nYou could add a few entries to the \"todo list\" as shown below.\n\n**👁️ Expected output**\n\n![gitpod](images/tutorials/quarkus-dev-3.png?raw=true)\n\n✅ **Step 7d: Quarkus dev metrics**\n\nYou can get Quarkus development metrics and so on hitting the `d` key as indicated in the help and this should bring up a window that looks like below.\n\n\u003e **NOTE:** Again, because of the way Gitpod works, this may not bring up the window. If it doesn't, go back to the browser window containing the running application and append `/q/dev` to the URL.\n\n**👁️ Expected output**\n\n![gitpod](images/tutorials/quarkus-dev-4.png?raw=true)\n\n\u003e The `/q/dev` end point can be accessed using the URL below when the application is running in `dev` mode. You can use another `bash` tab in the gitpod terminal window to enter the commands while the application is running and switch between tabs as required.\n\n```\necho $(gp url 8080)/q/dev\n```\n\nand the `openapi` spec is at\n\n```\necho $(gp url 8080)/q/openapi\n```\n\nas shown below.\n\n![gitpod](images/tutorials/quarkus-dev-5.png?raw=true)\n\nYou could continue developing your entire application without ever leaving dev mode! It will even handle refactorings and project dependency changes!\n\nLet's out of development mode by hitting `q` or hitting `\u003cCtrl\u003e+C`.\n\n✅ **Step 7e: Quarkus smart dispatch**\n\nLet's quickly examine the [Quarkus smart dispatching mechanism](https://quarkus.io/blog/resteasy-reactive-smart-dispatch). Let's open the `com.datastaxdev.todo.rest.TodoResource.java` class by executing the following in a terminal:\n\n```\ngp open src/main/java/com/datastaxdev/todo/rest/TodoResource.java\n```\n\nNotice some methods return [Mutiny reactive types](https://quarkus.io/guides/mutiny-primer) (i.e. `Uni` and `Multi`) while others return non-reactive types (i.e. `String`, `Response`, and `void`). Quarkus doesn't care whether you write reactive or blocking code. Quarkus will make sure reactive code runs on the I/O thread while blocking code will be moved off onto worker thread(s). As you can see, you can even mix and match within the same class!\n\nThis application was designed to illustrate both approaches. Which methods are implemented in which manner were randomly chosen.\n\n[🏠 Back to Table of Contents](#0-table-of-contents)\n\n## 8. Debugging\n\nYou can always get back to the file explorer view whenever by clicking on the hamburger menu on the top left followed by `View` and `Explorer` as shown below.\n\n![gitpod](images/tutorials/Filexplorer0.png?raw=true)\n\nLet's go ahead and hit `q` or `Ctrl+C` to exit out of the running application if you have not already.\n\nBefore we set a breakpoint and start debugging, let's explain the application's structure a bit. The `TodoResource` class (which you saw in the previous section) calls a `com.datastaxdev.todo.service.AstraService`. `AstraService` is an interface with 2 implementations:\n1. `com.datastaxdev.todo.service.CqlSessionAstraService.java`\n    - Uses the `com.datastax.oss.quarkus.runtime.api.session.QuarkusCqlSession` directly using CQL queries to implement the operations.\n2. `com.datastaxdev.todo.service.MapperAstraService.java`\n    - Uses the [DataStax Object Mapper](https://docs.datastax.com/en/developer/java-driver/latest/manual/mapper) and [Cassandra Entity Modeling](https://quarkus.io/guides/cassandra#creating-the-data-model-and-data-access-objects) to model entities as Java objects, greatly simplifying the application's data access layer by sparing you the hassle of writing CQL queries by hand. This is conceptually similar to how [Hibernate](https://hibernate.org) works in the [JPA](https://docs.oracle.com/javaee/6/tutorial/doc/bnbpz.html) world.\n    - Uses [Mapstruct](https://mapstruct.org) to easily convert between the `com.datastaxdev.todo.dao.TodoItem` dao entities and the `com.datastaxdev.todo.api.Todo` POJO used at the REST layer. See the `com.datastaxdev.todo.mapping.TodoMapper` class for details.\n\nThe application has a [build-time property](https://quarkus.io/guides/cdi-reference#enable_build_properties) (not overridable at runtime) called `astra-service.type`. Resolving dependency injection at build time is one of the key benefits of Quarkus, allowing Quarkus applications to be super small and memory-performant. \n\nBy default, if this property is undefined _OR_ has the value `cql-session`, `com.datastaxdev.todo.service.CqlSessionAstraService` will be injected as the implementation for `com.datastaxdev.todo.service.AstraService`.\n\nIf, at build time, `astra-service.type=dao`, then `com.datastaxdev.todo.service.MapperAstraService` will be used instead.\n\nThe `com.datastaxdev.todo.config.AstraConfig` class contains everything needed for reading the `astra-service.type` flag at build time and injecting the appropriate `com.datastaxdev.todo.service.AstraService` implementation.\n\nThere is a full suite of unit tests that cover both implementations! See `src/test/java/com/datastaxdev/todo/service/CqlSessionAstraServiceTests.java` and  `src/test/java/com/datastaxdev/todo/service/MapperAstraServiceTests.java` for details.\n\n\u003e If you'd like to play around with the mapper implementation, open `src/main/resources/application.properties` and un-comment the line `#astra-service.type=dao`.\n\nSince the application, by default, uses the `com.datastaxdev.todo.service.CqlSessionAstraService` implementation, we'll use that implementation for setting the breakpoint.\n\n✅ **Step 8a: Set breakpoint**\n\nNow issue the following command to open up the file where we will subsequently set a breakpoint to be hit whenever we create a new todo item.\n\n```\ngp open src/main/java/com/datastaxdev/todo/service/CqlSessionAstraService.java\n```\n\nNow navigate to line 52 and set a breakpoint by clicking to the left of the line number 52 and you'll see a stop sign as shown below.\n\n![gitpod](images/tutorials/debug1.png?raw=true)\n\nRe-run the application with the following command and we will debug it live.\n\n```bash\n./mvnw quarkus:dev\n```\n\n✅ **Step 8b: Start debugging**\n\nFirst, click on the debug button on the left towards top.\n\nThen, click on the arrow on the top left to start debugging as shown below.\n\n![gitpod](images/tutorials/debug2.png?raw=true)\n\nNotice debug related information populate in the left side of the window as shown below.\n\n![gitpod](images/tutorials/debug3.png?raw=true)\n\n\u003e If for some reason the debugger doesn't attach, there may be some weirdness going on with the Gitpod IDE. Refreshing the browser tab containing the workspace or restarting the workspace will usually fix it.\n\nWe will demonstrate debugging by fixing a todo item that was entered although there are more powerful features that you can try. \n\nGo to the new browser window you created and the application should be up and running. Hit enter after filling up a todo item as shown below. The application freezes and you see a red square that signals the breakpoint has been hit.\n\n![gitpod](images/tutorials/debug4.png?raw=true)\n\nNow that you hit the breakpoint, Cool! Let's go back to the Gitpod window and verify if the breakpoint was really hit. You should see something like below.\n\n**👁️ Expected output**\n\n![gitpod](images/tutorials/debug5.png?raw=true)\n\n✅ **Step 8c: Use debugger features**\n\nNow, fix the entry spelling in debug mode by clicking on the left(\u003e) arrow of `todo`, double clicking on the `title` entry and entering `debugging`. Finally, hit arrow button in the top small middle pane in the center which will allow the application to continue as shown below.\n\n![gitpod](images/tutorials/debug6.png?raw=true)\n\nGo back to your browser and check the todo item that was added to the list. You should see that the updated entry that you fixed with a debug session is what's persisted.\n\nHit `q` or `Ctrl+C` in the GitPod terminal window to exit the application.\n\n[🏠 Back to Table of Contents](#0-table-of-contents)\n\n## 9. Packaging\n\n✅ **Step 9a: Package**\nYou can package up the application with the command below.\n\n```bash\n./mvnw clean package -DskipTests\n```\n\n**👁️ Expected output**\n\n```\nPicked up JAVA_TOOL_OPTIONS:  -Xmx3435m\n[INFO] Scanning for projects...\n[INFO] \n[INFO] ---------\u003c quarkus-astra-intro-demo:quarkus-astra-intro-demo \u003e----------\n[INFO] Building quarkus-astra-intro-demo 0.01\n[INFO] --------------------------------[ jar ]---------------------------------\n[INFO] \n[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ quarkus-astra-intro-demo ---\n[INFO] Deleting /workspace/quarkus-astra-intro-demo/target\n[INFO] \n[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ quarkus-astra-intro-demo ---\n[INFO] Using 'UTF-8' encoding to copy filtered resources.\n[INFO] Copying 24 resources\n[INFO] \n[INFO] --- quarkus-maven-plugin:2.9.1.Final:generate-code (default) @ quarkus-astra-intro-demo ---\n[INFO] \n[INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) @ quarkus-astra-intro-demo ---\n[INFO] Changes detected - recompiling the module!\n[INFO] Compiling 10 source files to /workspace/quarkus-astra-intro-demo/target/classes\n[INFO] \n[INFO] --- quarkus-maven-plugin:2.9.1.Final:generate-code-tests (default) @ quarkus-astra-intro-demo ---\n[INFO] \n[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ quarkus-astra-intro-demo ---\n[INFO] Using 'UTF-8' encoding to copy filtered resources.\n[INFO] Copying 1 resource\n[INFO] \n[INFO] --- maven-compiler-plugin:3.8.1:testCompile (default-testCompile) @ quarkus-astra-intro-demo ---\n[INFO] Changes detected - recompiling the module!\n[INFO] Compiling 6 source files to /workspace/quarkus-astra-intro-demo/target/test-classes\n[INFO] \n[INFO] --- maven-surefire-plugin:3.0.0-M5:test (default-test) @ quarkus-astra-intro-demo ---\n[INFO] Tests are skipped.\n[INFO] \n[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ quarkus-astra-intro-demo ---\n[INFO] Building jar: /workspace/quarkus-astra-intro-demo/target/quarkus-astra-intro-demo-0.01.jar\n[INFO] \n[INFO] --- quarkus-maven-plugin:2.9.1.Final:build (default) @ quarkus-astra-intro-demo ---\n[WARNING] [io.quarkus.config] Unrecognized configuration key \"quarkus.kubernetes.env.secrets\" was provided; it will be ignored; verify that the dependency extension for this configuration is set or that you did not make a typo\n[WARNING] [io.quarkus.config] Unrecognized configuration key \"quarkus.kubernetes.service-type\" was provided; it will be ignored; verify that the dependency extension for this configuration is set or that you did not make a typo\n[INFO] [io.quarkus.deployment.QuarkusAugmentor] Quarkus augmentation completed in 2076ms\n[INFO] ------------------------------------------------------------------------\n[INFO] BUILD SUCCESS\n[INFO] ------------------------------------------------------------------------\n[INFO] Total time:  9.681 s\n[INFO] Finished at: 2022-05-16T20:21:41Z\n[INFO] ------------------------------------------------------------------------\n```\n\n✅ **Step 9b: Run**\n\nYou can run the recently packaged application as below.\n\n```bash\njava -jar ./target/quarkus-app/quarkus-run.jar\n```\n\n**👁️ Expected output**\n\n```\nPicked up JAVA_TOOL_OPTIONS:  -Xmx3435m\n__  ____  __  _____   ___  __ ____  ______ \n --/ __ \\/ / / / _ | / _ \\/ //_/ / / / __/ \n -/ /_/ / /_/ / __ |/ , _/ ,\u003c / /_/ /\\ \\   \n--\\___\\_\\____/_/ |_/_/|_/_/|_|\\____/___/   \nWARN  [io.qua.config] (main) Unrecognized configuration key \"quarkus.kubernetes.service-type\" was provided; it will be ignored; verify that the dependency extension for this configuration is set or that you did not make a typo\nWARN  [io.qua.config] (main) Unrecognized configuration key \"quarkus.kubernetes.env.secrets\" was provided; it will be ignored; verify that the dependency extension for this configuration is set or that you did not make a typo\nINFO  [com.dat.oss.qua.run.int.qua.CassandraClientRecorder] (main) Enabling Cassandra metrics using Micrometer.\nINFO  [io.qua.sma.ope.run.OpenApiRecorder] (main) Default CORS properties will be used, please use 'quarkus.http.cors' properties instead\nINFO  [com.dat.oss.qua.run.int.qua.CassandraClientStarter] (main) Eagerly initializing Quarkus Cassandra client.\nINFO  [com.dat.oss.dri.int.cor.DefaultMavenCoordinates] (main) DataStax Java driver for Apache Cassandra(R) (com.datastax.oss:java-driver-core) version 4.14.0\nINFO  [com.dat.oss.dri.int.cor.tim.Clock] (vert.x-eventloop-thread-0) Using native clock for microsecond precision\nINFO  [com.dat.oss.dri.int.cor.ses.DefaultSession] (vert.x-eventloop-thread-9) [s0] Negotiated protocol version V4 for the initial contact point, but cluster seems to support V5, keeping the negotiated version\nINFO  [com.dat.tod.res.TodoResource] (main) **** Table created true****\nINFO  [io.quarkus] (main) quarkus-astra-intro-demo 0.01 on JVM (powered by Quarkus 2.9.1.Final) started in 3.882s. Listening on: http://0.0.0.0:8080\nINFO  [io.quarkus] (main) Profile prod activated. \nINFO  [io.quarkus] (main) Installed features: [cassandra-client, cdi, micrometer, resteasy-reactive, resteasy-reactive-jackson, smallrye-context-propagation, smallrye-health, smallrye-openapi, swagger-ui, vertx]\n```\n\nYou can play with the application from the new browser window you created in step 4.\n\nHit `Ctrl+C` in the GitPod terminal window to exit the application.\n\n[🏠 Back to Table of Contents](#0-table-of-contents)\n\n## 10. Containerizing\n\n✅ **Step 10a: Adjust for containerization**\n\nWe are using the [Quarkus Jib container extension](https://quarkus.io/guides/container-image#jib) for easy containerization. Copy the secure connect bundle to the directory that Jib will create on the container as below. We take advantage of the property of Jib plugin which automaticaly includes the relevant artifacts from the `src/main/jib` sub-directory as part of the process -- we include the secure connect bundle to be able to connect to the Astra database.\n\n\n```bash\nmkdir -p src/main/jib/workspace/quarkus-astra-intro-demo/\ncp secure-connect-workshops.zip src/main/jib/workspace/quarkus-astra-intro-demo/\n```\n\n✅ **Step 10b: Containerize**\n\nLet's containerize the application with the following command.\n\n```bash\n./mvnw clean package -Dquarkus.container-image.build=true -DskipTests\n```\n\nOnce complete, check that the image exists on your local repository with the following command:\n\n```bash\ndocker images\n```\n\n**Expected Output**\n\n```\nREPOSITORY                 TAG       IMAGE ID       CREATED          SIZE\ngitpod/quarkus-cassandra   0.01      77431983359a   26 seconds ago   216MB\n```\n\n✅ **Step 10c: Run the containerized image**\n\nYou can execute the recently generated containerized image with the following command.\n\n```bash\ndocker run -i --rm -p 8080:8080 gitpod/quarkus-cassandra:0.01\n```\n\nHit \u003cCtrl+C\u003e in the GitPod terminal window to exit the application.\n\n✅ **Step 10d: docker login**\n\nLogin to Dockerhub to be able to push containerized images and to be able for you and the rest of the world to pull them.\n\nIf you do not have a docker login credential you can skip this step and go right to [Native Image](#11-native-image)\n\n```bash\ndocker login\n```\n\n**Expected Output**\n\n```\nLogin with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.\nUsername: ragsns\nPassword: \nWARNING! Your password will be stored unencrypted in /home/gitpod/.docker/config.json.\nConfigure a credential helper to remove this warning. See\nhttps://docs.docker.com/engine/reference/commandline/login/#credentials-store\n\nLogin Succeeded\n```\n\nGet the Docker ID as below.\n\n```bash\ndocker system info | grep -E 'Username' || echo \"you have not done a docker login(yet)\"\nDOCKER_LOGINID=$(docker system info | grep -E 'Username' | awk '{print $2}')\necho \"Docker login ID that will be used: \" \"$DOCKER_LOGINID\"\n```\n\nYou should see an output of your Docker Login ID. If you do not see this repeat this step from the beginning.\n\n```\nDocker login ID that will be used:  ragsns\n```\n\n✅ **Step 10e: Push to Dockerhub**\n\nLet's not only build the containerized image but also push it to DockerHub (**be sure to substitute the group with docker ID**) with the following command.\n\n```bash\n./mvnw clean package -Dquarkus.container-image.build=true -Dquarkus.container-image.push=true -Dquarkus.container-image.group=$DOCKER_LOGINID -DskipTests\n```\n\n**NOTE:** If the repo in your Docker Hub account didn't previously exist it will be created for you as a _private_ repo. You will need to go into your Docker Hub account and make the repo public.\n\nIn today's world of microservices and service meshes, it's all about deploying to Kubernetes. Quarkus gives us an easy way to do that!\n\n**Step A**: Quarkus includes the [Kubernetes extension](https://quarkus.io/guides/deploying-to-kubernetes), allowing developers to deploy directly to Kubernetes and use Kubernetes `ConfigMap`s and `Secret`s as configuration sources. To use this update `pom.xml` with the following command in the Gitpod ternimal window as below.\n\n```bash\n./mvnw quarkus:add-extension -Dextensions=\"kubernetes\"\n```\n\nand verify with the following command\n\n```bash\ngit diff pom.xml\n```\n\nwhich should that the `io.quarkus:quarkus-kubernetes` dependency has been added.\n\n```bash\ndiff --git a/pom.xml b/pom.xml\nindex 371e35e..4b842d8 100644\n--- a/pom.xml\n+++ b/pom.xml\n+    \u003cdependency\u003e\n+      \u003cgroupId\u003eio.quarkus\u003c/groupId\u003e\n+      \u003cartifactId\u003equarkus-kubernetes\u003c/artifactId\u003e\n+    \u003c/dependency\u003e\n```\n\n**Step B**:\nEnsure that `DOCKER_LOGINID` was set in the earlier step as below and the command should output the Docker login ID.\n\n```\necho $DOCKER_LOGINID\n```\n\nNext, let's generate the containerized image with the secrets as below.\n\n```\n./mvnw clean package -Dquarkus.container-image.build=true -Dquarkus.container-image.push=false -Dquarkus.container-image.group=$DOCKER_LOGINID -DskipTests\n```\n\nNext, let's generate and push the containerized image with the secrets removed as below.\n\n```\nsed -i '/# TBD Below/,+4 d' ./target/classes/application.properties\n./mvnw package -Dquarkus.container-image.build=true -Dquarkus.container-image.push=true -Dquarkus.container-image.group=$DOCKER_LOGINID -DskipTests\n```\n\n✅ **Step 10f: Stand up application in Kubernetes**\n\n\nHereafter, there are two paths -- steps prefixed with `Lens` OR steps prefixed with `Okteto` as summarized below.\n\n|Steps prefixed with|Details| First step|\n| ----------- | ----------- |-----|\n|Lens| Install on Lens IDE|Lens.A\n|Okteto| Sample Kubernetes provider|Okteto.A\n\nIf you're familiar with using `kubectl` command you can pick either. If you're not you're recommended to use Steps prefixed with `Lens`.\n\n**Step Lens.A**: Download Lens\n\n[Lens](https://k8slens.dev/) is a popular Integrated Development Environment (IDE) for Kubernetes and enables developers and engineers to develop and deploy apps on multiple clusters and adminster them easier than using command line tools like `kubectl`.\n\n[Download](https://docs.k8slens.dev/main/#downloading-lens) Lens on your local system.\n\n**Step Lens.B**: Download, install and run Lens Desktop\n\nSign up for a free trial and download Lens desktop and install it as shown below. Make sure you select the tiny icon on the bottom left and click on the free trial as shown below.\n\n![lens](images/tutorials/LensDownload1.png?raw=true)\n\n\nIf needed, launch the desktop manually as shown below.\n\n![lens](images/tutorials/LensLaunchManual1.png?raw=true)\n\nAfter the launch the Lens Desktop might be in a stopped state as shown in the bottom left below.\n\n![lens](images/tutorials/LensStop1.png?raw=true)\n\nClick on the `Lens Desktop Kube: Stopped` and pick appropriate values as shown below.\n\n![lens](images/tutorials/Lensvalues1.png?raw=true)\n\nNote that the current state is shown as stopped as shown below.\n\n![lens](images/tutorials/LensStopped1.png?raw=true)\n\nToggle the button as shown below to move it from stopped to running.\n\n![lens](images/tutorials/LensRunning1.png?raw=true)\n\nMake sure that Lens is running as shown below. **It might take well over five minutes for the state to move to running.**\n\n![lens](images/tutorials/LensRunning2.png?raw=true)\n\nYou should have Lens desktop in your clusters list as shown below.\n\n![lens](images/tutorials/LensLDK1.png?raw=true)\n\nNow that Lens Desktop is installed, up and running we're ready to deploy the ToDo app.\n\n**Step Lens.C**: Set up secrets\n\nStart by clicking on `Config`, `Secrets` and `+` as shown below.\n\n![lens](images/tutorials/Lenssecret01.png?raw=true)\n\nNow add the secret `astra` and the secrets `astra-username` and `astra-password`  as shown below.\n\n![lens](images/tutorials/Lenssecret02.png?raw=true)\n\nYou can verify you entered the values correctly by hitting the button as shown below which will show the values in clear.\n\n![lens](images/tutorials/Lenssecret03.png?raw=true)\n\n**Step Lens.D**: Start the workload\n\nWe use the generated `kubernetes.yml` file to install the workload in Lens.\n\nClick on `+` and `Create resource` as shown below.\n\n![lens](images/tutorials/Lensresource01.png?raw=true)\n\nWe are going to cut-n-paste the contents from the Gitpod window into Lens.\n\nIssue the following command in the Gitpod terminal window to look at the Kubernetes manifests that were automatically generated and applied to the cluster.\n\n```\ngp open target/kubernetes/kubernetes.yml\n```\n\nand cut-n-paste the contents into Lens as shown below and hit `Create` as shown below.\n\n![lens](images/tutorials/Lensresource02.png?raw=true)\n\nIf you dig into `Pods` you should be see it running as shown below.\n\n![lens](images/tutorials/Lensresource03.png?raw=true)\n\nYou can look through other Kubernetes artifacts which you can easily navigate via Lens.\n\n**Step Lens.F**: Setup port forwarding\n\nClick on Network, Services and Forward... as shown below.\n\n![lens](images/tutorials/LensPortForward1.png?raw=true)\n\nNext forward to `8080` as shown below.\n\n![lens](images/tutorials/LensPortForward2.png?raw=true)\n\nThis will setup the port forwarding to the appropriate pod. Ignore errors if any. You can now access the app via `8080` on `localhost`.\n\n**Step Lens.G**: Cleanup\n\nYou can delete the service, deployment and secret using Lens.\n\nYou're now done with Lens deployment and can skip other deployment(s).\n\n**OR**\n\n**Step Okteto.A**: Create a cluster\n\nWe've included some steps here using [okteto](https://www.okteto.com) (you can modify the steps below depending on your choice of provider).\n\nCreate a Kubernetes cluster. You can get one for free at [https://okteto.com](https://okteto.com) with your Github credentials.\n\n**Step Okteto.B**: Download config file\n\nDownload the `config` file from [https://cloud.okteto.com/#/settings/setup](https://cloud.okteto.com/#/settings/setup) locally as shown below.\n\n![okteto](images/tutorials/oktetoconfig1.png?raw=true)\n\n**Step Okteto.C**: Drag and drop config into Gitpod\n\nNow \"drag and drop\" it over to the gitpod window (similar to how we transferred the secure connect bundle) as shown below.\n\n![okteto](images/tutorials/oktetoconfig2.png?raw=true)\n\n**Step Okteto.D**: Setup config in Gitpod window\n\nUse the transferred okteto config file with the following command in the Gitpod terminal window and verify\n\n```bash\nexport KUBECONFIG=okteto-kube.config\nkubectl config get-contexts\nkubectl get all\n```\n\nIf you get a message like `error: You must be logged in to the server (Unauthorized)` reauthorize and download the `okteto-kube.config` file again.\n\nSince okteto only provides access to your namespace, you should see something like below and you won't be able to run other commands like you would normally with a cluster that you created.\n\n```\nNo resources found in ragsns namespace.\n```\n\n**Step Okteto.E**: Setup secrets\n\nThe `application.properties` file is setup to use the Kubernetes secrets already (`quarkus.kubernetes.env.secrets=astra`). Setup the Kubernetes secrets as below from the`Client Id` and `Client Secret` respectively as we did earlier.\n\n```\nkubectl create secret generic astra --from-literal=astra-username=\u003cClient Id\u003e --from-literal=astra-password=\u003cClient Secret\u003e\n```\n\nVerify the screts are setup properly with the following commands.\n\n```bash\nkubectl get secret astra -o jsonpath=\"{.data.astra-username}\" | base64 --decode\nkubectl get secret astra -o jsonpath=\"{.data.astra-password}\" | base64 --decode\n```\n\nThe `kubernetes.yml` deployment file that will be generated in the next step will be setup to use the secrets.\n\n**Step Okteto.F**: Push image\n\nYou may want to remove the actual values of `astra-username` and `astra-password` from the`application.properties` file as below before pushing the container image to a public registry.\n\n```\nsed -i '/# TBD Below/,+4 d' ./target/classes/application.properties\n./mvnw package -Dquarkus.container-image.build=true -Dquarkus.container-image.push=true -Dquarkus.container-image.group=$DOCKER_LOGINID -Dquarkus.kubernetes.deploy=true -DskipTests\n```\n\nThe result of this command will be that your application's container image is built, pushed to the registry, and then deployed on Kubernetes. The Quarkus Kubernetes extension generates all the necessary Kubernetes desriptors for you.\n\nIssue the following command in the Gitpod terminal window to look at the Kubernetes manifests that were automatically generated and applied to the cluster.\n\n```\ngp open target/kubernetes/kubernetes.yml\n```\n\nYou should see the following output which indicates the deployment and the service have been created. **You can ignore errors related to webhook.**\n\n```\n[INFO] [io.quarkus.container.image.jib.deployment.JibProcessor] Pushed container image xxx/quarkus-cassandra:0.01 (sha256:xxxxxx)\n\n[INFO] [io.quarkus.kubernetes.deployment.KubernetesDeployer] Deploying to kubernetes server: https://a.b.c.d:443/ in namespace: xxxx.\n[INFO] [io.quarkus.kubernetes.deployment.KubernetesDeployer] Applied: Service quarkus-cassandra.\n[INFO] [io.quarkus.kubernetes.deployment.KubernetesDeployer] Applied: Deployment quarkus-cassandra.\n[INFO] [io.quarkus.deployment.QuarkusAugmentor] Quarkus augmentation completed in 12904ms\n```\n\nRunning the command\n\n```bash\nkubectl get all\n```\n\nshould yield a different output as below.\n\n```\nNAME                                    READY   STATUS    RESTARTS   AGE\npod/quarkus-cassandra-5f4d69b8d-lx46l   1/1     Running   0          95s\n\nNAME                        TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE\nservice/quarkus-cassandra   ClusterIP   10.154.219.218   \u003cnone\u003e        80/TCP    96s\n\nNAME                                READY   UP-TO-DATE   AVAILABLE   AGE\ndeployment.apps/quarkus-cassandra   1/1     1            1           96s\n\nNAME                                          DESIRED   CURRENT   READY   AGE\nreplicaset.apps/quarkus-cassandra-5f4d69b8d   1         1         1       96s\n```\n\nYou should be able to access the application from the endpoint provided by the [okteto console](https://cloud.okteto.com/#/spaces) and also be able to access the application logs as shown below.\n\n![okteto](images/tutorials/oktetorunning1.png?raw=true)\n\nAlternately, you can access the application provided by the gitpod URL like we have always been doing throughout the workshop by issuing the following command.\n\n```\nkubectl port-forward svc/quarkus-cassandra 8080:80 \u0026\n```\n\n**Step Okteto.G**: Cleanup\n\nYou can stop the port forwarding by deleting the background job as below.\n\n```\nkill -9 %1\n``` \n\nYou can go ahead and get rid of the application as well with the following command from the Gitpod terminal window.\n\n```\nkubectl delete all --all\n```\n\nand you should see the following output.\n\n```\npod \"quarkus-cassandra-886d9f8b9-h7tw5\" deleted\nservice \"quarkus-cassandra\" deleted\ndeployment.apps \"quarkus-cassandra\" deleted\n```\n\nAdditionally, you should delete the `Secret` you created.\n\n```\nkubectl delete secret astra\n```\n\nIf the public docker image contains the credentials to be able to access the database, it's a good idea to delete the docker image [from docker hub](http://hub.docker.com) right away, anyway.\n\n[🏠 Back to Table of Contents](#0-table-of-contents)\n\n## 11. Native Image\n\nFinally, Quarkus can build a native executable image with the help of the GraalVM that was pre-installed with a simple command as below. **Get yourself some coffee** or water as this will take almost 10 minutes but exceuting this image will be super fast with minimal startup time since it does not depend on the JVM.\n\n✅ **Step 11a: Generating Native Image**\n\n```bash\n./mvnw clean package -Pnative -DskipTests\n```\n\n**Expected output:**\n\n```\nPicked up JAVA_TOOL_OPTIONS:  -Xmx3435m\n[INFO] Scanning for projects...\n[INFO] \n[INFO] ---------\u003c quarkus-astra-intro-demo:quarkus-astra-intro-demo \u003e----------\n[INFO] Building quarkus-astra-intro-demo 0.01\n[INFO] --------------------------------[ jar ]---------------------------------\n[INFO] \n[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ quarkus-astra-intro-demo ---\n[INFO] Deleting /workspace/quarkus-astra-intro-demo/target\n[INFO] \n[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ quarkus-astra-intro-demo ---\n[INFO] Using 'UTF-8' encoding to copy filtered resources.\n[INFO] Copying 24 resources\n[INFO] \n[INFO] --- quarkus-maven-plugin:2.9.1.Final:generate-code (default) @ quarkus-astra-intro-demo ---\n[INFO] \n[INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) @ quarkus-astra-intro-demo ---\n[INFO] Changes detected - recompiling the module!\n[INFO] Compiling 10 source files to /workspace/quarkus-astra-intro-demo/target/classes\n[INFO] \n[INFO] --- quarkus-maven-plugin:2.9.1.Final:generate-code-tests (default) @ quarkus-astra-intro-demo ---\n[INFO] \n[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ quarkus-astra-intro-demo ---\n[INFO] Using 'UTF-8' encoding to copy filtered resources.\n[INFO] Copying 1 resource\n[INFO] \n[INFO] --- maven-compiler-plugin:3.8.1:testCompile (default-testCompile) @ quarkus-astra-intro-demo ---\n[INFO] Changes detected - recompiling the module!\n[INFO] Compiling 6 source files to /workspace/quarkus-astra-intro-demo/target/test-classes\n[INFO] \n[INFO] --- maven-surefire-plugin:3.0.0-M5:test (default-test) @ quarkus-astra-intro-demo ---\n[INFO] Tests are skipped.\n[INFO] \n[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ quarkus-astra-intro-demo ---\n[INFO] Building jar: /workspace/quarkus-astra-intro-demo/target/quarkus-astra-intro-demo-0.01.jar\n[INFO] \n[INFO] --- quarkus-maven-plugin:2.9.1.Final:build (default) @ quarkus-astra-intro-demo ---\n[INFO] [io.quarkus.deployment.pkg.steps.JarResultBuildStep] Building native image source jar: /workspace/quarkus-astra-intro-demo/target/quarkus-astra-intro-demo-0.01-native-image-source-jar/quarkus-astra-intro-demo-0.01-runner.jar\n[INFO] Checking for existing resources in: /workspace/quarkus-astra-intro-demo/src/main/kubernetes.\n[INFO] [io.quarkus.deployment.pkg.steps.NativeImageBuildStep] Building native image from /workspace/quarkus-astra-intro-demo/target/quarkus-astra-intro-demo-0.01-native-image-source-jar/quarkus-astra-intro-demo-0.01-runner.jar\n[INFO] [io.quarkus.deployment.pkg.steps.NativeImageBuildStep] Running Quarkus native-image plugin on GraalVM 22.0.0.2 Java 11 CE (Java Version 11.0.14+9-jvmci-22.0-b05)\n[INFO] [io.quarkus.deployment.pkg.steps.NativeImageBuildRunner] /home/gitpod/.sdkman/candidates/java/current/bin/native-image -J-Dsun.nio.ch.maxUpdateArraySize=100 -J-Djava.util.logging.manager=org.jboss.logmanager.LogManager -J-Dvertx.logger-delegate-factory-class-name=io.quarkus.vertx.core.runtime.VertxLogDelegateFactory -J-Dvertx.disableDnsResolver=true -J-Dio.netty.leakDetection.level=DISABLED -J-Dio.netty.allocator.maxOrder=3 -J-Duser.language=en -J-Duser.country=US -J-Dfile.encoding=UTF-8 -H:-ParseOnce -J--add-exports=java.security.jgss/sun.security.krb5=ALL-UNNAMED -J--add-opens=java.base/java.text=ALL-UNNAMED -H:InitialCollectionPolicy=com.oracle.svm.core.genscavenge.CollectionPolicy\\$BySpaceAndTime -H:+JNI -H:+AllowFoldMethods -J-Djava.awt.headless=true -H:FallbackThreshold=0 -H:+ReportExceptionStackTraces -H:-AddAllCharsets -H:EnableURLProtocols=http,https -H:NativeLinkerOption=-no-pie -H:-UseServiceLoaderFeature -H:+StackTrace quarkus-astra-intro-demo-0.01-runner -jar quarkus-astra-intro-demo-0.01-runner.jar\nPicked up JAVA_TOOL_OPTIONS:  -Xmx3435m\n========================================================================================================================\nGraalVM Native Image: Generating 'quarkus-astra-intro-demo-0.01-runner'...\n========================================================================================================================\n[1/7] Initializing...                                                                                    (4.9s @ 0.42GB)\n Version info: 'GraalVM 22.0.0.2 Java 11 CE'\n 3 user-provided feature(s)\n  - io.quarkus.runner.AutoFeature\n  - io.quarkus.runtime.graal.DisableLoggingAutoFeature\n  - io.quarkus.runtime.graal.ResourcesFeature\n[2/7] Performing analysis...  [20:33:32,360 INFO  [com.dat.oss.qua.run.int.qua.CassandraClientRecorder] Enabling Cassandra metrics using Micrometer.\n20:33:36,471 INFO  [com.dat.oss.dri.int.cor.DefaultMavenCoordinates] DataStax Java driver for Apache Cassandra(R) (com.datastax.oss:java-driver-core) version 4.14.0\n**********]                                                              (31.7s @ 2.17GB)\n  14,155 (95.32%) of 14,850 classes reachable\n  20,586 (66.60%) of 30,912 fields reachable\n  69,696 (82.00%) of 84,993 methods reachable\n     482 classes,    39 fields, and   850 methods registered for reflection\n      68 classes,    88 fields, and    54 methods registered for JNI access\n[3/7] Building universe...                                                                               (2.0s @ 2.69GB)\n[4/7] Parsing methods...      [***]                                                                      (5.3s @ 1.81GB)\n[5/7] Inlining methods...     [*****]                                                                    (4.7s @ 3.18GB)\n[6/7] Compiling methods...    [*****]                                                                   (22.6s @ 3.42GB)\n[7/7] Creating image...                                                                                  (4.3s @ 2.54GB)\n  25.64MB (36.89%) for code area:   46,599 compilation units\n  37.07MB (53.33%) for image heap:   9,899 classes and 350,222 objects\n   6.80MB ( 9.78%) for other data\n  69.50MB in total\n------------------------------------------------------------------------------------------------------------------------\nTop 10 packages in code area:                               Top 10 object types in image heap:\n   1.67MB sun.security.ssl                                    19.83MB byte[] for general heap data\n   1.03MB java.util                                            3.40MB java.lang.Class\n 686.94KB com.sun.crypto.provider                              2.65MB java.lang.String\n 531.52KB io.quarkus.runtime.generated                         2.21MB byte[] for java.lang.String\n 490.01KB sun.security.x509                                  627.75KB java.util.HashMap$Node\n 458.87KB java.util.concurrent                               581.63KB java.util.LinkedHashMap\n 446.33KB io.netty.buffer                                    534.65KB com.oracle.svm.core.util.LazyFinalReference\n 426.93KB com.oracle.svm.core.reflect                        526.91KB java.lang.String[]\n 425.74KB com.typesafe.config.impl                           439.28KB byte[] for method metadata\n 379.99KB java.lang                                          427.69KB c.o.s.c.h.DynamicHub$$Lambda$~31d9af6a7fe68cfc2a1f\n      ... 661 additional packages                                 ... 3407 additional object types\n                                           (use GraalVM Dashboard to see all)\n------------------------------------------------------------------------------------------------------------------------\n                        6.2s (7.7% of total time) in 40 GCs | Peak RSS: 5.21GB | CPU load: 4.98\n------------------------------------------------------------------------------------------------------------------------\nProduced artifacts:\n /workspace/quarkus-astra-intro-demo/target/quarkus-astra-intro-demo-0.01-native-image-source-jar/quarkus-astra-intro-demo-0.01-runner (executable)\n /workspace/quarkus-astra-intro-demo/target/quarkus-astra-intro-demo-0.01-native-image-source-jar/quarkus-astra-intro-demo-0.01-runner.build_artifacts.txt\n========================================================================================================================\nFinished generating 'quarkus-astra-intro-demo-0.01-runner' in 1m 20s.\n[INFO] [io.quarkus.deployment.pkg.steps.NativeImageBuildRunner] objcopy --strip-debug quarkus-astra-intro-demo-0.01-runner\n[INFO] [io.quarkus.deployment.QuarkusAugmentor] Quarkus augmentation completed in 83782ms\n[INFO] ------------------------------------------------------------------------\n[INFO] BUILD SUCCESS\n[INFO] ------------------------------------------------------------------------\n[INFO] Total time:  01:29 min\n[INFO] Finished at: 2022-05-16T20:34:47Z\n[INFO] ------------------------------------------------------------------------\n```\n\n✅ **Step 11b: Running Native Image**\n\nRun the native image with the following command:\n\n```bash\n./target/quarkus-astra-intro-demo-0.01-runner\n```\n\n```\n__  ____  __  _____   ___  __ ____  ______ \n --/ __ \\/ / / / _ | / _ \\/ //_/ / / / __/ \n -/ /_/ / /_/ / __ |/ , _/ ,\u003c / /_/ /\\ \\   \n--\\___\\_\\____/_/ |_/_/|_/_/|_|\\____/___/   \nINFO  [io.qua.sma.ope.run.OpenApiRecorder] (main) Default CORS properties will be used, please use 'quarkus.http.cors' properties instead\nINFO  [com.dat.oss.qua.run.int.qua.CassandraClientStarter] (main) Eagerly initializing Quarkus Cassandra client.\nINFO  [com.dat.oss.dri.int.cor.os.Native] (vert.x-eventloop-thread-0) Using Graal-specific native functions\nINFO  [com.dat.oss.dri.int.cor.tim.Clock] (vert.x-eventloop-thread-0) Using native clock for microsecond precision\nINFO  [com.dat.oss.dri.int.cor.ses.DefaultSession] (vert.x-eventloop-thread-9) [s0] Negotiated protocol version V4 for the initial contact point, but cluster seems to support V5, keeping the negotiated version\nINFO  [com.dat.tod.res.TodoResource] (main) **** Table created true****\nINFO  [io.quarkus] (main) quarkus-astra-intro-demo 0.01 native (powered by Quarkus 2.9.1.Final) started in 2.273s. Listening on: http://0.0.0.0:8080\nINFO  [io.quarkus] (main) Profile prod activated. \nINFO  [io.quarkus] (main) Installed features: [cassandra-client, cdi, kubernetes, micrometer, resteasy-reactive, resteasy-reactive-jackson, smallrye-context-propagation, smallrye-health, smallrye-openapi, swagger-ui, vertx]\n```\n\nNotice the fast startup time since the image is running as a native image.\n\nHit `Ctrl+C` in the GitPod terminal window to exit the application.\n\n[🏠 Back to Table of Contents](#0-table-of-contents)\n\n## 12. Homework\n\n\u003cimg src=\"images/tutorials/badge.png?raw=true\" width=\"200\" align=\"right\" /\u003e\n\nDon't forget to complete your upgrade and get your verified skill badge! Finish and submit your homework! You have 2 options (option A or Option B). Pick whichever works for you.\n\nOption A. Complete the practice steps from this repository as described above (including optional steps 10d and 10e) and deploy to a Kubernetes cluster.  Make screenshots of the deployment to a Kubernetes cluster.\n\nOption B: Learn more about Quarkus and do some development with https://github.com/datastax/cassandra-quarkus. Send a screenshot of the working \"Fruits application\" with the following entry \"Jackfruit\" and the correpsonding description as \"King/Queen of fruits\".\n\nSubmit your homework [here](https://docs.google.com/forms/d/e/1FAIpQLSd3hMHgHURsNGq2-jDAIr-XPLJGHqaRAm9CAMkYveybuYfBRw/viewform)\n\nThat's it, you are done! Expect an email next week!\n\n[🏠 Back to Table of Contents](#0-table-of-contents)\n\n## 13. The END\n\nCongratulations, your made it to the END of the show.\n\n\n**🧑🏻‍🤝‍🧑🏽 Let's get in touch**\n\n| ![B](images/tutorials/rags.png)                           |\n| ---------------------------------------------------------- |\n| Rags Srinivas \u003cbr\u003e[@ragsns](https://github.com/ragsns) |\n\n[🏠 Back to Table of Contents](#0-table-of-contents)\n---\n\n[![thankyou](images/tutorials/thankyou.gif)]()\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdatastaxdevs%2Fworkshop-intro-quarkus-cassandra","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdatastaxdevs%2Fworkshop-intro-quarkus-cassandra","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdatastaxdevs%2Fworkshop-intro-quarkus-cassandra/lists"}