├── .gitpod.Dockerfile ├── img ├── splash.png ├── table-keys.png ├── title_quarkus.png ├── title_spring.png ├── cluster-docker.png ├── quarkus-swagger.png ├── title_micronaut.png ├── data-distribution.png ├── micronaut-output.png ├── micronaut_test_01.png ├── micronaut_test_02.png ├── micronaut_test_03.png ├── micronaut_test_04.png ├── quarkus-dashboard.png ├── spring_api_gitpod.png ├── spring_api_local.png ├── title_cloud-native.png ├── data-model-methodology.png ├── from-sql-to-cassandra.png ├── introduction-to-drivers.png ├── modelisation-workflow.png ├── title_data-distribution.png ├── introduction-to-cassandra.png ├── title_migrating-sql-to-nosql.png ├── title_introduction-to-drivers.png ├── title_data-modeling-methodology.png ├── title_introduction-to-cassandra.png └── title_getting-started-with-table-key.png ├── lab-spring ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties ├── src │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── datastax │ │ │ │ └── todo │ │ │ │ ├── conf │ │ │ │ └── IndexController.java │ │ │ │ ├── TodoCassandraSpringboot3Application.java │ │ │ │ └── todo │ │ │ │ ├── TodoRepositoryCassandra.java │ │ │ │ ├── TodoRepositorySimpleCassandra.java │ │ │ │ ├── Todo.java │ │ │ │ ├── TodoEntity.java │ │ │ │ └── TodoRestController.java │ │ └── resources │ │ │ ├── application.yml │ │ │ └── banner.txt │ └── test │ │ └── java │ │ └── com │ │ └── datastax │ │ └── todo │ │ ├── E01_SpringDataInitTest.java │ │ ├── E02_SpringDataRepositoryTest.java │ │ ├── E04_SpringControllerTest.java │ │ └── E03_SpringDataCassandraOperationsTest.java ├── .gitignore └── pom.xml ├── lab-cassandra-drivers ├── src │ ├── main │ │ ├── resources │ │ │ ├── cassandra_logo.png │ │ │ └── application.conf │ │ └── java │ │ │ └── com │ │ │ └── datastax │ │ │ └── devoxx │ │ │ ├── objectmapping │ │ │ ├── CommentDaoMapper.java │ │ │ ├── CommentByVideo.java │ │ │ ├── CommentByUser.java │ │ │ ├── CommentDao.java │ │ │ ├── Comment.java │ │ │ └── CommentDaoQueryProvider.java │ │ │ ├── dto │ │ │ ├── VideoFormatDto.java │ │ │ ├── UserDto.java │ │ │ ├── FileDto.java │ │ │ └── VideoDto.java │ │ │ ├── codec │ │ │ ├── BytesArrayTypeCodec.java │ │ │ ├── UdtVideoFormatCodec.java │ │ │ └── JsonJacksonTypeCodec.java │ │ │ └── schema │ │ │ ├── SchemaConstants.java │ │ │ └── SchemaUtils.java │ └── test │ │ ├── resources │ │ └── logback-test.xml │ │ └── java │ │ └── com │ │ └── datastax │ │ └── devoxx │ │ ├── E01_CreateSchemaTest.java │ │ ├── E00_ConnectivityTest.java │ │ ├── E09_ResultPagingTest.java │ │ ├── E08_LightweightTransactionsTest.java │ │ ├── E05_CountersTest.java │ │ ├── E12_ObjectMappingTest.java │ │ ├── E02_StatementsTest.java │ │ ├── E11_ReactiveProgrammingTest.java │ │ ├── E06_JsonTest.java │ │ └── E03_OperationsCrudTest.java └── pom.xml ├── lab-quarkus ├── src │ ├── main │ │ ├── resources │ │ │ ├── META-INF │ │ │ │ └── resources │ │ │ │ │ └── index.html │ │ │ └── application.properties │ │ ├── java │ │ │ └── com │ │ │ │ └── datastaxdev │ │ │ │ ├── utils │ │ │ │ └── ValidationUtils.java │ │ │ │ └── todo │ │ │ │ ├── cassandra │ │ │ │ ├── TodoItemMapper.java │ │ │ │ ├── TodoItemDao.java │ │ │ │ ├── TodoServicesCassandraOM.java │ │ │ │ └── TodoItem.java │ │ │ │ ├── TodoService.java │ │ │ │ ├── TodoDto.java │ │ │ │ ├── web │ │ │ │ └── Todo.java │ │ │ │ └── TodoRestController.java │ │ └── docker │ │ │ ├── Dockerfile.native │ │ │ └── Dockerfile.jvm │ └── test │ │ └── java │ │ └── com │ │ └── datastax │ │ └── workshop │ │ ├── E04_QuarkusController.java │ │ ├── E03_QuarkusObjectMapping.java │ │ ├── E02_QuarkusCql.java │ │ └── E01_QuarkusInit.java └── pom.xml ├── lab-micronaut ├── src │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── datastaxdev │ │ │ │ ├── TodoApplication.java │ │ │ │ ├── utils │ │ │ │ └── ValidationUtils.java │ │ │ │ ├── todo │ │ │ │ ├── cassandra │ │ │ │ │ ├── TodoItemMapper.java │ │ │ │ │ ├── TodoItemDao.java │ │ │ │ │ ├── TodoServicesCassandraOM.java │ │ │ │ │ └── TodoItem.java │ │ │ │ ├── web │ │ │ │ │ └── Todo.java │ │ │ │ └── TodoRestController.java │ │ │ │ ├── TodoApplicationStartup.java │ │ │ │ ├── TodoService.java │ │ │ │ └── TodoDto.java │ │ └── resources │ │ │ ├── application.yml │ │ │ └── logback.xml │ └── test │ │ └── java │ │ └── com │ │ └── datastaxdev │ │ ├── E03_MicronautObjectMappingTest.java │ │ ├── E02_MicronautCqlTest.java │ │ ├── E04_MicronautControllerTest.java │ │ └── E01_MicronautInitTest.java └── pom.xml ├── .gitignore ├── setup ├── start ├── tests ├── cassandra-cqlsh └── docker-compose.yml └── .gitpod.yml /.gitpod.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM gitpod/workspace-full 2 | -------------------------------------------------------------------------------- /img/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/conference-2022-devoxx/main/img/splash.png -------------------------------------------------------------------------------- /img/table-keys.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/conference-2022-devoxx/main/img/table-keys.png -------------------------------------------------------------------------------- /img/title_quarkus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/conference-2022-devoxx/main/img/title_quarkus.png -------------------------------------------------------------------------------- /img/title_spring.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/conference-2022-devoxx/main/img/title_spring.png -------------------------------------------------------------------------------- /img/cluster-docker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/conference-2022-devoxx/main/img/cluster-docker.png -------------------------------------------------------------------------------- /img/quarkus-swagger.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/conference-2022-devoxx/main/img/quarkus-swagger.png -------------------------------------------------------------------------------- /img/title_micronaut.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/conference-2022-devoxx/main/img/title_micronaut.png -------------------------------------------------------------------------------- /img/data-distribution.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/conference-2022-devoxx/main/img/data-distribution.png -------------------------------------------------------------------------------- /img/micronaut-output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/conference-2022-devoxx/main/img/micronaut-output.png -------------------------------------------------------------------------------- /img/micronaut_test_01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/conference-2022-devoxx/main/img/micronaut_test_01.png -------------------------------------------------------------------------------- /img/micronaut_test_02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/conference-2022-devoxx/main/img/micronaut_test_02.png -------------------------------------------------------------------------------- /img/micronaut_test_03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/conference-2022-devoxx/main/img/micronaut_test_03.png -------------------------------------------------------------------------------- /img/micronaut_test_04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/conference-2022-devoxx/main/img/micronaut_test_04.png -------------------------------------------------------------------------------- /img/quarkus-dashboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/conference-2022-devoxx/main/img/quarkus-dashboard.png -------------------------------------------------------------------------------- /img/spring_api_gitpod.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/conference-2022-devoxx/main/img/spring_api_gitpod.png -------------------------------------------------------------------------------- /img/spring_api_local.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/conference-2022-devoxx/main/img/spring_api_local.png -------------------------------------------------------------------------------- /img/title_cloud-native.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/conference-2022-devoxx/main/img/title_cloud-native.png -------------------------------------------------------------------------------- /img/data-model-methodology.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/conference-2022-devoxx/main/img/data-model-methodology.png -------------------------------------------------------------------------------- /img/from-sql-to-cassandra.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/conference-2022-devoxx/main/img/from-sql-to-cassandra.png -------------------------------------------------------------------------------- /img/introduction-to-drivers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/conference-2022-devoxx/main/img/introduction-to-drivers.png -------------------------------------------------------------------------------- /img/modelisation-workflow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/conference-2022-devoxx/main/img/modelisation-workflow.png -------------------------------------------------------------------------------- /img/title_data-distribution.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/conference-2022-devoxx/main/img/title_data-distribution.png -------------------------------------------------------------------------------- /img/introduction-to-cassandra.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/conference-2022-devoxx/main/img/introduction-to-cassandra.png -------------------------------------------------------------------------------- /img/title_migrating-sql-to-nosql.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/conference-2022-devoxx/main/img/title_migrating-sql-to-nosql.png -------------------------------------------------------------------------------- /img/title_introduction-to-drivers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/conference-2022-devoxx/main/img/title_introduction-to-drivers.png -------------------------------------------------------------------------------- /img/title_data-modeling-methodology.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/conference-2022-devoxx/main/img/title_data-modeling-methodology.png -------------------------------------------------------------------------------- /img/title_introduction-to-cassandra.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/conference-2022-devoxx/main/img/title_introduction-to-cassandra.png -------------------------------------------------------------------------------- /lab-spring/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/conference-2022-devoxx/main/lab-spring/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /img/title_getting-started-with-table-key.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/conference-2022-devoxx/main/img/title_getting-started-with-table-key.png -------------------------------------------------------------------------------- /lab-cassandra-drivers/src/main/resources/cassandra_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/conference-2022-devoxx/main/lab-cassandra-drivers/src/main/resources/cassandra_logo.png -------------------------------------------------------------------------------- /lab-quarkus/src/main/resources/META-INF/resources/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |

Please follow this link.

8 | 9 | 10 | -------------------------------------------------------------------------------- /lab-spring/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.6/apache-maven-3.8.6-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar 3 | -------------------------------------------------------------------------------- /lab-micronaut/src/main/java/com/datastaxdev/TodoApplication.java: -------------------------------------------------------------------------------- 1 | package com.datastaxdev; 2 | 3 | import io.micronaut.runtime.Micronaut; 4 | 5 | public class TodoApplication { 6 | 7 | public static void main(String[] args) { 8 | Micronaut.run(TodoApplication.class, args); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # eclipse conf file 2 | .settings 3 | .classpath 4 | .project 5 | .cache 6 | 7 | # idea conf files 8 | .idea 9 | *.ipr 10 | *.iws 11 | *.iml 12 | 13 | # building 14 | target 15 | build 16 | tmp 17 | dist 18 | 19 | # misc 20 | .DS_Store 21 | 22 | .factorypath 23 | /.metadata/ 24 | /.metadata/ 25 | -------------------------------------------------------------------------------- /setup/start: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | GREEN='\033[0;32m' 3 | BLUE='\033[0;34m' 4 | NC='\033[0m' 5 | 6 | clear 7 | echo -e "${BLUE}------------------------------------------------------------${NC}" 8 | echo -e "${BLUE}--- Welcome to Devoxx 2022 ---${NC}" 9 | echo -e "${BLUE}------------------------------------------------------------${NC}" 10 | echo -e "" 11 | cd /workspace/conference-2022-devoxx/ 12 | -------------------------------------------------------------------------------- /setup/tests: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | GREEN='\033[0;32m' 3 | BLUE='\033[0;34m' 4 | NC='\033[0m' 5 | 6 | clear 7 | echo -e "${BLUE}------------------------------------------------------------${NC}" 8 | echo -e "${BLUE}--- Here execute Maven commands ---${NC}" 9 | echo -e "${BLUE}------------------------------------------------------------${NC}" 10 | echo -e "" 11 | cd /workspace/conference-2022-devoxx/ 12 | -------------------------------------------------------------------------------- /lab-spring/src/main/java/com/datastax/todo/conf/IndexController.java: -------------------------------------------------------------------------------- 1 | package com.datastax.todo.conf; 2 | 3 | import org.springframework.web.bind.annotation.RequestMapping; 4 | import org.springframework.web.bind.annotation.RestController; 5 | 6 | @RestController 7 | public class IndexController { 8 | 9 | @RequestMapping("/") 10 | public String hello() { 11 | return "Todo endpoint is /api/v1/todos/"; 12 | } 13 | 14 | } -------------------------------------------------------------------------------- /lab-spring/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | cassandra: 3 | schema-action: create-if-not-exists 4 | keyspace-name: devoxx_spring 5 | contact-points: 127.0.0.1:9042 6 | local-datacenter: dc1 7 | request: 8 | timeout: 5s 9 | consistency: LOCAL_QUORUM 10 | page-size: 5000 11 | connection: 12 | connect-timeout: 10s 13 | init-query-timeout: 10s 14 | controlconnection: 15 | timeout: 10s -------------------------------------------------------------------------------- /setup/cassandra-cqlsh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | GREEN='\033[0;32m' 4 | BLUE='\033[0;34m' 5 | NC='\033[0m' 6 | 7 | echo -e "" 8 | echo -e "${BLUE}------------------------------------------------------------${NC}" 9 | echo -e "${BLUE}-- CqlSH (LOCAL DOCKER) ---${NC}" 10 | echo -e "${BLUE}------------------------------------------------------------${NC}" 11 | echo -e "" 12 | docker exec -it `docker ps | grep dc1_seed | cut -b 1-12` cqlsh -------------------------------------------------------------------------------- /lab-spring/src/main/java/com/datastax/todo/TodoCassandraSpringboot3Application.java: -------------------------------------------------------------------------------- 1 | package com.datastax.todo; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class TodoCassandraSpringboot3Application { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(TodoCassandraSpringboot3Application.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /lab-spring/src/main/java/com/datastax/todo/todo/TodoRepositoryCassandra.java: -------------------------------------------------------------------------------- 1 | package com.datastax.todo.todo; 2 | 3 | import java.util.UUID; 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 TodoRepositoryCassandra extends CassandraRepository { 13 | 14 | } 15 | -------------------------------------------------------------------------------- /lab-quarkus/src/test/java/com/datastax/workshop/E04_QuarkusController.java: -------------------------------------------------------------------------------- 1 | package com.datastax.workshop; 2 | 3 | import static io.restassured.RestAssured.given; 4 | 5 | import org.junit.jupiter.api.Test; 6 | 7 | import io.quarkus.test.junit.QuarkusTest; 8 | 9 | @QuarkusTest 10 | public class E04_QuarkusController { 11 | 12 | @Test 13 | public void testApi() { 14 | given().when().get("/api/v1/clun/todos/") 15 | .then() 16 | .statusCode(200); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /lab-cassandra-drivers/src/test/resources/logback-test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | %d{HH:mm:ss.SSS} %magenta(%-5level) %cyan(%-45logger) : %msg%n 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /lab-spring/.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /lab-quarkus/src/main/java/com/datastaxdev/utils/ValidationUtils.java: -------------------------------------------------------------------------------- 1 | package com.datastaxdev.utils; 2 | 3 | public class ValidationUtils { 4 | 5 | public static void assertNotEmpty(String str) { 6 | if (str == null || "".equals(str)) { 7 | throw new IllegalArgumentException("This string parameter cannot be null nor empty"); 8 | } 9 | } 10 | 11 | public static void assertNotNull(Object str) { 12 | if (str == null) { 13 | throw new IllegalArgumentException("This parameter cannot be null "); 14 | } 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /lab-micronaut/src/main/java/com/datastaxdev/utils/ValidationUtils.java: -------------------------------------------------------------------------------- 1 | package com.datastaxdev.utils; 2 | 3 | public class ValidationUtils { 4 | 5 | public static void assertNotEmpty(String str) { 6 | if (str == null || "".equals(str)) { 7 | throw new IllegalArgumentException("This string parameter cannot be null nor empty"); 8 | } 9 | } 10 | 11 | public static void assertNotNull(Object str) { 12 | if (str == null) { 13 | throw new IllegalArgumentException("This parameter cannot be null "); 14 | } 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /lab-micronaut/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | micronaut: 2 | application: 3 | name: lab-micronaut 4 | server: 5 | port: 8082 6 | cors: 7 | enabled: true 8 | cassandra: 9 | default: 10 | basic: 11 | request: 12 | timeout: 5 seconds 13 | session-keyspace: devoxx_micronaut 14 | contact-points: 15 | - "localhost:9042" 16 | load-balancing-policy: 17 | local-datacenter: dc1 18 | advanced: 19 | connection: 20 | init-query-timeout: 5 seconds 21 | set-keyspace-timeout: 5 seconds 22 | control-connection.timeout: 5 seconds 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /lab-cassandra-drivers/src/main/java/com/datastax/devoxx/objectmapping/CommentDaoMapper.java: -------------------------------------------------------------------------------- 1 | package com.datastax.devoxx.objectmapping; 2 | 3 | import com.datastax.oss.driver.api.core.CqlSession; 4 | import com.datastax.oss.driver.api.mapper.MapperBuilder; 5 | import com.datastax.oss.driver.api.mapper.annotations.DaoFactory; 6 | import com.datastax.oss.driver.api.mapper.annotations.Mapper; 7 | 8 | /** 9 | * Definition of operation for mapping. 10 | */ 11 | @Mapper 12 | public interface CommentDaoMapper { 13 | 14 | @DaoFactory 15 | CommentDao commentDao(); 16 | 17 | static MapperBuilder builder(CqlSession session) { 18 | return new CommentDaoMapperBuilder(session); 19 | } 20 | } 21 | 22 | -------------------------------------------------------------------------------- /lab-spring/src/main/resources/banner.txt: -------------------------------------------------------------------------------- 1 | 2 | ${AnsiColor.BLUE} ________ _______________ ________ ________ 3 | ${AnsiColor.BLUE} \______ \ _______ _________ ______ __\_____ \ _ \ \_____ \\_____ \ 4 | ${AnsiColor.BLUE} | | \_/ __ \ \/ / _ \ \/ /\ \/ // ____/ /_\ \ / ____/ / ____/ 5 | ${AnsiColor.BLUE} | ` \ ___/\ ( <_> > < > \_/ \____/__/\_ \/__/\_ \_______ \_____ /\_______ \_______ \ 7 | ${AnsiColor.BLUE} \/ \/ \/ \/ \/ \/ \/ \/ 8 | 9 | ${AnsiColor.GREEN} The application will start at ${AnsiColor.RED}http://localhost:8080${AnsiColor.BLACK} -------------------------------------------------------------------------------- /lab-quarkus/src/main/docker/Dockerfile.native: -------------------------------------------------------------------------------- 1 | #### 2 | # This Dockerfile is used in order to build a container that runs the Quarkus application in native (no JVM) mode 3 | # 4 | # Before building the docker image run: 5 | # 6 | # mvn package -Pnative -Dquarkus.native.container-build=true 7 | # 8 | # Then, build the image with: 9 | # 10 | # docker build -f src/main/docker/Dockerfile.native -t quarkus/my-artifactId . 11 | # 12 | # Then run the container using: 13 | # 14 | # docker run -i --rm -p 8080:8080 quarkus/my-artifactId 15 | # 16 | ### 17 | FROM registry.access.redhat.com/ubi8/ubi-minimal:8.1 18 | WORKDIR /work/ 19 | COPY --chown=1001:root target/*-runner /work/application 20 | 21 | EXPOSE 8080 22 | USER 1001 23 | 24 | CMD ["./application", "-Dquarkus.http.host=0.0.0.0"] -------------------------------------------------------------------------------- /lab-micronaut/src/main/java/com/datastaxdev/todo/cassandra/TodoItemMapper.java: -------------------------------------------------------------------------------- 1 | package com.datastaxdev.todo.cassandra; 2 | 3 | import com.datastax.oss.driver.api.core.CqlSession; 4 | import com.datastax.oss.driver.api.mapper.MapperBuilder; 5 | import com.datastax.oss.driver.api.mapper.annotations.DaoFactory; 6 | import com.datastax.oss.driver.api.mapper.annotations.Mapper; 7 | 8 | @Mapper 9 | public interface TodoItemMapper { 10 | 11 | @DaoFactory 12 | TodoItemDao todoItemDao(); 13 | 14 | /** 15 | * Utility to initialize. 16 | * 17 | * @param session 18 | * target session 19 | * @return 20 | * target builder 21 | */ 22 | static MapperBuilder builder(CqlSession session) { 23 | return new TodoItemMapperBuilder(session); 24 | } 25 | 26 | } -------------------------------------------------------------------------------- /lab-quarkus/src/main/java/com/datastaxdev/todo/cassandra/TodoItemMapper.java: -------------------------------------------------------------------------------- 1 | package com.datastaxdev.todo.cassandra; 2 | 3 | import com.datastax.oss.driver.api.core.CqlSession; 4 | import com.datastax.oss.driver.api.mapper.MapperBuilder; 5 | import com.datastax.oss.driver.api.mapper.annotations.DaoFactory; 6 | import com.datastax.oss.driver.api.mapper.annotations.Mapper; 7 | 8 | @Mapper 9 | public interface TodoItemMapper { 10 | 11 | @DaoFactory 12 | TodoItemDao todoItemDao(); 13 | 14 | /** 15 | * Utility to initialize. 16 | * 17 | * @param session 18 | * target session 19 | * @return 20 | * target builder 21 | */ 22 | static MapperBuilder builder(CqlSession session) { 23 | return new TodoItemMapperBuilder(session); 24 | } 25 | 26 | } -------------------------------------------------------------------------------- /lab-cassandra-drivers/src/main/resources/application.conf: -------------------------------------------------------------------------------- 1 | datastax-java-driver { 2 | 3 | # Core settings 4 | basic { 5 | contact-points = [ "127.0.0.1:9042"] 6 | session-name = labdrivers 7 | session-keyspace = devoxx_drivers 8 | config-reload-interval = 5 minutes 9 | 10 | request { 11 | timeout = 3 seconds 12 | consistency = LOCAL_QUORUM 13 | page-size = 5000 14 | } 15 | load-balancing-policy { 16 | class = DefaultLoadBalancingPolicy 17 | local-datacenter = dc1 18 | } 19 | } 20 | 21 | # Dedicated Profiles 22 | profiles { 23 | oltp { 24 | basic.request.timeout = 100 milliseconds 25 | basic.request.consistency = ONE 26 | } 27 | olap { 28 | basic.request.timeout = 5 seconds 29 | basic.request.consistency = QUORUM 30 | } 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /lab-spring/src/test/java/com/datastax/todo/E01_SpringDataInitTest.java: -------------------------------------------------------------------------------- 1 | package com.datastax.todo; 2 | 3 | import org.junit.jupiter.api.Assertions; 4 | import org.junit.jupiter.api.Test; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.boot.test.context.SpringBootTest; 9 | 10 | import com.datastax.oss.driver.api.core.CqlSession; 11 | 12 | @SpringBootTest 13 | public class E01_SpringDataInitTest { 14 | 15 | /** Logger for the class. */ 16 | static Logger LOGGER = LoggerFactory.getLogger(E01_SpringDataInitTest.class); 17 | 18 | @Autowired 19 | CqlSession cqlSession; 20 | 21 | @Test 22 | public void testCqlSession() { 23 | LOGGER.info("Creating your CqlSession to Cassandra..."); 24 | Assertions.assertTrue(cqlSession.getKeyspace().isPresent()); 25 | LOGGER.info("+ [OK] Your are connected to keyspace {}", cqlSession.getKeyspace().get()); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /lab-cassandra-drivers/src/main/java/com/datastax/devoxx/dto/VideoFormatDto.java: -------------------------------------------------------------------------------- 1 | package com.datastax.devoxx.dto; 2 | 3 | /** 4 | * CREATE TYPE IF NOT EXISTS video_format ( 5 | * width int, 6 | * height int, 7 | * frames list 8 | * ); 9 | */ 10 | public class VideoFormatDto { 11 | 12 | private int width = 0; 13 | 14 | private int height = 0; 15 | 16 | public VideoFormatDto() {} 17 | 18 | public VideoFormatDto(int w, int h) { 19 | this.width = w; 20 | this.height = h; 21 | } 22 | 23 | public int getWidth() { 24 | return width; 25 | } 26 | 27 | public void setWidth(int width) { 28 | this.width = width; 29 | } 30 | 31 | public int getHeight() { 32 | return height; 33 | } 34 | 35 | public void setHeight(int height) { 36 | this.height = height; 37 | } 38 | 39 | @Override 40 | public String toString() { 41 | return "VideoFormatDto [width=" + width + ", height=" + height; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /lab-micronaut/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | true 5 | 7 | 8 | %cyan(%d{HH:mm:ss.SSS}) %gray([%thread]) %highlight(%-5level) %magenta(%logger{36}) - %msg%n 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /lab-micronaut/src/test/java/com/datastaxdev/E03_MicronautObjectMappingTest.java: -------------------------------------------------------------------------------- 1 | package com.datastaxdev; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | 7 | import com.datastax.oss.driver.api.core.CqlSession; 8 | import com.datastaxdev.todo.cassandra.TodoServicesCassandraOM; 9 | 10 | import io.micronaut.test.extensions.junit5.annotation.MicronautTest; 11 | import jakarta.inject.Inject; 12 | 13 | @MicronautTest 14 | public class E03_MicronautObjectMappingTest { 15 | 16 | /** Logger for the class. */ 17 | static Logger LOGGER = LoggerFactory.getLogger(E03_MicronautObjectMappingTest.class); 18 | 19 | @Inject 20 | CqlSession quarkusCqlSession; 21 | 22 | @Inject 23 | TodoServicesCassandraOM todoService; 24 | 25 | @Test 26 | public void testExecuteCql() { 27 | LOGGER.info("Inserting Data"); 28 | TodoDto dto = new TodoDto(); 29 | dto.setUserId("clun"); 30 | dto.setCompleted(false); 31 | dto.setTitle("Apprendre Mapping Objet Micronaut"); 32 | todoService.save(dto); 33 | LOGGER.info("+ [OK]"); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /lab-quarkus/src/test/java/com/datastax/workshop/E03_QuarkusObjectMapping.java: -------------------------------------------------------------------------------- 1 | package com.datastax.workshop; 2 | 3 | import javax.inject.Inject; 4 | 5 | import org.junit.jupiter.api.Test; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | import com.datastax.oss.quarkus.runtime.api.session.QuarkusCqlSession; 10 | import com.datastaxdev.todo.TodoDto; 11 | import com.datastaxdev.todo.cassandra.TodoServicesCassandraOM; 12 | 13 | import io.quarkus.test.junit.QuarkusTest; 14 | 15 | @QuarkusTest 16 | public class E03_QuarkusObjectMapping { 17 | 18 | /** Logger for the class. */ 19 | static Logger LOGGER = LoggerFactory.getLogger(E02_QuarkusCql.class); 20 | 21 | @Inject 22 | QuarkusCqlSession quarkusCqlSession; 23 | 24 | @Inject 25 | TodoServicesCassandraOM todoService; 26 | 27 | @Test 28 | public void testExecuteCql() { 29 | LOGGER.info("Inserting Data"); 30 | TodoDto dto = new TodoDto(); 31 | dto.setUserId("clun"); 32 | dto.setCompleted(false); 33 | dto.setTitle("Apprendre Mapping Objet Quarkus"); 34 | todoService.save(dto); 35 | LOGGER.info("+ [OK]"); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /lab-micronaut/src/main/java/com/datastaxdev/todo/cassandra/TodoItemDao.java: -------------------------------------------------------------------------------- 1 | package com.datastaxdev.todo.cassandra; 2 | 3 | import java.util.Optional; 4 | import java.util.UUID; 5 | 6 | import com.datastax.oss.driver.api.core.PagingIterable; 7 | import com.datastax.oss.driver.api.mapper.annotations.Dao; 8 | import com.datastax.oss.driver.api.mapper.annotations.DefaultNullSavingStrategy; 9 | import com.datastax.oss.driver.api.mapper.annotations.Delete; 10 | import com.datastax.oss.driver.api.mapper.annotations.Insert; 11 | import com.datastax.oss.driver.api.mapper.annotations.Select; 12 | import com.datastax.oss.driver.api.mapper.entity.saving.NullSavingStrategy; 13 | 14 | @Dao 15 | @DefaultNullSavingStrategy(NullSavingStrategy.SET_TO_NULL) 16 | public interface TodoItemDao { 17 | 18 | @Delete(entityClass = TodoItem.class) 19 | void deleteByUser(String userId); 20 | 21 | @Delete(entityClass = TodoItem.class) 22 | void deleteById(String userId, UUID itemId); 23 | 24 | @Select 25 | PagingIterable findByUser(String userId); 26 | 27 | @Select 28 | Optional findById(String userId, UUID itemId); 29 | 30 | @Insert 31 | void save(TodoItem product); 32 | } 33 | -------------------------------------------------------------------------------- /lab-quarkus/src/main/java/com/datastaxdev/todo/cassandra/TodoItemDao.java: -------------------------------------------------------------------------------- 1 | package com.datastaxdev.todo.cassandra; 2 | 3 | import java.util.Optional; 4 | import java.util.UUID; 5 | 6 | import com.datastax.oss.driver.api.core.PagingIterable; 7 | import com.datastax.oss.driver.api.mapper.annotations.Dao; 8 | import com.datastax.oss.driver.api.mapper.annotations.DefaultNullSavingStrategy; 9 | import com.datastax.oss.driver.api.mapper.annotations.Delete; 10 | import com.datastax.oss.driver.api.mapper.annotations.Insert; 11 | import com.datastax.oss.driver.api.mapper.annotations.Select; 12 | import com.datastax.oss.driver.api.mapper.entity.saving.NullSavingStrategy; 13 | 14 | @Dao 15 | @DefaultNullSavingStrategy(NullSavingStrategy.SET_TO_NULL) 16 | public interface TodoItemDao { 17 | 18 | @Delete(entityClass = TodoItem.class) 19 | void deleteByUser(String userId); 20 | 21 | @Delete(entityClass = TodoItem.class) 22 | void deleteById(String userId, UUID itemId); 23 | 24 | @Select 25 | PagingIterable findByUser(String userId); 26 | 27 | @Select 28 | Optional findById(String userId, UUID itemId); 29 | 30 | @Insert 31 | void save(TodoItem product); 32 | } 33 | -------------------------------------------------------------------------------- /lab-micronaut/src/test/java/com/datastaxdev/E02_MicronautCqlTest.java: -------------------------------------------------------------------------------- 1 | package com.datastaxdev; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | 7 | import com.datastax.oss.driver.api.core.CqlSession; 8 | import com.datastaxdev.todo.cassandra.TodoServiceCassandraCql; 9 | 10 | import io.micronaut.test.extensions.junit5.annotation.MicronautTest; 11 | import jakarta.inject.Inject; 12 | 13 | @MicronautTest 14 | public class E02_MicronautCqlTest { 15 | 16 | /** Logger for the class. */ 17 | static Logger LOGGER = LoggerFactory.getLogger(E02_MicronautCqlTest.class); 18 | 19 | @Inject 20 | CqlSession cqlSession; 21 | 22 | @Inject 23 | TodoServiceCassandraCql todoService; 24 | 25 | @Test 26 | public void testExecuteCql() { 27 | LOGGER.info("Creating the schema..."); 28 | TodoServiceCassandraCql.createTableTodo(cqlSession); 29 | LOGGER.info("+ [OK]"); 30 | 31 | LOGGER.info("Inserting Data"); 32 | TodoDto dto = new TodoDto(); 33 | dto.setUserId("clun"); 34 | dto.setCompleted(false); 35 | dto.setTitle("Apprendre Micronaut"); 36 | todoService.save(dto); 37 | LOGGER.info("+ [OK]"); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /setup/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "2" 2 | services: 3 | 4 | # In a DC at least one node is a seed (one per rack) 5 | dc1_seed: 6 | image: cassandra:4.0.6 7 | ports: 8 | - 9042:9042 9 | networks: 10 | - cassandra 11 | mem_limit: 2G 12 | #volumes: 13 | # - ~/docker-volumes/dc1_seed/:/var/lib/cassandra/data 14 | environment: 15 | - CASSANDRA_DC=dc1 16 | - CASSANDRA_SEEDS=dc1_seed 17 | - CASSANDRA_CLUSTER_NAME=handson 18 | - CASSANDRA_ENDPOINT_SNITCH=GossipingPropertyFileSnitch 19 | - HEAP_NEWSIZE=128M 20 | - MAX_HEAP_SIZE=1024M 21 | 22 | dc1_node: 23 | image: cassandra:4.0.6 24 | command: /bin/bash -c "echo 'Waiting for dc1_seed to bootstrap for 30s' && sleep 30 && /usr/local/bin/docker-entrypoint.sh cassandra -f" 25 | mem_limit: 2G 26 | #volumes: 27 | # - ~/docker-volumes/dc1_noeud/:/var/lib/cassandra/data 28 | networks: 29 | - cassandra 30 | depends_on: 31 | - dc1_seed 32 | environment: 33 | - CASSANDRA_DC=dc1 34 | - CASSANDRA_SEEDS=dc1_seed 35 | - CASSANDRA_CLUSTER_NAME=handson 36 | - CASSANDRA_ENDPOINT_SNITCH=GossipingPropertyFileSnitch 37 | - HEAP_NEWSIZE=128M 38 | - MAX_HEAP_SIZE=1024M 39 | 40 | networks: 41 | cassandra: 42 | 43 | -------------------------------------------------------------------------------- /lab-micronaut/src/main/java/com/datastaxdev/TodoApplicationStartup.java: -------------------------------------------------------------------------------- 1 | package com.datastaxdev; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | import com.datastax.oss.driver.api.core.CqlSession; 7 | import com.datastaxdev.todo.cassandra.TodoServiceCassandraCql; 8 | 9 | import io.micronaut.context.event.ApplicationEventListener; 10 | import io.micronaut.discovery.event.ServiceReadyEvent; 11 | import jakarta.inject.Inject; 12 | import jakarta.inject.Singleton; 13 | 14 | /** 15 | * Execute some Action and application startup. 16 | * 17 | * @author Cedrick LUNVEN (@clunven) 18 | */ 19 | @Singleton 20 | public class TodoApplicationStartup implements ApplicationEventListener { 21 | 22 | /** Logger for the class. */ 23 | private static final Logger LOGGER = LoggerFactory.getLogger(TodoApplicationStartup.class); 24 | 25 | @Inject 26 | private CqlSession cqlSession; 27 | 28 | /** {@inheritDoc} */ 29 | @Override 30 | public void onApplicationEvent(final ServiceReadyEvent event) { 31 | LOGGER.info("Startup Initialization"); 32 | TodoServiceCassandraCql.createTableTodo(cqlSession); 33 | LOGGER.info("+ Table TodoItems created if needed."); 34 | LOGGER.info("[OK]"); 35 | } 36 | 37 | 38 | } 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /lab-quarkus/src/test/java/com/datastax/workshop/E02_QuarkusCql.java: -------------------------------------------------------------------------------- 1 | package com.datastax.workshop; 2 | 3 | import javax.inject.Inject; 4 | 5 | import org.junit.jupiter.api.Test; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | import com.datastax.oss.quarkus.runtime.api.session.QuarkusCqlSession; 10 | import com.datastaxdev.todo.TodoDto; 11 | import com.datastaxdev.todo.cassandra.TodoServiceCassandraCql; 12 | 13 | import io.quarkus.test.junit.QuarkusTest; 14 | 15 | @QuarkusTest 16 | public class E02_QuarkusCql { 17 | 18 | /** Logger for the class. */ 19 | static Logger LOGGER = LoggerFactory.getLogger(E02_QuarkusCql.class); 20 | 21 | @Inject 22 | QuarkusCqlSession quarkusCqlSession; 23 | 24 | @Inject 25 | TodoServiceCassandraCql todoService; 26 | 27 | @Test 28 | public void testExecuteCql() { 29 | LOGGER.info("Creating the schema..."); 30 | TodoServiceCassandraCql.createTableTodo(quarkusCqlSession); 31 | LOGGER.info("+ [OK]"); 32 | 33 | LOGGER.info("Inserting Data"); 34 | TodoDto dto = new TodoDto(); 35 | dto.setUserId("clun"); 36 | dto.setCompleted(false); 37 | dto.setTitle("Apprendre Quarkus"); 38 | todoService.save(dto); 39 | LOGGER.info("+ [OK]"); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /lab-quarkus/src/test/java/com/datastax/workshop/E01_QuarkusInit.java: -------------------------------------------------------------------------------- 1 | package com.datastax.workshop; 2 | 3 | import javax.inject.Inject; 4 | 5 | import org.eclipse.microprofile.config.inject.ConfigProperty; 6 | import org.junit.jupiter.api.Assertions; 7 | import org.junit.jupiter.api.Test; 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | 11 | import com.datastax.oss.quarkus.runtime.api.session.QuarkusCqlSession; 12 | 13 | import io.quarkus.test.junit.QuarkusTest; 14 | 15 | @QuarkusTest 16 | public class E01_QuarkusInit { 17 | 18 | /** Logger for the class. */ 19 | static Logger LOGGER = LoggerFactory.getLogger(E01_QuarkusInit.class); 20 | 21 | @Inject 22 | QuarkusCqlSession quarkusCqlSession; 23 | 24 | @Inject 25 | @ConfigProperty(name = "quarkus.cassandra.keyspace") 26 | String keyspace; 27 | 28 | @Test 29 | public void testCqlSession() { 30 | LOGGER.info("Creating your CqlSession to Cassandra..."); 31 | Assertions.assertNotNull(keyspace); 32 | Assertions.assertTrue(quarkusCqlSession.getKeyspace().isPresent()); 33 | LOGGER.info("+ [OK] Your are connected to keyspace {}", quarkusCqlSession.getKeyspace().get()); 34 | Assertions.assertEquals(keyspace, quarkusCqlSession.getKeyspace().get().toString()); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /lab-cassandra-drivers/src/main/java/com/datastax/devoxx/objectmapping/CommentByVideo.java: -------------------------------------------------------------------------------- 1 | package com.datastax.devoxx.objectmapping; 2 | 3 | import java.util.UUID; 4 | 5 | import com.datastax.devoxx.schema.SchemaConstants; 6 | import com.datastax.oss.driver.api.mapper.annotations.CqlName; 7 | import com.datastax.oss.driver.api.mapper.annotations.Entity; 8 | import com.datastax.oss.driver.api.mapper.annotations.PartitionKey; 9 | 10 | /** 11 | * Specialization for VIDEO. 12 | * 13 | * @author DataStax Developer Advocates team. 14 | */ 15 | @Entity 16 | @CqlName(SchemaConstants.COMMENT_BY_VIDEO_TABLENAME) 17 | public class CommentByVideo extends Comment { 18 | 19 | /** Serial. */ 20 | private static final long serialVersionUID = -6738790629520080307L; 21 | 22 | public CommentByVideo() { 23 | } 24 | 25 | public CommentByVideo(Comment c) { 26 | this.commentid = c.getCommentid(); 27 | this.userid = c.getUserid(); 28 | this.videoid = c.getVideoid(); 29 | this.comment = c.getComment(); 30 | } 31 | 32 | /** 33 | * Getter for attribute 'videoid'. 34 | * 35 | * @return 36 | * current value of 'videoid' 37 | */ 38 | @PartitionKey 39 | public UUID getVideoid() { 40 | return videoid; 41 | } 42 | 43 | 44 | } 45 | -------------------------------------------------------------------------------- /lab-spring/src/test/java/com/datastax/todo/E02_SpringDataRepositoryTest.java: -------------------------------------------------------------------------------- 1 | package com.datastax.todo; 2 | 3 | import org.junit.jupiter.api.Assertions; 4 | import org.junit.jupiter.api.Test; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.boot.test.context.SpringBootTest; 9 | 10 | import com.datastax.todo.todo.TodoEntity; 11 | import com.datastax.todo.todo.TodoRepositoryCassandra; 12 | 13 | @SpringBootTest 14 | public class E02_SpringDataRepositoryTest { 15 | 16 | /** Logger for the class. */ 17 | static Logger LOGGER = LoggerFactory.getLogger(E02_SpringDataRepositoryTest.class); 18 | 19 | @Autowired 20 | TodoRepositoryCassandra todoRepo; 21 | 22 | @Test 23 | public void testCassandraRepository() { 24 | // Given 25 | TodoEntity te = new TodoEntity("Apprendre Cassandra", 0); 26 | // When 27 | TodoEntity e = todoRepo.save(te); 28 | LOGGER.info("Tache enregistree avec id {}", e.getUid()); 29 | // Then 30 | Assertions.assertTrue(todoRepo.existsById(te.getUid())); 31 | // Listing 32 | LOGGER.info("Liste des Taches"); 33 | todoRepo.findAll().stream().map(Object::toString).forEach(LOGGER::info); 34 | } 35 | 36 | 37 | 38 | } 39 | -------------------------------------------------------------------------------- /lab-spring/src/main/java/com/datastax/todo/todo/TodoRepositorySimpleCassandra.java: -------------------------------------------------------------------------------- 1 | package com.datastax.todo.todo; 2 | 3 | import java.util.UUID; 4 | 5 | import org.springframework.data.cassandra.core.CassandraOperations; 6 | import org.springframework.data.cassandra.core.mapping.CassandraPersistentEntity; 7 | import org.springframework.data.cassandra.repository.support.MappingCassandraEntityInformation; 8 | import org.springframework.data.cassandra.repository.support.SimpleCassandraRepository; 9 | import org.springframework.stereotype.Service; 10 | 11 | import com.datastax.oss.driver.api.core.CqlSession; 12 | 13 | @Service 14 | public class TodoRepositorySimpleCassandra extends SimpleCassandraRepository { 15 | 16 | protected final CqlSession cqlSession; 17 | 18 | protected final CassandraOperations cassandraTemplate; 19 | 20 | @SuppressWarnings("unchecked") 21 | public TodoRepositorySimpleCassandra(CqlSession cqlSession, CassandraOperations ops) { 22 | super(new MappingCassandraEntityInformation( 23 | (CassandraPersistentEntity) ops.getConverter().getMappingContext() 24 | .getRequiredPersistentEntity(TodoEntity.class), ops.getConverter()), ops); 25 | this.cqlSession = cqlSession; 26 | this.cassandraTemplate = ops; 27 | } 28 | 29 | 30 | } 31 | -------------------------------------------------------------------------------- /lab-cassandra-drivers/src/main/java/com/datastax/devoxx/objectmapping/CommentByUser.java: -------------------------------------------------------------------------------- 1 | package com.datastax.devoxx.objectmapping; 2 | 3 | import java.util.UUID; 4 | 5 | import com.datastax.devoxx.schema.SchemaConstants; 6 | import com.datastax.oss.driver.api.mapper.annotations.CqlName; 7 | import com.datastax.oss.driver.api.mapper.annotations.Entity; 8 | import com.datastax.oss.driver.api.mapper.annotations.PartitionKey; 9 | 10 | /** 11 | * Specialization for USER. 12 | * 13 | * @author DataStax Developer Advocates team. 14 | */ 15 | @Entity 16 | @CqlName(SchemaConstants.COMMENT_BY_USER_TABLENAME) 17 | public class CommentByUser extends Comment { 18 | 19 | /** Serial. */ 20 | private static final long serialVersionUID = 1453554109222565840L; 21 | 22 | /** 23 | * Default constructor. 24 | */ 25 | public CommentByUser() {} 26 | 27 | /** 28 | * Copy constructor. 29 | * 30 | * @param c 31 | */ 32 | public CommentByUser(Comment c) { 33 | this.commentid = c.getCommentid(); 34 | this.userid = c.getUserid(); 35 | this.videoid = c.getVideoid(); 36 | this.comment = c.getComment(); 37 | } 38 | 39 | /** 40 | * Getter for attribute 'userid'. 41 | * 42 | * @return 43 | * current value of 'userid' 44 | */ 45 | @PartitionKey 46 | public UUID getUserid() { 47 | return userid; 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /lab-micronaut/src/test/java/com/datastaxdev/E04_MicronautControllerTest.java: -------------------------------------------------------------------------------- 1 | package com.datastaxdev; 2 | 3 | 4 | import static org.junit.jupiter.api.Assertions.assertFalse; 5 | 6 | import java.util.List; 7 | 8 | import org.junit.jupiter.api.Assertions; 9 | import org.junit.jupiter.api.Test; 10 | import org.slf4j.Logger; 11 | import org.slf4j.LoggerFactory; 12 | 13 | import io.micronaut.core.type.Argument; 14 | import io.micronaut.http.HttpRequest; 15 | import io.micronaut.http.client.HttpClient; 16 | import io.micronaut.http.client.annotation.Client; 17 | import io.micronaut.runtime.EmbeddedApplication; 18 | import io.micronaut.test.extensions.junit5.annotation.MicronautTest; 19 | import jakarta.inject.Inject; 20 | 21 | @MicronautTest 22 | public class E04_MicronautControllerTest { 23 | 24 | /** Logger for the class. */ 25 | static Logger LOGGER = LoggerFactory.getLogger(E04_MicronautControllerTest.class); 26 | 27 | @Inject 28 | EmbeddedApplication application; 29 | 30 | @Inject 31 | @Client("/api/v1/") 32 | HttpClient client; 33 | 34 | @Test 35 | public void testRunApplication() { 36 | Assertions.assertTrue(application.isRunning()); 37 | HttpRequest request = HttpRequest.GET("/clun/todos"); 38 | List todos = client.toBlocking().retrieve(request, Argument.listOf(TodoDto.class)); 39 | assertFalse(todos.isEmpty()); 40 | LOGGER.info("{} task retrieved", todos.size()); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /lab-cassandra-drivers/src/main/java/com/datastax/devoxx/objectmapping/CommentDao.java: -------------------------------------------------------------------------------- 1 | package com.datastax.devoxx.objectmapping; 2 | 3 | import java.util.UUID; 4 | 5 | import com.datastax.devoxx.schema.SchemaConstants; 6 | import com.datastax.oss.driver.api.core.PagingIterable; 7 | import com.datastax.oss.driver.api.mapper.annotations.Dao; 8 | import com.datastax.oss.driver.api.mapper.annotations.Query; 9 | import com.datastax.oss.driver.api.mapper.annotations.QueryProvider; 10 | 11 | /** 12 | * Implementation of Services to work with Comments in Killrvideo. We work with 13 | * 2 tables 'comments_by_user' and 'comments_by_video'. 14 | */ 15 | @Dao 16 | public interface CommentDao extends SchemaConstants { 17 | 18 | @Query("SELECT * FROM ${keyspaceId}.${tableId} " 19 | + "WHERE " + COMMENT_BY_USER_USERID + " = :userid ") 20 | PagingIterable retrieveUserComments(UUID userid); 21 | 22 | @Query("SELECT * FROM ${keyspaceId}.${tableId} " 23 | + "WHERE " + COMMENT_BY_VIDEO_VIDEOID + " = :videoid ") 24 | PagingIterable retrieveVideoComments(UUID videoid); 25 | 26 | @QueryProvider( 27 | providerClass = CommentDaoQueryProvider.class, 28 | entityHelpers = { CommentByUser.class, CommentByVideo.class}) 29 | void upsert(Comment comment); 30 | 31 | @QueryProvider( 32 | providerClass = CommentDaoQueryProvider.class, 33 | entityHelpers = { CommentByUser.class, CommentByVideo.class}) 34 | void delete(Comment res); 35 | } 36 | -------------------------------------------------------------------------------- /lab-micronaut/src/test/java/com/datastaxdev/E01_MicronautInitTest.java: -------------------------------------------------------------------------------- 1 | package com.datastaxdev; 2 | 3 | import org.junit.jupiter.api.Assertions; 4 | import org.junit.jupiter.api.Test; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | 8 | import com.datastax.oss.driver.api.core.CqlSession; 9 | 10 | import io.micronaut.context.BeanContext; 11 | import io.micronaut.context.annotation.Property; 12 | import io.micronaut.runtime.EmbeddedApplication; 13 | import io.micronaut.test.extensions.junit5.annotation.MicronautTest; 14 | import jakarta.inject.Inject; 15 | 16 | @MicronautTest(application=TodoApplication.class) 17 | public class E01_MicronautInitTest { 18 | 19 | @Inject 20 | EmbeddedApplication application; 21 | 22 | /** Logger for the class. */ 23 | static Logger LOGGER = LoggerFactory.getLogger(E01_MicronautInitTest.class); 24 | 25 | @Inject 26 | BeanContext beanContext; 27 | 28 | @Inject 29 | CqlSession cqlSession; 30 | 31 | @Inject 32 | @Property(name = "cassandra.default.basic.session-keyspace") 33 | String keyspace; 34 | 35 | @Test 36 | public void testConnectCassandra() { 37 | LOGGER.info("Creating your CqlSession to Cassandra..."); 38 | Assertions.assertNotNull(beanContext); 39 | Assertions.assertNotNull(cqlSession); 40 | Assertions.assertTrue(cqlSession.getKeyspace().isPresent()); 41 | LOGGER.info("+ [OK] Your are connected to keyspace {}", cqlSession.getKeyspace().get()); 42 | Assertions.assertEquals(keyspace, cqlSession.getKeyspace().get().toString()); 43 | } 44 | 45 | 46 | } 47 | -------------------------------------------------------------------------------- /lab-spring/src/test/java/com/datastax/todo/E04_SpringControllerTest.java: -------------------------------------------------------------------------------- 1 | package com.datastax.todo; 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.context.SpringBootTest.WebEnvironment; 7 | import org.springframework.boot.test.web.client.TestRestTemplate; 8 | import org.springframework.boot.test.web.server.LocalServerPort; 9 | import org.springframework.http.HttpEntity; 10 | import org.springframework.http.HttpHeaders; 11 | import org.springframework.http.HttpMethod; 12 | import org.springframework.http.HttpStatus; 13 | import org.springframework.util.StringUtils; 14 | 15 | import com.datastax.todo.todo.Todo; 16 | 17 | /** 18 | * Implementation of integration test 19 | * 20 | * @author Cedrick LUNVEN (@clunven) 21 | */ 22 | @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) 23 | public class E04_SpringControllerTest { 24 | 25 | public static String SPRING_DATA_URL = System.getenv("SPRING_DATA_URL"); 26 | 27 | @LocalServerPort 28 | public int port; 29 | 30 | @Test 31 | public void should_retrieve_todolist() { 32 | System.out.println(port); 33 | if (!StringUtils.hasLength(SPRING_DATA_URL)) { 34 | SPRING_DATA_URL = "http://localhost:" + port; 35 | } 36 | Assertions.assertEquals(HttpStatus.OK, 37 | new TestRestTemplate().exchange(SPRING_DATA_URL + "/api/v1/todos/", 38 | HttpMethod.GET, new HttpEntity(null, new HttpHeaders()), 39 | Todo[].class).getStatusCode()); 40 | } 41 | 42 | } 43 | 44 | -------------------------------------------------------------------------------- /lab-micronaut/src/main/java/com/datastaxdev/TodoService.java: -------------------------------------------------------------------------------- 1 | package com.datastaxdev; 2 | 3 | import java.util.List; 4 | import java.util.Optional; 5 | import java.util.UUID; 6 | 7 | /** 8 | * Definition of services to work with the Todo Application. 9 | * 10 | * @author Cedrick Lunven (@clunven) 11 | */ 12 | public interface TodoService { 13 | 14 | /** 15 | * Save Todoitems. 16 | * 17 | * @param todo 18 | * list of todos 19 | * @return 20 | * updated todo with if if relevant 21 | */ 22 | TodoDto save(TodoDto todo); 23 | 24 | /** 25 | * Retrieve an task by its itentifier. 26 | * 27 | * @param userId 28 | * userId 29 | * @param itemId 30 | * itemId 31 | * @return 32 | * if the Task exists 33 | */ 34 | Optional findById(String userId, UUID itemId); 35 | 36 | /** 37 | * Retrieve the list of Tasks for a user (if exist). 38 | * 39 | * @param userId 40 | * user identifier 41 | * @return 42 | * list of Tasks for the user 43 | */ 44 | List findByUser(String userId); 45 | 46 | /** 47 | * Delete a task from its identifier 48 | * 49 | * @param userId 50 | * user identifer 51 | * @param itemId 52 | * item identifier 53 | */ 54 | void deleteById(String userId, UUID itemId); 55 | 56 | /** 57 | * Delete all tasks for a user. 58 | * 59 | * @param userId 60 | * user identifier 61 | */ 62 | void deleteByUser(String userId); 63 | 64 | /** 65 | * Clean DB. 66 | */ 67 | void deleteAll(); 68 | 69 | } 70 | -------------------------------------------------------------------------------- /lab-quarkus/src/main/java/com/datastaxdev/todo/TodoService.java: -------------------------------------------------------------------------------- 1 | package com.datastaxdev.todo; 2 | 3 | import java.util.List; 4 | import java.util.Optional; 5 | import java.util.UUID; 6 | 7 | /** 8 | * Definition of services to work with the Todo Application. 9 | * 10 | * @author Cedrick Lunven (@clunven) 11 | */ 12 | public interface TodoService { 13 | 14 | /** 15 | * Save Todoitems. 16 | * 17 | * @param todo 18 | * list of todos 19 | * @return 20 | * updated todo with if if relevant 21 | */ 22 | TodoDto save(TodoDto todo); 23 | 24 | /** 25 | * Retrieve an task by its itentifier. 26 | * 27 | * @param userId 28 | * userId 29 | * @param itemId 30 | * itemId 31 | * @return 32 | * if the Task exists 33 | */ 34 | Optional findById(String userId, UUID itemId); 35 | 36 | /** 37 | * Retrieve the list of Tasks for a user (if exist). 38 | * 39 | * @param userId 40 | * user identifier 41 | * @return 42 | * list of Tasks for the user 43 | */ 44 | List findByUser(String userId); 45 | 46 | /** 47 | * Delete a task from its identifier 48 | * 49 | * @param userId 50 | * user identifer 51 | * @param itemId 52 | * item identifier 53 | */ 54 | void deleteById(String userId, UUID itemId); 55 | 56 | /** 57 | * Delete all tasks for a user. 58 | * 59 | * @param userId 60 | * user identifier 61 | */ 62 | void deleteByUser(String userId); 63 | 64 | /** 65 | * Clean DB. 66 | */ 67 | void deleteAll(); 68 | 69 | } 70 | -------------------------------------------------------------------------------- /lab-cassandra-drivers/src/test/java/com/datastax/devoxx/E01_CreateSchemaTest.java: -------------------------------------------------------------------------------- 1 | package com.datastax.devoxx; 2 | 3 | import static com.datastax.devoxx.schema.SchemaUtils.createTableCommentByUser; 4 | import static com.datastax.devoxx.schema.SchemaUtils.createTableCommentByVideo; 5 | import static com.datastax.devoxx.schema.SchemaUtils.createTableUser; 6 | import static com.datastax.devoxx.schema.SchemaUtils.createTableVideo; 7 | import static com.datastax.devoxx.schema.SchemaUtils.createTableVideoViews; 8 | import static com.datastax.devoxx.schema.SchemaUtils.createUdtVideoFormat; 9 | 10 | import org.junit.jupiter.api.Test; 11 | import org.slf4j.Logger; 12 | import org.slf4j.LoggerFactory; 13 | 14 | import com.datastax.devoxx.schema.SchemaConstants; 15 | /** 16 | * Sample code to create tables, types and objects in a keyspace. 17 | * 18 | * Pre-requisites: 19 | * - Cassandra running locally (127.0.0.1, port 9042) 20 | * - Keyspace killrvideo created {@link SampleCode4x_CONNECT_CreateKeyspace} 21 | */ 22 | import com.datastax.oss.driver.api.core.CqlSession; 23 | 24 | public class E01_CreateSchemaTest implements SchemaConstants { 25 | 26 | private static Logger LOGGER = LoggerFactory.getLogger(E01_CreateSchemaTest.class); 27 | 28 | @Test 29 | public void should_create_schema() { 30 | try(CqlSession cqlSession = CqlSession.builder().build()) { 31 | createUdtVideoFormat(cqlSession); 32 | createTableUser(cqlSession); 33 | createTableVideo(cqlSession); 34 | createTableVideoViews(cqlSession); 35 | createTableCommentByVideo(cqlSession); 36 | createTableCommentByUser(cqlSession); 37 | } 38 | LOGGER.info("[OK] Success"); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /lab-spring/src/test/java/com/datastax/todo/E03_SpringDataCassandraOperationsTest.java: -------------------------------------------------------------------------------- 1 | package com.datastax.todo; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.boot.test.context.SpringBootTest; 8 | import org.springframework.data.cassandra.core.CassandraOperations; 9 | 10 | import com.datastax.oss.driver.api.core.CqlSession; 11 | import com.datastax.todo.todo.TodoEntity; 12 | import com.datastax.todo.todo.TodoRepositorySimpleCassandra; 13 | 14 | @SpringBootTest 15 | public class E03_SpringDataCassandraOperationsTest { 16 | 17 | /** Logger for the class. */ 18 | static Logger LOGGER = LoggerFactory.getLogger(E02_SpringDataRepositoryTest.class); 19 | 20 | @Autowired 21 | CassandraOperations cassandraOps; 22 | 23 | @Autowired 24 | CqlSession cqlSession; 25 | 26 | @Autowired 27 | TodoRepositorySimpleCassandra todoRepoSimple; 28 | 29 | @Test 30 | public void testCassandraOperations() { 31 | LOGGER.info("Utilisation de CassandraOperations"); 32 | cassandraOps.select("select * from todos", TodoEntity.class) 33 | .stream() 34 | .map(Object::toString) 35 | .forEach(LOGGER::info); 36 | } 37 | 38 | @Test 39 | public void testSimpleCassandraRepository() { 40 | //TodoRepositorySimpleCassandra todoRepoSimple = 41 | // new TodoRepositorySimpleCassandra(cqlSession, cassandraOps); 42 | TodoEntity e = todoRepoSimple.save(new TodoEntity("Apprendre Cassandra", 0)); 43 | LOGGER.info("Tache enregistree avec id {}", e.getUid()); 44 | 45 | LOGGER.info("Liste des Taches"); 46 | todoRepoSimple.findAll().stream().map(Object::toString).forEach(LOGGER::info); 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /.gitpod.yml: -------------------------------------------------------------------------------- 1 | image: 2 | file: .gitpod.Dockerfile 3 | 4 | tasks: 5 | - name: setup 6 | before: | 7 | chmod 700 /workspace/conference-2022-devoxx/setup/start 8 | chmod 700 /workspace/conference-2022-devoxx/setup/tests 9 | sdk install micronaut 10 | docker pull cassandra:4.0.6 11 | init: | 12 | sed -i '1,$s/sdkman_auto_answer=false/sdkman_auto_answer=true/' /home/gitpod/.sdkman/etc/config 13 | sed -i '1,$s/sdkman_selfupdate_enable=true/sdkman_selfupdate_enable=false/' /home/gitpod/.sdkman/etc/config 14 | sdk install java 22.1.0.r17-grl -y 15 | gu install native-image 16 | cd /workspace/conference-2022-devoxx/ 17 | command: | 18 | clear 19 | /workspace/conference-2022-devoxx/setup/start 20 | - name: tests 21 | command: | 22 | clear 23 | /workspace/conference-2022-devoxx/setup/tests 24 | 25 | ports: 26 | # Cassandra Node in Docker 27 | - port: 9042 28 | onOpen: ignore 29 | visibility: public 30 | # Spring Application 31 | - port: 8080 32 | onOpen: open-browser 33 | visibility: public 34 | # Quarkus Application 35 | - port: 8081 36 | onOpen: open-browser 37 | visibility: public 38 | # Micronaut Application 39 | - port: 5005 40 | onOpen: ignore 41 | visibility: public 42 | # Micronaut Application 43 | - port: 8082 44 | onOpen: open-browser 45 | visibility: public 46 | 47 | github: 48 | prebuilds: 49 | master: true 50 | branches: true 51 | pullRequests: true 52 | pullRequestsFromForks: false 53 | addCheck: true 54 | addComment: false 55 | addBadge: true 56 | addLabel: false 57 | 58 | vscode: 59 | extensions: 60 | # Lombok 61 | - GabrielBB.vscode-lombok 62 | # Java 63 | - vscjava.vscode-java-pack 64 | # Spring Boot 65 | - Pivotal.vscode-boot-dev-pack 66 | # Docker Containers 67 | - ms-azuretools.vscode-docker 68 | 69 | -------------------------------------------------------------------------------- /lab-cassandra-drivers/src/test/java/com/datastax/devoxx/E00_ConnectivityTest.java: -------------------------------------------------------------------------------- 1 | package com.datastax.devoxx; 2 | 3 | import java.net.InetSocketAddress; 4 | 5 | import org.junit.jupiter.api.Assertions; 6 | import org.junit.jupiter.api.DisplayName; 7 | import org.junit.jupiter.api.Test; 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | 11 | import com.datastax.oss.driver.api.core.CqlSession; 12 | 13 | /** 14 | * Connect to your cluster. 15 | * 16 | * @author Cedrick LUNVEN (@clunven) 17 | */ 18 | public class E00_ConnectivityTest { 19 | 20 | private static Logger LOGGER = 21 | LoggerFactory.getLogger(E00_ConnectivityTest.class); 22 | 23 | @Test 24 | @DisplayName("Explicit connection") 25 | public void should_connect_to_cluster_explicit() { 26 | try (CqlSession cqlSession = CqlSession.builder() 27 | .addContactPoint(new InetSocketAddress("127.0.0.1", 9042)) 28 | .withKeyspace("devoxx") 29 | //.withLocalDatacenter("dc1") 30 | .build()) { 31 | displaySession(cqlSession); 32 | Assertions.assertTrue(cqlSession.getKeyspace().isPresent()); 33 | } 34 | } 35 | 36 | @Test 37 | @DisplayName("Connect to Cassandra Cluster") 38 | public void should_connect_to_cluster() { 39 | try(CqlSession cqlSession = CqlSession.builder().build()) { 40 | displaySession(cqlSession); 41 | Assertions.assertTrue(cqlSession.getKeyspace().isPresent()); 42 | } 43 | } 44 | 45 | /** 46 | * Mutualize test code 47 | * @param cqlSession 48 | * cql session 49 | */ 50 | private void displaySession(CqlSession cqlSession) { 51 | cqlSession.getMetadata() 52 | .getNodes() 53 | .entrySet() 54 | .stream() 55 | .forEach(e -> LOGGER.info("Node {} listening at {}" , 56 | e.getKey(), 57 | e.getValue().getEndPoint().toString())); 58 | LOGGER.info("[SUCCESS]"); 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /lab-quarkus/src/main/docker/Dockerfile.jvm: -------------------------------------------------------------------------------- 1 | #### 2 | # This Dockerfile is used in order to build a container that runs the Quarkus application in JVM mode 3 | # 4 | # Before building the docker image run: 5 | # 6 | # mvn package 7 | # 8 | # Then, build the image with: 9 | # 10 | # docker build -f src/main/docker/Dockerfile.jvm -t quarkus/my-artifactId-jvm . 11 | # 12 | # Then run the container using: 13 | # 14 | # docker run -i --rm -p 8080:8080 quarkus/my-artifactId-jvm 15 | # 16 | # If you want to include the debug port into your docker image 17 | # you will have to expose the debug port (default 5005) like this : EXPOSE 8080 5050 18 | # 19 | # Then run the container using : 20 | # 21 | # docker run -i --rm -p 8080:8080 -p 5005:5005 -e JAVA_ENABLE_DEBUG="true" quarkus/my-artifactId-jvm 22 | # 23 | ### 24 | FROM registry.access.redhat.com/ubi8/ubi-minimal:8.1 25 | 26 | ARG JAVA_PACKAGE=java-11-openjdk-headless 27 | ARG RUN_JAVA_VERSION=1.3.8 28 | 29 | ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en' 30 | 31 | # Install java and the run-java script 32 | # Also set up permissions for user `1001` 33 | RUN microdnf install curl ca-certificates ${JAVA_PACKAGE} \ 34 | && microdnf update \ 35 | && microdnf clean all \ 36 | && mkdir /deployments \ 37 | && chown 1001 /deployments \ 38 | && chmod "g+rwX" /deployments \ 39 | && chown 1001:root /deployments \ 40 | && curl https://repo1.maven.org/maven2/io/fabric8/run-java-sh/${RUN_JAVA_VERSION}/run-java-sh-${RUN_JAVA_VERSION}-sh.sh -o /deployments/run-java.sh \ 41 | && chown 1001 /deployments/run-java.sh \ 42 | && chmod 540 /deployments/run-java.sh \ 43 | && echo "securerandom.source=file:/dev/urandom" >> /etc/alternatives/jre/lib/security/java.security 44 | 45 | # Configure the JAVA_OPTIONS, you can add -XshowSettings:vm to also display the heap size. 46 | ENV JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager" 47 | 48 | COPY target/lib/* /deployments/lib/ 49 | COPY target/*-runner.jar /deployments/app.jar 50 | 51 | EXPOSE 8080 52 | USER 1001 53 | 54 | ENTRYPOINT [ "/deployments/run-java.sh" ] -------------------------------------------------------------------------------- /lab-micronaut/src/main/java/com/datastaxdev/TodoDto.java: -------------------------------------------------------------------------------- 1 | package com.datastaxdev; 2 | 3 | import java.util.UUID; 4 | 5 | public class TodoDto { 6 | 7 | private String userId; 8 | private UUID itemId; 9 | private String title; 10 | private Boolean completed; 11 | 12 | /** 13 | * Getter accessor for attribute 'userId'. 14 | * 15 | * @return 16 | * current value of 'userId' 17 | */ 18 | public String getUserId() { 19 | return userId; 20 | } 21 | /** 22 | * Setter accessor for attribute 'userId'. 23 | * @param userId 24 | * new value for 'userId ' 25 | */ 26 | public void setUserId(String userId) { 27 | this.userId = userId; 28 | } 29 | /** 30 | * Getter accessor for attribute 'itemId'. 31 | * 32 | * @return 33 | * current value of 'itemId' 34 | */ 35 | public UUID getItemId() { 36 | return itemId; 37 | } 38 | /** 39 | * Setter accessor for attribute 'itemId'. 40 | * @param itemId 41 | * new value for 'itemId ' 42 | */ 43 | public void setItemId(UUID itemId) { 44 | this.itemId = itemId; 45 | } 46 | /** 47 | * Getter accessor for attribute 'title'. 48 | * 49 | * @return 50 | * current value of 'title' 51 | */ 52 | public String getTitle() { 53 | return title; 54 | } 55 | /** 56 | * Setter accessor for attribute 'title'. 57 | * @param title 58 | * new value for 'title ' 59 | */ 60 | public void setTitle(String title) { 61 | this.title = title; 62 | } 63 | /** 64 | * Getter accessor for attribute 'completed'. 65 | * 66 | * @return 67 | * current value of 'completed' 68 | */ 69 | public Boolean getCompleted() { 70 | return completed; 71 | } 72 | /** 73 | * Setter accessor for attribute 'completed'. 74 | * @param completed 75 | * new value for 'completed ' 76 | */ 77 | public void setCompleted(Boolean completed) { 78 | this.completed = completed; 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /lab-quarkus/src/main/java/com/datastaxdev/todo/TodoDto.java: -------------------------------------------------------------------------------- 1 | package com.datastaxdev.todo; 2 | 3 | import java.util.UUID; 4 | 5 | public class TodoDto { 6 | 7 | private String userId; 8 | private UUID itemId; 9 | private String title; 10 | private Boolean completed; 11 | 12 | /** 13 | * Getter accessor for attribute 'userId'. 14 | * 15 | * @return 16 | * current value of 'userId' 17 | */ 18 | public String getUserId() { 19 | return userId; 20 | } 21 | /** 22 | * Setter accessor for attribute 'userId'. 23 | * @param userId 24 | * new value for 'userId ' 25 | */ 26 | public void setUserId(String userId) { 27 | this.userId = userId; 28 | } 29 | /** 30 | * Getter accessor for attribute 'itemId'. 31 | * 32 | * @return 33 | * current value of 'itemId' 34 | */ 35 | public UUID getItemId() { 36 | return itemId; 37 | } 38 | /** 39 | * Setter accessor for attribute 'itemId'. 40 | * @param itemId 41 | * new value for 'itemId ' 42 | */ 43 | public void setItemId(UUID itemId) { 44 | this.itemId = itemId; 45 | } 46 | /** 47 | * Getter accessor for attribute 'title'. 48 | * 49 | * @return 50 | * current value of 'title' 51 | */ 52 | public String getTitle() { 53 | return title; 54 | } 55 | /** 56 | * Setter accessor for attribute 'title'. 57 | * @param title 58 | * new value for 'title ' 59 | */ 60 | public void setTitle(String title) { 61 | this.title = title; 62 | } 63 | /** 64 | * Getter accessor for attribute 'completed'. 65 | * 66 | * @return 67 | * current value of 'completed' 68 | */ 69 | public Boolean getCompleted() { 70 | return completed; 71 | } 72 | /** 73 | * Setter accessor for attribute 'completed'. 74 | * @param completed 75 | * new value for 'completed ' 76 | */ 77 | public void setCompleted(Boolean completed) { 78 | this.completed = completed; 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /lab-cassandra-drivers/src/main/java/com/datastax/devoxx/codec/BytesArrayTypeCodec.java: -------------------------------------------------------------------------------- 1 | package com.datastax.devoxx.codec; 2 | 3 | import java.nio.ByteBuffer; 4 | import java.nio.charset.Charset; 5 | import java.nio.charset.StandardCharsets; 6 | 7 | import com.datastax.oss.driver.api.core.ProtocolVersion; 8 | import com.datastax.oss.driver.api.core.type.DataType; 9 | import com.datastax.oss.driver.api.core.type.DataTypes; 10 | import com.datastax.oss.driver.api.core.type.codec.TypeCodec; 11 | import com.datastax.oss.driver.api.core.type.reflect.GenericType; 12 | 13 | /** 14 | * Retrieve a blob as a byte array from Cassandra. 15 | */ 16 | public class BytesArrayTypeCodec implements TypeCodec { 17 | 18 | private Charset charSet = StandardCharsets.UTF_8; 19 | 20 | public BytesArrayTypeCodec(Charset charSet) { 21 | this.charSet = charSet; 22 | } 23 | 24 | /** Default constructor. */ 25 | public BytesArrayTypeCodec() { 26 | this(StandardCharsets.UTF_8); 27 | } 28 | 29 | /** {@inheritDoc} */ 30 | @Override 31 | public GenericType getJavaType() { 32 | return GenericType.of(byte[].class); 33 | } 34 | 35 | /** {@inheritDoc} */ 36 | @Override 37 | public DataType getCqlType() { 38 | return DataTypes.BLOB; 39 | } 40 | 41 | /** {@inheritDoc} */ 42 | @Override 43 | public ByteBuffer encode(byte[] value, ProtocolVersion protocolVersion) { 44 | if (value == null) return null; 45 | ByteBuffer byteBuffer = ByteBuffer.allocate(value.length); 46 | byteBuffer.put(value); 47 | return byteBuffer; 48 | } 49 | 50 | /** {@inheritDoc} */ 51 | @Override 52 | public byte[] decode(ByteBuffer byteBuffer, ProtocolVersion protocolVersion) { 53 | if (byteBuffer == null) return null; 54 | byte[] bytesArray = new byte[byteBuffer.remaining()]; 55 | byteBuffer.get(bytesArray, 0, bytesArray.length); 56 | return bytesArray; 57 | } 58 | 59 | /** {@inheritDoc} */ 60 | @Override 61 | public String format(byte[] value) { 62 | if (value == null) return "NULL"; 63 | return new String(value, charSet); 64 | } 65 | 66 | /** {@inheritDoc} */ 67 | @Override 68 | public byte[] parse(String value) { 69 | return (value == null || value.isEmpty() || value.equalsIgnoreCase("NULL")) 70 | ? null 71 | : value.getBytes(charSet); 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /lab-quarkus/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | quarkus.http.port=8081 2 | quarkus.container-image.registry=docker.io 3 | quarkus.profile=dev 4 | quarkus.container-image.name=quarkus-cassandra 5 | quarkus.kubernetes.service-type=load-balancer 6 | quarkus.cassandra.init.eager-init=true 7 | 8 | # Authentication 9 | quarkus.cassandra.contact-points=localhost:9042 10 | quarkus.cassandra.local-datacenter=dc1 11 | quarkus.cassandra.keyspace=devoxx_quarkus 12 | 13 | # Health Checks 14 | quarkus.cassandra.health.enabled=true 15 | 16 | # Metrics 17 | # See https://docs.datastax.com/en/developer/java-driver/latest/manual/core/metrics/ 18 | quarkus.cassandra.metrics.enabled=true 19 | quarkus.cassandra.metrics.session.enabled=\ 20 | bytes-sent,\ 21 | bytes-received,\ 22 | connected-nodes,\ 23 | cql-requests,\ 24 | cql-client-timeouts 25 | quarkus.cassandra.metrics.node.enabled=\ 26 | pool.open-connections,\ 27 | pool.in-flight,\ 28 | bytes-sent,\ 29 | bytes-received,\ 30 | cql-messages,\ 31 | errors.request.unsent,\ 32 | errors.request.aborted,\ 33 | errors.request.write-timeouts,\ 34 | errors.request.read-timeouts,\ 35 | errors.request.unavailables,\ 36 | errors.request.others,\ 37 | retries.total,\ 38 | retries.aborted,\ 39 | retries.read-timeout,\ 40 | retries.write-timeout,\ 41 | retries.unavailable,\ 42 | retries.other,\ 43 | ignores.total,\ 44 | ignores.aborted,\ 45 | ignores.read-timeout,\ 46 | ignores.write-timeout,\ 47 | ignores.unavailable,\ 48 | ignores.other,\ 49 | errors.connection.init,\ 50 | errors.connection.auth 51 | 52 | # Request properties 53 | #quarkus.cassandra.request.timeout=PT10S 54 | #quarkus.cassandra.request.consistency-level=LOCAL_QUORUM 55 | #quarkus.cassandra.request.serial-consistency-level=LOCAL_SERIAL 56 | #quarkus.cassandra.request.page-size=5000 57 | #quarkus.cassandra.request.default-idempotence=true 58 | 59 | # Protocol settings 60 | #quarkus.cassandra.protocol.compression=none 61 | 62 | # Startup and Initialization settings 63 | #quarkus.cassandra.init.eager-init=false 64 | #quarkus.cassandra.init.eager-init-timeout=PT10S 65 | #quarkus.cassandra.init.print-eager-init-info=true 66 | #quarkus.cassandra.init.reconnect-on-init=true 67 | #quarkus.cassandra.init.resolve-contact-points=false 68 | #quarkus.cassandra.init.use-quarkus-event-loop=true 69 | 70 | # Logging 71 | #quarkus.log.level=INFO 72 | #quarkus.log.min-level=DEBUG 73 | #quarkus.log.category."com.datastax.oss.quarkus".level=INFO 74 | #quarkus.log.category."com.datastax.oss.driver".level=INFO 75 | #quarkus.log.category."com.datastax.dse.driver".level=INFO 76 | 77 | -------------------------------------------------------------------------------- /lab-cassandra-drivers/src/main/java/com/datastax/devoxx/dto/UserDto.java: -------------------------------------------------------------------------------- 1 | package com.datastax.devoxx.dto; 2 | 3 | import java.io.Serializable; 4 | 5 | import com.datastax.devoxx.schema.SchemaConstants; 6 | import com.datastax.oss.driver.api.core.cql.Row; 7 | 8 | /** 9 | * Sample bean for row. 10 | */ 11 | public class UserDto implements Serializable, SchemaConstants { 12 | 13 | /** Serial. */ 14 | private static final long serialVersionUID = -6767335554891314036L; 15 | 16 | private String email; 17 | 18 | private String firstName; 19 | 20 | private String lastName; 21 | 22 | public UserDto() { 23 | } 24 | 25 | public UserDto(Row tableUsersRow) { 26 | super(); 27 | this.email = tableUsersRow.getString(USER_EMAIL); 28 | this.firstName = tableUsersRow.getString(USER_FIRSTNAME); 29 | this.lastName = tableUsersRow.getString(USER_LASTNAME); 30 | } 31 | 32 | public UserDto(String email, String firstName, String lastName) { 33 | super(); 34 | this.email = email; 35 | this.firstName = firstName; 36 | this.lastName = lastName; 37 | } 38 | 39 | /** 40 | * Getter accessor for attribute 'email'. 41 | * 42 | * @return 43 | * current value of 'email' 44 | */ 45 | public String getEmail() { 46 | return email; 47 | } 48 | 49 | /** 50 | * Setter accessor for attribute 'email'. 51 | * @param email 52 | * new value for 'email ' 53 | */ 54 | public void setEmail(String email) { 55 | this.email = email; 56 | } 57 | 58 | /** 59 | * Getter accessor for attribute 'firstName'. 60 | * 61 | * @return 62 | * current value of 'firstName' 63 | */ 64 | public String getFirstName() { 65 | return firstName; 66 | } 67 | 68 | /** 69 | * Setter accessor for attribute 'firstName'. 70 | * @param firstName 71 | * new value for 'firstName ' 72 | */ 73 | public void setFirstName(String firstName) { 74 | this.firstName = firstName; 75 | } 76 | 77 | /** 78 | * Getter accessor for attribute 'lastName'. 79 | * 80 | * @return 81 | * current value of 'lastName' 82 | */ 83 | public String getLastName() { 84 | return lastName; 85 | } 86 | 87 | /** 88 | * Setter accessor for attribute 'lastName'. 89 | * @param lastName 90 | * new value for 'lastName ' 91 | */ 92 | public void setLastName(String lastName) { 93 | this.lastName = lastName; 94 | } 95 | 96 | } 97 | -------------------------------------------------------------------------------- /lab-cassandra-drivers/src/main/java/com/datastax/devoxx/dto/FileDto.java: -------------------------------------------------------------------------------- 1 | package com.datastax.devoxx.dto; 2 | 3 | import java.io.Serializable; 4 | import java.nio.ByteBuffer; 5 | import java.time.Instant; 6 | 7 | /** 8 | * Sample POJO. 9 | */ 10 | public class FileDto implements Serializable { 11 | 12 | /** Serial. */ 13 | private static final long serialVersionUID = 7325306650146053028L; 14 | 15 | private String filename; 16 | 17 | private String extension; 18 | 19 | private Instant updload; 20 | 21 | private ByteBuffer content; 22 | 23 | public FileDto() { 24 | } 25 | 26 | /** 27 | * Getter accessor for attribute 'filename'. 28 | * 29 | * @return 30 | * current value of 'filename' 31 | */ 32 | public String getFilename() { 33 | return filename; 34 | } 35 | 36 | /** 37 | * Setter accessor for attribute 'filename'. 38 | * @param filename 39 | * new value for 'filename ' 40 | */ 41 | public void setFilename(String filename) { 42 | this.filename = filename; 43 | } 44 | 45 | /** 46 | * Getter accessor for attribute 'extension'. 47 | * 48 | * @return 49 | * current value of 'extension' 50 | */ 51 | public String getExtension() { 52 | return extension; 53 | } 54 | 55 | /** 56 | * Setter accessor for attribute 'extension'. 57 | * @param extension 58 | * new value for 'extension ' 59 | */ 60 | public void setExtension(String extension) { 61 | this.extension = extension; 62 | } 63 | 64 | /** 65 | * Getter accessor for attribute 'updload'. 66 | * 67 | * @return 68 | * current value of 'updload' 69 | */ 70 | public Instant getUpload() { 71 | return updload; 72 | } 73 | 74 | /** 75 | * Setter accessor for attribute 'updload'. 76 | * @param updload 77 | * new value for 'updload ' 78 | */ 79 | public void setUpload(Instant updload) { 80 | this.updload = updload; 81 | } 82 | 83 | /** 84 | * Getter accessor for attribute 'content'. 85 | * 86 | * @return 87 | * current value of 'content' 88 | */ 89 | public ByteBuffer getContent() { 90 | return content; 91 | } 92 | 93 | /** 94 | * Setter accessor for attribute 'content'. 95 | * @param content 96 | * new value for 'content ' 97 | */ 98 | public void setContent(ByteBuffer content) { 99 | this.content = content; 100 | } 101 | 102 | 103 | 104 | } 105 | -------------------------------------------------------------------------------- /lab-spring/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | com.datastax 6 | lab-spring 7 | 0.0.1-SNAPSHOT 8 | lab-spring 9 | SpringBoot3 Spring6 10 | 11 | 12 | org.springframework.boot 13 | spring-boot-starter-parent 14 | 3.0.0-SNAPSHOT 15 | 16 | 17 | 18 | 19 | 17 20 | 21 | 22 | 23 | 24 | 25 | org.springframework.boot 26 | spring-boot-starter-web 27 | 28 | 29 | 30 | org.springframework.boot 31 | spring-boot-starter-data-cassandra 32 | 33 | 34 | net.jpountz.lz4 35 | lz4 36 | 1.3 37 | 38 | 39 | 40 | org.springframework.boot 41 | spring-boot-starter-test 42 | test 43 | 44 | 45 | 46 | 47 | 48 | 49 | org.springframework.boot 50 | spring-boot-maven-plugin 51 | 52 | 53 | 54 | 55 | 56 | spring-milestones 57 | Spring Milestones 58 | https://repo.spring.io/milestone 59 | 60 | false 61 | 62 | 63 | 64 | spring-snapshots 65 | Spring Snapshots 66 | https://repo.spring.io/snapshot 67 | 68 | false 69 | 70 | 71 | 72 | 73 | 74 | spring-milestones 75 | Spring Milestones 76 | https://repo.spring.io/milestone 77 | 78 | false 79 | 80 | 81 | 82 | spring-snapshots 83 | Spring Snapshots 84 | https://repo.spring.io/snapshot 85 | 86 | false 87 | 88 | 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /lab-cassandra-drivers/src/main/java/com/datastax/devoxx/codec/UdtVideoFormatCodec.java: -------------------------------------------------------------------------------- 1 | package com.datastax.devoxx.codec; 2 | 3 | import java.nio.ByteBuffer; 4 | 5 | import com.datastax.devoxx.dto.VideoFormatDto; 6 | import com.datastax.devoxx.schema.SchemaConstants; 7 | import com.datastax.oss.driver.api.core.ProtocolVersion; 8 | import com.datastax.oss.driver.api.core.data.UdtValue; 9 | import com.datastax.oss.driver.api.core.type.DataType; 10 | import com.datastax.oss.driver.api.core.type.UserDefinedType; 11 | import com.datastax.oss.driver.api.core.type.codec.TypeCodec; 12 | import com.datastax.oss.driver.api.core.type.reflect.GenericType; 13 | 14 | /** 15 | * Codec. 16 | */ 17 | public class UdtVideoFormatCodec implements TypeCodec, SchemaConstants { 18 | 19 | final TypeCodec innerCodec; 20 | 21 | final UserDefinedType videoFormatUdt; 22 | 23 | public UdtVideoFormatCodec(TypeCodec innerCodec, Class javaType) { 24 | this.innerCodec = innerCodec; 25 | this.videoFormatUdt = (UserDefinedType) innerCodec.getCqlType(); 26 | } 27 | 28 | /** {@inheritDoc} */ 29 | @Override 30 | public GenericType getJavaType() { 31 | return GenericType.of(VideoFormatDto.class); 32 | } 33 | 34 | /** {@inheritDoc} */ 35 | @Override 36 | public DataType getCqlType() { 37 | return videoFormatUdt; 38 | } 39 | 40 | /** {@inheritDoc} */ 41 | @Override 42 | public ByteBuffer encode(VideoFormatDto value, ProtocolVersion protocolVersion) { 43 | return innerCodec.encode(toUDTValue(value), protocolVersion); 44 | } 45 | 46 | /** {@inheritDoc} */ 47 | @Override 48 | public VideoFormatDto decode(ByteBuffer bytes, ProtocolVersion protocolVersion) { 49 | return toVideoFormatDto(innerCodec.decode(bytes, protocolVersion)); 50 | } 51 | 52 | /** {@inheritDoc} */ 53 | @Override 54 | public String format(VideoFormatDto value) { 55 | return value == null ? "NULL" : innerCodec.format(toUDTValue(value)); 56 | } 57 | 58 | /** {@inheritDoc} */ 59 | @Override 60 | public VideoFormatDto parse(String value) { 61 | return value == null || value.isEmpty() || value.equalsIgnoreCase("NULL") ? 62 | null : toVideoFormatDto(innerCodec.parse(value)); 63 | } 64 | 65 | protected VideoFormatDto toVideoFormatDto(UdtValue value) { 66 | return value == null ? null : new VideoFormatDto( 67 | value.getInt(UDT_VIDEO_FORMAT_WIDTH), 68 | value.getInt(UDT_VIDEO_FORMAT_HEIGHT) 69 | ); 70 | } 71 | 72 | protected UdtValue toUDTValue(VideoFormatDto value) { 73 | return value == null ? null : videoFormatUdt.newValue() 74 | .setInt(UDT_VIDEO_FORMAT_WIDTH, value.getWidth()) 75 | .setInt(UDT_VIDEO_FORMAT_HEIGHT, value.getHeight()); 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /lab-micronaut/src/main/java/com/datastaxdev/todo/cassandra/TodoServicesCassandraOM.java: -------------------------------------------------------------------------------- 1 | package com.datastaxdev.todo.cassandra; 2 | 3 | import java.util.List; 4 | import java.util.Optional; 5 | import java.util.UUID; 6 | import java.util.stream.Collectors; 7 | 8 | import com.datastax.oss.driver.api.core.CqlSession; 9 | import com.datastax.oss.driver.api.core.uuid.Uuids; 10 | import com.datastax.oss.driver.api.mapper.annotations.Query; 11 | import com.datastaxdev.TodoDto; 12 | import com.datastaxdev.TodoService; 13 | 14 | import jakarta.inject.Singleton; 15 | 16 | /** 17 | * Implementation of the service with ObjectMapping. 18 | * 19 | * @author Cedrick LUNVEN (@clunven) 20 | */ 21 | @Singleton 22 | public class TodoServicesCassandraOM implements TodoService { 23 | 24 | /** Driver Dao. */ 25 | private TodoItemDao todoDao; 26 | 27 | /** 28 | * Constructor with parameters. 29 | * 30 | * @param cqlSession 31 | * current cqlSession 32 | */ 33 | public TodoServicesCassandraOM(CqlSession cqlSession) { 34 | todoDao = TodoItemMapper 35 | .builder(cqlSession) 36 | .withDefaultKeyspace(cqlSession.getKeyspace().get()) 37 | .build() 38 | .todoItemDao(); 39 | } 40 | 41 | @Override 42 | public TodoDto save(TodoDto todo) { 43 | if(null == todo.getItemId()) todo.setItemId(Uuids.timeBased()); 44 | todoDao.save(fromDtoToEntity(todo)); 45 | return todo; 46 | } 47 | 48 | @Override 49 | public Optional findById(String userId, UUID itemId) { 50 | return todoDao.findById(userId, itemId).map(this::fromEntityToDto); 51 | } 52 | 53 | @Override 54 | public List findByUser(String userId) { 55 | return todoDao.findByUser(userId) 56 | .all().stream() 57 | .map(this::fromEntityToDto) 58 | .collect(Collectors.toList()); 59 | } 60 | 61 | @Override 62 | public void deleteById(String userId, UUID itemId) { 63 | todoDao.deleteById(userId, itemId); 64 | } 65 | 66 | @Override 67 | public void deleteByUser(String userId) { 68 | todoDao.deleteByUser(userId); 69 | } 70 | 71 | @Override 72 | @Query("truncate todoitems") 73 | public void deleteAll() {} 74 | 75 | private TodoItem fromDtoToEntity(TodoDto todo) { 76 | TodoItem ti = new TodoItem(); 77 | ti.setCompleted(todo.getCompleted()); 78 | ti.setItemId(todo.getItemId()); 79 | ti.setTitle(todo.getTitle()); 80 | ti.setUserId(todo.getUserId()); 81 | return ti; 82 | } 83 | 84 | private TodoDto fromEntityToDto(TodoItem ti) { 85 | TodoDto dto = new TodoDto(); 86 | dto.setCompleted(ti.getCompleted()); 87 | dto.setItemId(ti.getItemId()); 88 | dto.setTitle(ti.getTitle()); 89 | dto.setUserId(ti.getUserId()); 90 | return dto; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /lab-quarkus/src/main/java/com/datastaxdev/todo/cassandra/TodoServicesCassandraOM.java: -------------------------------------------------------------------------------- 1 | package com.datastaxdev.todo.cassandra; 2 | 3 | import java.util.List; 4 | import java.util.Optional; 5 | import java.util.UUID; 6 | import java.util.stream.Collectors; 7 | 8 | import javax.enterprise.context.ApplicationScoped; 9 | 10 | import com.datastax.oss.driver.api.core.CqlSession; 11 | import com.datastax.oss.driver.api.core.uuid.Uuids; 12 | import com.datastax.oss.driver.api.mapper.annotations.Query; 13 | import com.datastaxdev.todo.TodoDto; 14 | import com.datastaxdev.todo.TodoService; 15 | 16 | /** 17 | * Implementation of the service with ObjectMapping. 18 | * 19 | * @author Cedrick LUNVEN (@clunven) 20 | */ 21 | @ApplicationScoped 22 | public class TodoServicesCassandraOM implements TodoService { 23 | 24 | /** Driver Dao. */ 25 | private TodoItemDao todoDao; 26 | 27 | /** 28 | * Constructor with parameters. 29 | * 30 | * @param cqlSession 31 | * current cqlSession 32 | */ 33 | public TodoServicesCassandraOM(CqlSession cqlSession) { 34 | todoDao = TodoItemMapper 35 | .builder(cqlSession) 36 | .withDefaultKeyspace(cqlSession.getKeyspace().get()) 37 | .build() 38 | .todoItemDao(); 39 | } 40 | 41 | @Override 42 | public TodoDto save(TodoDto todo) { 43 | if(null == todo.getItemId()) todo.setItemId(Uuids.timeBased()); 44 | todoDao.save(fromDtoToEntity(todo)); 45 | return todo; 46 | } 47 | 48 | @Override 49 | public Optional findById(String userId, UUID itemId) { 50 | return todoDao.findById(userId, itemId).map(this::fromEntityToDto); 51 | } 52 | 53 | @Override 54 | public List findByUser(String userId) { 55 | return todoDao.findByUser(userId) 56 | .all().stream() 57 | .map(this::fromEntityToDto) 58 | .collect(Collectors.toList()); 59 | } 60 | 61 | @Override 62 | public void deleteById(String userId, UUID itemId) { 63 | todoDao.deleteById(userId, itemId); 64 | } 65 | 66 | @Override 67 | public void deleteByUser(String userId) { 68 | todoDao.deleteByUser(userId); 69 | } 70 | 71 | @Override 72 | @Query("truncate todoitems") 73 | public void deleteAll() {} 74 | 75 | private TodoItem fromDtoToEntity(TodoDto todo) { 76 | TodoItem ti = new TodoItem(); 77 | ti.setCompleted(todo.getCompleted()); 78 | ti.setItemId(todo.getItemId()); 79 | ti.setTitle(todo.getTitle()); 80 | ti.setUserId(todo.getUserId()); 81 | return ti; 82 | } 83 | 84 | private TodoDto fromEntityToDto(TodoItem ti) { 85 | TodoDto dto = new TodoDto(); 86 | dto.setCompleted(ti.getCompleted()); 87 | dto.setItemId(ti.getItemId()); 88 | dto.setTitle(ti.getTitle()); 89 | dto.setUserId(ti.getUserId()); 90 | return dto; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /lab-quarkus/src/main/java/com/datastaxdev/todo/cassandra/TodoItem.java: -------------------------------------------------------------------------------- 1 | package com.datastaxdev.todo.cassandra; 2 | 3 | import static com.datastaxdev.todo.cassandra.TodoServiceCassandraCql.TABLE_TODOITEMS; 4 | import static com.datastaxdev.todo.cassandra.TodoServiceCassandraCql.TODO_COMPLETED; 5 | import static com.datastaxdev.todo.cassandra.TodoServiceCassandraCql.TODO_ITEM_ID; 6 | import static com.datastaxdev.todo.cassandra.TodoServiceCassandraCql.TODO_TITLE; 7 | import static com.datastaxdev.todo.cassandra.TodoServiceCassandraCql.TODO_USER_ID; 8 | 9 | import java.util.UUID; 10 | 11 | import com.datastax.oss.driver.api.mapper.annotations.ClusteringColumn; 12 | import com.datastax.oss.driver.api.mapper.annotations.CqlName; 13 | import com.datastax.oss.driver.api.mapper.annotations.Entity; 14 | import com.datastax.oss.driver.api.mapper.annotations.PartitionKey; 15 | 16 | @Entity 17 | @CqlName(TABLE_TODOITEMS) 18 | public class TodoItem { 19 | 20 | @PartitionKey 21 | @CqlName(TODO_USER_ID) 22 | private String userId; 23 | 24 | @ClusteringColumn 25 | @CqlName(TODO_ITEM_ID) 26 | private UUID itemId; 27 | 28 | @CqlName(TODO_TITLE) 29 | private String title; 30 | 31 | @CqlName(TODO_COMPLETED) 32 | private Boolean completed; 33 | 34 | /** 35 | * Getter accessor for attribute 'userId'. 36 | * 37 | * @return 38 | * current value of 'userId' 39 | */ 40 | public String getUserId() { 41 | return userId; 42 | } 43 | 44 | /** 45 | * Setter accessor for attribute 'userId'. 46 | * @param userId 47 | * new value for 'userId ' 48 | */ 49 | public void setUserId(String userId) { 50 | this.userId = userId; 51 | } 52 | 53 | /** 54 | * Getter accessor for attribute 'itemId'. 55 | * 56 | * @return 57 | * current value of 'itemId' 58 | */ 59 | public UUID getItemId() { 60 | return itemId; 61 | } 62 | 63 | /** 64 | * Setter accessor for attribute 'itemId'. 65 | * @param itemId 66 | * new value for 'itemId ' 67 | */ 68 | public void setItemId(UUID itemId) { 69 | this.itemId = itemId; 70 | } 71 | 72 | /** 73 | * Getter accessor for attribute 'title'. 74 | * 75 | * @return 76 | * current value of 'title' 77 | */ 78 | public String getTitle() { 79 | return title; 80 | } 81 | 82 | /** 83 | * Setter accessor for attribute 'title'. 84 | * @param title 85 | * new value for 'title ' 86 | */ 87 | public void setTitle(String title) { 88 | this.title = title; 89 | } 90 | 91 | /** 92 | * Getter accessor for attribute 'completed'. 93 | * 94 | * @return 95 | * current value of 'completed' 96 | */ 97 | public Boolean getCompleted() { 98 | return completed; 99 | } 100 | 101 | /** 102 | * Setter accessor for attribute 'completed'. 103 | * @param completed 104 | * new value for 'completed ' 105 | */ 106 | public void setCompleted(Boolean completed) { 107 | this.completed = completed; 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /lab-micronaut/src/main/java/com/datastaxdev/todo/cassandra/TodoItem.java: -------------------------------------------------------------------------------- 1 | package com.datastaxdev.todo.cassandra; 2 | 3 | import static com.datastaxdev.todo.cassandra.TodoServiceCassandraCql.TABLE_TODOITEMS; 4 | import static com.datastaxdev.todo.cassandra.TodoServiceCassandraCql.TODO_COMPLETED; 5 | import static com.datastaxdev.todo.cassandra.TodoServiceCassandraCql.TODO_ITEM_ID; 6 | import static com.datastaxdev.todo.cassandra.TodoServiceCassandraCql.TODO_TITLE; 7 | import static com.datastaxdev.todo.cassandra.TodoServiceCassandraCql.TODO_USER_ID; 8 | 9 | import java.util.UUID; 10 | 11 | import com.datastax.oss.driver.api.mapper.annotations.ClusteringColumn; 12 | import com.datastax.oss.driver.api.mapper.annotations.CqlName; 13 | import com.datastax.oss.driver.api.mapper.annotations.Entity; 14 | import com.datastax.oss.driver.api.mapper.annotations.PartitionKey; 15 | 16 | @Entity 17 | @CqlName(TABLE_TODOITEMS) 18 | public class TodoItem { 19 | 20 | @PartitionKey 21 | @CqlName(TODO_USER_ID) 22 | private String userId; 23 | 24 | @ClusteringColumn 25 | @CqlName(TODO_ITEM_ID) 26 | private UUID itemId; 27 | 28 | @CqlName(TODO_TITLE) 29 | private String title; 30 | 31 | @CqlName(TODO_COMPLETED) 32 | private Boolean completed; 33 | 34 | /** 35 | * Getter accessor for attribute 'userId'. 36 | * 37 | * @return 38 | * current value of 'userId' 39 | */ 40 | public String getUserId() { 41 | return userId; 42 | } 43 | 44 | /** 45 | * Setter accessor for attribute 'userId'. 46 | * @param userId 47 | * new value for 'userId ' 48 | */ 49 | public void setUserId(String userId) { 50 | this.userId = userId; 51 | } 52 | 53 | /** 54 | * Getter accessor for attribute 'itemId'. 55 | * 56 | * @return 57 | * current value of 'itemId' 58 | */ 59 | public UUID getItemId() { 60 | return itemId; 61 | } 62 | 63 | /** 64 | * Setter accessor for attribute 'itemId'. 65 | * @param itemId 66 | * new value for 'itemId ' 67 | */ 68 | public void setItemId(UUID itemId) { 69 | this.itemId = itemId; 70 | } 71 | 72 | /** 73 | * Getter accessor for attribute 'title'. 74 | * 75 | * @return 76 | * current value of 'title' 77 | */ 78 | public String getTitle() { 79 | return title; 80 | } 81 | 82 | /** 83 | * Setter accessor for attribute 'title'. 84 | * @param title 85 | * new value for 'title ' 86 | */ 87 | public void setTitle(String title) { 88 | this.title = title; 89 | } 90 | 91 | /** 92 | * Getter accessor for attribute 'completed'. 93 | * 94 | * @return 95 | * current value of 'completed' 96 | */ 97 | public Boolean getCompleted() { 98 | return completed; 99 | } 100 | 101 | /** 102 | * Setter accessor for attribute 'completed'. 103 | * @param completed 104 | * new value for 'completed ' 105 | */ 106 | public void setCompleted(Boolean completed) { 107 | this.completed = completed; 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /lab-quarkus/src/main/java/com/datastaxdev/todo/web/Todo.java: -------------------------------------------------------------------------------- 1 | package com.datastaxdev.todo.web; 2 | 3 | import java.util.UUID; 4 | 5 | /** 6 | * Implementa 7 | * 8 | * @author Cedrick LUNVEN (@clunven) 9 | */ 10 | public class Todo { 11 | 12 | private String url; 13 | private UUID uuid; 14 | private String title; 15 | private boolean completed = false; 16 | private Integer order = 0; 17 | 18 | public Todo() {} 19 | 20 | public Todo(String title, Integer order) { 21 | this.uuid = UUID.randomUUID(); 22 | this.title = title; 23 | this.order = order; 24 | } 25 | 26 | public Todo(String title, int order, boolean completed) { 27 | this(title, order); 28 | this.completed = completed; 29 | } 30 | 31 | public void setUrl(String myUrl) { 32 | this.url = myUrl; 33 | } 34 | 35 | /** 36 | * Getter accessor for attribute 'uuid'. 37 | * 38 | * @return 39 | * current value of 'uuid' 40 | */ 41 | public UUID getUuid() { 42 | return uuid; 43 | } 44 | 45 | /** 46 | * Setter accessor for attribute 'uuid'. 47 | * @param uuid 48 | * new value for 'uuid ' 49 | */ 50 | public void setUuid(UUID uuid) { 51 | this.uuid = uuid; 52 | } 53 | 54 | /** 55 | * Getter accessor for attribute 'title'. 56 | * 57 | * @return 58 | * current value of 'title' 59 | */ 60 | public String getTitle() { 61 | return title; 62 | } 63 | 64 | /** 65 | * Setter accessor for attribute 'title'. 66 | * @param title 67 | * new value for 'title ' 68 | */ 69 | public void setTitle(String title) { 70 | this.title = title; 71 | } 72 | 73 | /** 74 | * Getter accessor for attribute 'completed'. 75 | * 76 | * @return 77 | * current value of 'completed' 78 | */ 79 | public boolean isCompleted() { 80 | return completed; 81 | } 82 | 83 | /** 84 | * Setter accessor for attribute 'completed'. 85 | * @param completed 86 | * new value for 'completed ' 87 | */ 88 | public void setCompleted(boolean completed) { 89 | this.completed = completed; 90 | } 91 | 92 | /** 93 | * Getter accessor for attribute 'order'. 94 | * 95 | * @return 96 | * current value of 'order' 97 | */ 98 | public Integer getOrder() { 99 | return order; 100 | } 101 | 102 | /** 103 | * Setter accessor for attribute 'order'. 104 | * @param order 105 | * new value for 'order ' 106 | */ 107 | public void setOrder(Integer order) { 108 | this.order = order; 109 | } 110 | 111 | /** 112 | * Getter accessor for attribute 'url'. 113 | * 114 | * @return 115 | * current value of 'url' 116 | */ 117 | public String getUrl() { 118 | return url; 119 | } 120 | 121 | /** {@inheritDoc} */ 122 | @Override 123 | public String toString() { 124 | return "Todo [url=" + url + ", uuid=" + uuid + ", title=" + title + ", completed=" + completed + ", order=" + order + "]"; 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /lab-spring/src/main/java/com/datastax/todo/todo/Todo.java: -------------------------------------------------------------------------------- 1 | package com.datastax.todo.todo; 2 | 3 | import java.util.UUID; 4 | 5 | import jakarta.servlet.http.HttpServletRequest; 6 | 7 | public class Todo { 8 | 9 | private String url; 10 | private UUID uuid; 11 | private String title; 12 | private boolean completed = false; 13 | private int order = 0; 14 | 15 | public Todo() {} 16 | 17 | public Todo(String title, int order) { 18 | this.uuid = UUID.randomUUID(); 19 | this.title = title; 20 | this.order = order; 21 | } 22 | 23 | public Todo(String title, int order, boolean completed) { 24 | this(title, order); 25 | this.completed = completed; 26 | } 27 | 28 | public Todo setUrl(HttpServletRequest req) { 29 | if (url == null) { 30 | String reqUrl = req.getRequestURL().toString(); 31 | url = reqUrl.contains("gitpod") ? reqUrl.replaceAll("http", "https") : reqUrl; 32 | url += uuid; 33 | } 34 | return this; 35 | } 36 | 37 | public Todo setUrl(String myUrl) { 38 | if (url == null) { 39 | url = myUrl.contains("gitpod") ? myUrl.replaceAll("http", "https") : myUrl; 40 | } 41 | return this; 42 | } 43 | 44 | /** 45 | * Getter accessor for attribute 'uuid'. 46 | * 47 | * @return 48 | * current value of 'uuid' 49 | */ 50 | public UUID getUuid() { 51 | return uuid; 52 | } 53 | 54 | /** 55 | * Setter accessor for attribute 'uuid'. 56 | * @param uuid 57 | * new value for 'uuid ' 58 | */ 59 | public void setUuid(UUID uuid) { 60 | this.uuid = uuid; 61 | } 62 | 63 | /** 64 | * Getter accessor for attribute 'title'. 65 | * 66 | * @return 67 | * current value of 'title' 68 | */ 69 | public String getTitle() { 70 | return title; 71 | } 72 | 73 | /** 74 | * Setter accessor for attribute 'title'. 75 | * @param title 76 | * new value for 'title ' 77 | */ 78 | public void setTitle(String title) { 79 | this.title = title; 80 | } 81 | 82 | /** 83 | * Getter accessor for attribute 'completed'. 84 | * 85 | * @return 86 | * current value of 'completed' 87 | */ 88 | public boolean isCompleted() { 89 | return completed; 90 | } 91 | 92 | /** 93 | * Setter accessor for attribute 'completed'. 94 | * @param completed 95 | * new value for 'completed ' 96 | */ 97 | public void setCompleted(boolean completed) { 98 | this.completed = completed; 99 | } 100 | 101 | /** 102 | * Getter accessor for attribute 'order'. 103 | * 104 | * @return 105 | * current value of 'order' 106 | */ 107 | public int getOrder() { 108 | return order; 109 | } 110 | 111 | /** 112 | * Setter accessor for attribute 'order'. 113 | * @param order 114 | * new value for 'order ' 115 | */ 116 | public void setOrder(int order) { 117 | this.order = order; 118 | } 119 | 120 | /** 121 | * Getter accessor for attribute 'url'. 122 | * 123 | * @return 124 | * current value of 'url' 125 | */ 126 | public String getUrl() { 127 | return url; 128 | } 129 | 130 | 131 | } 132 | -------------------------------------------------------------------------------- /lab-cassandra-drivers/src/main/java/com/datastax/devoxx/schema/SchemaConstants.java: -------------------------------------------------------------------------------- 1 | package com.datastax.devoxx.schema; 2 | 3 | /** 4 | * Externalization of schema constant. 5 | */ 6 | public interface SchemaConstants { 7 | 8 | /** 9 | * Will be used for this table: 10 | * 11 | * CREATE TABLE IF NOT EXISTS users ( 12 | * email text, 13 | * firstname text, 14 | * lastname text, 15 | * PRIMARY KEY (email) 16 | * ); 17 | */ 18 | String USER_TABLENAME = "users"; 19 | String USER_EMAIL = "email"; 20 | String USER_FIRSTNAME = "firstname"; 21 | String USER_LASTNAME = "lastname"; 22 | 23 | /** 24 | * CREATE TYPE IF NOT EXISTS video_format ( 25 | * width int, 26 | * height int 27 | *); 28 | */ 29 | String UDT_VIDEO_FORMAT_NAME = "video_format"; 30 | String UDT_VIDEO_FORMAT_WIDTH = "width"; 31 | String UDT_VIDEO_FORMAT_HEIGHT = "height"; 32 | 33 | /** 34 | * CREATE TABLE IF NOT EXISTS videos ( 35 | * videoid uuid, 36 | * title text, 37 | * upload timestamp, 38 | * email text, 39 | * url text, 40 | * tags set , 41 | * frames list, 42 | * formats map >, 43 | * PRIMARY KEY (videoid) 44 | * ); 45 | **/ 46 | String VIDEO_TABLENAME = "videos"; 47 | String VIDEO_VIDEOID = "videoid"; 48 | String VIDEO_TITLE = "title"; 49 | String VIDEO_UPLOAD = "upload"; 50 | String VIDEO_USER_EMAIL = "email"; 51 | String VIDEO_FRAMES = "frames"; 52 | String VIDEO_URL = "url"; 53 | String VIDEO_TAGS = "tags"; 54 | String VIDEO_FORMAT = "formats"; 55 | 56 | /** 57 | * CREATE TABLE IF NOT EXISTS videos_views ( 58 | * videoid uuid, 59 | * views counter, 60 | * PRIMARY KEY (videoid) 61 | * ); 62 | */ 63 | String VIDEO_VIEWS_TABLENAME = "videos_views"; 64 | String VIDEO_VIEWS_VIDEOID = "videoid"; 65 | String VIDEO_VIEWS_VIEWS = "views"; 66 | 67 | /** 68 | * CREATE TABLE IF NOT EXISTS comments_by_video ( 69 | * videoid uuid, 70 | * commentid timeuuid, 71 | * userid uuid, 72 | * comment text, 73 | * PRIMARY KEY (videoid, commentid) 74 | * ) WITH CLUSTERING ORDER BY (commentid DESC); 75 | * 76 | * 77 | * CREATE TABLE IF NOT EXISTS comments_by_user ( 78 | * userid uuid, 79 | * commentid timeuuid, 80 | * videoid uuid, 81 | * comment text, 82 | * PRIMARY KEY (userid, commentid) 83 | * ) WITH CLUSTERING ORDER BY (commentid DESC); 84 | */ 85 | String COMMENT_BY_VIDEO_TABLENAME = "comments_by_video"; 86 | String COMMENT_BY_VIDEO_VIDEOID = "videoid"; 87 | String COMMENT_BY_VIDEO_COMMENTID = "commentid"; 88 | String COMMENT_BY_VIDEO_USERID = "userid"; 89 | String COMMENT_BY_VIDEO_COMMENT = "comment"; 90 | String COMMENT_BY_USER_TABLENAME = "comments_by_user"; 91 | String COMMENT_BY_USER_VIDEOID = COMMENT_BY_VIDEO_VIDEOID; 92 | String COMMENT_BY_USER_COMMENTID = COMMENT_BY_VIDEO_COMMENTID; 93 | String COMMENT_BY_USER_USERID = COMMENT_BY_VIDEO_USERID; 94 | String COMMENT_BY_USER_COMMENT = COMMENT_BY_VIDEO_COMMENT; 95 | 96 | String FILES_TABLENAME = "files"; 97 | String FILES_FILENAME = "filename"; 98 | String FILES_EXTENSION = "extension"; 99 | String FILES_UPLOAD = "upload"; 100 | String FILES_BINARY = "binary"; 101 | 102 | } 103 | -------------------------------------------------------------------------------- /lab-cassandra-drivers/src/main/java/com/datastax/devoxx/codec/JsonJacksonTypeCodec.java: -------------------------------------------------------------------------------- 1 | package com.datastax.devoxx.codec; 2 | 3 | import java.io.IOException; 4 | import java.io.Serializable; 5 | import java.nio.ByteBuffer; 6 | 7 | import com.datastax.oss.driver.api.core.ProtocolVersion; 8 | import com.datastax.oss.driver.api.core.type.DataType; 9 | import com.datastax.oss.driver.api.core.type.DataTypes; 10 | import com.datastax.oss.driver.api.core.type.codec.TypeCodec; 11 | import com.datastax.oss.driver.api.core.type.reflect.GenericType; 12 | import com.fasterxml.jackson.core.JsonProcessingException; 13 | import com.fasterxml.jackson.databind.ObjectMapper; 14 | import com.fasterxml.jackson.databind.type.TypeFactory; 15 | 16 | /** 17 | * Convert some PJP into JSON. 18 | * 19 | * @param 20 | */ 21 | public class JsonJacksonTypeCodec implements TypeCodec { 22 | 23 | /** 24 | * Jackson will help us here json <-> POJO 25 | */ 26 | private final ObjectMapper objectMapper = new ObjectMapper(); 27 | 28 | private Class javaType; 29 | 30 | public JsonJacksonTypeCodec(Class classType) { 31 | this.javaType = classType; 32 | } 33 | 34 | /** {@inheritDoc} */ 35 | @Override 36 | public GenericType getJavaType() { 37 | return GenericType.of(javaType); 38 | } 39 | 40 | /** {@inheritDoc} */ 41 | @Override 42 | public DataType getCqlType() { 43 | return DataTypes.TEXT; 44 | } 45 | 46 | /** {@inheritDoc} */ 47 | @Override 48 | public ByteBuffer encode(T value, ProtocolVersion protocolVersion) { 49 | if (value == null) 50 | return null; 51 | try { 52 | return ByteBuffer.wrap(objectMapper.writeValueAsBytes(value)); 53 | } catch (JsonProcessingException e) { 54 | throw new IllegalArgumentException(e.getMessage(), e); 55 | } 56 | } 57 | 58 | /** {@inheritDoc} */ 59 | @Override 60 | @SuppressWarnings("unchecked") 61 | public T decode(ByteBuffer bytes, ProtocolVersion protocolVersion) { 62 | if (bytes == null) 63 | return null; 64 | try { 65 | byte[] b = new byte[bytes.remaining()]; 66 | bytes.duplicate().get(b); 67 | return (T) objectMapper.readValue(b, TypeFactory.defaultInstance().constructType(getJavaType().getType())); 68 | } catch (IOException e) { 69 | throw new IllegalArgumentException(e.getMessage(), e); 70 | } 71 | } 72 | 73 | /** {@inheritDoc} */ 74 | @Override 75 | public String format(T value) { 76 | if (value == null) 77 | return "NULL"; 78 | String json; 79 | try { 80 | json = objectMapper.writeValueAsString(value); 81 | } catch (IOException e) { 82 | throw new IllegalArgumentException(e.getMessage(), e); 83 | } 84 | return '\'' + json.replace("\'", "''") + '\''; 85 | } 86 | 87 | /** {@inheritDoc} */ 88 | @Override 89 | @SuppressWarnings("unchecked") 90 | public T parse(String value) { 91 | if (value == null || value.isEmpty() || value.equalsIgnoreCase("NULL")) 92 | return null; 93 | if (value.charAt(0) != '\'' || value.charAt(value.length() - 1) != '\'') 94 | throw new IllegalArgumentException("JSON strings must be enclosed by single quotes"); 95 | String json = value.substring(1, value.length() - 1).replace("''", "'"); 96 | try { 97 | return (T) objectMapper.readValue(json, TypeFactory.defaultInstance().constructType(getJavaType().getType())); 98 | } catch (IOException e) { 99 | throw new IllegalArgumentException(e.getMessage(), e); 100 | } 101 | } 102 | 103 | } 104 | -------------------------------------------------------------------------------- /lab-cassandra-drivers/src/main/java/com/datastax/devoxx/objectmapping/Comment.java: -------------------------------------------------------------------------------- 1 | package com.datastax.devoxx.objectmapping; 2 | 3 | import java.io.Serializable; 4 | import java.util.UUID; 5 | 6 | import com.datastax.devoxx.schema.SchemaConstants; 7 | import com.datastax.oss.driver.api.core.uuid.Uuids; 8 | import com.datastax.oss.driver.api.mapper.annotations.ClusteringColumn; 9 | import com.datastax.oss.driver.api.mapper.annotations.CqlName; 10 | 11 | /** 12 | * Bean standing for comment on video. 13 | * 14 | * @author DataStax Developer Advocates team. 15 | */ 16 | public class Comment implements Serializable, SchemaConstants { 17 | 18 | /** Serial. */ 19 | private static final long serialVersionUID = 7675521710612951368L; 20 | 21 | @CqlName(COMMENT_BY_USER_USERID) 22 | protected UUID userid; 23 | 24 | @CqlName(COMMENT_BY_USER_VIDEOID) 25 | protected UUID videoid; 26 | 27 | @ClusteringColumn 28 | @CqlName(COMMENT_BY_USER_COMMENTID) 29 | protected UUID commentid; 30 | 31 | @CqlName(COMMENT_BY_USER_COMMENT) 32 | protected String comment; 33 | 34 | /** 35 | * Default constructor. 36 | */ 37 | public Comment() { 38 | } 39 | 40 | /** 41 | * Constructor with parameters. 42 | * 43 | * @param userid 44 | * user unique identifier 45 | * @param videoId 46 | * video unique identifier 47 | * @param comment 48 | * text value for the comment 49 | */ 50 | public Comment(UUID userid, UUID videoId, String comment) { 51 | this.userid = userid; 52 | this.videoid = videoId; 53 | this.comment = comment; 54 | this.commentid = Uuids.timeBased(); 55 | } 56 | 57 | /** 58 | * Default constructor. 59 | */ 60 | public Comment(String comment) { 61 | this.comment = comment; 62 | } 63 | 64 | /** 65 | * Setter for attribute 'userid'. 66 | * @param userid 67 | * new value for 'userid ' 68 | */ 69 | public void setUserid(UUID userid) { 70 | this.userid = userid; 71 | } 72 | 73 | /** 74 | * Setter for attribute 'videoid'. 75 | * @param videoid 76 | * new value for 'videoid ' 77 | */ 78 | public void setVideoid(UUID videoid) { 79 | this.videoid = videoid; 80 | } 81 | 82 | /** 83 | * Getter for attribute 'commentid'. 84 | * 85 | * @return 86 | * current value of 'commentid' 87 | */ 88 | public UUID getCommentid() { 89 | return commentid; 90 | } 91 | 92 | /** 93 | * Setter for attribute 'commentid'. 94 | * @param commentid 95 | * new value for 'commentid ' 96 | */ 97 | public void setCommentid(UUID commentid) { 98 | this.commentid = commentid; 99 | } 100 | 101 | /** 102 | * Getter for attribute 'comment'. 103 | * 104 | * @return 105 | * current value of 'comment' 106 | */ 107 | public String getComment() { 108 | return comment; 109 | } 110 | 111 | /** 112 | * Setter for attribute 'comment'. 113 | * @param comment 114 | * new value for 'comment ' 115 | */ 116 | public void setComment(String comment) { 117 | this.comment = comment; 118 | } 119 | 120 | /** 121 | * Getter for attribute 'userid'. 122 | * 123 | * @return 124 | * current value of 'userid' 125 | */ 126 | public UUID getUserid() { 127 | return userid; 128 | } 129 | 130 | /** 131 | * Getter for attribute 'videoid'. 132 | * 133 | * @return 134 | * current value of 'videoid' 135 | */ 136 | public UUID getVideoid() { 137 | return videoid; 138 | } 139 | 140 | 141 | } 142 | -------------------------------------------------------------------------------- /lab-micronaut/src/main/java/com/datastaxdev/todo/web/Todo.java: -------------------------------------------------------------------------------- 1 | package com.datastaxdev.todo.web; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashSet; 5 | import java.util.LinkedHashMap; 6 | import java.util.UUID; 7 | 8 | import com.fasterxml.jackson.databind.PropertyNamingStrategy; 9 | 10 | import io.micronaut.core.annotation.ReflectiveAccess; 11 | import io.micronaut.core.annotation.TypeHint; 12 | 13 | /** 14 | * Implementa 15 | * 16 | * @author Cedrick LUNVEN (@clunven) 17 | */ 18 | @SuppressWarnings("deprecation") 19 | @ReflectiveAccess 20 | @TypeHint( 21 | value = { 22 | PropertyNamingStrategy.UpperCamelCaseStrategy.class, 23 | ArrayList.class, 24 | LinkedHashMap.class, 25 | HashSet.class 26 | }, 27 | accessType = TypeHint.AccessType.ALL_DECLARED_CONSTRUCTORS 28 | ) 29 | public class Todo { 30 | 31 | private String url; 32 | private UUID uuid; 33 | private String title; 34 | private boolean completed = false; 35 | private Integer order = 0; 36 | 37 | public Todo() {} 38 | 39 | public Todo(String title, Integer order) { 40 | this.uuid = UUID.randomUUID(); 41 | this.title = title; 42 | this.order = order; 43 | } 44 | 45 | public Todo(String title, int order, boolean completed) { 46 | this(title, order); 47 | this.completed = completed; 48 | } 49 | 50 | public void setUrl(String myUrl) { 51 | this.url = myUrl; 52 | } 53 | 54 | /** 55 | * Getter accessor for attribute 'uuid'. 56 | * 57 | * @return 58 | * current value of 'uuid' 59 | */ 60 | public UUID getUuid() { 61 | return uuid; 62 | } 63 | 64 | /** 65 | * Setter accessor for attribute 'uuid'. 66 | * @param uuid 67 | * new value for 'uuid ' 68 | */ 69 | public void setUuid(UUID uuid) { 70 | this.uuid = uuid; 71 | } 72 | 73 | /** 74 | * Getter accessor for attribute 'title'. 75 | * 76 | * @return 77 | * current value of 'title' 78 | */ 79 | public String getTitle() { 80 | return title; 81 | } 82 | 83 | /** 84 | * Setter accessor for attribute 'title'. 85 | * @param title 86 | * new value for 'title ' 87 | */ 88 | public void setTitle(String title) { 89 | this.title = title; 90 | } 91 | 92 | /** 93 | * Getter accessor for attribute 'completed'. 94 | * 95 | * @return 96 | * current value of 'completed' 97 | */ 98 | public boolean isCompleted() { 99 | return completed; 100 | } 101 | 102 | /** 103 | * Setter accessor for attribute 'completed'. 104 | * @param completed 105 | * new value for 'completed ' 106 | */ 107 | public void setCompleted(boolean completed) { 108 | this.completed = completed; 109 | } 110 | 111 | /** 112 | * Getter accessor for attribute 'order'. 113 | * 114 | * @return 115 | * current value of 'order' 116 | */ 117 | public Integer getOrder() { 118 | return order; 119 | } 120 | 121 | /** 122 | * Setter accessor for attribute 'order'. 123 | * @param order 124 | * new value for 'order ' 125 | */ 126 | public void setOrder(Integer order) { 127 | this.order = order; 128 | } 129 | 130 | /** 131 | * Getter accessor for attribute 'url'. 132 | * 133 | * @return 134 | * current value of 'url' 135 | */ 136 | public String getUrl() { 137 | return url; 138 | } 139 | 140 | /** {@inheritDoc} */ 141 | @Override 142 | public String toString() { 143 | return "Todo [url=" + url + ", uuid=" + uuid + ", title=" + title + ", completed=" + completed + ", order=" + order + "]"; 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /lab-spring/src/main/java/com/datastax/todo/todo/TodoEntity.java: -------------------------------------------------------------------------------- 1 | package com.datastax.todo.todo; 2 | 3 | import java.util.UUID; 4 | 5 | import org.springframework.data.cassandra.core.mapping.CassandraType; 6 | import org.springframework.data.cassandra.core.mapping.CassandraType.Name; 7 | import org.springframework.data.cassandra.core.mapping.Column; 8 | import org.springframework.data.cassandra.core.mapping.PrimaryKey; 9 | import org.springframework.data.cassandra.core.mapping.Table; 10 | 11 | 12 | @Table(value = TodoEntity.TABLENAME) 13 | public class TodoEntity { 14 | 15 | public static final String TABLENAME = "todos"; 16 | public static final String COLUMN_UID = "uid"; 17 | public static final String COLUMN_TITLE = "title"; 18 | public static final String COLUMN_COMPLETED = "completed"; 19 | public static final String COLUMN_ORDER = "offset"; 20 | 21 | @PrimaryKey 22 | @Column(COLUMN_UID) 23 | @CassandraType(type = Name.UUID) 24 | private UUID uid; 25 | 26 | @Column(COLUMN_TITLE) 27 | @CassandraType(type = Name.TEXT) 28 | private String title; 29 | 30 | @Column(COLUMN_COMPLETED) 31 | @CassandraType(type = Name.BOOLEAN) 32 | private boolean completed = false; 33 | 34 | @Column(COLUMN_ORDER) 35 | @CassandraType(type = Name.INT) 36 | private int order = 0; 37 | 38 | 39 | public TodoEntity() {} 40 | 41 | public TodoEntity(UUID uid, String title, boolean completed, int order) { 42 | super(); 43 | this.uid = uid; 44 | this.title = title; 45 | this.completed = completed; 46 | this.order = order; 47 | } 48 | 49 | public TodoEntity(String title, int offset) { 50 | this(UUID.randomUUID(), title, false, offset); 51 | } 52 | 53 | 54 | 55 | /** 56 | * Getter accessor for attribute 'uid'. 57 | * 58 | * @return 59 | * current value of 'uid' 60 | */ 61 | public UUID getUid() { 62 | return uid; 63 | } 64 | 65 | /** 66 | * Setter accessor for attribute 'uid'. 67 | * @param uid 68 | * new value for 'uid ' 69 | */ 70 | public void setUid(UUID uid) { 71 | this.uid = uid; 72 | } 73 | 74 | /** 75 | * Getter accessor for attribute 'title'. 76 | * 77 | * @return 78 | * current value of 'title' 79 | */ 80 | public String getTitle() { 81 | return title; 82 | } 83 | 84 | /** 85 | * Setter accessor for attribute 'title'. 86 | * @param title 87 | * new value for 'title ' 88 | */ 89 | public void setTitle(String title) { 90 | this.title = title; 91 | } 92 | 93 | /** 94 | * Getter accessor for attribute 'completed'. 95 | * 96 | * @return 97 | * current value of 'completed' 98 | */ 99 | public boolean isCompleted() { 100 | return completed; 101 | } 102 | 103 | /** 104 | * Setter accessor for attribute 'completed'. 105 | * @param completed 106 | * new value for 'completed ' 107 | */ 108 | public void setCompleted(boolean completed) { 109 | this.completed = completed; 110 | } 111 | 112 | /** 113 | * Getter accessor for attribute 'order'. 114 | * 115 | * @return 116 | * current value of 'order' 117 | */ 118 | public int getOrder() { 119 | return order; 120 | } 121 | 122 | /** 123 | * Setter accessor for attribute 'order'. 124 | * @param order 125 | * new value for 'order ' 126 | */ 127 | public void setOrder(int order) { 128 | this.order = order; 129 | } 130 | 131 | /** {@inheritDoc} */ 132 | @Override 133 | public String toString() { 134 | return "+ TodoEntity [uid=" + uid + ", title=" + title + ", completed=" + completed + ", order=" + order + "]"; 135 | } 136 | 137 | } 138 | -------------------------------------------------------------------------------- /lab-cassandra-drivers/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | com.datastax 7 | lab-cassandra-drivers 8 | 1.0-SNAPSHOT 9 | jar 10 | lab-cassandra-drivers 11 | 12 | 13 | UTF-8 14 | 4.15.0 15 | 2.0.3 16 | 1.4.3 17 | 3.4.23 18 | 5.9.1 19 | 1.9.1 20 | 21 | 17 22 | 3.8.1 23 | 2.22.2 24 | 25 | 26 | 27 | 28 | 29 | 30 | com.datastax.oss 31 | java-driver-core 32 | ${cassandra-driver.version} 33 | 34 | 35 | com.datastax.oss 36 | java-driver-query-builder 37 | ${cassandra-driver.version} 38 | 39 | 40 | com.datastax.oss 41 | java-driver-mapper-runtime 42 | ${cassandra-driver.version} 43 | 44 | 45 | 46 | 47 | org.slf4j 48 | slf4j-api 49 | ${sl4j.version} 50 | 51 | 52 | ch.qos.logback 53 | logback-classic 54 | ${logback.version} 55 | 56 | 57 | 58 | 59 | 60 | io.projectreactor 61 | reactor-core 62 | ${reactor.version} 63 | 64 | 65 | 66 | 67 | org.junit.jupiter 68 | junit-jupiter-api 69 | ${junit.version} 70 | test 71 | 72 | 73 | org.junit.jupiter 74 | junit-jupiter-engine 75 | ${junit.version} 76 | test 77 | 78 | 79 | org.junit.platform 80 | junit-platform-runner 81 | ${junit-platform.version} 82 | test 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | org.apache.maven.plugins 93 | maven-surefire-plugin 94 | ${maven.plugin.surefire.version} 95 | 96 | 97 | 98 | 99 | 100 | org.apache.maven.plugins 101 | maven-compiler-plugin 102 | ${maven.plugin.compiler.version} 103 | 104 | ${java.version} 105 | ${java.version} 106 | ${java.version} 107 | 108 | 109 | com.datastax.oss 110 | java-driver-mapper-processor 111 | ${cassandra-driver.version} 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | -------------------------------------------------------------------------------- /lab-cassandra-drivers/src/test/java/com/datastax/devoxx/E09_ResultPagingTest.java: -------------------------------------------------------------------------------- 1 | package com.datastax.devoxx; 2 | 3 | import static com.datastax.devoxx.schema.SchemaUtils.createTableUser; 4 | import static com.datastax.devoxx.schema.SchemaUtils.truncateTable; 5 | 6 | import java.nio.ByteBuffer; 7 | import java.time.Duration; 8 | import java.util.Iterator; 9 | 10 | import org.junit.jupiter.api.BeforeAll; 11 | import org.junit.jupiter.api.Test; 12 | import org.slf4j.Logger; 13 | import org.slf4j.LoggerFactory; 14 | 15 | import com.datastax.devoxx.schema.SchemaConstants; 16 | import com.datastax.oss.driver.api.core.ConsistencyLevel; 17 | import com.datastax.oss.driver.api.core.CqlSession; 18 | import com.datastax.oss.driver.api.core.cql.BatchStatement; 19 | import com.datastax.oss.driver.api.core.cql.BatchStatementBuilder; 20 | import com.datastax.oss.driver.api.core.cql.DefaultBatchType; 21 | import com.datastax.oss.driver.api.core.cql.PreparedStatement; 22 | import com.datastax.oss.driver.api.core.cql.ResultSet; 23 | import com.datastax.oss.driver.api.core.cql.Row; 24 | import com.datastax.oss.driver.api.core.cql.SimpleStatement; 25 | import com.datastax.oss.driver.api.querybuilder.QueryBuilder; 26 | import com.datastax.oss.protocol.internal.util.Bytes; 27 | 28 | /** 29 | * !! WARNING Tests with no Assertions here (I assume) !! 30 | * 31 | * @author cedricklunven 32 | */ 33 | public class E09_ResultPagingTest implements SchemaConstants { 34 | 35 | private static Logger LOGGER = LoggerFactory.getLogger(E09_ResultPagingTest.class); 36 | 37 | private static PreparedStatement stmtCreateUser; 38 | 39 | @BeforeAll 40 | public static void shout_init_statements() { 41 | try(CqlSession cqlSession = CqlSession.builder().build()) { 42 | 43 | createTableUser(cqlSession); 44 | 45 | truncateTable(cqlSession, USER_TABLENAME); 46 | 47 | stmtCreateUser = 48 | cqlSession.prepare(QueryBuilder.insertInto(USER_TABLENAME) 49 | .value(USER_EMAIL, QueryBuilder.bindMarker()) 50 | .value(USER_FIRSTNAME, QueryBuilder.bindMarker()) 51 | .value(USER_LASTNAME, QueryBuilder.bindMarker()) 52 | .build()); 53 | } 54 | } 55 | 56 | @Test 57 | public void should_run_batch() { 58 | try(CqlSession cqlSession = CqlSession.builder().build()) { 59 | // Adding 50 records in the table 60 | BatchStatementBuilder bb = BatchStatement.builder(DefaultBatchType.LOGGED); 61 | for (int i = 0; i < 50; i++) { 62 | bb.addStatement(stmtCreateUser.bind("user_" + i + "@sample.com", "user_" + i, "lastname")); 63 | } 64 | cqlSession.execute(bb.build()); 65 | LOGGER.info("+ {} users have been created", 50); 66 | 67 | // Paged query 68 | SimpleStatement statement = QueryBuilder.selectFrom(USER_TABLENAME).all().build() 69 | .setPageSize(10) // 10 per pages 70 | .setTimeout(Duration.ofSeconds(1)) // 1s timeout 71 | .setConsistencyLevel(ConsistencyLevel.ONE); 72 | ResultSet page1 = cqlSession.execute(statement); 73 | 74 | // Checking 75 | LOGGER.info("+ Page 1 has {} items", page1.getAvailableWithoutFetching()); 76 | Iterator page1Iter = page1.iterator(); 77 | while (0 < page1.getAvailableWithoutFetching()) { 78 | LOGGER.info("Page1: " + page1Iter.next().getString(USER_EMAIL)); 79 | } 80 | 81 | // Notice that items are NOT ordered (it uses the hashed token) 82 | // From this point if you invoke .next() driver will look for page2. 83 | // But we can invoke page2 directly: (useful for delay between calls) 84 | ByteBuffer pagingStateAsBytes = page1.getExecutionInfo().getPagingState(); 85 | 86 | // If you need to to externalize this as a STRING 87 | Bytes.toHexString(pagingStateAsBytes); 88 | // If you need to go back to byteBuffer 89 | // ByteBuffer pagingStateAsBytesBack = Bytes.fromHexString(pageStateAsString); 90 | 91 | statement.setPagingState(pagingStateAsBytes); 92 | ResultSet page2 = cqlSession.execute(statement); 93 | LOGGER.info("+ Page 2 has {} items", page2.getAvailableWithoutFetching()); 94 | } 95 | } 96 | 97 | } 98 | -------------------------------------------------------------------------------- /lab-spring/src/main/java/com/datastax/todo/todo/TodoRestController.java: -------------------------------------------------------------------------------- 1 | package com.datastax.todo.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 org.springframework.http.HttpStatus; 17 | import org.springframework.http.ResponseEntity; 18 | import org.springframework.web.bind.annotation.CrossOrigin; 19 | import org.springframework.web.bind.annotation.DeleteMapping; 20 | import org.springframework.web.bind.annotation.GetMapping; 21 | import org.springframework.web.bind.annotation.PatchMapping; 22 | import org.springframework.web.bind.annotation.PathVariable; 23 | import org.springframework.web.bind.annotation.PostMapping; 24 | import org.springframework.web.bind.annotation.RequestBody; 25 | import org.springframework.web.bind.annotation.RequestMapping; 26 | import org.springframework.web.bind.annotation.RestController; 27 | 28 | import jakarta.servlet.http.HttpServletRequest; 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/todos/") 38 | public class TodoRestController { 39 | 40 | private TodoRepositorySimpleCassandra repo; 41 | 42 | public TodoRestController(TodoRepositorySimpleCassandra todoRepo) { 43 | this.repo = todoRepo; 44 | } 45 | 46 | @GetMapping 47 | public Stream findAll(HttpServletRequest req) { 48 | return repo.findAll().stream() 49 | .map(TodoRestController::mapAsTodo) 50 | .map(t -> t.setUrl(req)); 51 | } 52 | 53 | @GetMapping("/{uid}") 54 | public ResponseEntity findById(HttpServletRequest req, @PathVariable(value = "uid") String uid) { 55 | Optional e = repo.findById(UUID.fromString(uid)); 56 | if (!e.isPresent()) { 57 | return ResponseEntity.notFound().build(); 58 | } 59 | return ResponseEntity.ok(mapAsTodo(e.get()).setUrl(req.getRequestURL().toString())); 60 | } 61 | 62 | @PostMapping 63 | public ResponseEntity create(HttpServletRequest req, @RequestBody Todo todoReq) 64 | throws URISyntaxException { 65 | TodoEntity te = mapAsTodoEntity(todoReq); 66 | repo.save(te); 67 | todoReq.setUuid(te.getUid()); 68 | todoReq.setUrl(req); 69 | return ResponseEntity.created(new URI(todoReq.getUrl())).body(todoReq); 70 | } 71 | 72 | @PatchMapping("{uid}") 73 | public ResponseEntity update(HttpServletRequest req, @PathVariable(value = "uid") String uid, @RequestBody Todo todoReq) 74 | throws URISyntaxException { 75 | todoReq.setUuid(UUID.fromString(uid)); 76 | todoReq.setUrl(req.getRequestURL().toString()); 77 | repo.save(mapAsTodoEntity(todoReq)); 78 | return ResponseEntity.accepted().body(todoReq); 79 | } 80 | 81 | @DeleteMapping("{uid}") 82 | public ResponseEntity deleteById(@PathVariable(value = "uid") String uid) { 83 | if (!repo.existsById(UUID.fromString(uid))) { 84 | return ResponseEntity.notFound().build(); 85 | } 86 | repo.deleteById(UUID.fromString(uid)); 87 | return new ResponseEntity<>(HttpStatus.NO_CONTENT); 88 | } 89 | 90 | @DeleteMapping 91 | public ResponseEntity deleteAll(HttpServletRequest request) { 92 | repo.deleteAll(); 93 | return new ResponseEntity<>(HttpStatus.NO_CONTENT); 94 | } 95 | 96 | private static Todo mapAsTodo(TodoEntity te) { 97 | Todo todo = new Todo(); 98 | todo.setTitle(te.getTitle()); 99 | todo.setOrder(te.getOrder()); 100 | todo.setUuid(te.getUid()); 101 | todo.setCompleted(te.isCompleted()); 102 | return todo; 103 | } 104 | 105 | private static TodoEntity mapAsTodoEntity(Todo te) { 106 | TodoEntity todo = new TodoEntity(); 107 | if (null != te.getUuid()) { 108 | todo.setUid(te.getUuid()); 109 | } else { 110 | todo.setUid(UUID.randomUUID()); 111 | } 112 | todo.setTitle(te.getTitle()); 113 | todo.setOrder(te.getOrder()); 114 | todo.setCompleted(te.isCompleted()); 115 | return todo; 116 | } 117 | } -------------------------------------------------------------------------------- /lab-cassandra-drivers/src/main/java/com/datastax/devoxx/objectmapping/CommentDaoQueryProvider.java: -------------------------------------------------------------------------------- 1 | package com.datastax.devoxx.objectmapping; 2 | 3 | import java.util.UUID; 4 | 5 | import com.datastax.oss.driver.api.core.CqlSession; 6 | import com.datastax.oss.driver.api.core.PagingIterable; 7 | import com.datastax.oss.driver.api.core.cql.BatchStatement; 8 | import com.datastax.oss.driver.api.core.cql.BoundStatement; 9 | import com.datastax.oss.driver.api.core.cql.BoundStatementBuilder; 10 | import com.datastax.oss.driver.api.core.cql.DefaultBatchType; 11 | import com.datastax.oss.driver.api.core.cql.PreparedStatement; 12 | import com.datastax.oss.driver.api.mapper.MapperContext; 13 | import com.datastax.oss.driver.api.mapper.entity.EntityHelper; 14 | import com.datastax.oss.driver.api.mapper.entity.saving.NullSavingStrategy; 15 | import com.datastax.oss.driver.api.querybuilder.QueryBuilder; 16 | 17 | /** 18 | * Query implementation for Comment Dse and Mapper. 19 | * 20 | * @author DataStax Developer Advocates team. 21 | */ 22 | @SuppressWarnings("deprecation") 23 | public class CommentDaoQueryProvider implements CommentDao { 24 | 25 | private final CqlSession cqlSession; 26 | 27 | private final EntityHelper helperUser; 28 | private final EntityHelper helperVideo; 29 | 30 | private static PreparedStatement selectCommentByVideo; 31 | private static PreparedStatement selectCommentByUser; 32 | 33 | private PreparedStatement psInsertCommentUser; 34 | private PreparedStatement psDeleteCommentUser; 35 | private PreparedStatement psInsertCommentVideo; 36 | private PreparedStatement psDeleteCommentVideo; 37 | 38 | public CommentDaoQueryProvider(MapperContext context, 39 | EntityHelper helperUser, 40 | EntityHelper helperVideo) { 41 | 42 | this.cqlSession = context.getSession(); 43 | this.helperUser = helperUser; 44 | this.helperVideo = helperVideo; 45 | psInsertCommentUser = cqlSession.prepare(helperUser.insert().asCql()); 46 | psDeleteCommentUser = cqlSession.prepare(helperUser.deleteByPrimaryKey().asCql()); 47 | psInsertCommentVideo = cqlSession.prepare(helperVideo.insert().asCql()); 48 | psDeleteCommentVideo = cqlSession.prepare(helperVideo.deleteByPrimaryKey().asCql()); 49 | 50 | selectCommentByVideo = cqlSession.prepare( 51 | QueryBuilder.selectFrom(COMMENT_BY_VIDEO_TABLENAME).all() 52 | .whereColumn(COMMENT_BY_VIDEO_VIDEOID).isEqualTo(QueryBuilder.bindMarker()) 53 | .build()); 54 | selectCommentByUser = cqlSession.prepare( 55 | QueryBuilder.selectFrom(COMMENT_BY_USER_TABLENAME).all() 56 | .whereColumn(COMMENT_BY_USER_USERID).isEqualTo(QueryBuilder.bindMarker()) 57 | .build()); 58 | } 59 | 60 | /** {@inheritDoc} */ 61 | 62 | @Override 63 | public PagingIterable retrieveUserComments(UUID userid) { 64 | return cqlSession.execute(selectCommentByUser.bind(userid)).map(helperUser::get); 65 | } 66 | 67 | /** {@inheritDoc} */ 68 | @Override 69 | public PagingIterable retrieveVideoComments(UUID videoid) { 70 | return cqlSession.execute(selectCommentByVideo.bind(videoid)).map(helperVideo::get); 71 | } 72 | 73 | /** {@inheritDoc} */ 74 | @Override 75 | public void upsert(Comment comment) { 76 | cqlSession.execute(BatchStatement.builder(DefaultBatchType.LOGGED) 77 | .addStatement(bind(psInsertCommentUser, new CommentByUser(comment), helperUser)) 78 | .addStatement(bind(psInsertCommentVideo, new CommentByVideo(comment), helperVideo)) 79 | .build()); 80 | } 81 | 82 | /** {@inheritDoc} */ 83 | @Override 84 | public void delete(Comment comment) { 85 | 86 | CommentByUser cbu = new CommentByUser(); 87 | cbu.setCommentid(comment.getCommentid()); 88 | cbu.setUserid(comment.getUserid()); 89 | 90 | CommentByVideo cbv = new CommentByVideo(); 91 | cbv.setCommentid(comment.getCommentid()); 92 | cbv.setVideoid(comment.getVideoid()); 93 | 94 | cqlSession.execute( 95 | BatchStatement.builder(DefaultBatchType.LOGGED) 96 | .addStatement(bind(psDeleteCommentUser, cbu, helperUser)) 97 | .addStatement(bind(psDeleteCommentVideo, cbv, helperVideo)) 98 | .build()); 99 | } 100 | 101 | public static BoundStatement bind(PreparedStatement preparedStatement, T entity, EntityHelper entityHelper) { 102 | BoundStatementBuilder boundStatement = preparedStatement.boundStatementBuilder(); 103 | entityHelper.set(entity, boundStatement, NullSavingStrategy.DO_NOT_SET); 104 | return boundStatement.build(); 105 | } 106 | 107 | } 108 | -------------------------------------------------------------------------------- /lab-cassandra-drivers/src/test/java/com/datastax/devoxx/E08_LightweightTransactionsTest.java: -------------------------------------------------------------------------------- 1 | package com.datastax.devoxx; 2 | 3 | import static com.datastax.devoxx.schema.SchemaUtils.createTableUser; 4 | import static com.datastax.devoxx.schema.SchemaUtils.dropTableIfExists; 5 | import static com.datastax.devoxx.schema.SchemaUtils.truncateTable; 6 | 7 | import org.junit.jupiter.api.BeforeAll; 8 | import org.junit.jupiter.api.Test; 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | 12 | import com.datastax.devoxx.schema.SchemaConstants; 13 | import com.datastax.oss.driver.api.core.CqlSession; 14 | import com.datastax.oss.driver.api.core.cql.PreparedStatement; 15 | import com.datastax.oss.driver.api.querybuilder.QueryBuilder; 16 | 17 | /** 18 | * !! WARNING Tests with no Assertions here (I assume) !! 19 | * 20 | * @author cedricklunven 21 | */ 22 | public class E08_LightweightTransactionsTest implements SchemaConstants { 23 | 24 | private static Logger LOGGER = LoggerFactory.getLogger(E08_LightweightTransactionsTest.class); 25 | 26 | private static PreparedStatement stmtCreateUser; 27 | private static PreparedStatement stmtUpdateUserLwt; 28 | 29 | @BeforeAll 30 | public static void shout_init_statements() { 31 | try(CqlSession cqlSession = CqlSession.builder().build()) { 32 | dropTableIfExists(cqlSession, USER_TABLENAME); 33 | createTableUser(cqlSession); 34 | 35 | // Use PreparedStatement for queries that are executed multiple times in your application 36 | prepareStatements(cqlSession); 37 | 38 | // Empty tables for tests 39 | truncateTable(cqlSession, USER_TABLENAME); 40 | } 41 | } 42 | 43 | @Test 44 | public void should_test_batches() { 45 | try(CqlSession cqlSession = CqlSession.builder().build()) { 46 | 47 | // Insert if not exist 48 | boolean first = createUserIfNotExist(cqlSession, "clun@sample.com", "Cedric", "Lunven"); 49 | boolean second = createUserIfNotExist(cqlSession, "clun@sample.com", "Cedric", "Lunven"); 50 | LOGGER.info("+ Created first time ? {} and second time {}", first, second); 51 | 52 | // Update if condition 53 | boolean applied1 = updateIf(cqlSession, "clun@sample.com", "Cedric", "BEST"); 54 | boolean applied2 = updateIf(cqlSession, "clun@sample.com", "Cedrick", "Lunven"); 55 | LOGGER.info("+ Applied when correct value ? {} and invalid value {}", applied1, applied2); 56 | 57 | } 58 | } 59 | 60 | /** 61 | * The resultset is applied only if the record is created. If not the resultSet is populated 62 | * with existing data in DB (read) 63 | */ 64 | private static boolean createUserIfNotExist(CqlSession cqlSession, String email, String firstname, String lastname) { 65 | return cqlSession.execute(stmtCreateUser.bind(email, firstname, lastname)).wasApplied(); 66 | } 67 | 68 | /** 69 | * Note: we named the parameters as they are not in the same order in the query. 70 | */ 71 | private static boolean updateIf(CqlSession cqlSession, String email, String expectedFirstName, String newLastName) { 72 | return cqlSession.execute(stmtUpdateUserLwt.bind() 73 | .setString(USER_EMAIL, email) 74 | .setString(USER_FIRSTNAME, expectedFirstName) 75 | .setString(USER_LASTNAME, newLastName)).wasApplied(); 76 | } 77 | 78 | /** 79 | * Documentation 80 | * https://docs.datastax.com/en/developer/java-driver/3.8/manual/statements/prepared/#prepared-statements 81 | */ 82 | private static void prepareStatements(CqlSession cqlSession) { 83 | 84 | /* 85 | * INSERT INTO users (email, firstname, lastname) 86 | * VALUES(?,?,?) 87 | * IF NOT EXISTS 88 | */ 89 | stmtCreateUser = cqlSession.prepare(QueryBuilder.insertInto(USER_TABLENAME) 90 | .value(USER_EMAIL, QueryBuilder.bindMarker()) 91 | .value(USER_FIRSTNAME, QueryBuilder.bindMarker()) 92 | .value(USER_LASTNAME, QueryBuilder.bindMarker()) 93 | .ifNotExists() 94 | .build()); 95 | 96 | /* 97 | * UPDATE users SET lastname=:lastname 98 | * WHERE email=:email 99 | * IF firstname=:firstname 100 | * 101 | * Operators available for LWT Condition: 102 | * =, <, <=, >, >=, != and IN 103 | */ 104 | stmtUpdateUserLwt = cqlSession.prepare(QueryBuilder.update(USER_TABLENAME) 105 | .setColumn(USER_LASTNAME, QueryBuilder.bindMarker(USER_LASTNAME)) 106 | .whereColumn(USER_EMAIL).isEqualTo(QueryBuilder.bindMarker(USER_EMAIL)) 107 | .ifColumn(USER_FIRSTNAME).isEqualTo(QueryBuilder.bindMarker(USER_FIRSTNAME)) 108 | .build()); 109 | } 110 | 111 | } 112 | -------------------------------------------------------------------------------- /lab-cassandra-drivers/src/main/java/com/datastax/devoxx/dto/VideoDto.java: -------------------------------------------------------------------------------- 1 | package com.datastax.devoxx.dto; 2 | 3 | import java.io.Serializable; 4 | import java.time.Instant; 5 | import java.util.ArrayList; 6 | import java.util.HashMap; 7 | import java.util.HashSet; 8 | import java.util.List; 9 | import java.util.Map; 10 | import java.util.Set; 11 | import java.util.UUID; 12 | 13 | import com.fasterxml.jackson.annotation.JsonIgnore; 14 | 15 | /** 16 | * CREATE TABLE IF NOT EXISTS videos ( videoid uuid, title text, upload timestamp, email text, url text, tags set , formats 17 | * map >, PRIMARY KEY (videoid) ); 18 | */ 19 | public class VideoDto implements Serializable { 20 | 21 | /** Serial. */ 22 | private static final long serialVersionUID = -5086632646056781255L; 23 | 24 | private UUID videoid; 25 | 26 | private String title; 27 | 28 | private String email; 29 | 30 | private String url; 31 | 32 | @JsonIgnore 33 | private long upload = Instant.now().toEpochMilli(); 34 | 35 | private Set tags = new HashSet<>(); 36 | 37 | private List frames = new ArrayList<>(); 38 | 39 | private Map formats = new HashMap<>(); 40 | 41 | public VideoDto() {} 42 | 43 | public VideoDto(UUID videoId, String title, String email, String url) { 44 | super(); 45 | this.videoid = videoId; 46 | this.title = title; 47 | this.email = email; 48 | } 49 | 50 | /** 51 | * Getter accessor for attribute 'videoId'. 52 | * 53 | * @return current value of 'videoId' 54 | */ 55 | public UUID getVideoid() { 56 | return videoid; 57 | } 58 | 59 | /** 60 | * Setter accessor for attribute 'videoId'. 61 | * 62 | * @param videoId 63 | * new value for 'videoId ' 64 | */ 65 | public void setVideoid(UUID videoId) { 66 | this.videoid = videoId; 67 | } 68 | 69 | /** 70 | * Getter accessor for attribute 'title'. 71 | * 72 | * @return current value of 'title' 73 | */ 74 | public String getTitle() { 75 | return title; 76 | } 77 | 78 | /** 79 | * Setter accessor for attribute 'title'. 80 | * 81 | * @param title 82 | * new value for 'title ' 83 | */ 84 | public void setTitle(String title) { 85 | this.title = title; 86 | } 87 | 88 | /** 89 | * Getter accessor for attribute 'upload'. 90 | * 91 | * @return current value of 'upload' 92 | */ 93 | public Long getUpload() { 94 | return upload; 95 | } 96 | 97 | /** 98 | * Setter accessor for attribute 'upload'. 99 | * 100 | * @param upload 101 | * new value for 'upload ' 102 | */ 103 | public void setUpload(Long upload) { 104 | this.upload = upload; 105 | } 106 | 107 | /** 108 | * Getter accessor for attribute 'email'. 109 | * 110 | * @return current value of 'email' 111 | */ 112 | public String getEmail() { 113 | return email; 114 | } 115 | 116 | /** 117 | * Setter accessor for attribute 'email'. 118 | * 119 | * @param email 120 | * new value for 'email ' 121 | */ 122 | public void setEmail(String email) { 123 | this.email = email; 124 | } 125 | 126 | /** 127 | * Getter accessor for attribute 'tags'. 128 | * 129 | * @return current value of 'tags' 130 | */ 131 | public Set getTags() { 132 | return tags; 133 | } 134 | 135 | /** 136 | * Setter accessor for attribute 'tags'. 137 | * 138 | * @param tags 139 | * new value for 'tags ' 140 | */ 141 | public void setTags(Set tags) { 142 | this.tags = tags; 143 | } 144 | 145 | /** 146 | * Getter accessor for attribute 'formatsd'. 147 | * 148 | * @return current value of 'formatsd' 149 | */ 150 | public Map getFormats() { 151 | return formats; 152 | } 153 | 154 | /** 155 | * Setter accessor for attribute 'formatsd'. 156 | * 157 | * @param formatsd 158 | * new value for 'formatsd ' 159 | */ 160 | public void setFormats(Map formatsd) { 161 | this.formats = formatsd; 162 | } 163 | 164 | public String getUrl() { 165 | return url; 166 | } 167 | 168 | public void setUrl(String url) { 169 | this.url = url; 170 | } 171 | 172 | /** 173 | * Getter accessor for attribute 'frames'. 174 | * 175 | * @return current value of 'frames' 176 | */ 177 | public List getFrames() { 178 | return frames; 179 | } 180 | 181 | /** 182 | * Setter accessor for attribute 'frames'. 183 | * 184 | * @param frames 185 | * new value for 'frames ' 186 | */ 187 | public void setFrames(List frames) { 188 | this.frames = frames; 189 | } 190 | 191 | } 192 | -------------------------------------------------------------------------------- /lab-cassandra-drivers/src/test/java/com/datastax/devoxx/E05_CountersTest.java: -------------------------------------------------------------------------------- 1 | package com.datastax.devoxx; 2 | 3 | import static com.datastax.devoxx.schema.SchemaUtils.createTableVideoViews; 4 | import static com.datastax.devoxx.schema.SchemaUtils.truncateTable; 5 | 6 | import java.util.Optional; 7 | import java.util.UUID; 8 | 9 | import org.junit.jupiter.api.BeforeAll; 10 | import org.junit.jupiter.api.Test; 11 | import org.slf4j.Logger; 12 | import org.slf4j.LoggerFactory; 13 | 14 | import com.datastax.devoxx.schema.SchemaConstants; 15 | import com.datastax.oss.driver.api.core.CqlSession; 16 | import com.datastax.oss.driver.api.core.cql.PreparedStatement; 17 | import com.datastax.oss.driver.api.core.cql.Row; 18 | import com.datastax.oss.driver.api.querybuilder.QueryBuilder; 19 | 20 | /** 21 | * !! WARNING Tests with no Assertions here (I assume) !! 22 | * 23 | * @author cedricklunven 24 | */ 25 | public class E05_CountersTest implements SchemaConstants { 26 | 27 | private static Logger LOGGER = LoggerFactory.getLogger(E05_CountersTest.class); 28 | 29 | private static PreparedStatement stmtIncrement; 30 | private static PreparedStatement stmtDecrement; 31 | private static PreparedStatement stmtFindById; 32 | private static PreparedStatement stmtDelete; 33 | 34 | @BeforeAll 35 | public static void shout_init_statements() { 36 | 37 | try(CqlSession cqlSession = CqlSession.builder().build()) { 38 | 39 | // Create tables for tests 40 | createTableVideoViews(cqlSession); 41 | 42 | // Empty tables for tests 43 | truncateTable(cqlSession, VIDEO_VIEWS_TABLENAME); 44 | 45 | // Prepare your statements once and execute multiple times 46 | prepareStatements(cqlSession); 47 | } 48 | } 49 | 50 | @Test 51 | public void should_test_counters() { 52 | 53 | try(CqlSession cqlSession = CqlSession.builder().build()) { 54 | 55 | // We cannot insert in a table with a counter 56 | UUID videoId = UUID.randomUUID(); 57 | LOGGER.info("+ Video views {}", findById(cqlSession, videoId)); 58 | 59 | // ========= UPDATE ============ 60 | 61 | incrementBy(cqlSession, videoId, 10); 62 | LOGGER.info("+ Video views : {}", findById(cqlSession, videoId).get()); 63 | 64 | decrementBy(cqlSession, videoId, 8); 65 | LOGGER.info("+ Video views : {}", findById(cqlSession, videoId).get()); 66 | 67 | // ========= DELETE ============ 68 | 69 | delete(cqlSession, videoId); 70 | LOGGER.info("+ Video views {}", findById(cqlSession, videoId)); 71 | 72 | } 73 | } 74 | 75 | private static Optional findById(CqlSession cqlSession, UUID videoid) { 76 | Row record = cqlSession.execute(stmtFindById.bind(videoid)).one(); 77 | if (null != record) { 78 | return Optional.of(record.getLong(VIDEO_VIEWS_VIEWS)); 79 | } 80 | return Optional.empty(); 81 | } 82 | 83 | private static void incrementBy(CqlSession cqlSession, UUID videoid, long val) { 84 | cqlSession.execute(stmtIncrement.bind(val, videoid)); 85 | } 86 | 87 | private static void decrementBy(CqlSession cqlSession, UUID videoid, long val) { 88 | cqlSession.execute(stmtDecrement.bind(val, videoid)); 89 | } 90 | 91 | private static void delete(CqlSession cqlSession, UUID videoid) { 92 | cqlSession.execute(stmtDelete.bind(videoid)); 93 | } 94 | 95 | private static void prepareStatements(CqlSession cqlSession) { 96 | 97 | // update videos_views SET views = views + X WHERE videoid=... 98 | stmtIncrement = cqlSession.prepare(QueryBuilder 99 | .update(VIDEO_VIEWS_TABLENAME) 100 | .increment(VIDEO_VIEWS_VIEWS, QueryBuilder.bindMarker()) 101 | .whereColumn(VIDEO_VIEWS_VIDEOID).isEqualTo(QueryBuilder.bindMarker()) 102 | .build()); 103 | 104 | // update videos_views SET views = views + X WHERE videoid=.. 105 | stmtDecrement = cqlSession.prepare(QueryBuilder 106 | .update(VIDEO_VIEWS_TABLENAME) 107 | .decrement(VIDEO_VIEWS_VIEWS, QueryBuilder.bindMarker()) 108 | .whereColumn(VIDEO_VIEWS_VIDEOID).isEqualTo(QueryBuilder.bindMarker()) 109 | .build()); 110 | 111 | // SELECT views FROM videos_views WHERE videoid=... 112 | stmtFindById = cqlSession.prepare(QueryBuilder 113 | .selectFrom(VIDEO_VIEWS_TABLENAME).column(VIDEO_VIEWS_VIEWS) 114 | .whereColumn(VIDEO_VIEWS_VIDEOID).isEqualTo(QueryBuilder.bindMarker()) 115 | .build()); 116 | 117 | // DELETE FROM videos_views WHERE videoid=... 118 | stmtDelete = cqlSession.prepare(QueryBuilder 119 | .deleteFrom(VIDEO_VIEWS_TABLENAME) 120 | .whereColumn(VIDEO_VIEWS_VIDEOID).isEqualTo(QueryBuilder.bindMarker()) 121 | .build()); 122 | 123 | } 124 | 125 | } 126 | -------------------------------------------------------------------------------- /lab-cassandra-drivers/src/test/java/com/datastax/devoxx/E12_ObjectMappingTest.java: -------------------------------------------------------------------------------- 1 | package com.datastax.devoxx; 2 | 3 | import static com.datastax.devoxx.schema.SchemaUtils.createTableCommentByUser; 4 | import static com.datastax.devoxx.schema.SchemaUtils.createTableCommentByVideo; 5 | import static com.datastax.devoxx.schema.SchemaUtils.truncateTable; 6 | 7 | import java.util.UUID; 8 | 9 | import org.junit.jupiter.api.BeforeAll; 10 | import org.junit.jupiter.api.MethodOrderer.OrderAnnotation; 11 | import org.junit.jupiter.api.Order; 12 | import org.junit.jupiter.api.Test; 13 | import org.junit.jupiter.api.TestMethodOrder; 14 | import org.slf4j.Logger; 15 | import org.slf4j.LoggerFactory; 16 | 17 | import com.datastax.devoxx.objectmapping.Comment; 18 | import com.datastax.devoxx.objectmapping.CommentByUser; 19 | import com.datastax.devoxx.objectmapping.CommentByVideo; 20 | import com.datastax.devoxx.objectmapping.CommentDao; 21 | import com.datastax.devoxx.objectmapping.CommentDaoMapper; 22 | import com.datastax.devoxx.schema.SchemaConstants; 23 | import com.datastax.oss.driver.api.core.CqlSession; 24 | 25 | /** 26 | * !! WARNING Tests with no Assertions here (I assume) !! 27 | * 28 | * @author cedricklunven 29 | */ 30 | @TestMethodOrder(OrderAnnotation.class) 31 | public class E12_ObjectMappingTest implements SchemaConstants { 32 | 33 | private static Logger LOGGER = LoggerFactory.getLogger(E12_ObjectMappingTest.class); 34 | 35 | // DataSet 36 | private static UUID user_1 = UUID.randomUUID(); 37 | private static UUID user_2 = UUID.randomUUID(); 38 | private static UUID videoid_1 = UUID.randomUUID(); 39 | private static UUID videoid_2 = UUID.randomUUID(); 40 | private static Comment c1 = new Comment(user_1, videoid_1, "I am user1 and video1 is good"); 41 | private static Comment c2 = new Comment(user_2, videoid_1, "I am user2 and video1 is bad"); 42 | private static Comment c3 = new Comment(user_1, videoid_2, "Video2 is cool"); 43 | private static Comment c4 = new Comment(user_2, videoid_2, "Video2"); 44 | 45 | @BeforeAll 46 | public static void shout_init_statements() { 47 | try(CqlSession cqlSession = CqlSession.builder().build()) { 48 | 49 | // Create working table User (if needed) 50 | createTableCommentByUser(cqlSession); 51 | createTableCommentByVideo(cqlSession); 52 | 53 | // Comments are used in 2 queries, we need 2 tables to store it 54 | truncateTable(cqlSession, COMMENT_BY_USER_TABLENAME); 55 | truncateTable(cqlSession, COMMENT_BY_VIDEO_TABLENAME); 56 | } 57 | } 58 | 59 | @Test 60 | @Order(1) 61 | public void should_insert() { 62 | try(CqlSession cqlSession = CqlSession.builder().build()) { 63 | CommentDao dao = CommentDaoMapper.builder(cqlSession) 64 | .withDefaultKeyspace(cqlSession.getKeyspace().get()) 65 | .build().commentDao(); 66 | 67 | dao.upsert(c1);dao.upsert(c2); 68 | dao.upsert(c3);dao.upsert(c4); 69 | dao.retrieveVideoComments(videoid_2).all() 70 | .stream().map(CommentByVideo::getComment) 71 | .forEach(LOGGER::info); 72 | } 73 | } 74 | 75 | @Test 76 | @Order(2) 77 | public void should_delete() { 78 | try(CqlSession cqlSession = CqlSession.builder().build()) { 79 | c1.setComment("This is my new comment"); 80 | CommentDao dao = CommentDaoMapper.builder(cqlSession) 81 | .withDefaultKeyspace(cqlSession.getKeyspace().get()) 82 | .build().commentDao(); 83 | dao.upsert(c1); 84 | dao.retrieveVideoComments(videoid_1).all() 85 | .stream().map(CommentByVideo::getComment) 86 | .forEach(LOGGER::info); 87 | 88 | /* =============== DELETE =========================== 89 | * Delete one comment (in 2 tables with BATCH) == 90 | * Note that commentId is NOT ENOUGH as userid and == 91 | * videoid are part of the the primary keys. == 92 | * ==================================================*/ 93 | dao.delete(c1); 94 | dao.retrieveVideoComments(videoid_1).all() 95 | .stream().map(CommentByVideo::getComment) 96 | .forEach(LOGGER::info); 97 | 98 | /* 99 | * ============================ READ ================================ 100 | * == Query1: List comments for user_1 with table comment_by_user = 101 | * == Query2: List comments for video_2 with table comment_by_video = 102 | * ================================================================== 103 | */ 104 | 105 | dao.retrieveUserComments(videoid_2).all() 106 | .stream().map(CommentByUser::getComment) 107 | .forEach(LOGGER::info); 108 | 109 | dao.retrieveVideoComments(videoid_2).all() 110 | .stream().map(CommentByVideo::getComment) 111 | .forEach(LOGGER::info); 112 | 113 | } 114 | } 115 | 116 | } 117 | -------------------------------------------------------------------------------- /lab-cassandra-drivers/src/test/java/com/datastax/devoxx/E02_StatementsTest.java: -------------------------------------------------------------------------------- 1 | package com.datastax.devoxx; 2 | 3 | import java.time.Duration; 4 | 5 | import org.junit.jupiter.api.Test; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | import com.datastax.devoxx.schema.SchemaConstants; 10 | import com.datastax.oss.driver.api.core.ConsistencyLevel; 11 | import com.datastax.oss.driver.api.core.CqlSession; 12 | import com.datastax.oss.driver.api.core.cql.BoundStatement; 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.querybuilder.QueryBuilder; 16 | import com.datastax.oss.driver.shaded.guava.common.collect.ImmutableMap; 17 | 18 | /** 19 | * !! WARNING Tests with no Assertions here (I assume) !! 20 | * 21 | * @author cedricklunven 22 | */ 23 | public class E02_StatementsTest implements SchemaConstants { 24 | 25 | private static Logger LOGGER = LoggerFactory.getLogger(E02_StatementsTest.class); 26 | 27 | @Test 28 | public void should_execute_simple_statements() { 29 | 30 | try(CqlSession cqlSession = CqlSession.builder().build()) { 31 | 32 | // Execute Queries as STRING (never do THAT) 33 | cqlSession.execute("" 34 | + "INSERT INTO users (email, firstname, lastname) " 35 | + "VALUES ('clun@sample.com', 'Cedrick', 'Lunven')"); 36 | LOGGER.info("+ Insert as a String"); 37 | 38 | // String is actually a Statement 39 | cqlSession.execute(SimpleStatement.newInstance( 40 | "INSERT INTO users (email, firstname, lastname) " 41 | + "VALUES ('clun2@sample.com', 'Cedrick', 'Lunven')")); 42 | LOGGER.info("+ Insert as a Statement"); 43 | 44 | // #2.a Externalize parameters with '?' 45 | 46 | // -- option1: one by one 47 | cqlSession.execute(SimpleStatement 48 | .builder("INSERT INTO users (email, firstname, lastname) VALUES (?,?,?)") 49 | .addPositionalValue("clun3@gmail.com") 50 | .addPositionalValue("Cedrick") 51 | .addPositionalValue("Lunven").build()); 52 | LOGGER.info("+ Insert and externalize var with ?, option1"); 53 | 54 | // -- option2: all at once 55 | cqlSession.execute(SimpleStatement 56 | .builder("INSERT INTO users (email, firstname, lastname) VALUES (?,?,?)") 57 | .addPositionalValues("clun4@gmail.com", "Cedrick", "Lunven").build()); 58 | LOGGER.info("+ Insert and externalize var with ?, option2"); 59 | 60 | // #2.b Externalize parameters with labels:name 61 | 62 | // -- option1: one by one 63 | cqlSession.execute(SimpleStatement 64 | .builder("INSERT INTO users (email, firstname, lastname) VALUES (:e,:f,:l)") 65 | .addNamedValue("e", "clun5@gmail.com") 66 | .addNamedValue("f", "Cedrick") 67 | .addNamedValue("l", "Lunven").build()); 68 | LOGGER.info("+ Insert and externalize var with :labels, option1"); 69 | 70 | // -- option2: all at once 71 | cqlSession.execute(SimpleStatement 72 | .builder("INSERT INTO users (email, firstname, lastname) VALUES (:e,:f,:l)") 73 | .setConsistencyLevel(ConsistencyLevel.LOCAL_QUORUM) 74 | .setTimeout(Duration.ofSeconds(2)) 75 | .build() 76 | .setNamedValues(ImmutableMap.of( 77 | "e", "clun6@gmail.com", 78 | "f", "Cedrick", 79 | "l", "Lunven"))); 80 | LOGGER.info("+ Insert and externalize var with :labels, option2"); 81 | } 82 | } 83 | 84 | @Test 85 | public void should_execute_query_builder() { 86 | 87 | try(CqlSession cqlSession = CqlSession.builder().build()) { 88 | // Utilisation du QueryBuilder pour construire les requetes 89 | cqlSession.execute(QueryBuilder 90 | .insertInto(USER_TABLENAME) 91 | .value(USER_EMAIL, QueryBuilder.literal("clun5@gmail.com")) 92 | .value(USER_FIRSTNAME, QueryBuilder.literal("Cedrick")) 93 | .value(USER_LASTNAME, QueryBuilder.literal("Lunven")) 94 | .build()); 95 | LOGGER.info("+ Insert with QueryBuilder"); 96 | } 97 | } 98 | 99 | @Test 100 | public void should_prepare_statements() { 101 | 102 | try(CqlSession cqlSession = CqlSession.builder().build()) { 103 | // #5. il faut preparer ses statements 104 | 105 | // 5.a Parameteres avec `?` 106 | PreparedStatement ps1 = cqlSession.prepare("INSERT INTO users (email, firstname, lastname) " 107 | + "VALUES (?,?,?)"); 108 | BoundStatement bs1 = ps1.bind("clun6@gmail.com", "Cedrick", "Lunven"); 109 | cqlSession.execute(bs1); 110 | LOGGER.info("+ Insert with PrepareStatements"); 111 | 112 | 113 | // 5.b Pour utiliser un prepare statement par la suite on bind les valeurs avec 'bindMarker' 114 | PreparedStatement ps2 = cqlSession.prepare(QueryBuilder 115 | .insertInto(USER_TABLENAME) 116 | .value(USER_EMAIL, QueryBuilder.bindMarker()) 117 | .value(USER_FIRSTNAME, QueryBuilder.bindMarker()) 118 | .value(USER_LASTNAME, QueryBuilder.bindMarker()) 119 | .build()); 120 | cqlSession.execute(ps2.bind("clun7@gmail.com", "Cedrick", "Lunven")); 121 | LOGGER.info("+ Insert with PrepareStatements + QueryBuilder"); 122 | } 123 | } 124 | 125 | 126 | 127 | 128 | 129 | } 130 | -------------------------------------------------------------------------------- /lab-quarkus/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | com.datastax.samples 6 | lab-quarkus 7 | 0.0.1-SNAPSHOT 8 | 9 | 10 | UTF-8 11 | UTF-8 12 | 2.13.1.Final 13 | true 14 | 3.8.1 15 | 17 16 | 17 17 | 3.0.0-M5 18 | 19 | 20 | 21 | 22 | 23 | io.quarkus.platform 24 | quarkus-bom 25 | ${quarkus.platform.version} 26 | pom 27 | import 28 | 29 | 30 | 31 | 32 | 33 | io.quarkus 34 | quarkus-resteasy-reactive 35 | 36 | 37 | io.quarkus 38 | quarkus-resteasy-reactive-jackson 39 | 40 | 41 | com.datastax.oss.quarkus 42 | cassandra-quarkus-client 43 | 1.1.2 44 | 45 | 46 | com.datastax.oss 47 | java-driver-mapper-runtime 48 | 4.15.0 49 | 50 | 51 | io.quarkus 52 | quarkus-micrometer 53 | 54 | 55 | io.quarkus 56 | quarkus-micrometer-registry-prometheus 57 | 58 | 59 | io.quarkus 60 | quarkus-smallrye-openapi 61 | 62 | 63 | io.quarkus 64 | quarkus-smallrye-health 65 | 66 | 67 | io.quarkus 68 | quarkus-junit5 69 | test 70 | 71 | 72 | io.rest-assured 73 | rest-assured 74 | test 75 | 76 | 77 | io.quarkus 78 | quarkus-kubernetes 79 | 80 | 81 | io.quarkus 82 | quarkus-container-image-jib 83 | 84 | 85 | 86 | 87 | 88 | io.quarkus.platform 89 | quarkus-maven-plugin 90 | ${quarkus.platform.version} 91 | true 92 | 93 | 94 | 95 | build 96 | generate-code 97 | generate-code-tests 98 | 99 | 100 | 101 | 102 | 103 | maven-compiler-plugin 104 | ${compiler-plugin.version} 105 | 106 | 107 | 108 | com.datastax.oss 109 | java-driver-mapper-processor 110 | 4.15.0 111 | 112 | 113 | 114 | 115 | 116 | maven-surefire-plugin 117 | ${surefire-plugin.version} 118 | 119 | 120 | org.jboss.logmanager.LogManager 121 | ${maven.home} 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | native 130 | 131 | 132 | native 133 | 134 | 135 | 136 | 137 | 138 | maven-failsafe-plugin 139 | ${surefire-plugin.version} 140 | 141 | 142 | 143 | integration-test 144 | verify 145 | 146 | 147 | 148 | ${project.build.directory}/${project.build.finalName}-runner 149 | org.jboss.logmanager.LogManager 150 | ${maven.home} 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | native 160 | 161 | 162 | 163 | 164 | -------------------------------------------------------------------------------- /lab-micronaut/src/main/java/com/datastaxdev/todo/TodoRestController.java: -------------------------------------------------------------------------------- 1 | package com.datastaxdev.todo; 2 | 3 | import java.net.URI; 4 | import java.net.URISyntaxException; 5 | import java.util.List; 6 | import java.util.Optional; 7 | import java.util.UUID; 8 | import java.util.stream.Collectors; 9 | 10 | import javax.validation.constraints.NotEmpty; 11 | import javax.validation.constraints.NotNull; 12 | 13 | import com.datastax.oss.driver.api.core.CqlSession; 14 | import com.datastaxdev.TodoDto; 15 | import com.datastaxdev.TodoService; 16 | import com.datastaxdev.todo.cassandra.TodoServiceCassandraCql; 17 | import com.datastaxdev.todo.web.Todo; 18 | 19 | import io.micronaut.http.HttpRequest; 20 | import io.micronaut.http.HttpResponse; 21 | import io.micronaut.http.annotation.Body; 22 | import io.micronaut.http.annotation.Controller; 23 | import io.micronaut.http.annotation.Delete; 24 | import io.micronaut.http.annotation.Get; 25 | import io.micronaut.http.annotation.Patch; 26 | import io.micronaut.http.annotation.PathVariable; 27 | import io.micronaut.http.annotation.Post; 28 | import io.micronaut.http.context.ServerRequestContext; 29 | import io.micronaut.http.uri.UriBuilder; 30 | import io.micronaut.validation.Validated; 31 | import jakarta.inject.Inject; 32 | 33 | @Validated 34 | @Controller("/api/v1") 35 | public class TodoRestController { 36 | 37 | /** CqlSession initialized from application.yaml */ 38 | @Inject 39 | private CqlSession cqlSession; 40 | 41 | /** Todo service reference. */ 42 | private TodoService repo; 43 | 44 | @Get(value = "/{user}/todos/") 45 | public List findAllByUser( 46 | @PathVariable(value = "user") @NotEmpty String user) { 47 | return getTodoService().findByUser(user) 48 | .stream() 49 | .map(this::fromDto) 50 | .map(t -> populateUrlWithId(t, ServerRequestContext.currentRequest().get())) 51 | .collect(Collectors.toList()); 52 | } 53 | 54 | @Get("/{user}/todos/{uid}") 55 | public HttpResponse findById( 56 | @PathVariable(value = "user") @NotEmpty String user, 57 | @PathVariable(value = "uid") @NotEmpty String itemId) { 58 | Optional e = getTodoService().findById(user, UUID.fromString(itemId)); 59 | if (!e.isPresent()) return HttpResponse.notFound(); 60 | Todo todo = fromDto(e.get()); 61 | populateUrl(todo, ServerRequestContext.currentRequest().get()); 62 | //LOGGER.info("Find user={}, TODO={}", user, todo); 63 | return HttpResponse.ok(todo); 64 | } 65 | 66 | @Post("/{user}/todos/") 67 | public HttpResponse create( 68 | @PathVariable(value = "user") String user, 69 | @Body @NotNull Todo todoReq) throws URISyntaxException { 70 | TodoDto te = toDto(todoReq, user); 71 | te = getTodoService().save(te); 72 | todoReq.setUuid(te.getItemId()); 73 | populateUrlWithId(todoReq, ServerRequestContext.currentRequest().get()); 74 | //LOGGER.info("Created user={}, TODO={}", user, todoReq); 75 | return HttpResponse.created(new URI(todoReq.getUrl())).body(todoReq); 76 | } 77 | 78 | @Patch("/{user}/todos/{uid}") 79 | public HttpResponse update( 80 | @PathVariable(value = "user") @NotEmpty String user, 81 | @PathVariable(value = "uid") @NotEmpty String itemId, 82 | @Body @NotNull Todo todo) 83 | throws URISyntaxException { 84 | //LOGGER.info("Updating user={} id={} with TODO {}", user, itemId, todo); 85 | Optional e = getTodoService().findById(user, UUID.fromString(itemId)); 86 | if (!e.isPresent()) return HttpResponse.notFound(); 87 | todo.setUuid(UUID.fromString(itemId)); 88 | TodoDto todoDto = toDto(todo, user); 89 | todoDto = getTodoService().save(todoDto); 90 | populateUrl(todo, ServerRequestContext.currentRequest().get()); 91 | return HttpResponse.ok(todo); 92 | } 93 | 94 | @Delete("/{user}/todos/{uid}") 95 | public HttpResponse deleteById( 96 | @PathVariable(value = "user") String user, 97 | @PathVariable(value = "uid") String uid) { 98 | //LOGGER.info("Delete TODO id={} for user={}", uid, user); 99 | if (!getTodoService().findById(user, UUID.fromString(uid)).isPresent()) { 100 | return HttpResponse.notFound(); 101 | } 102 | getTodoService().deleteById(user, UUID.fromString(uid)); 103 | return HttpResponse.noContent(); 104 | } 105 | 106 | @Delete("/{user}/todos/") 107 | public HttpResponse deleteAllByUser(@PathVariable(value = "user") String user) { 108 | getTodoService().deleteByUser(user); 109 | return HttpResponse.noContent(); 110 | } 111 | 112 | /** 113 | * Access todo service. 114 | * 115 | * @return 116 | * todo services 117 | */ 118 | public TodoService getTodoService() { 119 | if (repo == null) { 120 | repo = new TodoServiceCassandraCql(cqlSession); 121 | } 122 | return repo; 123 | } 124 | 125 | private Todo fromDto(TodoDto te) { 126 | Todo todo = new Todo(); 127 | todo.setTitle(te.getTitle()); 128 | todo.setUuid(te.getItemId()); 129 | todo.setCompleted(te.getCompleted()); 130 | return todo; 131 | } 132 | 133 | private TodoDto toDto(Todo te, String user) { 134 | TodoDto dto = new TodoDto(); 135 | dto.setUserId(user); 136 | dto.setItemId(te.getUuid()); 137 | dto.setTitle(te.getTitle()); 138 | dto.setCompleted(te.isCompleted()); 139 | return dto; 140 | } 141 | 142 | private Todo populateUrlWithId(Todo t, HttpRequest req) { 143 | String fullUrl = new StringBuilder("http://") 144 | .append(req.getServerAddress().getHostName()) 145 | .append(":") 146 | .append(req.getServerAddress().getPort()) 147 | .append(UriBuilder.of(req.getUri()).path(t.getUuid().toString())) 148 | .toString(); 149 | if (fullUrl.contains("gitpod")) { 150 | fullUrl.replaceAll("http://", "https://"); 151 | } 152 | t.setUrl(fullUrl); 153 | return t; 154 | } 155 | 156 | private Todo populateUrl(Todo t, HttpRequest req) { 157 | String fullUrl = new StringBuilder("http://") 158 | .append(req.getServerAddress().getHostName()) 159 | .append(":") 160 | .append(req.getServerAddress().getPort()) 161 | .append(UriBuilder.of(req.getUri())) 162 | .toString(); 163 | if (fullUrl.contains("gitpod")) { 164 | fullUrl.replaceAll("http://", "https://"); 165 | } 166 | t.setUrl(fullUrl); 167 | return t; 168 | } 169 | } -------------------------------------------------------------------------------- /lab-quarkus/src/main/java/com/datastaxdev/todo/TodoRestController.java: -------------------------------------------------------------------------------- 1 | package com.datastaxdev.todo; 2 | 3 | import java.net.URI; 4 | import java.net.URISyntaxException; 5 | import java.util.List; 6 | import java.util.Optional; 7 | import java.util.UUID; 8 | import java.util.stream.Collectors; 9 | 10 | import javax.enterprise.context.ApplicationScoped; 11 | import javax.enterprise.event.Observes; 12 | import javax.inject.Inject; 13 | import javax.ws.rs.Consumes; 14 | import javax.ws.rs.DELETE; 15 | import javax.ws.rs.GET; 16 | import javax.ws.rs.PATCH; 17 | import javax.ws.rs.POST; 18 | import javax.ws.rs.Path; 19 | import javax.ws.rs.PathParam; 20 | import javax.ws.rs.Produces; 21 | import javax.ws.rs.core.Context; 22 | import javax.ws.rs.core.MediaType; 23 | import javax.ws.rs.core.Response; 24 | import javax.ws.rs.core.Response.Status; 25 | import javax.ws.rs.core.UriInfo; 26 | 27 | import com.datastax.oss.quarkus.runtime.api.session.QuarkusCqlSession; 28 | import com.datastaxdev.todo.cassandra.TodoServiceCassandraCql; 29 | import com.datastaxdev.todo.web.Todo; 30 | 31 | import io.quarkus.runtime.StartupEvent; 32 | import io.smallrye.common.annotation.Blocking; 33 | 34 | /** 35 | * Expose the todo Interface. 36 | * 37 | * @author Cedrick LUNVEN (@clunven) 38 | * 39 | * @see https://quarkus.io/guides/rest-json 40 | */ 41 | @ApplicationScoped 42 | @Path("/api/v1") 43 | public class TodoRestController { 44 | 45 | @Inject 46 | QuarkusCqlSession cqlSession; 47 | 48 | @Context 49 | UriInfo uriInfo; 50 | 51 | /** Todo service reference. */ 52 | private TodoService todoService; 53 | 54 | /** 55 | * Initialized at beginning of the Application. 56 | * 57 | * @param ev 58 | * startup event 59 | * @return 60 | * if the operation is applied 61 | */ 62 | public boolean onStart(@Observes StartupEvent ev){ 63 | TodoServiceCassandraCql.createTableTodo(cqlSession); 64 | return true; 65 | } 66 | 67 | @GET 68 | @Path("/{user}/todos/") 69 | @Blocking 70 | @Produces(MediaType.APPLICATION_JSON) 71 | public List findAllByUser(@PathParam(value = "user") String user) { 72 | return getTodoService().findByUser(user) 73 | .stream() 74 | .map(this::fromDto) 75 | .map(t -> populateUrlWithId(t)) 76 | .collect(Collectors.toList()); 77 | } 78 | 79 | @GET 80 | @Path("/{user}/todos/{uid}") 81 | @Blocking 82 | @Produces(MediaType.APPLICATION_JSON) 83 | public Response findById( 84 | @PathParam(value = "user") String user, 85 | @PathParam(value = "uid") String itemId) { 86 | Optional e = getTodoService().findById(user, UUID.fromString(itemId)); 87 | if (e.isEmpty()) return Response.status(Status.NOT_FOUND).build(); 88 | Todo todo = fromDto(e.get()); 89 | populateUrl(todo); 90 | return Response.ok(todo).build(); 91 | } 92 | 93 | @POST 94 | @Path("/{user}/todos/") 95 | @Blocking 96 | @Produces(MediaType.APPLICATION_JSON) 97 | @Consumes(MediaType.APPLICATION_JSON) 98 | public Response create( 99 | @PathParam(value = "user") String user, 100 | Todo todoReq) throws URISyntaxException { 101 | TodoDto te = toDto(todoReq, user); 102 | te = getTodoService().save(te); 103 | todoReq.setUuid(te.getItemId()); 104 | populateUrlWithId(todoReq); 105 | return Response 106 | .created(new URI(todoReq.getUrl())) 107 | .entity(todoReq) 108 | .build(); 109 | } 110 | 111 | @PATCH 112 | @Path("/{user}/todos/{uid}") 113 | @Blocking 114 | @Produces(MediaType.APPLICATION_JSON) 115 | @Consumes(MediaType.APPLICATION_JSON) 116 | public Response update( 117 | @PathParam(value = "user") String user, 118 | @PathParam(value = "uid") String itemId, 119 | Todo todo) 120 | throws URISyntaxException { 121 | Optional e = getTodoService().findById(user, UUID.fromString(itemId)); 122 | if (e.isEmpty()) return Response.status(Status.NOT_FOUND).build(); 123 | todo.setUuid(UUID.fromString(itemId)); 124 | TodoDto todoDto = toDto(todo, user); 125 | todoDto = getTodoService().save(todoDto); 126 | populateUrl(todo); 127 | return Response.ok().entity(todo).build(); 128 | } 129 | 130 | @DELETE 131 | @Path("/{user}/todos/{uid}") 132 | @Blocking 133 | public Response deleteById( 134 | @PathParam(value = "user") String user, 135 | @PathParam(value = "uid") String uid) { 136 | if (getTodoService().findById(user, UUID.fromString(uid)).isEmpty()) { 137 | return Response.status(Status.NOT_FOUND).build(); 138 | } 139 | getTodoService().deleteById(user, UUID.fromString(uid)); 140 | return Response.noContent().build(); 141 | } 142 | 143 | @DELETE 144 | @Path("/{user}/todos/") 145 | public Response deleteAllByUser(@PathParam(value = "user") String user) { 146 | getTodoService().deleteByUser(user); 147 | return Response.noContent().build(); 148 | } 149 | 150 | /** 151 | * Access todo service. 152 | * 153 | * @return 154 | * todo services 155 | */ 156 | public TodoService getTodoService() { 157 | if (todoService == null) { 158 | todoService = new TodoServiceCassandraCql(cqlSession); 159 | //todoService = new TodoServicesCassandraOM(cqlSession); 160 | } 161 | return todoService; 162 | } 163 | 164 | private Todo fromDto(TodoDto te) { 165 | Todo todo = new Todo(); 166 | todo.setTitle(te.getTitle()); 167 | todo.setUuid(te.getItemId()); 168 | todo.setCompleted(te.getCompleted()); 169 | return todo; 170 | } 171 | 172 | private TodoDto toDto(Todo te, String user) { 173 | TodoDto dto = new TodoDto(); 174 | dto.setUserId(user); 175 | dto.setItemId(te.getUuid()); 176 | dto.setTitle(te.getTitle()); 177 | dto.setCompleted(te.isCompleted()); 178 | return dto; 179 | } 180 | 181 | private Todo populateUrlWithId(Todo t) { 182 | String url = uriInfo.getAbsolutePathBuilder().scheme("http").build().toString(); 183 | if (url.contains("gitpod")) { 184 | url.replaceAll("http://", "https://"); 185 | } 186 | url += t.getUuid().toString(); 187 | t.setUrl(url); 188 | return t; 189 | } 190 | 191 | private Todo populateUrl(Todo t) { 192 | String url = uriInfo.getAbsolutePathBuilder().scheme("http").build().toString(); 193 | if (url.contains("gitpod")) { 194 | url.replaceAll("http://", "https://"); 195 | } 196 | t.setUrl(url); 197 | return t; 198 | } 199 | 200 | } 201 | -------------------------------------------------------------------------------- /lab-micronaut/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | com.datastaxdev 7 | lab-micronaut 8 | lab-micronaut 9 | jar 10 | 0.1.0-SNAPSHOT 11 | 12 | 13 | io.micronaut 14 | micronaut-parent 15 | 3.7.1 16 | 17 | 18 | 19 | 17 20 | 4.15.0 21 | 2.13.4 22 | 23 | 1.9.0 24 | 5.9.0 25 | 26 | com.datastaxdev.TodoApplication 27 | netty 28 | 3.4.0 29 | 3.8.1 30 | 2.22.2 31 | 32 | 33 | 34 | 35 | 36 | 37 | com.fasterxml.jackson 38 | jackson-bom 39 | ${jackson.version} 40 | import 41 | pom 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | com.datastax.oss 51 | java-driver-core 52 | ${java-driver.version} 53 | 54 | 55 | com.datastax.oss 56 | java-driver-query-builder 57 | ${java-driver.version} 58 | 59 | 60 | com.datastax.oss 61 | java-driver-mapper-runtime 62 | ${java-driver.version} 63 | 64 | 65 | com.datastax.oss 66 | java-driver-mapper-processor 67 | ${java-driver.version} 68 | 69 | 70 | 71 | 72 | ch.qos.logback 73 | logback-classic 74 | 75 | 76 | 77 | jakarta.annotation 78 | jakarta.annotation-api 79 | compile 80 | 81 | 82 | 83 | 84 | io.micronaut 85 | micronaut-http-server-netty 86 | compile 87 | 88 | 89 | io.micronaut 90 | micronaut-inject 91 | compile 92 | 93 | 94 | io.micronaut 95 | micronaut-inject-java 96 | compile 97 | 98 | 99 | org.slf4j 100 | slf4j-simple 101 | 102 | 103 | 104 | 105 | io.micronaut 106 | micronaut-validation 107 | compile 108 | 109 | 110 | io.micronaut 111 | micronaut-runtime 112 | compile 113 | 114 | 115 | io.micronaut.cassandra 116 | micronaut-cassandra 117 | compile 118 | 119 | 120 | io.micronaut.test 121 | micronaut-test-junit5 122 | test 123 | 124 | 125 | io.micronaut 126 | micronaut-inject-java-test 127 | test 128 | 129 | 130 | 131 | 132 | io.micronaut 133 | micronaut-http-client 134 | compile 135 | 136 | 137 | org.junit.jupiter 138 | junit-jupiter-api 139 | test 140 | 141 | 142 | org.junit.jupiter 143 | junit-jupiter-engine 144 | test 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | org.apache.maven.plugins 153 | maven-surefire-plugin 154 | ${maven.plugin.surefire.version} 155 | 156 | 157 | 158 | io.micronaut.build 159 | micronaut-maven-plugin 160 | 161 | 162 | 163 | org.apache.maven.plugins 164 | maven-compiler-plugin 165 | ${maven.plugin.compiler.version} 166 | 167 | ${java.version} 168 | ${java.version} 169 | false 170 | 172 | 173 | com.datastax.oss 174 | java-driver-mapper-processor 175 | ${java-driver.version} 176 | 177 | 178 | io.micronaut 179 | micronaut-inject-java 180 | ${micronaut.version} 181 | 182 | 183 | io.micronaut 184 | micronaut-validation 185 | ${micronaut.version} 186 | 187 | 188 | io.micronaut 189 | micronaut-http-validation 190 | ${micronaut.version} 191 | 192 | 193 | io.micronaut 194 | micronaut-graal 195 | ${micronaut.version} 196 | 197 | 198 | 199 | -Amicronaut.processing.group=com.datastaxdev 200 | -Amicronaut.processing.module=lab4-micronaut 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | -------------------------------------------------------------------------------- /lab-cassandra-drivers/src/test/java/com/datastax/devoxx/E11_ReactiveProgrammingTest.java: -------------------------------------------------------------------------------- 1 | package com.datastax.devoxx; 2 | 3 | import static com.datastax.devoxx.schema.SchemaUtils.createTableUser; 4 | import static com.datastax.devoxx.schema.SchemaUtils.truncateTable; 5 | 6 | import java.util.Optional; 7 | 8 | import org.junit.jupiter.api.BeforeAll; 9 | import org.junit.jupiter.api.MethodOrderer.OrderAnnotation; 10 | import org.junit.jupiter.api.Order; 11 | import org.junit.jupiter.api.Test; 12 | import org.junit.jupiter.api.TestMethodOrder; 13 | import org.slf4j.Logger; 14 | import org.slf4j.LoggerFactory; 15 | 16 | import com.datastax.devoxx.dto.UserDto; 17 | import com.datastax.devoxx.schema.SchemaConstants; 18 | import com.datastax.dse.driver.api.core.cql.reactive.ReactiveResultSet; 19 | import com.datastax.oss.driver.api.core.CqlSession; 20 | import com.datastax.oss.driver.api.core.cql.PreparedStatement; 21 | import com.datastax.oss.driver.api.core.cql.SimpleStatement; 22 | import com.datastax.oss.driver.api.querybuilder.QueryBuilder; 23 | 24 | import reactor.core.publisher.Flux; 25 | import reactor.core.publisher.Mono; 26 | 27 | /** 28 | * !! WARNING Tests with no Assertions here (I assume) !! 29 | * 30 | * @author cedricklunven 31 | */ 32 | @TestMethodOrder(OrderAnnotation.class) 33 | public class E11_ReactiveProgrammingTest implements SchemaConstants { 34 | 35 | private static Logger LOGGER = LoggerFactory.getLogger(E11_ReactiveProgrammingTest.class); 36 | 37 | private static PreparedStatement stmtUpsertUser; 38 | private static PreparedStatement stmtExistUser; 39 | private static PreparedStatement stmtDeleteUser; 40 | private static PreparedStatement stmtFindUser; 41 | 42 | @BeforeAll 43 | public static void shout_init_statements() { 44 | try(CqlSession cqlSession = CqlSession.builder().build()) { 45 | 46 | // Create working table User (if needed) 47 | createTableUser(cqlSession); 48 | 49 | // Empty tables for tests 50 | truncateTable(cqlSession, USER_TABLENAME); 51 | 52 | // Prepare your statements once and execute multiple times 53 | prepareStatements(cqlSession); 54 | } 55 | } 56 | 57 | String userEmail = "clun@sample.com"; 58 | String userEmail2 = "ram@sample.com"; 59 | 60 | @Test 61 | @Order(1) 62 | public void should_reactive() throws InterruptedException { 63 | try(CqlSession cqlSession = CqlSession.builder().build()) { 64 | // Test existence of user 1 to false and then create user 1 65 | existUserReactive(cqlSession, userEmail) 66 | .doOnNext(exist -> LOGGER.info("+ '{}' exists ? (expecting false): {}", userEmail, exist)) 67 | .and(upsertUserReactive(cqlSession, userEmail, "Cedric", "Lunven")) 68 | .block(); 69 | 70 | // User 1 now exist and we log (blocking call) 71 | existUserReactive(cqlSession, userEmail) 72 | .doOnNext(exist -> LOGGER.info("+ '{}' exists ? (expecting false): {}", userEmail, exist)) 73 | .block(); 74 | 75 | // Creating user 2 to be deleted 76 | upsertUserReactive(cqlSession, userEmail2, "Eric", "Ramirez") 77 | .doOnNext(exist -> LOGGER.info("+ '{}' exists ? (expecting false): {}", userEmail2, exist)) 78 | .block(); 79 | 80 | // ========= DELETE ============ 81 | 82 | deleteUserReactive(cqlSession, userEmail2) 83 | .doOnNext(exist -> LOGGER.info("+ '{}' exists ? (expecting false) {}", userEmail2, exist)) 84 | .block(); // enforce blocking call to have logs. 85 | 86 | // ========= READ ============== 87 | 88 | // User 2 has been deleted as such will be empty 89 | findUserByIdReactive(cqlSession, "eram@sample.com") 90 | .doOnNext(erick -> LOGGER.info("+ Retrieved '{}': (expecting Optional.empty) {}", userEmail2, erick)) 91 | .block(); // enforce blocking call to have logs. 92 | 93 | // User 1 is there so we should lie 94 | findUserByIdReactive(cqlSession, "clun@sample.com") 95 | .doOnNext(erick -> LOGGER.info("+ Retrieved '{}': (expecting result) {}", userEmail2, erick)) 96 | .block(); // enforce blocking call to have logs. 97 | 98 | // creating user 2 again to have 2 records in the tables 99 | upsertUserReactive(cqlSession, userEmail2, "Eric", "Ramirez") 100 | .doOnNext(exist -> LOGGER.info("+ '{}' exists ? (expecting false): {}", userEmail2, exist)) 101 | .block(); 102 | // Listing users 103 | listAllUserReactive(cqlSession) 104 | .map(UserDto::getEmail) 105 | .doOnNext(email -> LOGGER.info("+ '{}' email found", email)) 106 | .blockLast(); 107 | 108 | Thread.sleep(500); 109 | } 110 | } 111 | 112 | private static Mono existUserReactive(CqlSession cqlSession, String email) { 113 | ReactiveResultSet rrs = cqlSession.executeReactive(stmtExistUser.bind(email)); 114 | return Mono.from(rrs).map(rs -> true).defaultIfEmpty(false); 115 | } 116 | 117 | private static Mono> findUserByIdReactive(CqlSession cqlSession, String email) { 118 | return Mono.from(cqlSession.executeReactive(stmtFindUser.bind(email))) 119 | .doOnNext(row -> LOGGER.info("+ Retrieved '{}': (expecting result) {}", row.getString(USER_EMAIL), email)) 120 | .map(UserDto::new).map(Optional::of) 121 | .defaultIfEmpty(Optional.empty()); 122 | } 123 | 124 | private static Mono upsertUserReactive(CqlSession cqlSession, String email, String firstname, String lastname) { 125 | ReactiveResultSet rrs = cqlSession.executeReactive(stmtUpsertUser.bind(email, firstname, lastname)); 126 | return Mono.from(rrs).then(); 127 | } 128 | 129 | private static Mono deleteUserReactive(CqlSession cqlSession, String email) { 130 | return Mono.from(cqlSession.executeReactive(stmtDeleteUser.bind(email))).then(); 131 | } 132 | 133 | private static Flux listAllUserReactive(CqlSession cqlSession) { 134 | SimpleStatement queryAllUser = QueryBuilder.selectFrom(USER_TABLENAME).all().build(); 135 | return Flux.from(cqlSession.executeReactive(queryAllUser)).map(UserDto::new); 136 | } 137 | 138 | private static void prepareStatements(CqlSession cqlSession) { 139 | stmtUpsertUser = cqlSession.prepare(QueryBuilder.insertInto(USER_TABLENAME) 140 | .value(USER_EMAIL, QueryBuilder.bindMarker()) 141 | .value(USER_FIRSTNAME, QueryBuilder.bindMarker()) 142 | .value(USER_LASTNAME, QueryBuilder.bindMarker()) 143 | .build()); 144 | stmtExistUser = cqlSession.prepare(QueryBuilder 145 | .selectFrom(USER_TABLENAME).column(USER_EMAIL) 146 | .whereColumn(USER_EMAIL) 147 | .isEqualTo(QueryBuilder.bindMarker()) 148 | .build()); 149 | stmtDeleteUser = cqlSession.prepare(QueryBuilder 150 | .deleteFrom(USER_TABLENAME) 151 | .whereColumn(USER_EMAIL) 152 | .isEqualTo(QueryBuilder.bindMarker()) 153 | .build()); 154 | stmtFindUser = cqlSession.prepare(QueryBuilder 155 | .selectFrom(USER_TABLENAME).all() 156 | .whereColumn(USER_EMAIL) 157 | .isEqualTo(QueryBuilder.bindMarker()) 158 | .build()); 159 | 160 | } 161 | 162 | } 163 | -------------------------------------------------------------------------------- /lab-cassandra-drivers/src/main/java/com/datastax/devoxx/schema/SchemaUtils.java: -------------------------------------------------------------------------------- 1 | package com.datastax.devoxx.schema; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | import com.datastax.oss.driver.api.core.CqlSession; 7 | import com.datastax.oss.driver.api.core.metadata.schema.ClusteringOrder; 8 | import com.datastax.oss.driver.api.core.type.DataTypes; 9 | import com.datastax.oss.driver.api.querybuilder.QueryBuilder; 10 | import com.datastax.oss.driver.api.querybuilder.SchemaBuilder; 11 | 12 | /** 13 | * Code reused in multiple samples. 14 | */ 15 | public class SchemaUtils implements SchemaConstants { 16 | 17 | private static Logger LOGGER = LoggerFactory.getLogger(SchemaUtils.class); 18 | 19 | public static void closeSession(CqlSession session) { 20 | if (session != null) session.close(); 21 | LOGGER.info("[OK]Session is now closed"); 22 | } 23 | 24 | public static void truncateTable(CqlSession session, String tableName) { 25 | session.execute(QueryBuilder.truncate(tableName).build()); 26 | } 27 | 28 | public static void dropTableIfExists(CqlSession session, String tableName) { 29 | session.execute(SchemaBuilder.dropTable(tableName).ifExists().build()); 30 | } 31 | 32 | public static void dropTypeIffExists(CqlSession session, String typeName) { 33 | session.execute(SchemaBuilder.dropType(typeName).ifExists().build()); 34 | } 35 | 36 | /** 37 | * CREATE TABLE IF NOT EXISTS users ( 38 | * email text, 39 | * firstname text, 40 | * lastname text, 41 | * PRIMARY KEY (email) 42 | * ); 43 | */ 44 | public static void createTableUser(CqlSession session) { 45 | session.execute(SchemaBuilder.createTable(USER_TABLENAME) 46 | .ifNotExists() 47 | .withPartitionKey(USER_EMAIL, DataTypes.TEXT) 48 | .withColumn(USER_FIRSTNAME, DataTypes.TEXT) 49 | .withColumn(USER_LASTNAME, DataTypes.TEXT) 50 | .build()); 51 | LOGGER.info("+ Table '{}' has been created (if needed).", USER_TABLENAME); 52 | } 53 | 54 | /** 55 | * CREATE TYPE IF NOT EXISTS video_format ( 56 | * width int, 57 | * height int 58 | *); 59 | */ 60 | public static void createUdtVideoFormat(CqlSession session) { 61 | session.execute(SchemaBuilder 62 | .createType(UDT_VIDEO_FORMAT_NAME) 63 | .ifNotExists() 64 | .withField(UDT_VIDEO_FORMAT_WIDTH, DataTypes.INT) 65 | .withField(UDT_VIDEO_FORMAT_HEIGHT, DataTypes.INT) 66 | .build()); 67 | LOGGER.info("+ Type '{}' has been created (if needed).", UDT_VIDEO_FORMAT_NAME); 68 | } 69 | 70 | /** 71 | * CREATE TABLE IF NOT EXISTS videos ( 72 | * videoid uuid, 73 | * title text, 74 | * upload timestamp, 75 | * email text, 76 | * url text, 77 | * tags set , 78 | * frames list, 79 | * formats map >, 80 | * PRIMARY KEY (videoid) 81 | * ); 82 | **/ 83 | public static void createTableVideo(CqlSession session) { 84 | session.execute(SchemaBuilder 85 | .createTable(VIDEO_TABLENAME) 86 | .ifNotExists() 87 | .withPartitionKey(VIDEO_VIDEOID, DataTypes.UUID) 88 | .withColumn(VIDEO_TITLE, DataTypes.TEXT) 89 | .withColumn(VIDEO_UPLOAD, DataTypes.TIMESTAMP) 90 | .withColumn(VIDEO_USER_EMAIL, DataTypes.TEXT) 91 | .withColumn(VIDEO_URL, DataTypes.TEXT) 92 | .withColumn(VIDEO_TAGS, DataTypes.setOf(DataTypes.TEXT)) 93 | .withColumn(VIDEO_FRAMES, DataTypes.listOf(DataTypes.INT)) 94 | .withColumn(VIDEO_FORMAT, DataTypes.mapOf(DataTypes.TEXT, 95 | SchemaBuilder.udt(UDT_VIDEO_FORMAT_NAME, true))).build()); 96 | LOGGER.info("+ Table '{}' has been created (if needed).", VIDEO_TABLENAME); 97 | } 98 | 99 | /** 100 | * CREATE TABLE IF NOT EXISTS videos_views ( 101 | * videoid uuid, 102 | * views counter, 103 | * PRIMARY KEY (videoid) 104 | * ); 105 | */ 106 | public static void createTableVideoViews(CqlSession session) { 107 | session.execute(SchemaBuilder 108 | .createTable(VIDEO_VIEWS_TABLENAME) 109 | .ifNotExists() 110 | .withPartitionKey(VIDEO_VIEWS_VIDEOID, DataTypes.UUID) 111 | .withColumn(VIDEO_VIEWS_VIEWS, DataTypes.COUNTER) 112 | .build()); 113 | LOGGER.info("+ Table '{}' has been created (if needed).", VIDEO_VIEWS_TABLENAME); 114 | } 115 | 116 | /** 117 | * CREATE TABLE IF NOT EXISTS comments_by_user ( 118 | * userid uuid, 119 | * commentid timeuuid, 120 | * videoid uuid, 121 | * comment text, 122 | * PRIMARY KEY (userid, commentid) 123 | * ) WITH CLUSTERING ORDER BY (commentid DESC); 124 | */ 125 | public static void createTableCommentByUser(CqlSession session) { 126 | 127 | 128 | session.execute(SchemaBuilder 129 | .createTable(COMMENT_BY_USER_TABLENAME) 130 | .ifNotExists() 131 | .withPartitionKey(COMMENT_BY_USER_USERID, DataTypes.UUID) 132 | .withClusteringColumn(COMMENT_BY_USER_COMMENTID, DataTypes.TIMEUUID) 133 | .withColumn(COMMENT_BY_USER_VIDEOID, DataTypes.UUID) 134 | .withColumn(COMMENT_BY_USER_COMMENT, DataTypes.TEXT) 135 | .withClusteringOrder(COMMENT_BY_USER_COMMENTID, ClusteringOrder.DESC) 136 | .build()); 137 | LOGGER.info("+ Table '{}' has been created (if needed).", COMMENT_BY_USER_TABLENAME); 138 | } 139 | 140 | /** 141 | * CREATE TABLE IF NOT EXISTS comments_by_video ( 142 | * videoid uuid, 143 | * commentid timeuuid, 144 | * userid uuid, 145 | * comment text, 146 | * PRIMARY KEY (videoid, commentid) 147 | * ) WITH CLUSTERING ORDER BY (commentid DESC); 148 | */ 149 | public static void createTableCommentByVideo(CqlSession session) { 150 | session.execute(SchemaBuilder 151 | .createTable(COMMENT_BY_VIDEO_TABLENAME) 152 | .ifNotExists() 153 | .withPartitionKey(COMMENT_BY_VIDEO_VIDEOID, DataTypes.UUID) 154 | .withClusteringColumn(COMMENT_BY_VIDEO_COMMENTID, DataTypes.TIMEUUID) 155 | .withColumn(COMMENT_BY_VIDEO_USERID, DataTypes.UUID) 156 | .withColumn(COMMENT_BY_VIDEO_COMMENT, DataTypes.TEXT) 157 | .withClusteringOrder(COMMENT_BY_VIDEO_COMMENTID, ClusteringOrder.DESC) 158 | .build()); 159 | LOGGER.info("+ Table '{}' has been created (if needed).", COMMENT_BY_VIDEO_TABLENAME); 160 | } 161 | 162 | /** 163 | * CREATE TABLE IF NOT EXISTS files ( 164 | * filename text, 165 | * upload timestamp, 166 | * extension text static, 167 | * binary blob, 168 | * PRIMARY KEY((filename), upload) 169 | * ) WITH CLUSTERING ORDER BY (upload DESC); 170 | */ 171 | public static void createTableFiles(CqlSession session) { 172 | session.execute(SchemaBuilder 173 | .createTable(FILES_TABLENAME).ifNotExists() 174 | .withPartitionKey(FILES_FILENAME, DataTypes.TEXT) 175 | .withClusteringColumn(FILES_UPLOAD, DataTypes.TIMESTAMP) 176 | .withStaticColumn(FILES_EXTENSION, DataTypes.TEXT) 177 | .withColumn(FILES_BINARY, DataTypes.BLOB) 178 | .withClusteringOrder(FILES_UPLOAD, ClusteringOrder.DESC) 179 | .build()); 180 | LOGGER.info("+ Table '{}' has been created (if needed).", FILES_TABLENAME); 181 | } 182 | 183 | } 184 | -------------------------------------------------------------------------------- /lab-cassandra-drivers/src/test/java/com/datastax/devoxx/E06_JsonTest.java: -------------------------------------------------------------------------------- 1 | package com.datastax.devoxx; 2 | 3 | import static com.datastax.devoxx.schema.SchemaUtils.createTableVideo; 4 | import static com.datastax.devoxx.schema.SchemaUtils.createUdtVideoFormat; 5 | import static com.datastax.devoxx.schema.SchemaUtils.truncateTable; 6 | 7 | import java.time.Instant; 8 | import java.util.Arrays; 9 | import java.util.HashSet; 10 | import java.util.UUID; 11 | 12 | import org.junit.jupiter.api.BeforeAll; 13 | import org.junit.jupiter.api.Test; 14 | import org.slf4j.Logger; 15 | import org.slf4j.LoggerFactory; 16 | 17 | import com.datastax.devoxx.codec.JsonJacksonTypeCodec; 18 | import com.datastax.devoxx.dto.VideoDto; 19 | import com.datastax.devoxx.schema.SchemaConstants; 20 | import com.datastax.oss.driver.api.core.CqlSession; 21 | import com.datastax.oss.driver.api.core.cql.ResultSet; 22 | import com.datastax.oss.driver.api.core.cql.Row; 23 | import com.datastax.oss.driver.api.core.cql.SimpleStatement; 24 | import com.datastax.oss.driver.api.core.type.codec.TypeCodec; 25 | import com.datastax.oss.driver.api.core.type.codec.registry.MutableCodecRegistry; 26 | import com.datastax.oss.driver.api.querybuilder.QueryBuilder; 27 | 28 | /** 29 | * !! WARNING Tests with no Assertions here (I assume) !! 30 | * 31 | * @author cedricklunven 32 | */ 33 | public class E06_JsonTest implements SchemaConstants { 34 | 35 | private static Logger LOGGER = LoggerFactory.getLogger(E06_JsonTest.class); 36 | 37 | @BeforeAll 38 | public static void shout_init_statements() { 39 | try(CqlSession cqlSession = CqlSession.builder().build()) { 40 | createUdtVideoFormat(cqlSession); 41 | createTableVideo(cqlSession); 42 | truncateTable(cqlSession, VIDEO_TABLENAME); 43 | } 44 | } 45 | 46 | @Test 47 | public void should_use_json() { 48 | try(CqlSession cqlSession = CqlSession.builder().build()) { 49 | 50 | // Insert as a String - with regular Core CQL 51 | UUID videoid1 = UUID.randomUUID(); 52 | cqlSession.execute("" 53 | + "INSERT INTO " + VIDEO_TABLENAME + "(videoid, email, title, upload, url, tags, frames, formats) " 54 | + "VALUES("+ videoid1.toString() +", " 55 | + " 'clu@sample.com', 'sample video'," 56 | + " toTimeStamp(now()), 'http://google.fr', " 57 | + " { 'cassandra','accelerate','2020'}, " 58 | + " [ 1, 2, 3, 4], " 59 | + " { 'mp4':{width:1,height:1}, " 60 | + " 'ogg':{width:1,height:1} " 61 | + " });"); 62 | LOGGER.info("+ Video 'e7ae5cf3-d358-4d99-b900-85902fda9bb0' has been inserted"); 63 | 64 | // Insert as a String - with a Column as JSON 65 | UUID videoid2 = UUID.randomUUID(); 66 | cqlSession.execute(SimpleStatement.builder( 67 | "INSERT INTO " + VIDEO_TABLENAME + "(videoid, email, title, upload, url, tags, frames, formats) " 68 | + "VALUES(?,?,?,?,?,?,?,fromJson(?))") 69 | .addPositionalValue(videoid2) 70 | .addPositionalValue("clu@sample.com") 71 | .addPositionalValue("sample video") 72 | .addPositionalValue(Instant.now()) 73 | .addPositionalValue("http://google.fr") 74 | .addPositionalValue(new HashSet<>()) 75 | .addPositionalValue(Arrays.asList(1,2,3,4)) 76 | .addPositionalValue("{ \"mp4\":{\"width\":1,\"height\":1}, \"ogg\":{\"width\":1,\"height\":1} }") 77 | .build()); 78 | LOGGER.info("+ Video '{}' has been inserted", videoid2); 79 | 80 | // Insert as a JSON String 81 | UUID videoid3 = UUID.randomUUID(); 82 | cqlSession.execute("" 83 | + "INSERT INTO " + VIDEO_TABLENAME + " JSON '{" 84 | + "\"videoid\":\""+videoid3.toString()+"\"," 85 | + "\"email\":\"clu@sample.com\"," 86 | + "\"title\":\"sample video\"," 87 | + "\"upload\":\"2020-02-26 15:09:22 +00:00\"," 88 | + "\"url\":\"http://google.fr\"," 89 | + "\"frames\": [1,2,3,4]," 90 | + "\"tags\": [\"cassandra\",\"accelerate\", \"2020\"]," 91 | + "\"formats\": {" 92 | + " \"mp4\":{\"width\":1,\"height\":1}," 93 | + " \"ogg\":{\"width\":1,\"height\":1}" 94 | + "}}'"); 95 | LOGGER.info("+ Video '{}' has been inserted", videoid3); 96 | 97 | // Insert as a JSON Param 98 | UUID videoid4 = UUID.randomUUID(); 99 | cqlSession.execute(SimpleStatement.builder("INSERT INTO " + VIDEO_TABLENAME + " JSON ? ") 100 | .addPositionalValue("{" 101 | + "\"videoid\":\""+ videoid4.toString() + "\"," 102 | + "\"email\":\"clu@sample.com\"," 103 | + "\"title\":\"sample video\"," 104 | + "\"upload\":\"2020-02-26 15:09:22 +00:00\"," 105 | + "\"url\":\"http://google.fr\"," 106 | + "\"frames\": [1,2,3,4]," 107 | + "\"tags\": [\"cassandra\",\"accelerate\", \"2020\"]," 108 | + "\"formats\": {" 109 | + " \"mp4\":{\"width\":1,\"height\":1}," 110 | + " \"ogg\":{\"width\":1,\"height\":1}" 111 | + "}}") 112 | .build()); 113 | LOGGER.info("+ Video '{}' has been inserted", videoid4); 114 | 115 | // Insert with QueryBuilder - as a JSON String 116 | UUID videoid5 = UUID.randomUUID(); 117 | cqlSession.execute(QueryBuilder.insertInto(VIDEO_TABLENAME) 118 | .json("{" 119 | + "\"videoid\":\""+ videoid5.toString() + "\"," 120 | + "\"email\":\"clu@sample.com\"," 121 | + "\"title\":\"sample video\"," 122 | + "\"upload\":\"2020-02-26 15:09:22 +00:00\"," 123 | + "\"url\":\"http://google.fr\"," 124 | + "\"frames\": [1,2,3,4]," 125 | + "\"tags\": [\"cassandra\",\"accelerate\", \"2020\"]," 126 | + "\"formats\": {" 127 | + " \"mp4\":{\"width\":1,\"height\":1}," 128 | + " \"ogg\":{\"width\":1,\"height\":1}" 129 | + "}}") 130 | .build()); 131 | LOGGER.info("+ Video '{}' has been inserted", videoid5); 132 | LOGGER.info("[OK] - All video Inserted"); 133 | 134 | /** 135 | * Register a Codec at runtime 136 | * Can also be achieved at session init with 137 | * .addTypeCodecs(new JsonJacksonTypeCodec(VideoDto.class)) 138 | */ 139 | MutableCodecRegistry registry = (MutableCodecRegistry) cqlSession.getContext().getCodecRegistry(); 140 | TypeCodec jsonCodec = new JsonJacksonTypeCodec(VideoDto.class); 141 | registry.register(jsonCodec); 142 | 143 | // Insert with QueryBuilder - As an object + Jackson Codec 144 | UUID videoid6 = UUID.randomUUID(); 145 | VideoDto dto = new VideoDto(videoid6, "sample video", "clu@sample.com", "http://google.fr"); 146 | cqlSession.execute(QueryBuilder 147 | .insertInto(VIDEO_TABLENAME) 148 | .json(dto, jsonCodec).build()); 149 | LOGGER.info("+ Video '{}' has been inserted", videoid5); 150 | 151 | // Read with QueryBuilder - As an object + Jackson Codec 152 | ResultSet rows = cqlSession.execute(QueryBuilder.selectFrom(VIDEO_TABLENAME).json().all().build()); 153 | for (Row row : rows) { 154 | VideoDto myVideo = row.get(0, VideoDto.class); 155 | LOGGER.info("+ Video '{}' has been read ", myVideo.getVideoid()); 156 | } 157 | LOGGER.info("[OK] - All video read"); 158 | } 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /lab-cassandra-drivers/src/test/java/com/datastax/devoxx/E03_OperationsCrudTest.java: -------------------------------------------------------------------------------- 1 | package com.datastax.devoxx; 2 | 3 | import static com.datastax.devoxx.schema.SchemaUtils.createTableUser; 4 | import static com.datastax.devoxx.schema.SchemaUtils.truncateTable; 5 | 6 | import java.util.List; 7 | import java.util.Optional; 8 | import java.util.stream.Collectors; 9 | 10 | import org.junit.jupiter.api.MethodOrderer.OrderAnnotation; 11 | import org.junit.jupiter.api.BeforeAll; 12 | import org.junit.jupiter.api.Order; 13 | import org.junit.jupiter.api.Test; 14 | import org.junit.jupiter.api.TestMethodOrder; 15 | import org.slf4j.Logger; 16 | import org.slf4j.LoggerFactory; 17 | 18 | import com.datastax.devoxx.dto.UserDto; 19 | import com.datastax.devoxx.schema.SchemaConstants; 20 | import com.datastax.oss.driver.api.core.CqlSession; 21 | import com.datastax.oss.driver.api.core.cql.PreparedStatement; 22 | import com.datastax.oss.driver.api.core.cql.ResultSet; 23 | import com.datastax.oss.driver.api.core.cql.Row; 24 | import com.datastax.oss.driver.api.querybuilder.QueryBuilder; 25 | 26 | /** 27 | * !! WARNING Tests with no Assertions here (I assume) !! 28 | * 29 | * @author cedricklunven 30 | */ 31 | @TestMethodOrder(OrderAnnotation.class) 32 | public class E03_OperationsCrudTest implements SchemaConstants { 33 | 34 | private static Logger LOGGER = 35 | LoggerFactory.getLogger(E03_OperationsCrudTest.class); 36 | 37 | private static PreparedStatement stmtCreateUser; 38 | private static PreparedStatement stmtUpsertUser; 39 | private static PreparedStatement stmtExistUser; 40 | private static PreparedStatement stmtDeleteUser; 41 | private static PreparedStatement stmtFindUser; 42 | 43 | String userEmail = "clun@sample.com"; 44 | String userEmail2 = "eram@sample.com"; 45 | 46 | @BeforeAll 47 | public static void should_prepare_statements() { 48 | try(CqlSession cqlSession = CqlSession.builder().build()) { 49 | 50 | // Create working table User (if needed) 51 | createTableUser(cqlSession); 52 | 53 | // Empty tables for tests 54 | truncateTable(cqlSession, USER_TABLENAME); 55 | 56 | // Prepare your statements once and execute multiple times 57 | prepareStatements(cqlSession); 58 | 59 | } 60 | } 61 | 62 | @Test 63 | @Order(1) 64 | public void should_create_statements() { 65 | 66 | try(CqlSession cqlSession = CqlSession.builder().build()) { 67 | 68 | if (!existUser(cqlSession, userEmail)) { 69 | LOGGER.info("+ {} does not exists in table 'user'", userEmail); 70 | } 71 | 72 | createUser(cqlSession, userEmail, "Cedric", "Lunven"); 73 | 74 | if (existUser(cqlSession, userEmail)) { 75 | LOGGER.info("+ {} now exists in table 'user'", userEmail); 76 | } 77 | } 78 | } 79 | 80 | @Test 81 | @Order(2) 82 | public void should_update_statements() { 83 | 84 | try(CqlSession cqlSession = CqlSession.builder().build()) { 85 | 86 | 87 | 88 | if (!existUser(cqlSession, userEmail2)) { 89 | LOGGER.info("+ {} does not exists in table 'user'", userEmail2); 90 | } 91 | 92 | updateUser(cqlSession, userEmail2, "Eric", "Ramirez"); 93 | 94 | if (existUser(cqlSession, userEmail2)) { 95 | LOGGER.info("+ {} now exists in table 'user'", userEmail2); 96 | } 97 | } 98 | } 99 | 100 | @Test 101 | @Order(3) 102 | public void should_delete_statements() { 103 | 104 | try(CqlSession cqlSession = CqlSession.builder().build()) { 105 | 106 | // Delete an existing user by its email (if email does not exist, no error) 107 | deleteUser(cqlSession, userEmail2); 108 | if (!existUser(cqlSession, userEmail2)) { 109 | LOGGER.info("+ {} does not exists in table 'user'", userEmail2); 110 | } 111 | } 112 | } 113 | 114 | 115 | @Test 116 | @Order(4) 117 | public void should_read_statements() { 118 | 119 | try(CqlSession cqlSession = CqlSession.builder().build()) { 120 | 121 | // ========= READ ============== 122 | 123 | // Will be empty as we have deleted it 124 | Optional erick = findUserById(cqlSession, userEmail2); 125 | LOGGER.info("+ Retrieved {}: {}", userEmail2,erick); // Expected Optiona.empty() 126 | 127 | // Not null 128 | Optional cedrick = findUserById(cqlSession, userEmail); 129 | LOGGER.info("+ Retrieved {}: {}", userEmail, cedrick.get().getEmail()); 130 | 131 | // Read all (first upserts) 132 | updateUser(cqlSession, userEmail2, "Eric", "Ramirez"); 133 | updateUser(cqlSession, userEmail, "Cedrick", "Lunven"); 134 | List allUsers = cqlSession 135 | .execute(QueryBuilder.selectFrom(USER_TABLENAME).all().build()) 136 | .all().stream().map(UserDto::new) 137 | .collect(Collectors.toList()); 138 | LOGGER.info("+ Retrieved users count {}", allUsers.size()); 139 | } 140 | } 141 | 142 | private static boolean existUser(CqlSession cqlSession, String email) { 143 | return cqlSession.execute(stmtExistUser.bind(email)).getAvailableWithoutFetching() > 0; 144 | } 145 | 146 | private static void createUser(CqlSession cqlSession, String email, String firstname, String lastname) { 147 | ResultSet rs = cqlSession.execute(stmtCreateUser.bind(email, firstname, lastname)); 148 | if (!rs.wasApplied()) { 149 | throw new IllegalArgumentException("Email '" + email + "' already exist in Database. Cannot create new user"); 150 | } 151 | LOGGER.info("+ User {} has been created", email); 152 | } 153 | 154 | private static void updateUser(CqlSession cqlSession, String email, String firstname, String lastname) { 155 | cqlSession.execute(stmtUpsertUser.bind(email, firstname, lastname)); 156 | LOGGER.info("+ User {} has been updated", email); 157 | } 158 | 159 | private static void deleteUser(CqlSession cqlSession, String email) { 160 | cqlSession.execute(stmtDeleteUser.bind(email)); 161 | LOGGER.info("+ User {} has been deleted", email); 162 | } 163 | 164 | private static Optional < UserDto > findUserById(CqlSession cqlSession, String email) { 165 | ResultSet rs = cqlSession.execute(stmtFindUser.bind(email)); 166 | // We query by the primary key ensuring unicity 167 | Row record = rs.one(); 168 | return (null != record) ? Optional.of(new UserDto(record)) :Optional.empty(); 169 | } 170 | 171 | private static void prepareStatements(CqlSession cqlSession) { 172 | stmtCreateUser = cqlSession.prepare(QueryBuilder.insertInto(USER_TABLENAME) 173 | .value(USER_EMAIL, QueryBuilder.bindMarker()) 174 | .value(USER_FIRSTNAME, QueryBuilder.bindMarker()) 175 | .value(USER_LASTNAME, QueryBuilder.bindMarker()) 176 | .ifNotExists().build()); 177 | // Using a - SLOW - lightweight transaction to check user existence 178 | stmtUpsertUser = cqlSession.prepare(QueryBuilder.insertInto(USER_TABLENAME) 179 | .value(USER_EMAIL, QueryBuilder.bindMarker()) 180 | .value(USER_FIRSTNAME, QueryBuilder.bindMarker()) 181 | .value(USER_LASTNAME, QueryBuilder.bindMarker()) 182 | .build()); 183 | stmtExistUser = cqlSession.prepare(QueryBuilder 184 | .selectFrom(USER_TABLENAME).column(USER_EMAIL) 185 | .whereColumn(USER_EMAIL) 186 | .isEqualTo(QueryBuilder.bindMarker()) 187 | .build()); 188 | stmtDeleteUser = cqlSession.prepare(QueryBuilder 189 | .deleteFrom(USER_TABLENAME) 190 | .whereColumn(USER_EMAIL) 191 | .isEqualTo(QueryBuilder.bindMarker()) 192 | .build()); 193 | stmtFindUser = cqlSession.prepare(QueryBuilder 194 | .selectFrom(USER_TABLENAME).all() 195 | .whereColumn(USER_EMAIL) 196 | .isEqualTo(QueryBuilder.bindMarker()) 197 | .build()); 198 | } 199 | 200 | } 201 | --------------------------------------------------------------------------------