├── .gitignore ├── .travis.yml ├── README.md ├── pom.xml ├── vertx-cassandra-mapping ├── README.md ├── pom.xml └── src │ ├── main │ └── java │ │ └── com │ │ └── englishtown │ │ └── vertx │ │ └── cassandra │ │ └── mapping │ │ ├── VertxMapper.java │ │ ├── VertxMappingManager.java │ │ ├── guice │ │ ├── GuiceMappingBinder.java │ │ └── WhenGuiceMappingBinder.java │ │ ├── hk2 │ │ ├── HK2MappingBinder.java │ │ └── WhenHK2MappingBinder.java │ │ ├── impl │ │ ├── DefaultVertxMapper.java │ │ └── DefaultVertxMappingManager.java │ │ └── promises │ │ ├── WhenVertxMapper.java │ │ ├── WhenVertxMappingManager.java │ │ └── impl │ │ ├── DefaultWhenVertxMapper.java │ │ └── DefaultWhenVertxMappingManager.java │ └── test │ └── java │ └── com │ └── englishtown │ └── vertx │ └── cassandra │ └── mapping │ ├── impl │ ├── DefaultVertxMapperTest.java │ └── DefaultVertxMappingManagerTest.java │ └── integration │ ├── MappingIntegrationTest.java │ ├── TestEntity.java │ ├── WhenMappingIntegrationTest.java │ ├── guice │ ├── GuiceMappingIntegrationTest.java │ └── GuiceWhenMappingIntegrationTest.java │ └── hk2 │ ├── HK2MappingIntegrationTest.java │ └── HK2WhenMappingIntegrationTest.java └── vertx-cassandra ├── pom.xml └── src ├── main └── java │ └── com │ └── englishtown │ └── vertx │ └── cassandra │ ├── CassandraConfigurator.java │ ├── CassandraSession.java │ ├── FutureUtils.java │ ├── guice │ ├── GuiceCassandraBinder.java │ ├── GuiceWhenCassandraBinder.java │ └── GuiceZooKeeperCassandraBinder.java │ ├── hk2 │ ├── HK2CassandraBinder.java │ ├── HK2WhenCassandraBinder.java │ └── HK2ZooKeeperCassandraBinder.java │ ├── impl │ ├── DefaultCassandraSession.java │ ├── EnvironmentCassandraConfigurator.java │ ├── JsonCassandraConfigurator.java │ └── Metrics.java │ ├── keyspacebuilder │ ├── AlterKeyspace.java │ ├── BuiltKeyspaceStatement.java │ ├── CreateKeyspace.java │ ├── DropKeyspace.java │ ├── KeyspaceBuilder.java │ └── KeyspaceBuilderBase.java │ ├── promises │ ├── WhenCassandraSession.java │ └── impl │ │ └── DefaultWhenCassandraSession.java │ ├── tablebuilder │ ├── AlterTable.java │ ├── BuiltTableStatement.java │ ├── CreateTable.java │ ├── DropTable.java │ ├── PrimaryKeyType.java │ └── TableBuilder.java │ └── zookeeper │ └── ZooKeeperCassandraConfigurator.java └── test ├── java └── com │ └── englishtown │ └── vertx │ └── cassandra │ ├── impl │ ├── DefaultCassandraSessionTest.java │ ├── EnvironmentCassandraConfiguratorTest.java │ └── JsonCassandraConfiguratorTest.java │ ├── integration │ ├── CassandraSessionIntegrationTest.java │ ├── IntegrationTestBase.java │ ├── Locator.java │ ├── TableBuilderIntegrationTest.java │ ├── WhenCassandraSessionIntegrationTest.java │ ├── guice │ │ ├── GuiceCassandraSessionIntegrationTest.java │ │ ├── GuiceLocator.java │ │ ├── GuiceTableBuilderIntegrationTest.java │ │ └── GuiceWhenCassandraSessionIntegrationTest.java │ └── hk2 │ │ ├── HK2CassandraSessionIntegrationTest.java │ │ ├── HK2Locator.java │ │ ├── HK2TableBuilderIntegrationTest.java │ │ └── HK2WhenCassandraSessionIntegrationTest.java │ ├── keyspacebuilder │ ├── AlterKeyspaceTest.java │ ├── CreateKeyspaceTest.java │ └── DropKeyspaceTest.java │ ├── promises │ └── impl │ │ └── DefaultWhenCassandraSessionTest.java │ └── tablebuilder │ ├── AlterTableTest.java │ ├── CreateTableTest.java │ ├── DropTableTest.java │ └── TableBuilderTest.java └── resources ├── cassandra.yaml └── test_config.json /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | *.iml 3 | *.ipr 4 | *.iws 5 | .classpath 6 | .project 7 | .settings/ 8 | 9 | .gradle/ 10 | build/ 11 | target/ 12 | 13 | mods/ 14 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | jdk: 3 | - oraclejdk8 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vertx-cassandra 2 | Talk to Cassandra asynchronously from vert.x and run your callbacks on the vert.x event loop. 3 | 4 | [![Build Status](http://img.shields.io/travis/ef-labs/vertx-cassandra.svg?maxAge=2592000&style=flat-square)](https://travis-ci.org/ef-labs/vertx-cassandra) 5 | [![Maven Central](https://img.shields.io/maven-central/v/com.englishtown.vertx/vertx-cassandra.svg?maxAge=2592000&style=flat-square)](https://maven-badges.herokuapp.com/maven-central/com.englishtown.vertx/vertx-cassandra/) 6 | 7 | ## Getting Started 8 | 9 | Add a dependency to vertx-cassandra: 10 | 11 | ```xml 12 | 13 | com.englishtown.vertx 14 | vertx-cassandra 15 | 3.2.0 16 | 17 | ``` 18 | 19 | | vertx-cassandra | vert.x | cassandra | 20 | |-----------------|--------|-----------| 21 | | 3.6.0 | 3.5.0 | 3.11 | 22 | | 3.4.0 | 3.3.0 | 3.7 | 23 | | 3.2.0 | 3.2.0 | 3.0 | 24 | | 3.1.0 | 3.1.0 | 2.1 | 25 | | 3.0.0 | 3.0.0 | 2.1 | 26 | 27 | ## Configuration 28 | The main configuration is via the normal config.json file for a Vert.x module. 29 | 30 | ```json 31 | { 32 | "cassandra": { 33 | "seeds": [], 34 | 35 | "query": { 36 | "consistency_level": , 37 | "serial_consistency_level": , 38 | "fetch_size": , 39 | }, 40 | 41 | "policies": { 42 | "load_balancing": { 43 | "name": "", 44 | }, 45 | "reconnection": { 46 | "name": "" 47 | } 48 | }, 49 | 50 | "pooling": { 51 | "core_connections_per_host_local": , 52 | "core_connections_per_host_remote": , 53 | "heartbeat_interval_seconds": , 54 | "idle_timeout_seconds": , 55 | "max_queue_size": , 56 | "max_requests_per_connection_local": , 57 | "max_requests_per_connection_remote": , 58 | "max_connections_per_host_local": , 59 | "max_connections_per_host_remote": , 60 | "new_connection_threshold_local": , 61 | "new_connection_threshold_remote": 62 | }, 63 | 64 | "socket": { 65 | "connect_timeout_millis": , 66 | "read_timeout_millis": , 67 | "keep_alive": , 68 | "reuse_address": , 69 | "receive_buffer_size": , 70 | "send_buffer_size": , 71 | "so_linger": , 72 | "tcp_no_delay": 73 | } 74 | } 75 | } 76 | ``` 77 | 78 | * `seeds` - an array of string seed IP or host names. At least one seed must be provided. 79 | * `lb_policy_name` - (optional) the load balancing policy name. The following values are accepted: 80 | * "DCAwareRoundRobinPolicy" - requires string field `local_dc` and optional numeric field `used_hosts_per_remote_dc` 81 | * Any FQCN such of a class that implements `LoadBalancingPolicy` 82 | * `reconnect_policy_name` - (optional) the reconnect policy name. The following values are accepted: 83 | * "constant"|"ConstantReconnectionPolicy" - creates a `ConstantReconnectionPolicy` policy. Expects additional numeric field `delay` in ms. 84 | * "exponential"|"ExponentialReconnectionPolicy" - creates an `ExponentialReconnectionPolicy` policy. Expects additional numeric fields `base_delay` and `max_delay` in ms. 85 | 86 | Refer to the [Cassandra Java driver documentation](http://www.datastax.com/documentation/developer/java-driver/2.0/index.html) for a description of the remaining configuration options. 87 | 88 | 89 | A sample config looks like: 90 | 91 | ```json 92 | { 93 | "cassandra": { 94 | "seeds": ["10.0.0.1", "10.0.0.2"], 95 | 96 | "policies": { 97 | "load_balancing": { 98 | "name": "DCAwareRoundRobinPolicy", 99 | "local_dc": "LOCAL1", 100 | "used_hosts_per_remote_dc": 1 101 | }, 102 | "reconnection": { 103 | "name": "exponential", 104 | "base_delay": 1000, 105 | "max_delay": 10000 106 | } 107 | }, 108 | } 109 | } 110 | ``` 111 | 112 | ### Overriding with Environment Variables 113 | It is possible to override the seeds and policies section of the configuration using environment variables. The two environment variables are: 114 | 115 | CASSANDRA_SEEDS="{ip}|{ip}|{ip}..." 116 | CASSANDRA_LOCAL_DC="{Local DC Name}" 117 | 118 | So an example would be: 119 | 120 | CASSANDRA_SEEDS="10.0.0.3|10.0.0.4" 121 | CASSANDRA_LOCAL_DC="REMOTE1" 122 | 123 | The latter, the `CASSANDRA_LOCAL_DC`, if used will override the entire load balancing section of the configuration, setting it to `DCAwareRoundRobinPolicy`, with a `used_hosts` value of 0 and the `local_dc` set to whatever is placed in the environment variable. 124 | 125 | So the examples given here are akin to having this in the config file: 126 | 127 | "seeds": ["10.0.0.3", "10.0.0.4"], 128 | "policies": { 129 | "load_balancing": { 130 | "name": "DCAwareRoundRobinPolicy", 131 | "local_dc": "REMOTE1", 132 | "used_hosts_per_remote_dc": 0 133 | } 134 | } 135 | 136 | ### Defaults 137 | If there is no configuration, neither JSON nor environment variables, the module will default to looking for cassandra at 127.0.0.1 with the Cassandra driver defaults for everything. 138 | 139 | ## How to Use 140 | This module uses HK2 or Guice to provide an implementation of `CassandraSession` via injection. `CassandraSession` provides methods that allow statements to be executed, statements to be prepared and for the reading of metadata. 141 | 142 | The execution and preparation methods have both synchronous and asynchronous variants. The asynchronous versions take a `FutureCallBack` class that is updated once the method has finished. 143 | 144 | `FutureCallback` is part of [Guava](http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/util/concurrent/FutureCallback.html) and the JAR is included as part of the Datastax java driver used by this module. 145 | 146 | The general best practice is to inject one `CassandraSession` per verticle. 147 | 148 | ### Promises Variant 149 | There is a promises variant of `CassandraSession`, which is used by injecting `WhenCassandraSession` instead. This provides all of the same functionality, but instead of callbacks this class returns promises. 150 | 151 | The promises used are from the Englishtown when.java package, which can be found on [Github](https://github.com/englishtown/when.java). 152 | 153 | If you intend to use this implementation, you must include the when.java dependency in your application as it is not provided by this module. 154 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | vertx-cassandra-parent 6 | pom 7 | 3.7.0-SNAPSHOT 8 | 9 | 10 | vertx-cassandra 11 | vertx-cassandra-mapping 12 | 13 | 14 | 15 | com.englishtown.vertx 16 | oss-parent-vertx 17 | 2.2.1 18 | 19 | 20 | 21 | 22 | 3.3.2 23 | 3.11.1 24 | 3.5.0 25 | 2.4.0 26 | 2.3.0 27 | 4.2.0 28 | 3.1.0 29 | 4.1.15.Final 30 | 31 | 32 | "localhost" 33 | 9042 34 | 35 | 36 | 37 | 38 | 39 | com.datastax.cassandra 40 | cassandra-driver-core 41 | ${cassandra.driver.version} 42 | 43 | 44 | com.datastax.cassandra 45 | cassandra-driver-mapping 46 | ${cassandra.driver.version} 47 | 48 | 49 | 50 | io.netty 51 | netty-handler 52 | ${netty.version} 53 | 54 | 55 | io.netty 56 | netty-all 57 | ${netty.version} 58 | 59 | 60 | 61 | 62 | com.englishtown.vertx 63 | vertx-hk2 64 | ${vertx.hk2.version} 65 | true 66 | 67 | 68 | com.englishtown.vertx 69 | vertx-guice 70 | ${vertx.guice.version} 71 | true 72 | 73 | 74 | com.englishtown.vertx 75 | vertx-when 76 | ${vertx.when.version} 77 | true 78 | 79 | 80 | com.englishtown.vertx 81 | vertx-curator 82 | ${vertx.curator.version} 83 | true 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | org.mockito 93 | mockito-core 94 | test 95 | 96 | 97 | org.hamcrest 98 | hamcrest-core 99 | test 100 | 101 | 102 | org.apache.cassandra 103 | cassandra-all 104 | ${cassandra.version} 105 | test 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | src/test/resources 114 | true 115 | 116 | 117 | 118 | 119 | 120 | 121 | embedded 122 | 123 | true 124 | 125 | 126 | 19042 127 | 128 | 129 | 130 | 131 | org.apache.maven.plugins 132 | maven-surefire-plugin 133 | 134 | 135 | true 136 | 137 | 138 | 139 | 140 | org.apache.maven.plugins 141 | maven-failsafe-plugin 142 | 143 | 144 | true 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | localhost 153 | 154 | 155 | docker 156 | 157 | "dockerhost" 158 | 159 | 160 | 161 | 162 | 163 | 164 | sling.englishtown.com 165 | 166 | dav:https://sling.englishtown.com/content/docs/${project.groupId}/${project.artifactId}/${project.version} 167 | 168 | 169 | 170 | 171 | 172 | scm:git:ssh://git@github.com/ef-labs/${project.artifactId}.git 173 | scm:git:ssh://git@github.com/ef-labs/${project.artifactId}.git 174 | HEAD 175 | https://github.com/ef-labs/${project.artifactId} 176 | 177 | 178 | 179 | -------------------------------------------------------------------------------- /vertx-cassandra-mapping/README.md: -------------------------------------------------------------------------------- 1 | # vertx-cassandra-mapping 2 | 3 | Provides vert.x wrappers for com.datastax.cassandra:cassandra-driver-mapping objects to run on the vert.x context. 4 | 5 | ## Getting Started 6 | 7 | Add a dependency to 8 | 9 | ```xml 10 | 11 | com.englishtown.vertx 12 | vertx-cassandra-mapping 13 | 3.2.0 14 | 15 | ``` 16 | 17 | Inject or create an instance of `com.englishtown.vertx.cassandra.mapping.VertxMappingManager` and create a POJO with the datastax mapping annotations (`@Table`, `@Column`, `@PartitionKey`, etc.). 18 | 19 | ## Examples 20 | 21 | #### Save 22 | 23 | ```java 24 | // Get a mapper from the vert.x mapping manager 25 | VertxMappingManager mappingManager = getMappingManager(); 26 | VertxMapper mapper = mappingManager.mapper(MyEntity.class); 27 | 28 | MyEntity entity = getEntity(); 29 | 30 | mapper.saveAsync(entity, new FutureCallback() { 31 | @Override 32 | public void onSuccess(Void aVoid) { 33 | // Entity saved successfully 34 | } 35 | 36 | @Override 37 | public void onFailure(Throwable t) { 38 | // Entity save failed 39 | } 40 | }); 41 | ``` 42 | 43 | #### Get 44 | 45 | ```java 46 | // Get a mapper from the vert.x mapping manager 47 | VertxMappingManager mappingManager = getMappingManager(); 48 | VertxMapper mapper = mappingManager.mapper(MyEntity.class); 49 | 50 | String entityId = "123"; 51 | 52 | mapper.getAsync(new FutureCallback() { 53 | @Override 54 | public void onSuccess(MyEntity entity) { 55 | // Entity loaded from cassandra (if it existed) 56 | } 57 | 58 | @Override 59 | public void onFailure(Throwable t) { 60 | // Entity failed to load 61 | } 62 | }, entityId); 63 | ``` 64 | 65 | See the [integration test](src/test/java/com/englishtown/vertx/cassandra/mapping/integration/MappingIntegrationTest.java) for more details. 66 | 67 | 68 | ## Constructing VertxMappingManager 69 | 70 | #### Dependency Injection 71 | 72 | Guice and HK2 Binders have been provided for injecting a singleton instance of `VertxMappingManager` 73 | 74 | * `com.englishtown.vertx.cassandra.mapping.guice.GuiceMappingBinder` 75 | * `com.englishtown.vertx.cassandra.mapping.hk2.HK2MappingBinder` 76 | 77 | #### Manual Instantiation 78 | 79 | The `VertxMappingManager` can be instantiated by passing your instance of `CassandraSession`: 80 | 81 | ```java 82 | CassandraSession session = getSession(); 83 | VertxMappingManager mappingManager = new DefaultVertxMappingManager(session); 84 | ``` 85 | 86 | ## Promises 87 | 88 | A when.java version has also been provided `com.englishtown.vertx.cassandra.mapping.promises.WhenVertxMappingManager` to work with promises. 89 | 90 | See the [when integration test](src/test/java/com/englishtown/vertx/cassandra/mapping/integration/WhenMappingIntegrationTest.java) for more details. -------------------------------------------------------------------------------- /vertx-cassandra-mapping/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | vertx-cassandra-mapping 6 | 7 | 8 | vertx-cassandra-parent 9 | com.englishtown.vertx 10 | 3.7.0-SNAPSHOT 11 | 12 | 13 | 14 | 15 | com.englishtown.vertx 16 | vertx-cassandra 17 | ${project.version} 18 | 19 | 20 | com.datastax.cassandra 21 | cassandra-driver-mapping 22 | 23 | 24 | 25 | 26 | com.englishtown.vertx 27 | vertx-hk2 28 | true 29 | 30 | 31 | com.englishtown.vertx 32 | vertx-guice 33 | true 34 | 35 | 36 | com.englishtown.vertx 37 | vertx-when 38 | true 39 | 40 | 41 | 42 | 43 | com.englishtown.vertx 44 | vertx-cassandra 45 | ${project.version} 46 | test-jar 47 | test 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /vertx-cassandra-mapping/src/main/java/com/englishtown/vertx/cassandra/mapping/VertxMapper.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.mapping; 2 | 3 | import com.datastax.driver.mapping.Mapper; 4 | import com.google.common.util.concurrent.FutureCallback; 5 | 6 | /** 7 | * Vert.x wrapper over a datastax {@link Mapper} 8 | */ 9 | public interface VertxMapper { 10 | 11 | Mapper getMapper(); 12 | 13 | void saveAsync(T entity, FutureCallback callback); 14 | 15 | void deleteAsync(T entity, FutureCallback callback); 16 | 17 | void deleteAsync(FutureCallback callback, Object... primaryKey); 18 | 19 | void getAsync(FutureCallback callback, Object... primaryKey); 20 | 21 | } 22 | -------------------------------------------------------------------------------- /vertx-cassandra-mapping/src/main/java/com/englishtown/vertx/cassandra/mapping/VertxMappingManager.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.mapping; 2 | 3 | import com.datastax.driver.mapping.MappingManager; 4 | 5 | /** 6 | * Vert.x wrapper over a datastax {@link com.datastax.driver.mapping.MappingManager} 7 | */ 8 | public interface VertxMappingManager { 9 | 10 | /** 11 | * Gets the underlying datastax {@link MappingManager} 12 | * 13 | * @return 14 | */ 15 | MappingManager getMappingManager(); 16 | 17 | /** 18 | * Returns a vert.x wrapped {@link com.datastax.driver.mapping.Mapper} 19 | * 20 | * @param klass 21 | * @param 22 | * @return 23 | */ 24 | VertxMapper mapper(Class klass); 25 | 26 | } 27 | -------------------------------------------------------------------------------- /vertx-cassandra-mapping/src/main/java/com/englishtown/vertx/cassandra/mapping/guice/GuiceMappingBinder.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.mapping.guice; 2 | 3 | import com.englishtown.vertx.cassandra.mapping.VertxMappingManager; 4 | import com.englishtown.vertx.cassandra.mapping.impl.DefaultVertxMappingManager; 5 | import com.google.inject.AbstractModule; 6 | 7 | import javax.inject.Singleton; 8 | 9 | /** 10 | * Guice binder for cassandra mapping 11 | */ 12 | public class GuiceMappingBinder extends AbstractModule { 13 | /** 14 | * {@inheritDoc} 15 | */ 16 | @Override 17 | protected void configure() { 18 | 19 | bind(VertxMappingManager.class).to(DefaultVertxMappingManager.class).in(Singleton.class); 20 | 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /vertx-cassandra-mapping/src/main/java/com/englishtown/vertx/cassandra/mapping/guice/WhenGuiceMappingBinder.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.mapping.guice; 2 | 3 | import com.englishtown.vertx.cassandra.mapping.promises.WhenVertxMappingManager; 4 | import com.englishtown.vertx.cassandra.mapping.promises.impl.DefaultWhenVertxMappingManager; 5 | import com.google.inject.AbstractModule; 6 | 7 | import javax.inject.Singleton; 8 | 9 | /** 10 | * Guice binder for when.java cassandra mapping 11 | */ 12 | public class WhenGuiceMappingBinder extends AbstractModule { 13 | /** 14 | * {@inheritDoc} 15 | */ 16 | @Override 17 | protected void configure() { 18 | install(new GuiceMappingBinder()); 19 | 20 | bind(WhenVertxMappingManager.class).to(DefaultWhenVertxMappingManager.class).in(Singleton.class); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /vertx-cassandra-mapping/src/main/java/com/englishtown/vertx/cassandra/mapping/hk2/HK2MappingBinder.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.mapping.hk2; 2 | 3 | import com.englishtown.vertx.cassandra.mapping.VertxMappingManager; 4 | import com.englishtown.vertx.cassandra.mapping.impl.DefaultVertxMappingManager; 5 | import org.glassfish.hk2.utilities.binding.AbstractBinder; 6 | 7 | import javax.inject.Singleton; 8 | 9 | /** 10 | * HK2 binder for cassandra mapping 11 | */ 12 | public class HK2MappingBinder extends AbstractBinder { 13 | /** 14 | * {@inheritDoc} 15 | */ 16 | @Override 17 | protected void configure() { 18 | 19 | bind(DefaultVertxMappingManager.class).to(VertxMappingManager.class).in(Singleton.class); 20 | 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /vertx-cassandra-mapping/src/main/java/com/englishtown/vertx/cassandra/mapping/hk2/WhenHK2MappingBinder.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.mapping.hk2; 2 | 3 | import com.englishtown.vertx.cassandra.mapping.promises.WhenVertxMappingManager; 4 | import com.englishtown.vertx.cassandra.mapping.promises.impl.DefaultWhenVertxMappingManager; 5 | import org.glassfish.hk2.utilities.binding.AbstractBinder; 6 | 7 | import javax.inject.Singleton; 8 | 9 | /** 10 | * HK2 binder for when.java cassandra mapping 11 | */ 12 | public class WhenHK2MappingBinder extends AbstractBinder { 13 | /** 14 | * {@inheritDoc} 15 | */ 16 | @Override 17 | protected void configure() { 18 | install(new HK2MappingBinder()); 19 | 20 | bind(DefaultWhenVertxMappingManager.class).to(WhenVertxMappingManager.class).in(Singleton.class); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /vertx-cassandra-mapping/src/main/java/com/englishtown/vertx/cassandra/mapping/impl/DefaultVertxMapper.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.mapping.impl; 2 | 3 | import com.datastax.driver.mapping.Mapper; 4 | import com.englishtown.vertx.cassandra.FutureUtils; 5 | import com.englishtown.vertx.cassandra.mapping.VertxMapper; 6 | import com.google.common.util.concurrent.FutureCallback; 7 | import com.google.common.util.concurrent.ListenableFuture; 8 | import io.vertx.core.Vertx; 9 | 10 | /** 11 | * Default implementation of {@link VertxMapper} 12 | */ 13 | public class DefaultVertxMapper implements VertxMapper { 14 | 15 | private final Mapper mapper; 16 | private final Vertx vertx; 17 | 18 | public DefaultVertxMapper(Mapper mapper, Vertx vertx) { 19 | this.mapper = mapper; 20 | this.vertx = vertx; 21 | } 22 | 23 | @Override 24 | public Mapper getMapper() { 25 | return mapper; 26 | } 27 | 28 | @Override 29 | public void saveAsync(T entity, FutureCallback callback) { 30 | ListenableFuture future = mapper.saveAsync(entity); 31 | FutureUtils.addCallback(future, callback, vertx); 32 | } 33 | 34 | @Override 35 | public void deleteAsync(T entity, FutureCallback callback) { 36 | ListenableFuture future = mapper.deleteAsync(entity); 37 | FutureUtils.addCallback(future, callback, vertx); 38 | } 39 | 40 | @Override 41 | public void deleteAsync(FutureCallback callback, Object... primaryKey) { 42 | ListenableFuture future = mapper.deleteAsync(primaryKey); 43 | FutureUtils.addCallback(future, callback, vertx); 44 | } 45 | 46 | @Override 47 | public void getAsync(FutureCallback callback, Object... primaryKey) { 48 | ListenableFuture future = mapper.getAsync(primaryKey); 49 | FutureUtils.addCallback(future, callback, vertx); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /vertx-cassandra-mapping/src/main/java/com/englishtown/vertx/cassandra/mapping/impl/DefaultVertxMappingManager.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.mapping.impl; 2 | 3 | import com.datastax.driver.mapping.Mapper; 4 | import com.datastax.driver.mapping.MappingManager; 5 | import com.englishtown.vertx.cassandra.CassandraSession; 6 | import com.englishtown.vertx.cassandra.mapping.VertxMapper; 7 | import com.englishtown.vertx.cassandra.mapping.VertxMappingManager; 8 | 9 | import javax.inject.Inject; 10 | 11 | /** 12 | * Default implementation of {@link VertxMappingManager} 13 | */ 14 | public class DefaultVertxMappingManager implements VertxMappingManager { 15 | 16 | private final CassandraSession session; 17 | private final MappingManager mappingManager; 18 | 19 | @Inject 20 | public DefaultVertxMappingManager(CassandraSession session) { 21 | this.session = session; 22 | this.mappingManager = new MappingManager(session); 23 | } 24 | 25 | /** 26 | * Gets the underlying datastax {@link MappingManager} 27 | * 28 | * @return 29 | */ 30 | @Override 31 | public MappingManager getMappingManager() { 32 | return mappingManager; 33 | } 34 | 35 | /** 36 | * Returns a vert.x wrapped {@link Mapper} 37 | * 38 | * @param klass 39 | * @return 40 | */ 41 | @Override 42 | public VertxMapper mapper(Class klass) { 43 | Mapper mapper = getMappingManager().mapper(klass); 44 | return new DefaultVertxMapper<>(mapper, session.getVertx()); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /vertx-cassandra-mapping/src/main/java/com/englishtown/vertx/cassandra/mapping/promises/WhenVertxMapper.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.mapping.promises; 2 | 3 | import com.datastax.driver.mapping.Mapper; 4 | import com.englishtown.promises.Promise; 5 | import com.englishtown.vertx.cassandra.mapping.VertxMapper; 6 | 7 | /** 8 | * When.java wrapper over {@link VertxMapper} 9 | */ 10 | public interface WhenVertxMapper { 11 | 12 | Mapper getMapper(); 13 | 14 | Promise saveAsync(T entity); 15 | 16 | Promise deleteAsync(T entity); 17 | 18 | Promise deleteAsync(Object... primaryKey); 19 | 20 | Promise getAsync(Object... primaryKey); 21 | 22 | } 23 | -------------------------------------------------------------------------------- /vertx-cassandra-mapping/src/main/java/com/englishtown/vertx/cassandra/mapping/promises/WhenVertxMappingManager.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.mapping.promises; 2 | 3 | import com.datastax.driver.mapping.MappingManager; 4 | import com.englishtown.vertx.cassandra.mapping.VertxMappingManager; 5 | 6 | /** 7 | * When.java wrapper over {@link VertxMappingManager} 8 | */ 9 | public interface WhenVertxMappingManager { 10 | 11 | /** 12 | * Gets the underlying datastax {@link MappingManager} 13 | * 14 | * @return 15 | */ 16 | MappingManager getMappingManager(); 17 | 18 | /** 19 | * Returns a vert.x wrapped {@link com.datastax.driver.mapping.Mapper} 20 | * 21 | * @param klass 22 | * @param 23 | * @return 24 | */ 25 | WhenVertxMapper mapper(Class klass); 26 | 27 | 28 | } 29 | -------------------------------------------------------------------------------- /vertx-cassandra-mapping/src/main/java/com/englishtown/vertx/cassandra/mapping/promises/impl/DefaultWhenVertxMapper.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.mapping.promises.impl; 2 | 3 | import com.datastax.driver.mapping.Mapper; 4 | import com.englishtown.promises.Deferred; 5 | import com.englishtown.promises.Promise; 6 | import com.englishtown.promises.When; 7 | import com.englishtown.vertx.cassandra.FutureUtils; 8 | import com.englishtown.vertx.cassandra.mapping.promises.WhenVertxMapper; 9 | import com.google.common.util.concurrent.FutureCallback; 10 | import com.google.common.util.concurrent.ListenableFuture; 11 | import io.vertx.core.Vertx; 12 | 13 | /** 14 | * Default implementation of {@link WhenVertxMapper} 15 | */ 16 | public class DefaultWhenVertxMapper implements WhenVertxMapper { 17 | 18 | private final Mapper mapper; 19 | private final When when; 20 | private final Vertx vertx; 21 | 22 | public DefaultWhenVertxMapper(Mapper mapper, When when, Vertx vertx) { 23 | this.mapper = mapper; 24 | this.when = when; 25 | this.vertx = vertx; 26 | } 27 | 28 | @Override 29 | public Mapper getMapper() { 30 | return mapper; 31 | } 32 | 33 | @Override 34 | public Promise saveAsync(T entity) { 35 | return convertFuture(mapper.saveAsync(entity)); 36 | } 37 | 38 | @Override 39 | public Promise deleteAsync(T entity) { 40 | return convertFuture(mapper.deleteAsync(entity)); 41 | } 42 | 43 | @Override 44 | public Promise deleteAsync(Object... primaryKey) { 45 | return convertFuture(mapper.deleteAsync(primaryKey)); 46 | } 47 | 48 | @Override 49 | public Promise getAsync(Object... primaryKey) { 50 | return convertFuture(mapper.getAsync(primaryKey)); 51 | } 52 | 53 | private Promise convertFuture(ListenableFuture future) { 54 | 55 | Deferred d = when.defer(); 56 | 57 | FutureCallback callback = new FutureCallback() { 58 | @Override 59 | public void onSuccess(T result) { 60 | d.resolve(result); 61 | } 62 | 63 | @Override 64 | public void onFailure(Throwable t) { 65 | d.reject(t); 66 | } 67 | }; 68 | 69 | FutureUtils.addCallback(future, callback, vertx); 70 | return d.getPromise(); 71 | 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /vertx-cassandra-mapping/src/main/java/com/englishtown/vertx/cassandra/mapping/promises/impl/DefaultWhenVertxMappingManager.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.mapping.promises.impl; 2 | 3 | import com.datastax.driver.mapping.Mapper; 4 | import com.datastax.driver.mapping.MappingManager; 5 | import com.englishtown.promises.When; 6 | import com.englishtown.vertx.cassandra.CassandraSession; 7 | import com.englishtown.vertx.cassandra.mapping.promises.WhenVertxMapper; 8 | import com.englishtown.vertx.cassandra.mapping.promises.WhenVertxMappingManager; 9 | 10 | import javax.inject.Inject; 11 | 12 | /** 13 | * Default implementation of {@link WhenVertxMappingManager} 14 | */ 15 | public class DefaultWhenVertxMappingManager implements WhenVertxMappingManager { 16 | 17 | private final CassandraSession session; 18 | private final When when; 19 | private final MappingManager mappingManager; 20 | 21 | @Inject 22 | public DefaultWhenVertxMappingManager(CassandraSession session, When when) { 23 | this.session = session; 24 | this.when = when; 25 | this.mappingManager = new MappingManager(session); 26 | } 27 | 28 | /** 29 | * Gets the underlying datastax {@link MappingManager} 30 | * 31 | * @return 32 | */ 33 | @Override 34 | public MappingManager getMappingManager() { 35 | return mappingManager; 36 | } 37 | 38 | /** 39 | * Returns a vert.x wrapped {@link Mapper} 40 | * 41 | * @param klass 42 | * @return 43 | */ 44 | @Override 45 | public WhenVertxMapper mapper(Class klass) { 46 | Mapper mapper = getMappingManager().mapper(klass); 47 | return new DefaultWhenVertxMapper<>(mapper, when, session.getVertx()); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /vertx-cassandra-mapping/src/test/java/com/englishtown/vertx/cassandra/mapping/impl/DefaultVertxMapperTest.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.mapping.impl; 2 | 3 | import com.datastax.driver.mapping.Mapper; 4 | import com.englishtown.vertx.cassandra.mapping.integration.TestEntity; 5 | import com.google.common.util.concurrent.FutureCallback; 6 | import com.google.common.util.concurrent.ListenableFuture; 7 | import io.vertx.core.Vertx; 8 | import org.junit.Before; 9 | import org.junit.Test; 10 | import org.junit.runner.RunWith; 11 | import org.mockito.Matchers; 12 | import org.mockito.Mock; 13 | import org.mockito.runners.MockitoJUnitRunner; 14 | 15 | import static org.junit.Assert.*; 16 | import static org.mockito.Matchers.any; 17 | import static org.mockito.Matchers.eq; 18 | import static org.mockito.Mockito.verify; 19 | import static org.mockito.Mockito.when; 20 | 21 | /** 22 | * Unit tests for {@link DefaultVertxMapper} 23 | */ 24 | @RunWith(MockitoJUnitRunner.class) 25 | public class DefaultVertxMapperTest { 26 | 27 | private DefaultVertxMapper mapper; 28 | private TestEntity entity = new TestEntity(); 29 | 30 | @Mock 31 | private Mapper rawMapper; 32 | @Mock 33 | private Vertx vertx; 34 | @Mock 35 | private FutureCallback voidCallback; 36 | @Mock 37 | private FutureCallback entityCallback; 38 | @Mock 39 | private ListenableFuture voidFuture; 40 | @Mock 41 | private ListenableFuture entityFuture; 42 | 43 | @Before 44 | public void setUp() throws Exception { 45 | 46 | mapper = new DefaultVertxMapper<>(rawMapper, vertx); 47 | 48 | when(rawMapper.saveAsync(eq(entity))).thenReturn(voidFuture); 49 | when(rawMapper.deleteAsync(eq(entity))).thenReturn(voidFuture); 50 | when(rawMapper.deleteAsync(any(), any())).thenReturn(voidFuture); 51 | when(rawMapper.deleteAsync(Matchers.anyVararg())).thenReturn(voidFuture); 52 | when(rawMapper.getAsync(any(), any())).thenReturn(entityFuture); 53 | 54 | } 55 | 56 | @Test 57 | public void testGetMapper() throws Exception { 58 | assertEquals(rawMapper, mapper.getMapper()); 59 | } 60 | 61 | @Test 62 | public void testSaveAsync() throws Exception { 63 | 64 | mapper.saveAsync(entity, voidCallback); 65 | verify(rawMapper).saveAsync(eq(entity)); 66 | verify(voidFuture).addListener(any(), any()); 67 | 68 | } 69 | 70 | @Test 71 | public void testDeleteAsync() throws Exception { 72 | 73 | mapper.deleteAsync(entity, voidCallback); 74 | verify(rawMapper).deleteAsync(eq(entity)); 75 | verify(voidFuture).addListener(any(), any()); 76 | 77 | } 78 | 79 | @Test 80 | public void testDeleteAsync_ById() throws Exception { 81 | 82 | Object key1 = new Object(); 83 | Object key2 = new Object(); 84 | 85 | mapper.deleteAsync(voidCallback, key1, key2); 86 | verify(rawMapper).deleteAsync(eq(key1), eq(key2)); 87 | verify(voidFuture).addListener(any(), any()); 88 | 89 | } 90 | 91 | @Test 92 | public void testGetAsync() throws Exception { 93 | 94 | Object key1 = new Object(); 95 | Object key2 = new Object(); 96 | 97 | mapper.getAsync(entityCallback, key1, key2); 98 | verify(rawMapper).getAsync(eq(key1), eq(key2)); 99 | verify(entityFuture).addListener(any(), any()); 100 | 101 | } 102 | 103 | } -------------------------------------------------------------------------------- /vertx-cassandra-mapping/src/test/java/com/englishtown/vertx/cassandra/mapping/impl/DefaultVertxMappingManagerTest.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.mapping.impl; 2 | 3 | import com.datastax.driver.core.*; 4 | import com.datastax.driver.mapping.MappingManager; 5 | import com.englishtown.vertx.cassandra.CassandraSession; 6 | import com.englishtown.vertx.cassandra.mapping.VertxMapper; 7 | import com.englishtown.vertx.cassandra.mapping.integration.TestEntity; 8 | import org.junit.Before; 9 | import org.junit.Test; 10 | import org.junit.runner.RunWith; 11 | import org.mockito.Mock; 12 | import org.mockito.runners.MockitoJUnitRunner; 13 | 14 | import static org.hamcrest.CoreMatchers.instanceOf; 15 | import static org.junit.Assert.*; 16 | import static org.mockito.Matchers.anyString; 17 | import static org.mockito.Mockito.when; 18 | 19 | /** 20 | * Unit tests for {@link DefaultVertxMapper} 21 | */ 22 | @RunWith(MockitoJUnitRunner.class) 23 | public class DefaultVertxMappingManagerTest { 24 | 25 | private DefaultVertxMappingManager manager; 26 | 27 | @Mock 28 | private CassandraSession session; 29 | @Mock 30 | private Cluster cluster; 31 | @Mock 32 | private Metadata metadata; 33 | @Mock 34 | private KeyspaceMetadata keyspaceMetadata; 35 | @Mock 36 | private TableMetadata tableMetadata; 37 | @Mock 38 | private ColumnMetadata columnMetadata; 39 | @Mock 40 | private Configuration configuration; 41 | @Mock 42 | private ProtocolOptions protocolOptions; 43 | 44 | @Before 45 | public void setUp() throws Exception { 46 | 47 | when(session.getCluster()).thenReturn(cluster); 48 | when(cluster.getMetadata()).thenReturn(metadata); 49 | when(metadata.getKeyspace(anyString())).thenReturn(keyspaceMetadata); 50 | when(keyspaceMetadata.getTable(anyString())).thenReturn(tableMetadata); 51 | when(tableMetadata.getColumn(anyString())).thenReturn(columnMetadata); 52 | when(cluster.getConfiguration()).thenReturn(configuration); 53 | when(configuration.getProtocolOptions()).thenReturn(protocolOptions); 54 | when(protocolOptions.getProtocolVersion()).thenReturn(ProtocolVersion.NEWEST_SUPPORTED); 55 | 56 | manager = new DefaultVertxMappingManager(session); 57 | 58 | } 59 | 60 | @Test 61 | public void testGetMappingManager() throws Exception { 62 | 63 | assertThat(manager.getMappingManager(), instanceOf(MappingManager.class)); 64 | 65 | } 66 | 67 | @Test 68 | public void testMapper() throws Exception { 69 | 70 | VertxMapper mapper = manager.mapper(TestEntity.class); 71 | 72 | assertNotNull(mapper); 73 | assertNotNull(mapper.getMapper()); 74 | 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /vertx-cassandra-mapping/src/test/java/com/englishtown/vertx/cassandra/mapping/integration/MappingIntegrationTest.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.mapping.integration; 2 | 3 | import com.datastax.driver.core.Statement; 4 | import com.englishtown.vertx.cassandra.integration.IntegrationTestBase; 5 | import com.englishtown.vertx.cassandra.mapping.VertxMapper; 6 | import com.englishtown.vertx.cassandra.mapping.VertxMappingManager; 7 | import com.englishtown.vertx.cassandra.tablebuilder.TableBuilder; 8 | import com.google.common.util.concurrent.FutureCallback; 9 | import org.junit.Test; 10 | 11 | import java.util.function.Consumer; 12 | 13 | /** 14 | * Cassandra driver mapping integration tests 15 | */ 16 | public abstract class MappingIntegrationTest extends IntegrationTestBase { 17 | 18 | private VertxMappingManager manager; 19 | 20 | @Override 21 | public void setUp() throws Exception { 22 | super.setUp(); 23 | 24 | Statement statement = TableBuilder.create(TEST_KEYSPACE, TestEntity.TABLE_NAME) 25 | .ifNotExists() 26 | .column("id", "text") 27 | .column("prop1", "text") 28 | .column("prop2", "int") 29 | .primaryKey("id"); 30 | 31 | session.execute(statement); 32 | manager = getInstance(VertxMappingManager.class); 33 | 34 | } 35 | 36 | @Test 37 | public void testMapper() throws Exception { 38 | 39 | VertxMapper mapper = manager.mapper(TestEntity.class); 40 | 41 | TestEntity entity = new TestEntity(); 42 | entity.setId("1"); 43 | entity.setProp1("p1"); 44 | entity.setProp2(2); 45 | 46 | // Save the entity 47 | mapper.saveAsync(entity, callback(aVoid1 -> { 48 | 49 | // Get it from db 50 | mapper.getAsync(callback(dbEntity -> { 51 | 52 | assertEquals(entity.getId(), dbEntity.getId()); 53 | assertEquals(entity.getProp1(), dbEntity.getProp1()); 54 | assertEquals(entity.getProp2(), dbEntity.getProp2()); 55 | 56 | // Delete the entity 57 | mapper.deleteAsync(dbEntity, callback(aVoid2 -> { 58 | 59 | // Get it again and ensure null 60 | mapper.getAsync(callback(dbEntity2 -> { 61 | 62 | assertNull(dbEntity2); 63 | testComplete(); 64 | 65 | }), entity.getId()); 66 | 67 | })); 68 | 69 | }), entity.getId()); 70 | 71 | })); 72 | 73 | await(); 74 | 75 | } 76 | 77 | private FutureCallback callback(Consumer onSuccess) { 78 | return new FutureCallback() { 79 | @Override 80 | public void onSuccess(T result) { 81 | onSuccess.accept(result); 82 | } 83 | 84 | @Override 85 | public void onFailure(Throwable t) { 86 | try { 87 | t.printStackTrace(); 88 | } catch (Throwable t2) { 89 | } 90 | fail(t.getMessage()); 91 | } 92 | }; 93 | } 94 | 95 | } 96 | -------------------------------------------------------------------------------- /vertx-cassandra-mapping/src/test/java/com/englishtown/vertx/cassandra/mapping/integration/TestEntity.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.mapping.integration; 2 | 3 | import com.datastax.driver.mapping.annotations.Column; 4 | import com.datastax.driver.mapping.annotations.PartitionKey; 5 | import com.datastax.driver.mapping.annotations.Table; 6 | import com.englishtown.vertx.cassandra.integration.IntegrationTestBase; 7 | 8 | /** 9 | * 10 | */ 11 | @Table(keyspace = IntegrationTestBase.TEST_KEYSPACE, name = TestEntity.TABLE_NAME) 12 | public class TestEntity { 13 | 14 | public static final String TABLE_NAME = "test_entity"; 15 | 16 | @PartitionKey 17 | private String id; 18 | @Column 19 | private String prop1; 20 | @Column 21 | private Integer prop2; 22 | 23 | public String getId() { 24 | return id; 25 | } 26 | 27 | public void setId(String id) { 28 | this.id = id; 29 | } 30 | 31 | public String getProp1() { 32 | return prop1; 33 | } 34 | 35 | public void setProp1(String prop1) { 36 | this.prop1 = prop1; 37 | } 38 | 39 | public Integer getProp2() { 40 | return prop2; 41 | } 42 | 43 | public void setProp2(Integer prop2) { 44 | this.prop2 = prop2; 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /vertx-cassandra-mapping/src/test/java/com/englishtown/vertx/cassandra/mapping/integration/WhenMappingIntegrationTest.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.mapping.integration; 2 | 3 | import com.datastax.driver.core.Statement; 4 | import com.englishtown.vertx.cassandra.integration.IntegrationTestBase; 5 | import com.englishtown.vertx.cassandra.mapping.promises.WhenVertxMapper; 6 | import com.englishtown.vertx.cassandra.mapping.promises.WhenVertxMappingManager; 7 | import com.englishtown.vertx.cassandra.tablebuilder.TableBuilder; 8 | import org.junit.Test; 9 | 10 | /** 11 | * Cassandra driver mapping integration tests 12 | */ 13 | public abstract class WhenMappingIntegrationTest extends IntegrationTestBase { 14 | 15 | private WhenVertxMappingManager manager; 16 | 17 | @Override 18 | public void setUp() throws Exception { 19 | super.setUp(); 20 | 21 | Statement statement = TableBuilder.create(TEST_KEYSPACE, TestEntity.TABLE_NAME) 22 | .ifNotExists() 23 | .column("id", "text") 24 | .column("prop1", "text") 25 | .column("prop2", "int") 26 | .primaryKey("id"); 27 | 28 | session.execute(statement); 29 | manager = getInstance(WhenVertxMappingManager.class); 30 | 31 | } 32 | 33 | @Test 34 | public void testMapper() throws Exception { 35 | 36 | WhenVertxMapper mapper = manager.mapper(TestEntity.class); 37 | 38 | TestEntity entity = new TestEntity(); 39 | entity.setId("1"); 40 | entity.setProp1("p1"); 41 | entity.setProp2(2); 42 | 43 | mapper.saveAsync(entity) 44 | .then(aVoid -> mapper.getAsync(entity.getId())) 45 | .then(dbEntity -> { 46 | assertEquals(entity.getId(), dbEntity.getId()); 47 | assertEquals(entity.getProp1(), dbEntity.getProp1()); 48 | assertEquals(entity.getProp2(), dbEntity.getProp2()); 49 | 50 | return mapper.deleteAsync(dbEntity); 51 | }) 52 | .then(aVoid -> mapper.getAsync(entity.getId())) 53 | .then(dbEntity -> { 54 | assertNull(dbEntity); 55 | testComplete(); 56 | return null; 57 | }) 58 | .otherwise(t -> { 59 | try { 60 | t.printStackTrace(); 61 | } catch (Throwable t2) { 62 | } 63 | fail(t.getMessage()); 64 | return null; 65 | }); 66 | 67 | await(); 68 | 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /vertx-cassandra-mapping/src/test/java/com/englishtown/vertx/cassandra/mapping/integration/guice/GuiceMappingIntegrationTest.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.mapping.integration.guice; 2 | 3 | import com.englishtown.vertx.cassandra.integration.Locator; 4 | import com.englishtown.vertx.cassandra.integration.guice.GuiceLocator; 5 | import com.englishtown.vertx.cassandra.mapping.guice.GuiceMappingBinder; 6 | import com.englishtown.vertx.cassandra.mapping.integration.MappingIntegrationTest; 7 | 8 | /** 9 | * Guice version of {@link MappingIntegrationTest} 10 | */ 11 | public class GuiceMappingIntegrationTest extends MappingIntegrationTest { 12 | 13 | @Override 14 | protected Locator createLocator() { 15 | return new GuiceLocator(vertx, new GuiceMappingBinder()); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /vertx-cassandra-mapping/src/test/java/com/englishtown/vertx/cassandra/mapping/integration/guice/GuiceWhenMappingIntegrationTest.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.mapping.integration.guice; 2 | 3 | import com.englishtown.vertx.cassandra.integration.Locator; 4 | import com.englishtown.vertx.cassandra.integration.guice.GuiceLocator; 5 | import com.englishtown.vertx.cassandra.mapping.guice.WhenGuiceMappingBinder; 6 | import com.englishtown.vertx.cassandra.mapping.integration.WhenMappingIntegrationTest; 7 | 8 | /** 9 | * Guice version of {@link WhenMappingIntegrationTest} 10 | */ 11 | public class GuiceWhenMappingIntegrationTest extends WhenMappingIntegrationTest { 12 | 13 | @Override 14 | protected Locator createLocator() { 15 | return new GuiceLocator(vertx, new WhenGuiceMappingBinder()); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /vertx-cassandra-mapping/src/test/java/com/englishtown/vertx/cassandra/mapping/integration/hk2/HK2MappingIntegrationTest.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.mapping.integration.hk2; 2 | 3 | import com.englishtown.vertx.cassandra.integration.Locator; 4 | import com.englishtown.vertx.cassandra.integration.hk2.HK2Locator; 5 | import com.englishtown.vertx.cassandra.mapping.hk2.HK2MappingBinder; 6 | import com.englishtown.vertx.cassandra.mapping.integration.MappingIntegrationTest; 7 | 8 | /** 9 | * HK2 version of {@link MappingIntegrationTest} 10 | */ 11 | public class HK2MappingIntegrationTest extends MappingIntegrationTest { 12 | 13 | @Override 14 | protected Locator createLocator() { 15 | return new HK2Locator(vertx, new HK2MappingBinder()); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /vertx-cassandra-mapping/src/test/java/com/englishtown/vertx/cassandra/mapping/integration/hk2/HK2WhenMappingIntegrationTest.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.mapping.integration.hk2; 2 | 3 | import com.englishtown.vertx.cassandra.integration.Locator; 4 | import com.englishtown.vertx.cassandra.integration.hk2.HK2Locator; 5 | import com.englishtown.vertx.cassandra.mapping.hk2.WhenHK2MappingBinder; 6 | import com.englishtown.vertx.cassandra.mapping.integration.WhenMappingIntegrationTest; 7 | 8 | /** 9 | * HK2 version of {@link WhenMappingIntegrationTest} 10 | */ 11 | public class HK2WhenMappingIntegrationTest extends WhenMappingIntegrationTest { 12 | 13 | @Override 14 | protected Locator createLocator() { 15 | return new HK2Locator(vertx, new WhenHK2MappingBinder()); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /vertx-cassandra/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | vertx-cassandra 6 | 7 | 8 | vertx-cassandra-parent 9 | com.englishtown.vertx 10 | 3.7.0-SNAPSHOT 11 | 12 | 13 | 14 | 15 | com.datastax.cassandra 16 | cassandra-driver-core 17 | 18 | 19 | 20 | 21 | com.englishtown.vertx 22 | vertx-hk2 23 | true 24 | 25 | 26 | com.englishtown.vertx 27 | vertx-guice 28 | true 29 | 30 | 31 | com.englishtown.vertx 32 | vertx-when 33 | true 34 | 35 | 36 | com.englishtown.vertx 37 | vertx-curator 38 | true 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | org.apache.maven.plugins 47 | maven-jar-plugin 48 | 49 | 50 | 51 | test-jar 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /vertx-cassandra/src/main/java/com/englishtown/vertx/cassandra/CassandraConfigurator.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra; 2 | 3 | import com.datastax.driver.core.*; 4 | import com.datastax.driver.core.policies.LoadBalancingPolicy; 5 | import com.datastax.driver.core.policies.ReconnectionPolicy; 6 | import io.vertx.core.AsyncResult; 7 | import io.vertx.core.Handler; 8 | 9 | import java.util.List; 10 | 11 | /** 12 | * Provides cassandra configuration for the session 13 | */ 14 | public interface CassandraConfigurator { 15 | 16 | /** 17 | * List of cassandra seed hosts or IPs 18 | * 19 | * @return 20 | */ 21 | List getSeeds(); 22 | 23 | /** 24 | * Optional port to use to connect to cassandra. 25 | * 26 | * @return 27 | */ 28 | Integer getPort(); 29 | 30 | /** 31 | * Optional load balancing policy 32 | * 33 | * @return 34 | */ 35 | LoadBalancingPolicy getLoadBalancingPolicy(); 36 | 37 | /** 38 | * Optional reconnection policy 39 | * 40 | * @return 41 | */ 42 | ReconnectionPolicy getReconnectionPolicy(); 43 | 44 | /** 45 | * Optional pooling options 46 | * 47 | * @return 48 | */ 49 | PoolingOptions getPoolingOptions(); 50 | 51 | /** 52 | * Optional socket options 53 | * 54 | * @return 55 | */ 56 | SocketOptions getSocketOptions(); 57 | 58 | /** 59 | * Optional query options 60 | * 61 | * @return 62 | */ 63 | QueryOptions getQueryOptions(); 64 | 65 | /** 66 | * Optional metrics options 67 | * 68 | * @return 69 | */ 70 | MetricsOptions getMetricsOptions(); 71 | 72 | /** 73 | * Optional auth provider 74 | * 75 | * @return 76 | */ 77 | AuthProvider getAuthProvider(); 78 | 79 | /** 80 | * Register a callback for when the configurator is ready to use 81 | * 82 | * @param callback 83 | */ 84 | void onReady(Handler> callback); 85 | } 86 | -------------------------------------------------------------------------------- /vertx-cassandra/src/main/java/com/englishtown/vertx/cassandra/CassandraSession.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra; 2 | 3 | import com.datastax.driver.core.*; 4 | import com.google.common.util.concurrent.FutureCallback; 5 | import io.vertx.core.AsyncResult; 6 | import io.vertx.core.Handler; 7 | import io.vertx.core.Vertx; 8 | 9 | /** 10 | * Interface that represents a cassandra session 11 | */ 12 | public interface CassandraSession extends Session, AutoCloseable { 13 | 14 | /** 15 | * Executes a cassandra statement asynchronously. Ensures the callback is executed on the correct vert.x context. 16 | * 17 | * @param statement the statement to execute 18 | * @param callback the callback for on completion 19 | */ 20 | void executeAsync(Statement statement, final FutureCallback callback); 21 | 22 | /** 23 | * Executes a cassandra CQL query asynchronously. Ensures the callback is executed on the correct vert.x context. 24 | * 25 | * @param query the CQL query to execute 26 | * @param callback the callback for on completion 27 | */ 28 | void executeAsync(String query, final FutureCallback callback); 29 | 30 | /** 31 | * Prepares the provided query statement 32 | * 33 | * @param statement the query statement to prepare 34 | * @param callback the callback for on completion 35 | */ 36 | void prepareAsync(RegularStatement statement, FutureCallback callback); 37 | 38 | /** 39 | * Prepares the provided query 40 | * 41 | * @param query the query to prepare 42 | * @param callback the callback for on completion 43 | */ 44 | void prepareAsync(String query, FutureCallback callback); 45 | 46 | /** 47 | * Returns cassandra metadata 48 | * 49 | * @return returns the cassandra metadata for the current session 50 | */ 51 | Metadata getMetadata(); 52 | 53 | /** 54 | * Reconnects to the cluster with a new session. Any existing session is closed asynchronously. 55 | */ 56 | void reconnect(); 57 | 58 | /** 59 | * Reconnects to the cluster with a new session. Any existing session is closed asynchronously. 60 | */ 61 | void reconnectAsync(Handler> callback); 62 | 63 | /** 64 | * Flag to indicate if the the session is initialized and ready to use 65 | * 66 | * @return 67 | */ 68 | boolean initialized(); 69 | 70 | /** 71 | * Callback for when the session is initialized and ready 72 | * 73 | * @param callback 74 | */ 75 | void onReady(Handler> callback); 76 | 77 | /** 78 | * Returns current the underlying DataStax {@link com.datastax.driver.core.Session} 79 | * 80 | * @return 81 | */ 82 | Session getSession(); 83 | 84 | /** 85 | * Returns the vert.x instance 86 | * 87 | * @return 88 | */ 89 | Vertx getVertx(); 90 | 91 | } 92 | -------------------------------------------------------------------------------- /vertx-cassandra/src/main/java/com/englishtown/vertx/cassandra/FutureUtils.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra; 2 | 3 | import com.google.common.util.concurrent.FutureCallback; 4 | import com.google.common.util.concurrent.Futures; 5 | import com.google.common.util.concurrent.ListenableFuture; 6 | import io.vertx.core.Context; 7 | import io.vertx.core.Vertx; 8 | 9 | /** 10 | * Future vert.x utils 11 | */ 12 | public class FutureUtils { 13 | 14 | private FutureUtils() { 15 | } 16 | 17 | /** 18 | * Add a future callback to run on the vert.x context 19 | * 20 | * @param future listenable future to have the callback added to 21 | * @param callback the callback for the listenable future 22 | * @param vertx 23 | * @param 24 | */ 25 | public static void addCallback(final ListenableFuture future, FutureCallback callback, Vertx vertx) { 26 | final Context context = vertx.getOrCreateContext(); 27 | Futures.addCallback(future, callback, command -> context.runOnContext(aVoid -> command.run())); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /vertx-cassandra/src/main/java/com/englishtown/vertx/cassandra/guice/GuiceCassandraBinder.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.guice; 2 | 3 | import com.datastax.driver.core.Cluster; 4 | import com.englishtown.vertx.cassandra.CassandraConfigurator; 5 | import com.englishtown.vertx.cassandra.CassandraSession; 6 | import com.englishtown.vertx.cassandra.impl.DefaultCassandraSession; 7 | import com.englishtown.vertx.cassandra.impl.EnvironmentCassandraConfigurator; 8 | import com.google.inject.AbstractModule; 9 | 10 | import javax.inject.Singleton; 11 | 12 | /** 13 | * Guice injection bindings 14 | */ 15 | public class GuiceCassandraBinder extends AbstractModule { 16 | /** 17 | * Configures a {@link com.google.inject.Binder} via the exposed methods. 18 | */ 19 | @Override 20 | protected void configure() { 21 | 22 | bind(Cluster.Builder.class); 23 | bind(CassandraSession.class).to(DefaultCassandraSession.class).in(Singleton.class); 24 | bind(CassandraConfigurator.class).to(EnvironmentCassandraConfigurator.class).in(Singleton.class); 25 | bind(EnvironmentCassandraConfigurator.EnvVarDelegate.class).to(EnvironmentCassandraConfigurator.DefaultEnvVarDelegate.class); 26 | 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /vertx-cassandra/src/main/java/com/englishtown/vertx/cassandra/guice/GuiceWhenCassandraBinder.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.guice; 2 | 3 | import com.englishtown.vertx.cassandra.promises.WhenCassandraSession; 4 | import com.englishtown.vertx.cassandra.promises.impl.DefaultWhenCassandraSession; 5 | import com.google.inject.AbstractModule; 6 | 7 | import javax.inject.Singleton; 8 | 9 | /** 10 | * Guice injection bindings for when.java cassandra sessions 11 | */ 12 | public class GuiceWhenCassandraBinder extends AbstractModule { 13 | /** 14 | * Configures a {@link com.google.inject.Binder} via the exposed methods. 15 | */ 16 | @Override 17 | protected void configure() { 18 | 19 | // Install main bindings 20 | install(new GuiceCassandraBinder()); 21 | 22 | // when.java bindings 23 | bind(WhenCassandraSession.class).to(DefaultWhenCassandraSession.class).in(Singleton.class); 24 | 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /vertx-cassandra/src/main/java/com/englishtown/vertx/cassandra/guice/GuiceZooKeeperCassandraBinder.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.guice; 2 | 3 | import com.englishtown.vertx.cassandra.CassandraConfigurator; 4 | import com.englishtown.vertx.cassandra.zookeeper.ZooKeeperCassandraConfigurator; 5 | import com.google.inject.AbstractModule; 6 | 7 | import javax.inject.Singleton; 8 | 9 | /** 10 | * Guice binder for zookeeper cassandra configuration 11 | */ 12 | public class GuiceZooKeeperCassandraBinder extends AbstractModule { 13 | /** 14 | * Implement to provide binding definitions using the exposed binding 15 | * methods. 16 | */ 17 | @Override 18 | protected void configure() { 19 | 20 | // Install main bindings 21 | install(new GuiceCassandraBinder()); 22 | 23 | // zookeeper bindings 24 | bind(CassandraConfigurator.class).to(ZooKeeperCassandraConfigurator.class).in(Singleton.class); 25 | 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /vertx-cassandra/src/main/java/com/englishtown/vertx/cassandra/hk2/HK2CassandraBinder.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.hk2; 2 | 3 | import com.datastax.driver.core.Cluster; 4 | import com.englishtown.vertx.cassandra.CassandraConfigurator; 5 | import com.englishtown.vertx.cassandra.CassandraSession; 6 | import com.englishtown.vertx.cassandra.impl.DefaultCassandraSession; 7 | import com.englishtown.vertx.cassandra.impl.EnvironmentCassandraConfigurator; 8 | import org.glassfish.hk2.utilities.binding.AbstractBinder; 9 | 10 | import javax.inject.Singleton; 11 | 12 | /** 13 | * HK2 injection binder 14 | */ 15 | public class HK2CassandraBinder extends AbstractBinder { 16 | /** 17 | * Implement to provide binding definitions using the exposed binding 18 | * methods. 19 | */ 20 | @Override 21 | protected void configure() { 22 | 23 | bind(Cluster.Builder.class).to(Cluster.Builder.class); 24 | bind(DefaultCassandraSession.class).to(CassandraSession.class).in(Singleton.class); 25 | bind(EnvironmentCassandraConfigurator.class).to(CassandraConfigurator.class).in(Singleton.class); 26 | bind(EnvironmentCassandraConfigurator.DefaultEnvVarDelegate.class).to(EnvironmentCassandraConfigurator.EnvVarDelegate.class); 27 | 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /vertx-cassandra/src/main/java/com/englishtown/vertx/cassandra/hk2/HK2WhenCassandraBinder.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.hk2; 2 | 3 | import com.englishtown.vertx.cassandra.promises.WhenCassandraSession; 4 | import com.englishtown.vertx.cassandra.promises.impl.DefaultWhenCassandraSession; 5 | import org.glassfish.hk2.utilities.binding.AbstractBinder; 6 | 7 | import javax.inject.Singleton; 8 | 9 | /** 10 | * HK2 Binder for when.java cassandra sessions 11 | */ 12 | public class HK2WhenCassandraBinder extends AbstractBinder { 13 | /** 14 | * Implement to provide binding definitions using the exposed binding 15 | * methods. 16 | */ 17 | @Override 18 | protected void configure() { 19 | 20 | // Install main bindings 21 | install(new HK2CassandraBinder()); 22 | 23 | // when.java bindings 24 | bind(DefaultWhenCassandraSession.class).to(WhenCassandraSession.class).in(Singleton.class); 25 | 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /vertx-cassandra/src/main/java/com/englishtown/vertx/cassandra/hk2/HK2ZooKeeperCassandraBinder.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.hk2; 2 | 3 | import com.englishtown.vertx.cassandra.CassandraConfigurator; 4 | import com.englishtown.vertx.cassandra.zookeeper.ZooKeeperCassandraConfigurator; 5 | import org.glassfish.hk2.utilities.binding.AbstractBinder; 6 | 7 | import javax.inject.Singleton; 8 | 9 | /** 10 | * HK2 binder for zookeeper cassandra configuration 11 | */ 12 | public class HK2ZooKeeperCassandraBinder extends AbstractBinder { 13 | /** 14 | * Implement to provide binding definitions using the exposed binding 15 | * methods. 16 | */ 17 | @Override 18 | protected void configure() { 19 | 20 | // Install main bindings 21 | install(new HK2CassandraBinder()); 22 | 23 | // zookeeper bindings 24 | bind(ZooKeeperCassandraConfigurator.class).to(CassandraConfigurator.class).in(Singleton.class).ranked(10); 25 | 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /vertx-cassandra/src/main/java/com/englishtown/vertx/cassandra/impl/DefaultCassandraSession.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.impl; 2 | 3 | import com.datastax.driver.core.*; 4 | import com.englishtown.vertx.cassandra.CassandraConfigurator; 5 | import com.englishtown.vertx.cassandra.CassandraSession; 6 | import com.englishtown.vertx.cassandra.FutureUtils; 7 | import com.google.common.util.concurrent.FutureCallback; 8 | import com.google.common.util.concurrent.ListenableFuture; 9 | import io.vertx.core.AsyncResult; 10 | import io.vertx.core.Future; 11 | import io.vertx.core.Handler; 12 | import io.vertx.core.Vertx; 13 | import io.vertx.core.logging.Logger; 14 | import io.vertx.core.logging.LoggerFactory; 15 | 16 | import javax.inject.Inject; 17 | import java.util.ArrayList; 18 | import java.util.List; 19 | import java.util.Map; 20 | 21 | /** 22 | * Default implementation of {@link CassandraSession} 23 | */ 24 | public class DefaultCassandraSession implements CassandraSession { 25 | 26 | private Cluster.Builder clusterBuilder; 27 | private final Vertx vertx; 28 | private List>> onReadyCallbacks = new ArrayList<>(); 29 | 30 | protected Cluster cluster; 31 | protected Session session; 32 | protected Metrics metrics; 33 | protected CassandraConfigurator configurator; 34 | protected AsyncResult initResult; 35 | 36 | private final Logger logger = LoggerFactory.getLogger(DefaultCassandraSession.class); 37 | 38 | @Inject 39 | public DefaultCassandraSession(Cluster.Builder clusterBuilder, CassandraConfigurator configurator, Vertx vertx) { 40 | this.clusterBuilder = clusterBuilder; 41 | this.configurator = configurator; 42 | this.vertx = vertx; 43 | this.metrics = new Metrics(this); 44 | 45 | configurator.onReady(result -> { 46 | if (result.failed()) { 47 | initResult = result; 48 | runOnReadyCallbacks(initResult); 49 | return; 50 | } 51 | try { 52 | init(configurator); 53 | } catch (Throwable t) { 54 | initResult = Future.failedFuture(t); 55 | runOnReadyCallbacks(initResult); 56 | } 57 | }); 58 | } 59 | 60 | CassandraConfigurator getConfigurator() { 61 | return configurator; 62 | } 63 | 64 | protected void init(CassandraConfigurator configurator) { 65 | 66 | // Get array of IPs, default to localhost 67 | List seeds = configurator.getSeeds(); 68 | if (seeds == null || seeds.isEmpty()) { 69 | throw new RuntimeException("Cassandra seeds are missing"); 70 | } 71 | 72 | // Add cassandra cluster contact points 73 | for (String seed : seeds) { 74 | clusterBuilder.addContactPoint(seed); 75 | } 76 | 77 | if (configurator.getPort() != null) { 78 | clusterBuilder.withPort(configurator.getPort()); 79 | } 80 | 81 | // Add policies to cluster builder 82 | if (configurator.getLoadBalancingPolicy() != null) { 83 | clusterBuilder.withLoadBalancingPolicy(configurator.getLoadBalancingPolicy()); 84 | } 85 | if (configurator.getReconnectionPolicy() != null) { 86 | clusterBuilder.withReconnectionPolicy(configurator.getReconnectionPolicy()); 87 | } 88 | 89 | // Add pooling options to cluster builder 90 | if (configurator.getPoolingOptions() != null) { 91 | clusterBuilder.withPoolingOptions(configurator.getPoolingOptions()); 92 | } 93 | 94 | // Add socket options to cluster builder 95 | if (configurator.getSocketOptions() != null) { 96 | clusterBuilder.withSocketOptions(configurator.getSocketOptions()); 97 | } 98 | 99 | if (configurator.getQueryOptions() != null) { 100 | clusterBuilder.withQueryOptions(configurator.getQueryOptions()); 101 | } 102 | 103 | if (configurator.getMetricsOptions() != null) { 104 | if (!configurator.getMetricsOptions().isJMXReportingEnabled()) { 105 | clusterBuilder.withoutJMXReporting(); 106 | } 107 | } 108 | 109 | if (configurator.getAuthProvider() != null) { 110 | clusterBuilder.withAuthProvider(configurator.getAuthProvider()); 111 | } 112 | 113 | // Build cluster and connect 114 | cluster = clusterBuilder.build(); 115 | reconnectAsync(result -> { 116 | initResult = result; 117 | runOnReadyCallbacks(initResult); 118 | }); 119 | 120 | } 121 | 122 | private void runOnReadyCallbacks(AsyncResult result) { 123 | initResult = result; 124 | onReadyCallbacks.forEach(handler -> handler.handle(result)); 125 | onReadyCallbacks.clear(); 126 | } 127 | 128 | /** 129 | * {@inheritDoc} 130 | */ 131 | @Override 132 | public Metadata getMetadata() { 133 | Cluster cluster = getCluster(); 134 | return cluster == null ? null : cluster.getMetadata(); 135 | } 136 | 137 | /** 138 | * {@inheritDoc} 139 | */ 140 | @Override 141 | public boolean isClosed() { 142 | return (session == null || session.isClosed()); 143 | } 144 | 145 | /** 146 | * {@inheritDoc} 147 | */ 148 | @Override 149 | public Cluster getCluster() { 150 | return session == null ? null : session.getCluster(); 151 | } 152 | 153 | /** 154 | * {@inheritDoc} 155 | */ 156 | @Override 157 | public State getState() { 158 | return getSession().getState(); 159 | } 160 | 161 | /** 162 | * {@inheritDoc} 163 | */ 164 | @Override 165 | public void reconnect() { 166 | logger.debug("Call to reconnect the session has been made"); 167 | Session oldSession = session; 168 | session = cluster.connect(); 169 | if (oldSession != null) { 170 | oldSession.closeAsync(); 171 | } 172 | metrics.afterReconnect(); 173 | } 174 | 175 | @Override 176 | public void reconnectAsync(Handler> callback) { 177 | logger.debug("Call to reconnect the session has been made"); 178 | Session oldSession = session; 179 | FutureUtils.addCallback(cluster.connectAsync(), new FutureCallback() { 180 | @Override 181 | public void onSuccess(Session session) { 182 | DefaultCassandraSession.this.session = session; 183 | if (oldSession != null) { 184 | oldSession.closeAsync(); 185 | } 186 | callback.handle(Future.succeededFuture()); 187 | metrics.afterReconnect(); 188 | } 189 | 190 | @Override 191 | public void onFailure(Throwable throwable) { 192 | callback.handle(Future.failedFuture(throwable)); 193 | } 194 | }, vertx); 195 | } 196 | 197 | /** 198 | * {@inheritDoc} 199 | */ 200 | @Override 201 | public boolean initialized() { 202 | return initResult != null; 203 | } 204 | 205 | /** 206 | * {@inheritDoc} 207 | */ 208 | @Override 209 | public void onReady(Handler> callback) { 210 | if (initResult != null) { 211 | callback.handle(initResult); 212 | } else { 213 | onReadyCallbacks.add(callback); 214 | } 215 | } 216 | 217 | /** 218 | * {@inheritDoc} 219 | */ 220 | @Override 221 | public Session getSession() { 222 | checkInitialized(); 223 | return session; 224 | } 225 | 226 | /** 227 | * Returns the vert.x instance 228 | * 229 | * @return 230 | */ 231 | @Override 232 | public Vertx getVertx() { 233 | return vertx; 234 | } 235 | 236 | /** 237 | * {@inheritDoc} 238 | */ 239 | @Override 240 | public String getLoggedKeyspace() { 241 | return getSession().getLoggedKeyspace(); 242 | } 243 | 244 | /** 245 | * {@inheritDoc} 246 | */ 247 | @Override 248 | public Session init() { 249 | return getSession().init(); 250 | } 251 | 252 | @Override 253 | public ListenableFuture initAsync() { 254 | return getSession().initAsync(); 255 | } 256 | 257 | /** 258 | * {@inheritDoc} 259 | */ 260 | @Override 261 | public ResultSet execute(String query) { 262 | return getSession().execute(query); 263 | } 264 | 265 | /** 266 | * {@inheritDoc} 267 | */ 268 | @Override 269 | public ResultSet execute(String query, Object... values) { 270 | return getSession().execute(query, values); 271 | } 272 | 273 | /** 274 | * {@inheritDoc} 275 | */ 276 | @Override 277 | public ResultSet execute(String query, Map values) { 278 | return getSession().execute(query, values); 279 | } 280 | 281 | /** 282 | * {@inheritDoc} 283 | */ 284 | @Override 285 | public ResultSet execute(Statement statement) { 286 | return getSession().execute(statement); 287 | } 288 | 289 | /** 290 | * {@inheritDoc} 291 | */ 292 | @Override 293 | public ResultSetFuture executeAsync(String query) { 294 | return getSession().executeAsync(query); 295 | } 296 | 297 | /** 298 | * {@inheritDoc} 299 | */ 300 | @Override 301 | public ResultSetFuture executeAsync(String query, Object... values) { 302 | return getSession().executeAsync(query, values); 303 | } 304 | 305 | /** 306 | * {@inheritDoc} 307 | */ 308 | @Override 309 | public ResultSetFuture executeAsync(String query, Map values) { 310 | return getSession().executeAsync(query, values); 311 | } 312 | 313 | /** 314 | * {@inheritDoc} 315 | */ 316 | @Override 317 | public ResultSetFuture executeAsync(Statement statement) { 318 | return getSession().executeAsync(statement); 319 | } 320 | 321 | /** 322 | * Executes a cassandra statement asynchronously. Ensures the callback is executed on the correct vert.x context. 323 | * 324 | * @param statement the statement to execute 325 | * @param callback the callback for on completion 326 | */ 327 | @Override 328 | public void executeAsync(Statement statement, FutureCallback callback) { 329 | addCallback(executeAsync(statement), callback); 330 | } 331 | 332 | /** 333 | * Executes a cassandra CQL query asynchronously. Ensures the callback is executed on the correct vert.x context. 334 | * 335 | * @param query the CQL query to execute 336 | * @param callback the callback for on completion 337 | */ 338 | @Override 339 | public void executeAsync(String query, FutureCallback callback) { 340 | addCallback(executeAsync(query), callback); 341 | } 342 | 343 | /** 344 | * {@inheritDoc} 345 | */ 346 | @Override 347 | public PreparedStatement prepare(String query) { 348 | return getSession().prepare(query); 349 | } 350 | 351 | /** 352 | * {@inheritDoc} 353 | */ 354 | @Override 355 | public PreparedStatement prepare(RegularStatement statement) { 356 | return getSession().prepare(statement); 357 | } 358 | 359 | /** 360 | * {@inheritDoc} 361 | */ 362 | @Override 363 | public ListenableFuture prepareAsync(String query) { 364 | return getSession().prepareAsync(query); 365 | } 366 | 367 | /** 368 | * {@inheritDoc} 369 | */ 370 | @Override 371 | public ListenableFuture prepareAsync(RegularStatement statement) { 372 | return getSession().prepareAsync(statement); 373 | } 374 | 375 | /** 376 | * Prepares the provided query statement 377 | * 378 | * @param statement the query statement to prepare 379 | * @param callback the callback for on completion 380 | */ 381 | @Override 382 | public void prepareAsync(RegularStatement statement, FutureCallback callback) { 383 | addCallback(prepareAsync(statement), callback); 384 | } 385 | 386 | /** 387 | * Prepares the provided query 388 | * 389 | * @param query the query to prepare 390 | * @param callback the callback for on completion 391 | */ 392 | @Override 393 | public void prepareAsync(String query, FutureCallback callback) { 394 | addCallback(prepareAsync(query), callback); 395 | } 396 | 397 | /** 398 | * {@inheritDoc} 399 | */ 400 | @Override 401 | public CloseFuture closeAsync() { 402 | return getSession().closeAsync(); 403 | } 404 | 405 | @Override 406 | public void close() { 407 | logger.debug("Call to close the session has been made"); 408 | if (metrics != null) { 409 | metrics.close(); 410 | metrics = null; 411 | } 412 | if (cluster != null) { 413 | cluster.closeAsync().force(); 414 | cluster = null; 415 | session = null; 416 | } 417 | clusterBuilder = null; 418 | } 419 | 420 | private void addCallback(final ListenableFuture future, FutureCallback callback) { 421 | FutureUtils.addCallback(future, callback, vertx); 422 | } 423 | 424 | private void checkInitialized() { 425 | if (!initialized()) { 426 | throw new IllegalStateException("Cassandra session is not ready for use yet"); 427 | } 428 | } 429 | 430 | } -------------------------------------------------------------------------------- /vertx-cassandra/src/main/java/com/englishtown/vertx/cassandra/impl/EnvironmentCassandraConfigurator.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.impl; 2 | 3 | import com.datastax.driver.core.PlainTextAuthProvider; 4 | import com.datastax.driver.core.policies.DCAwareRoundRobinPolicy; 5 | import com.google.common.base.Strings; 6 | import com.google.common.collect.ImmutableList; 7 | import io.vertx.core.Vertx; 8 | import io.vertx.core.json.JsonObject; 9 | import io.vertx.core.logging.Logger; 10 | import io.vertx.core.logging.LoggerFactory; 11 | 12 | import javax.inject.Inject; 13 | 14 | /** 15 | * 16 | */ 17 | public class EnvironmentCassandraConfigurator extends JsonCassandraConfigurator { 18 | 19 | // The environment variable that contains the pipe delimited list of seeds 20 | public static final String ENV_VAR_SEEDS = "CASSANDRA_SEEDS"; 21 | public static final String ENV_VAR_LOCAL_DC = "CASSANDRA_LOCAL_DC"; 22 | public static final String ENV_VAR_USERNAME = "CASSANDRA_USERNAME"; 23 | public static final String ENV_VAR_PASSWORD = "CASSANDRA_PASSWORD"; 24 | 25 | public static final Logger logger = LoggerFactory.getLogger(EnvironmentCassandraConfigurator.class); 26 | private final EnvVarDelegate envVarDelegate; 27 | 28 | @Inject 29 | public EnvironmentCassandraConfigurator(Vertx vertx, EnvVarDelegate envVarDelegate) { 30 | super(vertx); 31 | this.envVarDelegate = envVarDelegate; 32 | init(); 33 | } 34 | 35 | public EnvironmentCassandraConfigurator(JsonObject config, EnvVarDelegate envVarDelegate) { 36 | super(config); 37 | this.envVarDelegate = envVarDelegate; 38 | init(); 39 | } 40 | 41 | private void init() { 42 | initSeeds(); 43 | initLoadBalancingPolicy(); 44 | initAuthProvider(); 45 | } 46 | 47 | private void initSeeds() { 48 | String envVarSeeds = envVarDelegate.get(ENV_VAR_SEEDS); 49 | 50 | if (!Strings.isNullOrEmpty(envVarSeeds)) { 51 | logger.debug("Using environment configuration of " + envVarSeeds); 52 | String[] seedsArray = envVarSeeds.split("\\|"); 53 | this.seeds = ImmutableList.copyOf(seedsArray); 54 | } 55 | } 56 | 57 | private void initLoadBalancingPolicy() { 58 | String localDC = envVarDelegate.get(ENV_VAR_LOCAL_DC); 59 | 60 | if (!Strings.isNullOrEmpty(localDC)) { 61 | logger.debug("Using environment config for Local DC of " + localDC); 62 | loadBalancingPolicy = DCAwareRoundRobinPolicy.builder() 63 | .withLocalDc(localDC) 64 | .build(); 65 | } else { 66 | logger.debug("No environment configuration found for local DC"); 67 | } 68 | } 69 | 70 | private void initAuthProvider() { 71 | String username = envVarDelegate.get(ENV_VAR_USERNAME); 72 | String password = envVarDelegate.get(ENV_VAR_PASSWORD); 73 | 74 | if (!Strings.isNullOrEmpty(username) && !Strings.isNullOrEmpty(password)) { 75 | authProvider = new PlainTextAuthProvider(username, password); 76 | } 77 | } 78 | 79 | public interface EnvVarDelegate { 80 | String get(String name); 81 | } 82 | 83 | public static class DefaultEnvVarDelegate implements EnvVarDelegate { 84 | 85 | @Override 86 | public String get(String name) { 87 | return System.getenv(name); 88 | } 89 | } 90 | 91 | } 92 | -------------------------------------------------------------------------------- /vertx-cassandra/src/main/java/com/englishtown/vertx/cassandra/impl/JsonCassandraConfigurator.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.impl; 2 | 3 | import com.datastax.driver.core.*; 4 | import com.datastax.driver.core.policies.*; 5 | import com.englishtown.vertx.cassandra.CassandraConfigurator; 6 | import com.google.common.base.Strings; 7 | import com.google.common.collect.ImmutableList; 8 | import io.vertx.core.AsyncResult; 9 | import io.vertx.core.Future; 10 | import io.vertx.core.Handler; 11 | import io.vertx.core.Vertx; 12 | import io.vertx.core.json.JsonArray; 13 | import io.vertx.core.json.JsonObject; 14 | 15 | import javax.inject.Inject; 16 | import java.util.ArrayList; 17 | import java.util.List; 18 | 19 | /** 20 | * Json configuration based implementation of {@link com.englishtown.vertx.cassandra.CassandraConfigurator} 21 | */ 22 | public class JsonCassandraConfigurator implements CassandraConfigurator { 23 | 24 | protected List seeds; 25 | protected Integer port; 26 | protected LoadBalancingPolicy loadBalancingPolicy; 27 | protected ReconnectionPolicy reconnectionPolicy; 28 | protected PoolingOptions poolingOptions; 29 | protected SocketOptions socketOptions; 30 | protected QueryOptions queryOptions; 31 | protected MetricsOptions metricsOptions; 32 | protected AuthProvider authProvider; 33 | 34 | protected final List DEFAULT_SEEDS = ImmutableList.of("127.0.0.1"); 35 | 36 | public static final String CONFIG_CASSANDRA = "cassandra"; 37 | public static final String CONFIG_SEEDS = "seeds"; 38 | public static final String CONFIG_PORT = "port"; 39 | public static final String CONFIG_POLICIES = "policies"; 40 | public static final String CONFIG_POLICIES_LOAD_BALANCING = "load_balancing"; 41 | public static final String CONFIG_POLICIES_RECONNECTION = "reconnection"; 42 | public static final String CONFIG_POOLING = "pooling"; 43 | public static final String CONFIG_SOCKET = "socket"; 44 | public static final String CONFIG_METRICS = "metrics"; 45 | public static final String CONFIG_AUTH = "auth"; 46 | public static final String CONFIG_QUERY = "query"; 47 | public static final String CONFIG_CONSISTENCY_LEVEL = "consistency_level"; 48 | public static final String CONFIG_SERIAL_CONSISTENCY_LEVEL = "serial_consistency_level"; 49 | public static final String CONFIG_FETCH_SIZE = "fetch_size"; 50 | 51 | public static final String CONSISTENCY_ANY = "ANY"; 52 | public static final String CONSISTENCY_ONE = "ONE"; 53 | public static final String CONSISTENCY_TWO = "TWO"; 54 | public static final String CONSISTENCY_THREE = "THREE"; 55 | public static final String CONSISTENCY_QUORUM = "QUORUM"; 56 | public static final String CONSISTENCY_ALL = "ALL"; 57 | public static final String CONSISTENCY_LOCAL_ONE = "LOCAL_ONE"; 58 | public static final String CONSISTENCY_LOCAL_QUORUM = "LOCAL_QUORUM"; 59 | public static final String CONSISTENCY_EACH_QUORUM = "EACH_QUORUM"; 60 | 61 | public static final String CONSISTENCY_SERIAL = "SERIAL"; 62 | public static final String CONSISTENCY_LOCAL_SERIAL = "LOCAL_SERIAL"; 63 | 64 | @Inject 65 | public JsonCassandraConfigurator(Vertx vertx) { 66 | this(vertx.getOrCreateContext().config().getJsonObject(CONFIG_CASSANDRA, new JsonObject())); 67 | } 68 | 69 | public JsonCassandraConfigurator(JsonObject config) { 70 | init(config); 71 | } 72 | 73 | @Override 74 | public List getSeeds() { 75 | return seeds; 76 | } 77 | 78 | /** 79 | * Optional port to use to connect to cassandra. 80 | * 81 | * @return 82 | */ 83 | @Override 84 | public Integer getPort() { 85 | return port; 86 | } 87 | 88 | @Override 89 | public LoadBalancingPolicy getLoadBalancingPolicy() { 90 | return loadBalancingPolicy; 91 | } 92 | 93 | @Override 94 | public ReconnectionPolicy getReconnectionPolicy() { 95 | return reconnectionPolicy; 96 | } 97 | 98 | @Override 99 | public QueryOptions getQueryOptions() { 100 | return queryOptions; 101 | } 102 | 103 | @Override 104 | public MetricsOptions getMetricsOptions() { 105 | return metricsOptions; 106 | } 107 | 108 | @Override 109 | public AuthProvider getAuthProvider() { 110 | return authProvider; 111 | } 112 | 113 | @Override 114 | public void onReady(Handler> callback) { 115 | callback.handle(Future.succeededFuture(null)); 116 | } 117 | 118 | @Override 119 | public PoolingOptions getPoolingOptions() { 120 | return poolingOptions; 121 | } 122 | 123 | @Override 124 | public SocketOptions getSocketOptions() { 125 | return socketOptions; 126 | } 127 | 128 | protected void init(JsonObject config) { 129 | 130 | initSeeds(config.getJsonArray(CONFIG_SEEDS)); 131 | initPort(config); 132 | initPolicies(config.getJsonObject(CONFIG_POLICIES)); 133 | initPoolingOptions(config.getJsonObject(CONFIG_POOLING)); 134 | initSocketOptions(config.getJsonObject(CONFIG_SOCKET)); 135 | initQueryOptions(config.getJsonObject(CONFIG_QUERY, config)); 136 | initMetricsOptions(config.getJsonObject(CONFIG_METRICS)); 137 | initAuthProvider(config.getJsonObject(CONFIG_AUTH)); 138 | 139 | } 140 | 141 | protected void initSeeds(JsonArray seeds) { 142 | 143 | // Get array of IPs, default to localhost 144 | if (seeds == null || seeds.size() == 0) { 145 | this.seeds = DEFAULT_SEEDS; 146 | return; 147 | } 148 | 149 | this.seeds = new ArrayList<>(); 150 | for (int i = 0; i < seeds.size(); i++) { 151 | this.seeds.add(seeds.getString(i)); 152 | } 153 | } 154 | 155 | protected void initPort(JsonObject config) { 156 | Integer i = config.getInteger(CONFIG_PORT); 157 | 158 | if (i == null || i <= 0) { 159 | return; 160 | } 161 | 162 | port = i; 163 | } 164 | 165 | protected void initPolicies(JsonObject policyConfig) { 166 | 167 | if (policyConfig == null) { 168 | return; 169 | } 170 | 171 | initLoadBalancingPolicy(policyConfig.getJsonObject(CONFIG_POLICIES_LOAD_BALANCING)); 172 | initReconnectionPolicy(policyConfig.getJsonObject(CONFIG_POLICIES_RECONNECTION)); 173 | } 174 | 175 | protected void initLoadBalancingPolicy(JsonObject loadBalancing) { 176 | 177 | if (loadBalancing == null) { 178 | return; 179 | } 180 | 181 | String name = loadBalancing.getString("name"); 182 | 183 | if (name == null || name.isEmpty()) { 184 | throw new IllegalArgumentException("A load balancing policy must have a class name field"); 185 | 186 | } else if ("DCAwareRoundRobinPolicy".equalsIgnoreCase(name) 187 | || "com.datastax.driver.core.policies.DCAwareRoundRobinPolicy".equalsIgnoreCase(name)) { 188 | 189 | String localDc = loadBalancing.getString("local_dc"); 190 | int usedHostsPerRemoteDc = loadBalancing.getInteger("used_hosts_per_remote_dc", 0); 191 | 192 | if (localDc == null || localDc.isEmpty()) { 193 | throw new IllegalArgumentException("A DCAwareRoundRobinPolicy requires a local_dc in configuration."); 194 | } 195 | 196 | loadBalancingPolicy = DCAwareRoundRobinPolicy.builder() 197 | .withLocalDc(localDc) 198 | .withUsedHostsPerRemoteDc(usedHostsPerRemoteDc) 199 | .build(); 200 | 201 | } else { 202 | 203 | Class clazz; 204 | try { 205 | clazz = Thread.currentThread().getContextClassLoader().loadClass(name); 206 | } catch (ClassNotFoundException e) { 207 | throw new RuntimeException(e); 208 | } 209 | if (LoadBalancingPolicy.class.isAssignableFrom(clazz)) { 210 | try { 211 | loadBalancingPolicy = (LoadBalancingPolicy) clazz.newInstance(); 212 | } catch (IllegalAccessException | InstantiationException e) { 213 | throw new RuntimeException(e); 214 | } 215 | } else { 216 | throw new IllegalArgumentException("Class " + name + " does not implement LoadBalancingPolicy"); 217 | } 218 | 219 | } 220 | 221 | } 222 | 223 | protected void initReconnectionPolicy(JsonObject reconnection) { 224 | 225 | if (reconnection == null) { 226 | return; 227 | } 228 | 229 | String name = reconnection.getString("name"); 230 | 231 | if (name == null || name.isEmpty()) { 232 | throw new IllegalArgumentException("A reconnection policy must have a class name field"); 233 | 234 | } else if ("ConstantReconnectionPolicy".equalsIgnoreCase(name) || "constant".equalsIgnoreCase(name)) { 235 | Integer delay = reconnection.getInteger("delay"); 236 | 237 | if (delay == null) { 238 | throw new IllegalArgumentException("ConstantReconnectionPolicy requires a delay in configuration"); 239 | } 240 | 241 | reconnectionPolicy = new ConstantReconnectionPolicy(delay.intValue()); 242 | 243 | } else if ("ExponentialReconnectionPolicy".equalsIgnoreCase(name) || "exponential".equalsIgnoreCase(name)) { 244 | Long baseDelay = reconnection.getLong("base_delay"); 245 | Long maxDelay = reconnection.getLong("max_delay"); 246 | 247 | if (baseDelay == null && maxDelay == null) { 248 | throw new IllegalArgumentException("ExponentialReconnectionPolicy requires base_delay and max_delay in configuration"); 249 | } 250 | 251 | reconnectionPolicy = new ExponentialReconnectionPolicy(baseDelay.longValue(), maxDelay.longValue()); 252 | 253 | } else { 254 | Class clazz; 255 | try { 256 | clazz = Thread.currentThread().getContextClassLoader().loadClass(name); 257 | } catch (ClassNotFoundException e) { 258 | throw new RuntimeException(e); 259 | } 260 | 261 | if (!ReconnectionPolicy.class.isAssignableFrom(clazz)) { 262 | throw new IllegalArgumentException("Class " + name + " does not implement ReconnectionPolicy"); 263 | } 264 | 265 | try { 266 | reconnectionPolicy = (ReconnectionPolicy) clazz.newInstance(); 267 | } catch (IllegalAccessException | InstantiationException e) { 268 | throw new RuntimeException(e); 269 | } 270 | } 271 | 272 | } 273 | 274 | protected void initPoolingOptions(JsonObject poolingConfig) { 275 | 276 | if (poolingConfig == null) { 277 | return; 278 | } 279 | 280 | poolingOptions = new PoolingOptions(); 281 | 282 | Integer core_connections_per_host_local = poolingConfig.getInteger("core_connections_per_host_local"); 283 | Integer core_connections_per_host_remote = poolingConfig.getInteger("core_connections_per_host_remote"); 284 | Integer heartbeat_interval_seconds = poolingConfig.getInteger("heartbeat_interval_seconds"); 285 | Integer idle_timeout_seconds = poolingConfig.getInteger("idle_timeout_seconds"); 286 | Integer max_connections_per_host_local = poolingConfig.getInteger("max_connections_per_host_local"); 287 | Integer max_connections_per_host_remote = poolingConfig.getInteger("max_connections_per_host_remote"); 288 | Integer max_queue_size = poolingConfig.getInteger("max_queue_size"); 289 | Integer max_requests_per_connection_local = poolingConfig.getInteger("max_requests_per_connection_local"); 290 | Integer max_requests_per_connection_remote = poolingConfig.getInteger("max_requests_per_connection_remote"); 291 | Integer new_connection_threshold_local = poolingConfig.getInteger("new_connection_threshold_local"); 292 | Integer new_connection_threshold_remote = poolingConfig.getInteger("new_connection_threshold_remote"); 293 | 294 | if (core_connections_per_host_local != null) { 295 | poolingOptions.setCoreConnectionsPerHost(HostDistance.LOCAL, core_connections_per_host_local); 296 | } 297 | if (core_connections_per_host_remote != null) { 298 | poolingOptions.setCoreConnectionsPerHost(HostDistance.REMOTE, core_connections_per_host_remote); 299 | } 300 | if (heartbeat_interval_seconds != null) { 301 | poolingOptions.setHeartbeatIntervalSeconds(heartbeat_interval_seconds); 302 | } 303 | if (idle_timeout_seconds != null) { 304 | poolingOptions.setIdleTimeoutSeconds(idle_timeout_seconds); 305 | } 306 | if (max_connections_per_host_local != null) { 307 | poolingOptions.setMaxConnectionsPerHost(HostDistance.LOCAL, max_connections_per_host_local); 308 | } 309 | if (max_connections_per_host_remote != null) { 310 | poolingOptions.setMaxConnectionsPerHost(HostDistance.REMOTE, max_connections_per_host_remote); 311 | } 312 | if (max_queue_size != null) { 313 | poolingOptions.setMaxQueueSize(max_queue_size); 314 | } 315 | if (max_requests_per_connection_local != null) { 316 | poolingOptions.setMaxRequestsPerConnection(HostDistance.LOCAL, max_requests_per_connection_local); 317 | } 318 | if (max_requests_per_connection_remote != null) { 319 | poolingOptions.setMaxRequestsPerConnection(HostDistance.REMOTE, max_requests_per_connection_remote); 320 | } 321 | if (new_connection_threshold_local != null) { 322 | poolingOptions.setNewConnectionThreshold(HostDistance.LOCAL, new_connection_threshold_local); 323 | } 324 | if (new_connection_threshold_remote != null) { 325 | poolingOptions.setNewConnectionThreshold(HostDistance.REMOTE, new_connection_threshold_remote); 326 | } 327 | 328 | } 329 | 330 | protected void initSocketOptions(JsonObject socketConfig) { 331 | 332 | if (socketConfig == null) { 333 | return; 334 | } 335 | 336 | socketOptions = new SocketOptions(); 337 | 338 | Integer connect_timeout_millis = socketConfig.getInteger("connect_timeout_millis"); 339 | Integer read_timeout_millis = socketConfig.getInteger("read_timeout_millis"); 340 | Boolean keep_alive = socketConfig.getBoolean("keep_alive"); 341 | Boolean reuse_address = socketConfig.getBoolean("reuse_address"); 342 | Integer receive_buffer_size = socketConfig.getInteger("receive_buffer_size"); 343 | Integer send_buffer_size = socketConfig.getInteger("send_buffer_size"); 344 | Integer so_linger = socketConfig.getInteger("so_linger"); 345 | Boolean tcp_no_delay = socketConfig.getBoolean("tcp_no_delay"); 346 | 347 | if (connect_timeout_millis != null) { 348 | socketOptions.setConnectTimeoutMillis(connect_timeout_millis); 349 | } 350 | if (read_timeout_millis != null) { 351 | socketOptions.setReadTimeoutMillis(read_timeout_millis); 352 | } 353 | if (keep_alive != null) { 354 | socketOptions.setKeepAlive(keep_alive); 355 | } 356 | if (reuse_address != null) { 357 | socketOptions.setReuseAddress(reuse_address); 358 | } 359 | if (receive_buffer_size != null) { 360 | socketOptions.setReceiveBufferSize(receive_buffer_size); 361 | } 362 | if (send_buffer_size != null) { 363 | socketOptions.setSendBufferSize(send_buffer_size); 364 | } 365 | if (so_linger != null) { 366 | socketOptions.setSoLinger(so_linger); 367 | } 368 | if (tcp_no_delay != null) { 369 | socketOptions.setTcpNoDelay(tcp_no_delay); 370 | } 371 | 372 | } 373 | 374 | protected void initQueryOptions(JsonObject queryConfig) { 375 | 376 | if (queryConfig == null) { 377 | return; 378 | } 379 | 380 | queryOptions = new QueryOptions(); 381 | 382 | ConsistencyLevel consistency = getConsistency(queryConfig.getString(CONFIG_CONSISTENCY_LEVEL)); 383 | if (consistency != null) { 384 | queryOptions.setConsistencyLevel(consistency); 385 | } 386 | 387 | ConsistencyLevel serialConsistency = getConsistency(queryConfig.getString(CONFIG_SERIAL_CONSISTENCY_LEVEL)); 388 | if (serialConsistency != null) { 389 | queryOptions.setSerialConsistencyLevel(serialConsistency); 390 | } 391 | 392 | Integer fetchSize = queryConfig.getInteger(CONFIG_FETCH_SIZE); 393 | if (fetchSize != null) { 394 | queryOptions.setFetchSize(fetchSize); 395 | } 396 | 397 | } 398 | 399 | protected ConsistencyLevel getConsistency(String consistency) { 400 | 401 | if (consistency == null || consistency.isEmpty()) { 402 | return null; 403 | } 404 | 405 | if (consistency.equalsIgnoreCase(CONSISTENCY_ANY)) { 406 | return ConsistencyLevel.ANY; 407 | } 408 | if (consistency.equalsIgnoreCase(CONSISTENCY_ONE)) { 409 | return ConsistencyLevel.ONE; 410 | } 411 | if (consistency.equalsIgnoreCase(CONSISTENCY_TWO)) { 412 | return ConsistencyLevel.TWO; 413 | } 414 | if (consistency.equalsIgnoreCase(CONSISTENCY_THREE)) { 415 | return ConsistencyLevel.THREE; 416 | } 417 | if (consistency.equalsIgnoreCase(CONSISTENCY_QUORUM)) { 418 | return ConsistencyLevel.QUORUM; 419 | } 420 | if (consistency.equalsIgnoreCase(CONSISTENCY_ALL)) { 421 | return ConsistencyLevel.ALL; 422 | } 423 | if (consistency.equalsIgnoreCase(CONSISTENCY_LOCAL_ONE)) { 424 | return ConsistencyLevel.LOCAL_ONE; 425 | } 426 | if (consistency.equalsIgnoreCase(CONSISTENCY_LOCAL_QUORUM)) { 427 | return ConsistencyLevel.LOCAL_QUORUM; 428 | } 429 | if (consistency.equalsIgnoreCase(CONSISTENCY_EACH_QUORUM)) { 430 | return ConsistencyLevel.EACH_QUORUM; 431 | } 432 | if (consistency.equalsIgnoreCase(CONSISTENCY_SERIAL)) { 433 | return ConsistencyLevel.SERIAL; 434 | } 435 | if (consistency.equalsIgnoreCase(CONSISTENCY_LOCAL_SERIAL)) { 436 | return ConsistencyLevel.LOCAL_SERIAL; 437 | } 438 | 439 | throw new IllegalArgumentException("'" + consistency + "' is not a valid consistency level."); 440 | } 441 | 442 | protected void initMetricsOptions(JsonObject metrics) { 443 | 444 | if (metrics == null) { 445 | return; 446 | } 447 | 448 | boolean enabled = metrics.getBoolean("enabled", true); 449 | boolean jmx_enabled = metrics.getBoolean("jmx_enabled", true); 450 | metricsOptions = new MetricsOptions(enabled, jmx_enabled); 451 | 452 | } 453 | 454 | protected void initAuthProvider(JsonObject auth) { 455 | 456 | if (auth == null) { 457 | return; 458 | } 459 | 460 | String username = auth.getString("username"); 461 | String password = auth.getString("password"); 462 | 463 | if (Strings.isNullOrEmpty(username)) { 464 | throw new IllegalArgumentException("A username field must be provided on an auth field."); 465 | } 466 | if (Strings.isNullOrEmpty(password)) { 467 | throw new IllegalArgumentException("A password field must be provided on an auth field."); 468 | } 469 | 470 | authProvider = new PlainTextAuthProvider(username, password); 471 | 472 | } 473 | 474 | } 475 | -------------------------------------------------------------------------------- /vertx-cassandra/src/main/java/com/englishtown/vertx/cassandra/impl/Metrics.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.impl; 2 | 3 | import com.codahale.metrics.Gauge; 4 | import com.codahale.metrics.JmxReporter; 5 | import com.codahale.metrics.MetricRegistry; 6 | import com.datastax.driver.core.*; 7 | import com.datastax.driver.core.policies.LoadBalancingPolicy; 8 | import com.datastax.driver.core.policies.Policies; 9 | import com.datastax.driver.core.policies.ReconnectionPolicy; 10 | import com.datastax.driver.core.policies.RetryPolicy; 11 | import com.englishtown.vertx.cassandra.CassandraConfigurator; 12 | import io.vertx.core.json.JsonArray; 13 | import io.vertx.core.json.JsonObject; 14 | 15 | import java.util.List; 16 | import java.util.concurrent.ConcurrentHashMap; 17 | import java.util.concurrent.ConcurrentMap; 18 | 19 | /** 20 | * Metrics container 21 | */ 22 | class Metrics implements AutoCloseable { 23 | 24 | private final DefaultCassandraSession session; 25 | private final MetricRegistry registry = new MetricRegistry(); 26 | private JmxReporter reporter; 27 | private GaugeStateListener listener; 28 | 29 | Metrics(DefaultCassandraSession session) { 30 | this.session = session; 31 | } 32 | 33 | protected void afterReconnect() { 34 | 35 | // Close any existing metrics 36 | close(); 37 | 38 | final Cluster cluster = session.getCluster(); 39 | Configuration configuration = cluster.getConfiguration(); 40 | 41 | String name = "config"; 42 | final String config = getConfiguration(session.getConfigurator(), configuration).encodePrettily(); 43 | registry.remove(name); 44 | registry.>register(name, () -> config); 45 | 46 | name = "closed"; 47 | registry.remove(name); 48 | registry.>register(name, () -> session.isClosed()); 49 | 50 | listener = new GaugeStateListener(); 51 | cluster.register(listener); 52 | 53 | if (configuration.getMetricsOptions().isJMXReportingEnabled()) { 54 | String domain = "et.cass." + cluster.getClusterName() + "-metrics"; 55 | reporter = JmxReporter 56 | .forRegistry(registry) 57 | .inDomain(domain) 58 | .build(); 59 | 60 | reporter.start(); 61 | } 62 | 63 | } 64 | 65 | private JsonObject getConfiguration(CassandraConfigurator configurator, Configuration configuration) { 66 | 67 | JsonObject json = new JsonObject(); 68 | 69 | // Add seeds 70 | List seeds = configurator.getSeeds(); 71 | JsonArray arr = new JsonArray(); 72 | json.put("seeds", arr); 73 | if (seeds != null) { 74 | seeds.forEach(arr::add); 75 | } 76 | 77 | Policies policies = configuration.getPolicies(); 78 | JsonObject policiesJson = new JsonObject(); 79 | json.put("policies", policiesJson); 80 | 81 | if (policies != null) { 82 | LoadBalancingPolicy lbPolicy = policies.getLoadBalancingPolicy(); 83 | policiesJson.put("load_balancing", lbPolicy == null ? null : lbPolicy.getClass().getSimpleName()); 84 | ReconnectionPolicy reconnectionPolicy = policies.getReconnectionPolicy(); 85 | policiesJson.put("reconnection", reconnectionPolicy == null ? null : reconnectionPolicy.getClass().getSimpleName()); 86 | RetryPolicy retryPolicy = policies.getRetryPolicy(); 87 | policiesJson.put("retry", retryPolicy == null ? null : retryPolicy.getClass().getSimpleName()); 88 | } 89 | 90 | PoolingOptions poolingOptions = configuration.getPoolingOptions(); 91 | JsonObject pooling = new JsonObject(); 92 | json.put("pooling", pooling); 93 | 94 | if (poolingOptions != null) { 95 | pooling.put("core_connections_per_host_local", poolingOptions.getCoreConnectionsPerHost(HostDistance.LOCAL)); 96 | pooling.put("core_connections_per_host_remote", poolingOptions.getCoreConnectionsPerHost(HostDistance.REMOTE)); 97 | pooling.put("max_connections_per_host_local", poolingOptions.getMaxConnectionsPerHost(HostDistance.LOCAL)); 98 | pooling.put("max_connections_per_host_remote", poolingOptions.getMaxConnectionsPerHost(HostDistance.REMOTE)); 99 | 100 | pooling.put("new_connection_threshold_local", poolingOptions.getNewConnectionThreshold(HostDistance.LOCAL)); 101 | pooling.put("new_connection_threshold_remote", poolingOptions.getNewConnectionThreshold(HostDistance.REMOTE)); 102 | } 103 | 104 | SocketOptions socketOptions = configuration.getSocketOptions(); 105 | JsonObject socket = new JsonObject(); 106 | json.put("socket", socket); 107 | 108 | if (socketOptions != null) { 109 | socket.put("connect_timeout_millis", socketOptions.getConnectTimeoutMillis()); 110 | socket.put("read_timeout_millis", socketOptions.getReadTimeoutMillis()); 111 | socket.put("receive_buffer_size", socketOptions.getReceiveBufferSize()); 112 | socket.put("send_buffer_size", socketOptions.getSendBufferSize()); 113 | socket.put("so_linger", socketOptions.getSoLinger()); 114 | socket.put("keep_alive", socketOptions.getKeepAlive()); 115 | socket.put("reuse_address", socketOptions.getReuseAddress()); 116 | socket.put("tcp_no_delay", socketOptions.getTcpNoDelay()); 117 | } 118 | 119 | QueryOptions queryOptions = configuration.getQueryOptions(); 120 | JsonObject query = new JsonObject(); 121 | json.put("query", query); 122 | 123 | if (queryOptions != null) { 124 | ConsistencyLevel consistency = queryOptions.getConsistencyLevel(); 125 | query.put("consistency", consistency == null ? null : consistency.name()); 126 | consistency = queryOptions.getSerialConsistencyLevel(); 127 | query.put("serial_consistency", consistency == null ? null : consistency.name()); 128 | query.put("fetch_size", queryOptions.getFetchSize()); 129 | } 130 | 131 | return json; 132 | } 133 | 134 | @Override 135 | public void close() { 136 | if (listener != null) { 137 | session.getCluster().unregister(listener); 138 | listener = null; 139 | } 140 | if (reporter != null) { 141 | reporter.stop(); 142 | reporter = null; 143 | } 144 | } 145 | 146 | private class GaugeStateListener implements Host.StateListener { 147 | 148 | private final ConcurrentMap addedHosts = new ConcurrentHashMap<>(); 149 | private final ConcurrentMap upHosts = new ConcurrentHashMap<>(); 150 | private final ConcurrentMap removedHosts = new ConcurrentHashMap<>(); 151 | private final ConcurrentMap downHosts = new ConcurrentHashMap<>(); 152 | 153 | public GaugeStateListener() { 154 | 155 | String name; 156 | 157 | name = "added-hosts"; 158 | registry.remove(name); 159 | registry.>register(name, () -> stringify(addedHosts)); 160 | 161 | name = "up-hosts"; 162 | registry.remove(name); 163 | registry.>register(name, () -> stringify(upHosts)); 164 | 165 | name = "down-hosts"; 166 | registry.remove(name); 167 | registry.>register(name, () -> stringify(downHosts)); 168 | 169 | name = "removed-hosts"; 170 | registry.remove(name); 171 | registry.>register(name, () -> stringify(removedHosts)); 172 | 173 | } 174 | 175 | private String stringify(ConcurrentMap hosts) { 176 | 177 | StringBuilder sb = new StringBuilder(); 178 | String delimiter = ""; 179 | 180 | for (String key : hosts.keySet()) { 181 | Host host = hosts.get(key); 182 | if (host != null) { 183 | sb.append(delimiter) 184 | .append(host.toString()) 185 | .append(" (dc=") 186 | .append(host.getDatacenter()) 187 | .append(" up=") 188 | .append(host.isUp()) 189 | .append(")"); 190 | 191 | delimiter = "\n"; 192 | } 193 | } 194 | 195 | return sb.toString(); 196 | } 197 | 198 | private String getKey(Host host) { 199 | return host.getAddress().toString(); 200 | } 201 | 202 | /** 203 | * Called when a new node is added to the cluster. 204 | *

205 | * The newly added node should be considered up. 206 | * 207 | * @param host the host that has been newly added. 208 | */ 209 | @Override 210 | public void onAdd(Host host) { 211 | String key = getKey(host); 212 | addedHosts.put(key, host); 213 | removedHosts.remove(key); 214 | } 215 | 216 | /** 217 | * Called when a node is determined to be up. 218 | * 219 | * @param host the host that has been detected up. 220 | */ 221 | @Override 222 | public void onUp(Host host) { 223 | String key = getKey(host); 224 | upHosts.put(key, host); 225 | downHosts.remove(key); 226 | } 227 | 228 | /** 229 | * Called when a node is determined to be down. 230 | * 231 | * @param host the host that has been detected down. 232 | */ 233 | @Override 234 | public void onDown(Host host) { 235 | String key = getKey(host); 236 | downHosts.put(key, host); 237 | upHosts.remove(key); 238 | } 239 | 240 | /** 241 | * Called when a node is removed from the cluster. 242 | * 243 | * @param host the removed host. 244 | */ 245 | @Override 246 | public void onRemove(Host host) { 247 | String key = getKey(host); 248 | removedHosts.put(key, host); 249 | addedHosts.remove(key); 250 | } 251 | 252 | @Override 253 | public void onRegister(Cluster cluster) { 254 | } 255 | 256 | @Override 257 | public void onUnregister(Cluster cluster) { 258 | } 259 | } 260 | } 261 | -------------------------------------------------------------------------------- /vertx-cassandra/src/main/java/com/englishtown/vertx/cassandra/keyspacebuilder/AlterKeyspace.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.keyspacebuilder; 2 | 3 | /** 4 | * ALTER KEYSPACE CQL3 statement builder 5 | */ 6 | public class AlterKeyspace extends KeyspaceBuilderBase { 7 | 8 | AlterKeyspace(String keyspace) { 9 | super(keyspace); 10 | } 11 | 12 | /** 13 | * {@inheritDoc} 14 | */ 15 | @Override 16 | public StringBuilder buildQueryString() { 17 | StringBuilder sb = new StringBuilder(); 18 | 19 | sb.append("ALTER KEYSPACE ").append(keyspace); 20 | buildReplicationStrategy(sb); 21 | sb.append(" }"); 22 | 23 | return sb; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /vertx-cassandra/src/main/java/com/englishtown/vertx/cassandra/keyspacebuilder/BuiltKeyspaceStatement.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.keyspacebuilder; 2 | 3 | import com.datastax.driver.core.CodecRegistry; 4 | import com.datastax.driver.core.ProtocolVersion; 5 | import com.datastax.driver.core.RegularStatement; 6 | 7 | import java.nio.ByteBuffer; 8 | import java.util.Map; 9 | 10 | /** 11 | * A built CQL3 keyspace statement 12 | */ 13 | public abstract class BuiltKeyspaceStatement extends RegularStatement { 14 | 15 | protected String keyspace; 16 | 17 | protected BuiltKeyspaceStatement(String keyspace) { 18 | this.keyspace = keyspace; 19 | } 20 | 21 | /** 22 | * Builds the CQL3 statement 23 | * 24 | * @return a {@link java.lang.StringBuilder} of the CQL statement 25 | */ 26 | public abstract StringBuilder buildQueryString(); 27 | 28 | /** 29 | * {@inheritDoc} 30 | */ 31 | @Override 32 | public String getQueryString() { 33 | return buildQueryString().toString(); 34 | } 35 | 36 | /** 37 | * {@inheritDoc} 38 | */ 39 | @Override 40 | public String getQueryString(CodecRegistry codecRegistry) { 41 | return getQueryString(); 42 | } 43 | 44 | /** 45 | * {@inheritDoc} 46 | */ 47 | @Override 48 | public ByteBuffer[] getValues(ProtocolVersion protocolVersion, CodecRegistry codecRegistry) { 49 | return null; 50 | } 51 | 52 | /** 53 | * {@inheritDoc} 54 | */ 55 | @Override 56 | public boolean hasValues() { 57 | return false; 58 | } 59 | 60 | /** 61 | * {@inheritDoc} 62 | */ 63 | @Override 64 | public boolean hasValues(CodecRegistry codecRegistry) { 65 | return false; 66 | } 67 | 68 | /** 69 | * {@inheritDoc} 70 | */ 71 | @Override 72 | public ByteBuffer getRoutingKey(ProtocolVersion protocolVersion, CodecRegistry codecRegistry) { 73 | return null; 74 | } 75 | 76 | /** 77 | * {@inheritDoc} 78 | */ 79 | @Override 80 | public String getKeyspace() { 81 | return keyspace; 82 | } 83 | 84 | /** 85 | * {@inheritDoc} 86 | */ 87 | @Override 88 | public Map getNamedValues(ProtocolVersion protocolVersion, CodecRegistry codecRegistry) { 89 | return null; 90 | } 91 | 92 | /** 93 | * {@inheritDoc} 94 | */ 95 | @Override 96 | public boolean usesNamedValues() { 97 | return false; 98 | } 99 | 100 | } 101 | -------------------------------------------------------------------------------- /vertx-cassandra/src/main/java/com/englishtown/vertx/cassandra/keyspacebuilder/CreateKeyspace.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.keyspacebuilder; 2 | 3 | /** 4 | * CREATE KEYSPACE CQL3 statement builder 5 | */ 6 | public class CreateKeyspace extends KeyspaceBuilderBase { 7 | 8 | private boolean ifNotExists; 9 | 10 | CreateKeyspace(String keyspace) { 11 | super(keyspace); 12 | } 13 | 14 | public CreateKeyspace ifNotExists() { 15 | ifNotExists = true; 16 | return this; 17 | } 18 | 19 | /** 20 | * {@inheritDoc} 21 | */ 22 | @Override 23 | public StringBuilder buildQueryString() { 24 | StringBuilder sb = new StringBuilder(); 25 | 26 | sb.append("CREATE KEYSPACE "); 27 | if (ifNotExists) { 28 | sb.append("IF NOT EXISTS "); 29 | } 30 | sb.append(keyspace); 31 | buildReplicationStrategy(sb); 32 | sb.append(" }"); 33 | return sb; 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /vertx-cassandra/src/main/java/com/englishtown/vertx/cassandra/keyspacebuilder/DropKeyspace.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.keyspacebuilder; 2 | 3 | /** 4 | * DROP KEYSPACE CQL3 statement builder 5 | */ 6 | public class DropKeyspace extends BuiltKeyspaceStatement { 7 | 8 | private boolean ifExists; 9 | 10 | DropKeyspace(String keyspace) { 11 | super(keyspace); 12 | } 13 | 14 | public DropKeyspace ifExists() { 15 | ifExists = true; 16 | return this; 17 | } 18 | 19 | /** 20 | * {@inheritDoc} 21 | */ 22 | @Override 23 | public StringBuilder buildQueryString() { 24 | StringBuilder sb = new StringBuilder(); 25 | 26 | sb.append("DROP KEYSPACE "); 27 | if (ifExists) { 28 | sb.append("IF EXISTS "); 29 | } 30 | sb.append(keyspace); 31 | 32 | return sb; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /vertx-cassandra/src/main/java/com/englishtown/vertx/cassandra/keyspacebuilder/KeyspaceBuilder.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.keyspacebuilder; 2 | 3 | /** 4 | * Static methods to build a CQL3 keyspace statement 5 | */ 6 | public class KeyspaceBuilder { 7 | 8 | /** 9 | * Returns a {@link com.englishtown.vertx.cassandra.keyspacebuilder.CreateKeyspace} builder 10 | * 11 | * @param keyspace the keyspace to be created 12 | * @return the create keyspace builder 13 | */ 14 | public static CreateKeyspace create(String keyspace) { 15 | return new CreateKeyspace(keyspace); 16 | } 17 | 18 | /** 19 | * Returns a {@link com.englishtown.vertx.cassandra.keyspacebuilder.AlterKeyspace} builder 20 | * 21 | * @param keyspace the keyspace to be altered 22 | * @return the alter keyspace builder 23 | */ 24 | public static AlterKeyspace alter(String keyspace) { 25 | return new AlterKeyspace(keyspace); 26 | } 27 | 28 | /** 29 | * Returns a {@link com.englishtown.vertx.cassandra.keyspacebuilder.DropKeyspace} builder 30 | * 31 | * @param keyspace the keyspace to drop 32 | * @return the drop keyspace builder 33 | */ 34 | public static DropKeyspace drop(String keyspace) { 35 | return new DropKeyspace(keyspace); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /vertx-cassandra/src/main/java/com/englishtown/vertx/cassandra/keyspacebuilder/KeyspaceBuilderBase.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.keyspacebuilder; 2 | 3 | import java.util.LinkedHashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * Base class for CREATE/ALTER KEYSPACE builders 8 | */ 9 | abstract class KeyspaceBuilderBase extends BuiltKeyspaceStatement { 10 | 11 | private String strategy = REPLICATION_STRATEGY_SIMPLE; 12 | private int replicationFactor = 1; 13 | private Map dcReplicationFactors = new LinkedHashMap<>(); 14 | 15 | public static final String REPLICATION_STRATEGY_SIMPLE = "SimpleStrategy"; 16 | public static final String REPLICATION_STRATEGY_NETWORK_TOPOLOGY = "NetworkTopologyStrategy"; 17 | 18 | protected KeyspaceBuilderBase(String keyspace) { 19 | super(keyspace); 20 | } 21 | 22 | public KeyspaceBuilderBase simpleStrategy(int replicationFactor) { 23 | strategy = REPLICATION_STRATEGY_SIMPLE; 24 | this.replicationFactor = replicationFactor; 25 | return this; 26 | } 27 | 28 | public Datacenter networkTopologyStrategy() { 29 | strategy = REPLICATION_STRATEGY_NETWORK_TOPOLOGY; 30 | return new Datacenter(keyspace); 31 | } 32 | 33 | protected StringBuilder buildReplicationStrategy(StringBuilder sb) { 34 | sb.append(" WITH REPLICATION = { 'class' : '"); 35 | 36 | if (REPLICATION_STRATEGY_SIMPLE.equals(strategy)) { 37 | sb.append(REPLICATION_STRATEGY_SIMPLE) 38 | .append("', 'replication_factor' : ") 39 | .append(replicationFactor); 40 | } else { 41 | sb.append(REPLICATION_STRATEGY_NETWORK_TOPOLOGY) 42 | .append("'"); 43 | for (Map.Entry entry : dcReplicationFactors.entrySet()) { 44 | sb.append(", '") 45 | .append(entry.getKey()) 46 | .append("' : ") 47 | .append(entry.getValue()); 48 | } 49 | } 50 | 51 | return sb; 52 | } 53 | 54 | public class Datacenter extends BuiltKeyspaceStatement { 55 | 56 | private Datacenter(String keyspace) { 57 | super(keyspace); 58 | } 59 | 60 | public Datacenter dc(String name, int replicationFactor) { 61 | dcReplicationFactors.put(name, replicationFactor); 62 | return this; 63 | } 64 | 65 | /** 66 | * Builds the CQL3 statement 67 | * 68 | * @return a {@link StringBuilder} of the CQL statement 69 | */ 70 | @Override 71 | public StringBuilder buildQueryString() { 72 | return KeyspaceBuilderBase.this.buildQueryString(); 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /vertx-cassandra/src/main/java/com/englishtown/vertx/cassandra/promises/WhenCassandraSession.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.promises; 2 | 3 | import com.datastax.driver.core.*; 4 | import com.englishtown.promises.Promise; 5 | import com.englishtown.vertx.cassandra.CassandraSession; 6 | 7 | /** 8 | * When.java wrapper over {@link com.datastax.driver.core.Session} 9 | */ 10 | public interface WhenCassandraSession extends AutoCloseable { 11 | 12 | /** 13 | * Executes a cassandra statement asynchronously. Ensures the callback is executed on the correct vert.x context. 14 | * 15 | * @param statement the statement to execute 16 | * @return the promise for the {@link com.datastax.driver.core.ResultSet} 17 | */ 18 | Promise executeAsync(Statement statement); 19 | 20 | /** 21 | * Executes a cassandra CQL query asynchronously. Ensures the callback is executed on the correct vert.x context. 22 | * 23 | * @param query the CQL query to execute 24 | * @return the promise for the {@link com.datastax.driver.core.ResultSet} 25 | */ 26 | Promise executeAsync(String query); 27 | 28 | /** 29 | * This is a convenience method for {@code executeAsync(new SimpleStatement(query, values))}. 30 | * 31 | * @param query 32 | * @param values 33 | * @return 34 | */ 35 | Promise executeAsync(String query, Object... values); 36 | 37 | /** 38 | * Prepares the provided query statement 39 | * 40 | * @param statement the query statement to prepare 41 | * @return the promise for the {@link com.datastax.driver.core.PreparedStatement} 42 | */ 43 | Promise prepareAsync(RegularStatement statement); 44 | 45 | /** 46 | * Prepares the provided query 47 | * 48 | * @param query the query to prepare 49 | * @return the promise for the {@link com.datastax.driver.core.PreparedStatement} 50 | */ 51 | Promise prepareAsync(String query); 52 | 53 | /** 54 | * Returns cassandra metadata 55 | * 56 | * @return returns the cassandra metadata for the current session 57 | */ 58 | Metadata getMetadata(); 59 | 60 | /** 61 | * Whether this Session instance has been closed. 62 | * 63 | * @return {@code true} if this Session instance has been closed, {@code false} 64 | * otherwise. 65 | */ 66 | boolean isClosed(); 67 | 68 | /** 69 | * Returns the {@code Cluster} object this session is part of. 70 | * 71 | * @return the {@code Cluster} object this session is part of. 72 | */ 73 | Cluster getCluster(); 74 | 75 | /** 76 | * Return the {@link com.englishtown.vertx.cassandra.CassandraSession} 77 | * 78 | * @return 79 | */ 80 | CassandraSession getSession(); 81 | 82 | /** 83 | * Promise for when the session is ready 84 | * 85 | * @return 86 | */ 87 | Promise ready(); 88 | 89 | } 90 | -------------------------------------------------------------------------------- /vertx-cassandra/src/main/java/com/englishtown/vertx/cassandra/promises/impl/DefaultWhenCassandraSession.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.promises.impl; 2 | 3 | import com.datastax.driver.core.*; 4 | import com.englishtown.promises.Deferred; 5 | import com.englishtown.promises.Promise; 6 | import com.englishtown.promises.When; 7 | import com.englishtown.vertx.cassandra.CassandraSession; 8 | import com.englishtown.vertx.cassandra.FutureUtils; 9 | import com.englishtown.vertx.cassandra.promises.WhenCassandraSession; 10 | import com.google.common.util.concurrent.FutureCallback; 11 | import com.google.common.util.concurrent.ListenableFuture; 12 | import io.vertx.core.Vertx; 13 | 14 | import javax.inject.Inject; 15 | 16 | /** 17 | * Default implementation of {@link com.englishtown.vertx.cassandra.promises.WhenCassandraSession} 18 | */ 19 | public class DefaultWhenCassandraSession implements WhenCassandraSession { 20 | 21 | private final CassandraSession session; 22 | private final When when; 23 | private final Vertx vertx; 24 | 25 | @Inject 26 | public DefaultWhenCassandraSession(CassandraSession session, When when, Vertx vertx) { 27 | this.session = session; 28 | this.when = when; 29 | this.vertx = vertx; 30 | } 31 | 32 | /** 33 | * Executes a cassandra statement asynchronously. Ensures the callback is executed on the correct vert.x context. 34 | * 35 | * @param statement the statement to execute 36 | * @return the promise for the {@link com.datastax.driver.core.ResultSet} 37 | */ 38 | @Override 39 | 40 | public Promise executeAsync(Statement statement) { 41 | return convertFuture(session.executeAsync(statement)); 42 | } 43 | 44 | /** 45 | * Executes a cassandra CQL query asynchronously. Ensures the callback is executed on the correct vert.x context. 46 | * 47 | * @param query the CQL query to execute 48 | * @return the promise for the {@link com.datastax.driver.core.ResultSet} 49 | */ 50 | @Override 51 | public Promise executeAsync(String query) { 52 | return convertFuture(session.executeAsync(query)); 53 | } 54 | 55 | /** 56 | * This is a convenience method for {@code executeAsync(new SimpleStatement(query, values))}. 57 | * 58 | * @param query 59 | * @param values 60 | * @return 61 | */ 62 | @Override 63 | public Promise executeAsync(String query, Object... values) { 64 | return convertFuture(session.executeAsync(query, values)); 65 | } 66 | 67 | /** 68 | * Prepares the provided query statement 69 | * 70 | * @param statement the query statement to prepare 71 | * @return the promise for the {@link com.datastax.driver.core.PreparedStatement} 72 | */ 73 | @Override 74 | public Promise prepareAsync(RegularStatement statement) { 75 | return convertFuture(session.prepareAsync(statement)); 76 | } 77 | 78 | /** 79 | * Prepares the provided query 80 | * 81 | * @param query the query to prepare 82 | * @return the promise for the {@link com.datastax.driver.core.PreparedStatement} 83 | */ 84 | @Override 85 | public Promise prepareAsync(String query) { 86 | return convertFuture(session.prepareAsync(query)); 87 | } 88 | 89 | /** 90 | * Returns cassandra metadata 91 | * 92 | * @return returns the cassandra metadata for the current session 93 | */ 94 | @Override 95 | public Metadata getMetadata() { 96 | return session.getMetadata(); 97 | } 98 | 99 | /** 100 | * Whether this Session instance has been closed. 101 | * 102 | * @return {@code true} if this Session instance has been closed, {@code false} 103 | * otherwise. 104 | */ 105 | @Override 106 | public boolean isClosed() { 107 | return session.isClosed(); 108 | } 109 | 110 | /** 111 | * Returns the {@code Cluster} object this session is part of. 112 | * 113 | * @return the {@code Cluster} object this session is part of. 114 | */ 115 | @Override 116 | public Cluster getCluster() { 117 | return session.getCluster(); 118 | } 119 | 120 | /** 121 | * Return the {@link com.englishtown.vertx.cassandra.CassandraSession} 122 | * 123 | * @return 124 | */ 125 | @Override 126 | public CassandraSession getSession() { 127 | return session; 128 | } 129 | 130 | /** 131 | * Promise for when the session is ready 132 | * 133 | * @return 134 | */ 135 | @Override 136 | public Promise ready() { 137 | Deferred d = when.defer(); 138 | 139 | session.onReady(result -> { 140 | if (result.succeeded()) { 141 | d.resolve((Void) null); 142 | } else { 143 | d.reject(result.cause()); 144 | } 145 | }); 146 | 147 | return d.getPromise(); 148 | } 149 | 150 | /** 151 | * {@inheritDoc} 152 | */ 153 | @Override 154 | public void close() throws Exception { 155 | session.close(); 156 | } 157 | 158 | private Promise convertFuture(ListenableFuture future) { 159 | 160 | Deferred d = when.defer(); 161 | 162 | FutureCallback callback = new FutureCallback() { 163 | @Override 164 | public void onSuccess(T result) { 165 | d.resolve(result); 166 | } 167 | 168 | @Override 169 | public void onFailure(Throwable t) { 170 | d.reject(t); 171 | } 172 | }; 173 | 174 | FutureUtils.addCallback(future, callback, vertx); 175 | return d.getPromise(); 176 | 177 | } 178 | 179 | } 180 | -------------------------------------------------------------------------------- /vertx-cassandra/src/main/java/com/englishtown/vertx/cassandra/tablebuilder/AlterTable.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.tablebuilder; 2 | 3 | /** 4 | * ALTER TABLE CQL3 statement builder 5 | */ 6 | public class AlterTable extends BuiltTableStatement { 7 | 8 | private Column alterColumn; 9 | private Column addColumn; 10 | private Column dropColumn; 11 | private Column renameColumnFrom; 12 | private Column renameColumnTo; 13 | 14 | AlterTable(String keyspace, String table) { 15 | super(keyspace, table); 16 | } 17 | 18 | public AlterTable alterColumn(String column, String type) { 19 | alterColumn = new Column(column, type, false); 20 | return this; 21 | } 22 | 23 | public AlterTable addColumn(String column, String type) { 24 | addColumn = new Column(column, type, false); 25 | return this; 26 | } 27 | 28 | public AlterTable dropColumn(String column) { 29 | dropColumn = new Column(column, null, false); 30 | return this; 31 | } 32 | 33 | public AlterTable renameColumn(String columnFrom, String columnTo) { 34 | renameColumnFrom = new Column(columnFrom, null, false); 35 | renameColumnTo = new Column(columnTo, null, false); 36 | return this; 37 | } 38 | 39 | /** 40 | * {@inheritDoc} 41 | */ 42 | @Override 43 | public StringBuilder buildQueryString() { 44 | StringBuilder sb = new StringBuilder(); 45 | 46 | sb.append("ALTER TABLE "); 47 | if (keyspace != null) { 48 | sb.append(keyspace).append("."); 49 | } 50 | sb.append(table).append(" "); 51 | 52 | if (alterColumn != null) { 53 | sb.append("ALTER ") 54 | .append(alterColumn.getName()) 55 | .append(" TYPE ") 56 | .append(alterColumn.getType()); 57 | } else if (addColumn != null) { 58 | sb.append("ADD ") 59 | .append(addColumn.getName()) 60 | .append(" ") 61 | .append(addColumn.getType()); 62 | } else if (dropColumn != null) { 63 | sb.append("DROP ") 64 | .append(dropColumn.getName()); 65 | } else if (renameColumnFrom != null && renameColumnTo != null) { 66 | sb.append("RENAME ") 67 | .append(renameColumnFrom.getName()) 68 | .append(" TO ") 69 | .append(renameColumnTo.getName()); 70 | } 71 | 72 | return sb; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /vertx-cassandra/src/main/java/com/englishtown/vertx/cassandra/tablebuilder/BuiltTableStatement.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.tablebuilder; 2 | 3 | import com.datastax.driver.core.CodecRegistry; 4 | import com.datastax.driver.core.ProtocolVersion; 5 | import com.datastax.driver.core.RegularStatement; 6 | 7 | import java.nio.ByteBuffer; 8 | import java.util.Map; 9 | 10 | /** 11 | * Builds a CQL3 statement to manipulate tables 12 | */ 13 | public abstract class BuiltTableStatement extends RegularStatement { 14 | 15 | protected String keyspace; 16 | protected String table; 17 | 18 | protected BuiltTableStatement(String keyspace, String table) { 19 | this.keyspace = keyspace; 20 | this.table = table; 21 | } 22 | 23 | /** 24 | * Builds the CQL3 statement 25 | * 26 | * @return a {@link java.lang.StringBuilder} of the CQL statement 27 | */ 28 | public abstract StringBuilder buildQueryString(); 29 | 30 | /** 31 | * {@inheritDoc} 32 | */ 33 | @Override 34 | public String getQueryString() { 35 | return buildQueryString().toString(); 36 | } 37 | 38 | @Override 39 | public String getQueryString(CodecRegistry codecRegistry) { 40 | return getQueryString(); 41 | } 42 | 43 | /** 44 | * {@inheritDoc} 45 | */ 46 | @Override 47 | public ByteBuffer[] getValues(ProtocolVersion protocolVersion, CodecRegistry codecRegistry) { 48 | return null; 49 | } 50 | 51 | /** 52 | * {@inheritDoc} 53 | */ 54 | @Override 55 | public boolean hasValues(CodecRegistry codecRegistry) { 56 | return false; 57 | } 58 | 59 | /** 60 | * {@inheritDoc} 61 | */ 62 | @Override 63 | public ByteBuffer getRoutingKey(ProtocolVersion protocolVersion, CodecRegistry codecRegistry) { 64 | return null; 65 | } 66 | 67 | /** 68 | * {@inheritDoc} 69 | */ 70 | @Override 71 | public String getKeyspace() { 72 | return keyspace; 73 | } 74 | 75 | /** 76 | * Returns the table name 77 | * 78 | * @return the table name 79 | */ 80 | public String getTable() { 81 | return table; 82 | } 83 | 84 | /** 85 | * {@inheritDoc} 86 | */ 87 | @Override 88 | public Map getNamedValues(ProtocolVersion protocolVersion, CodecRegistry codecRegistry) { 89 | return null; 90 | } 91 | 92 | /** 93 | * {@inheritDoc} 94 | */ 95 | @Override 96 | public boolean usesNamedValues() { 97 | return false; 98 | } 99 | 100 | /** 101 | * A CQL3 column 102 | */ 103 | public static class Column { 104 | 105 | protected Column(String name, String type, boolean isStatic) { 106 | this.name = name; 107 | this.type = type; 108 | this.isStatic = isStatic; 109 | } 110 | 111 | private String name; 112 | private String type; 113 | private boolean isStatic; 114 | 115 | public String getName() { 116 | return name; 117 | } 118 | 119 | public String getType() { 120 | return type; 121 | } 122 | 123 | public boolean getIsStatic() { 124 | return isStatic; 125 | } 126 | 127 | } 128 | 129 | } 130 | -------------------------------------------------------------------------------- /vertx-cassandra/src/main/java/com/englishtown/vertx/cassandra/tablebuilder/CreateTable.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.tablebuilder; 2 | 3 | import java.util.*; 4 | 5 | /** 6 | * CREATE TABLE CQL3 statement builder 7 | */ 8 | public class CreateTable extends BuiltTableStatement { 9 | 10 | 11 | private Map columns = new TreeMap<>(); 12 | private boolean ifNotExists = false; 13 | private Set primaryKeys = new LinkedHashSet<>(); 14 | private Set partitioningKeys = new LinkedHashSet<>(); 15 | 16 | CreateTable(String keyspace, String table) { 17 | super(keyspace, table); 18 | } 19 | 20 | /** 21 | * Returns a collection of the columns to be created 22 | * 23 | * @return collection of columns to create 24 | */ 25 | public Collection getColumns() { 26 | return columns.values(); 27 | } 28 | 29 | /** 30 | * Adds the "IF NOT EXISTS" cql clause 31 | * 32 | * @return the current {@link com.englishtown.vertx.cassandra.tablebuilder.CreateTable} 33 | */ 34 | public CreateTable ifNotExists() { 35 | ifNotExists = true; 36 | return this; 37 | } 38 | 39 | /** 40 | * Adds a column 41 | * 42 | * @param name the column name 43 | * @param type the column CQL3 type 44 | * @return the current {@link com.englishtown.vertx.cassandra.tablebuilder.BuiltTableStatement} 45 | */ 46 | public CreateTable column(String name, String type) { 47 | return addColumn(new Column(name, type, false)); 48 | } 49 | 50 | /** 51 | * Adds a column 52 | * 53 | * @param name the column name 54 | * @param type the column CQL3 type 55 | * @return the current {@link com.englishtown.vertx.cassandra.tablebuilder.BuiltTableStatement} 56 | */ 57 | public CreateTable staticColumn(String name, String type) { 58 | return addColumn(new Column(name, type, true)); 59 | } 60 | 61 | private CreateTable addColumn(Column column) { 62 | columns.put(column.getName(), column); 63 | return this; 64 | } 65 | 66 | /** 67 | * Adds multiple columns 68 | * 69 | * @param names the column names 70 | * @param types the column CQL3 types 71 | * @return the current {@link com.englishtown.vertx.cassandra.tablebuilder.BuiltTableStatement} 72 | */ 73 | public CreateTable columns(String[] names, String[] types) { 74 | if (names.length != types.length) { 75 | throw new IllegalArgumentException(String.format("Got %d names but %d types", names.length, types.length)); 76 | } 77 | for (int i = 0; i < names.length; i++) { 78 | column(names[i], types[i]); 79 | } 80 | return this; 81 | } 82 | 83 | /** 84 | * Sets one or more primary key columns 85 | * 86 | * @param column column name 87 | * @return the current {@link com.englishtown.vertx.cassandra.tablebuilder.CreateTable} 88 | */ 89 | public CreateTable primaryKeys(String... column) { 90 | Collections.addAll(primaryKeys, column); 91 | return this; 92 | } 93 | 94 | /** 95 | * Sets a primary key 96 | * 97 | * @param column column name 98 | * @return the current {@link com.englishtown.vertx.cassandra.tablebuilder.CreateTable} 99 | */ 100 | public CreateTable primaryKey(String column) { 101 | primaryKeys.add(column); 102 | return this; 103 | } 104 | 105 | /** 106 | * Sets a primary key and type. This allows you to create a table with a composite partition key 107 | * 108 | * @param column column name 109 | * @param type partitioning or clustering 110 | * @return the current {@link com.englishtown.vertx.cassandra.tablebuilder.CreateTable} 111 | */ 112 | public CreateTable primaryKey(String column, PrimaryKeyType type) { 113 | switch (type) { 114 | case PARTITIONING: 115 | primaryKeys.remove(column); 116 | partitioningKeys.add(column); 117 | break; 118 | default: 119 | primaryKeys.add(column); 120 | break; 121 | } 122 | return this; 123 | } 124 | 125 | /** 126 | * {@inheritDoc} 127 | */ 128 | public StringBuilder buildQueryString() { 129 | StringBuilder sb = new StringBuilder(); 130 | 131 | sb.append("CREATE TABLE "); 132 | if (ifNotExists) { 133 | sb.append("IF NOT EXISTS "); 134 | } 135 | if (keyspace != null) { 136 | sb.append(keyspace).append("."); 137 | } 138 | sb.append(table).append(" ("); 139 | 140 | String delimiter = ""; 141 | 142 | // Add columns 143 | for (Column column : columns.values()) { 144 | sb.append(delimiter).append(column.getName()).append(" ").append(column.getType()); 145 | if (column.getIsStatic()) { 146 | sb.append(" STATIC"); 147 | } 148 | delimiter = ", "; 149 | } 150 | 151 | // Add primary keys 152 | sb.append(delimiter).append("PRIMARY KEY("); 153 | delimiter = ""; 154 | if (!partitioningKeys.isEmpty()) { 155 | sb.append("("); 156 | for (String column : partitioningKeys) { 157 | sb.append(delimiter).append(column); 158 | delimiter = ", "; 159 | } 160 | sb.append(")"); 161 | } 162 | for (String column : primaryKeys) { 163 | sb.append(delimiter).append(column); 164 | delimiter = ", "; 165 | } 166 | sb.append(")"); 167 | 168 | sb.append(")"); 169 | 170 | return sb; 171 | } 172 | 173 | /** 174 | * {@inheritDoc} 175 | */ 176 | @Override 177 | public String toString() { 178 | return getQueryString(); 179 | } 180 | 181 | } 182 | -------------------------------------------------------------------------------- /vertx-cassandra/src/main/java/com/englishtown/vertx/cassandra/tablebuilder/DropTable.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.tablebuilder; 2 | 3 | /** 4 | * DROP TABLE CQL3 statement builder 5 | */ 6 | public class DropTable extends BuiltTableStatement { 7 | 8 | private boolean ifExists = false; 9 | 10 | DropTable(String keyspace, String table) { 11 | super(keyspace, table); 12 | } 13 | 14 | public DropTable ifExists() { 15 | ifExists = true; 16 | return this; 17 | } 18 | 19 | /** 20 | * {@inheritDoc} 21 | */ 22 | @Override 23 | public StringBuilder buildQueryString() { 24 | StringBuilder sb = new StringBuilder(); 25 | 26 | sb.append("DROP TABLE "); 27 | if (ifExists) { 28 | sb.append("IF EXISTS "); 29 | } 30 | if (keyspace != null) { 31 | sb.append(keyspace).append("."); 32 | } 33 | sb.append(table); 34 | 35 | return sb; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /vertx-cassandra/src/main/java/com/englishtown/vertx/cassandra/tablebuilder/PrimaryKeyType.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.tablebuilder; 2 | 3 | /** 4 | * CQL3 Primary Key types 5 | */ 6 | public enum PrimaryKeyType { 7 | /** 8 | * A partitioning primary key 9 | * Useful for composite partitioning primary keys 10 | */ 11 | PARTITIONING, 12 | /** 13 | * A clustering primary key used in compound primary keys 14 | */ 15 | CLUSTERING 16 | } 17 | -------------------------------------------------------------------------------- /vertx-cassandra/src/main/java/com/englishtown/vertx/cassandra/tablebuilder/TableBuilder.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.tablebuilder; 2 | 3 | import com.datastax.driver.core.AbstractTableMetadata; 4 | import com.datastax.driver.core.ColumnMetadata; 5 | import com.datastax.driver.core.TableMetadata; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | /** 11 | * Static methods to build a CQL3 table statement 12 | */ 13 | public final class TableBuilder { 14 | 15 | private TableBuilder() { 16 | } 17 | 18 | /** 19 | * Returns a {@link com.englishtown.vertx.cassandra.tablebuilder.CreateTable} builder 20 | * 21 | * @param keyspace the keyspace for the table to create 22 | * @param table the table name 23 | * @return the create table builder 24 | */ 25 | public static CreateTable create(String keyspace, String table) { 26 | return new CreateTable(keyspace, table); 27 | } 28 | 29 | /** 30 | * Returns a {@link com.englishtown.vertx.cassandra.tablebuilder.AlterTable} builder 31 | * 32 | * @param keyspace the keyspace for the table to create 33 | * @param table the table name 34 | * @return the create table builder 35 | */ 36 | public static AlterTable alter(String keyspace, String table) { 37 | return new AlterTable(keyspace, table); 38 | } 39 | 40 | /** 41 | * Returns a {@link com.datastax.driver.core.BatchStatement} with all the alter statements necessary to modify an existing table. 42 | *

43 | * Note: Columns will only be added or modified, not dropped. 44 | * 45 | * @param existing the existing table to be modified 46 | * @param desired the desired end result 47 | * @return a set of statements to modify an existing table 48 | */ 49 | public static List alter(AbstractTableMetadata existing, CreateTable desired) { 50 | List results = new ArrayList<>(); 51 | 52 | for (BuiltTableStatement.Column column : desired.getColumns()) { 53 | ColumnMetadata columnMetadata = existing.getColumn(column.getName()); 54 | if (columnMetadata == null) { 55 | results.add(alter(desired.getKeyspace(), desired.getTable()).addColumn(column.getName(), column.getType())); 56 | } else if (!columnMetadata.getType().toString().equalsIgnoreCase(column.getType())) { 57 | if (columnMetadata.isStatic()) { 58 | throw new IllegalArgumentException("A static column cannot have its type modified"); 59 | } 60 | results.add(alter(desired.getKeyspace(), desired.getTable()).alterColumn(column.getName(), column.getType())); 61 | } 62 | } 63 | 64 | return results; 65 | } 66 | 67 | /** 68 | * Returns a {@link com.englishtown.vertx.cassandra.tablebuilder.DropTable} statement 69 | * 70 | * @param keyspace the keyspace for the table to create 71 | * @param table the table name 72 | * @return the drop table builder 73 | */ 74 | public static DropTable drop(String keyspace, String table) { 75 | return new DropTable(keyspace, table); 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /vertx-cassandra/src/main/java/com/englishtown/vertx/cassandra/zookeeper/ZooKeeperCassandraConfigurator.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.zookeeper; 2 | 3 | import com.englishtown.promises.Promise; 4 | import com.englishtown.promises.When; 5 | import com.englishtown.vertx.cassandra.impl.EnvironmentCassandraConfigurator; 6 | import com.englishtown.vertx.curator.CuratorClient; 7 | import com.englishtown.vertx.curator.promises.WhenConfiguratorHelper; 8 | import io.vertx.core.AsyncResult; 9 | import io.vertx.core.Future; 10 | import io.vertx.core.Handler; 11 | import io.vertx.core.Vertx; 12 | import io.vertx.core.json.JsonArray; 13 | import io.vertx.core.json.JsonObject; 14 | import org.apache.curator.utils.ZKPaths; 15 | 16 | import javax.inject.Inject; 17 | import java.util.ArrayList; 18 | import java.util.List; 19 | 20 | /** 21 | * ZooKeeper implementation of {@link com.englishtown.vertx.cassandra.CassandraConfigurator} 22 | */ 23 | public class ZooKeeperCassandraConfigurator extends EnvironmentCassandraConfigurator { 24 | 25 | private final WhenConfiguratorHelper helper; 26 | private final When when; 27 | private AsyncResult initResult; 28 | private final List>> onReadyCallbacks = new ArrayList<>(); 29 | protected String pathPrefix = "cassandra"; 30 | 31 | @Inject 32 | public ZooKeeperCassandraConfigurator(CuratorClient client, WhenConfiguratorHelper helper, When when, Vertx vertx, EnvVarDelegate envVarDelegate) { 33 | super(vertx, envVarDelegate); 34 | this.helper = helper; 35 | this.when = when; 36 | 37 | client.onReady(result -> { 38 | if (result.failed()) { 39 | runOnReadyCallbacks(result); 40 | return; 41 | } 42 | initZooKeeper(); 43 | }); 44 | } 45 | 46 | private void initZooKeeper() { 47 | 48 | List> promises = new ArrayList<>(); 49 | 50 | if (DEFAULT_SEEDS.equals(seeds)) { 51 | promises.add(helper.getConfigElement(ZKPaths.makePath(getPathPrefix(), "seeds")).then( 52 | value -> { 53 | JsonArray array = value.asJsonArray(); 54 | if (array != null) { 55 | initSeeds(array); 56 | } 57 | return null; 58 | })); 59 | } 60 | 61 | if (loadBalancingPolicy == null) { 62 | promises.add(helper.getConfigElement(ZKPaths.makePath(getPathPrefix(), "policies/load_balancing")).then( 63 | value -> { 64 | JsonObject json = value.asJsonObject(); 65 | if (json != null) { 66 | initLoadBalancingPolicy(json); 67 | } 68 | return null; 69 | })); 70 | } 71 | 72 | if (reconnectionPolicy == null) { 73 | promises.add(helper.getConfigElement(ZKPaths.makePath(getPathPrefix(), "policies/reconnection")).then( 74 | value -> { 75 | JsonObject json = value.asJsonObject(); 76 | if (json != null) { 77 | initLoadBalancingPolicy(json); 78 | } 79 | return null; 80 | })); 81 | } 82 | 83 | if (poolingOptions == null) { 84 | promises.add(helper.getConfigElement(ZKPaths.makePath(getPathPrefix(), "pooling")).then( 85 | value -> { 86 | JsonObject json = value.asJsonObject(); 87 | if (json != null) { 88 | initPoolingOptions(json); 89 | } 90 | return null; 91 | })); 92 | } 93 | 94 | if (socketOptions == null) { 95 | promises.add(helper.getConfigElement(ZKPaths.makePath(getPathPrefix(), "socket")).then( 96 | value -> { 97 | JsonObject json = value.asJsonObject(); 98 | if (json != null) { 99 | initSocketOptions(json); 100 | } 101 | return null; 102 | })); 103 | } 104 | 105 | if (queryOptions == null) { 106 | promises.add(helper.getConfigElement(ZKPaths.makePath(getPathPrefix(), "query")).then( 107 | value -> { 108 | JsonObject json = value.asJsonObject(); 109 | if (json != null) { 110 | initQueryOptions(json); 111 | } 112 | return null; 113 | })); 114 | } 115 | 116 | if (metricsOptions == null) { 117 | promises.add(helper.getConfigElement(ZKPaths.makePath(getPathPrefix(), "metrics")).then( 118 | value -> { 119 | JsonObject json = value.asJsonObject(); 120 | if (json != null) { 121 | initMetricsOptions(json); 122 | } 123 | return null; 124 | })); 125 | } 126 | 127 | if (authProvider == null) { 128 | promises.add(helper.getConfigElement(ZKPaths.makePath(getPathPrefix(), "auth")).then( 129 | value -> { 130 | JsonObject json = value.asJsonObject(); 131 | if (json != null) { 132 | initAuthProvider(json); 133 | } 134 | return null; 135 | })); 136 | } 137 | 138 | when.all(promises) 139 | .then(aVoid -> { 140 | runOnReadyCallbacks(Future.succeededFuture(null)); 141 | return null; 142 | }) 143 | .otherwise(t -> { 144 | runOnReadyCallbacks(Future.failedFuture(t)); 145 | return null; 146 | }); 147 | } 148 | 149 | private void runOnReadyCallbacks(AsyncResult result) { 150 | initResult = result; 151 | onReadyCallbacks.forEach(callback -> callback.handle(result)); 152 | onReadyCallbacks.clear(); 153 | } 154 | 155 | @Override 156 | public void onReady(Handler> callback) { 157 | if (initResult != null) { 158 | callback.handle(initResult); 159 | } else { 160 | onReadyCallbacks.add(callback); 161 | } 162 | } 163 | 164 | protected String getPathPrefix() { 165 | return pathPrefix; 166 | } 167 | 168 | } 169 | -------------------------------------------------------------------------------- /vertx-cassandra/src/test/java/com/englishtown/vertx/cassandra/impl/DefaultCassandraSessionTest.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.impl; 2 | 3 | import com.datastax.driver.core.*; 4 | import com.datastax.driver.core.policies.LoadBalancingPolicy; 5 | import com.datastax.driver.core.querybuilder.QueryBuilder; 6 | import com.englishtown.vertx.cassandra.CassandraConfigurator; 7 | import com.google.common.util.concurrent.FutureCallback; 8 | import com.google.common.util.concurrent.ListenableFuture; 9 | import com.google.common.util.concurrent.SettableFuture; 10 | import io.vertx.core.*; 11 | import org.junit.Before; 12 | import org.junit.Test; 13 | import org.junit.runner.RunWith; 14 | import org.mockito.ArgumentCaptor; 15 | import org.mockito.Captor; 16 | import org.mockito.Mock; 17 | import org.mockito.runners.MockitoJUnitRunner; 18 | 19 | import java.util.ArrayList; 20 | import java.util.Collection; 21 | import java.util.Iterator; 22 | import java.util.List; 23 | import java.util.concurrent.CompletableFuture; 24 | import java.util.concurrent.Executor; 25 | import java.util.function.BiConsumer; 26 | import java.util.function.Consumer; 27 | 28 | import static org.junit.Assert.assertEquals; 29 | import static org.junit.Assert.fail; 30 | import static org.mockito.Matchers.anyString; 31 | import static org.mockito.Mockito.*; 32 | 33 | /** 34 | * Unit tests for {@link DefaultCassandraSession} 35 | */ 36 | @RunWith(MockitoJUnitRunner.class) 37 | public class DefaultCassandraSessionTest { 38 | 39 | DefaultCassandraSession cassandraSession; 40 | List seeds = new ArrayList<>(); 41 | Configuration configuration = Configuration.builder().build(); 42 | 43 | @Mock 44 | Vertx vertx; 45 | @Mock 46 | Context context; 47 | @Mock 48 | CassandraConfigurator configurator; 49 | @Mock 50 | Cluster.Builder clusterBuilder; 51 | @Mock 52 | Cluster cluster; 53 | @Mock 54 | Session session; 55 | @Mock 56 | Metadata metadata; 57 | @Mock 58 | FutureCallback callback; 59 | @Mock 60 | ListenableFuture preparedStatementFuture; 61 | @Mock 62 | FutureCallback preparedStatementCallback; 63 | @Mock 64 | CloseFuture closeFuture; 65 | @Captor 66 | ArgumentCaptor statementCaptor; 67 | @Captor 68 | ArgumentCaptor queryCaptor; 69 | @Captor 70 | ArgumentCaptor runnableCaptor; 71 | @Captor 72 | ArgumentCaptor> handlerCaptor; 73 | @Captor 74 | ArgumentCaptor>> onReadyCaptor; 75 | @Captor 76 | ArgumentCaptor executorCaptor; 77 | 78 | private BiConsumer> onReadyFail = (cassandraSession, future) -> { 79 | cassandraSession.onReady(result -> { 80 | if (result.succeeded()) { 81 | future.completeExceptionally(new RuntimeException("Should not succeed")); 82 | } else { 83 | future.complete(null); 84 | } 85 | }); 86 | }; 87 | 88 | public static class TestLoadBalancingPolicy implements LoadBalancingPolicy { 89 | @Override 90 | public void init(Cluster cluster, Collection hosts) { 91 | } 92 | 93 | @Override 94 | public HostDistance distance(Host host) { 95 | return null; 96 | } 97 | 98 | @Override 99 | public Iterator newQueryPlan(String loggedKeyspace, Statement statement) { 100 | return null; 101 | } 102 | 103 | @Override 104 | public void onAdd(Host host) { 105 | } 106 | 107 | @Override 108 | public void onUp(Host host) { 109 | } 110 | 111 | @Override 112 | public void onDown(Host host) { 113 | } 114 | 115 | @Override 116 | public void onRemove(Host host) { 117 | } 118 | 119 | @Override 120 | public void close() { 121 | 122 | } 123 | } 124 | 125 | @Before 126 | public void setUp() { 127 | 128 | SettableFuture sessionFuture = SettableFuture.create(); 129 | 130 | when(vertx.getOrCreateContext()).thenReturn(context); 131 | doAnswer(invocation -> { 132 | Handler handler = (Handler) invocation.getArguments()[0]; 133 | handler.handle(null); 134 | return null; 135 | }).when(context).runOnContext(any()); 136 | 137 | when(clusterBuilder.build()).thenReturn(cluster); 138 | when(cluster.getConfiguration()).thenReturn(configuration); 139 | when(cluster.connectAsync()).thenReturn(sessionFuture); 140 | when(cluster.getMetadata()).thenReturn(metadata); 141 | when(cluster.closeAsync()).thenReturn(closeFuture); 142 | when(closeFuture.force()).thenReturn(closeFuture); 143 | 144 | when(configurator.getSeeds()).thenReturn(seeds); 145 | seeds.add("127.0.0.1"); 146 | 147 | when(session.getCluster()).thenReturn(cluster); 148 | when(session.prepareAsync(any(RegularStatement.class))).thenReturn(preparedStatementFuture); 149 | when(session.prepareAsync(anyString())).thenReturn(preparedStatementFuture); 150 | 151 | cassandraSession = new DefaultCassandraSession(clusterBuilder, configurator, vertx); 152 | 153 | verify(configurator).onReady(onReadyCaptor.capture()); 154 | onReadyCaptor.getValue().handle(Future.succeededFuture()); 155 | 156 | sessionFuture.set(session); 157 | 158 | } 159 | 160 | @Test 161 | public void testInit() throws Exception { 162 | 163 | seeds.clear(); 164 | seeds.add("127.0.0.1"); 165 | seeds.add("127.0.0.2"); 166 | seeds.add("127.0.0.3"); 167 | 168 | LoadBalancingPolicy lbPolicy = mock(LoadBalancingPolicy.class); 169 | when(configurator.getLoadBalancingPolicy()).thenReturn(lbPolicy); 170 | PoolingOptions poolingOptions = mock(PoolingOptions.class); 171 | when(configurator.getPoolingOptions()).thenReturn(poolingOptions); 172 | SocketOptions socketOptions = mock(SocketOptions.class); 173 | when(configurator.getSocketOptions()).thenReturn(socketOptions); 174 | QueryOptions queryOptions = mock(QueryOptions.class); 175 | when(configurator.getQueryOptions()).thenReturn(queryOptions); 176 | MetricsOptions metricsOptions = mock(MetricsOptions.class); 177 | when(configurator.getMetricsOptions()).thenReturn(metricsOptions); 178 | 179 | cassandraSession.init(configurator); 180 | verify(clusterBuilder, times(4)).addContactPoint(anyString()); 181 | verify(clusterBuilder).withLoadBalancingPolicy(eq(lbPolicy)); 182 | verify(clusterBuilder).withPoolingOptions(eq(poolingOptions)); 183 | verify(clusterBuilder, times(2)).build(); 184 | verify(cluster, times(2)).connectAsync(); 185 | 186 | verify(cluster, times(0)).getMetadata(); 187 | cassandraSession.getMetadata(); 188 | verify(cluster, times(1)).getMetadata(); 189 | 190 | verify(cluster, times(0)).isClosed(); 191 | verify(session, times(0)).isClosed(); 192 | cassandraSession.isClosed(); 193 | verify(cluster, times(0)).isClosed(); 194 | verify(session, times(1)).isClosed(); 195 | 196 | assertEquals(cluster, cassandraSession.getCluster()); 197 | 198 | seeds.clear(); 199 | try { 200 | cassandraSession.init(configurator); 201 | fail(); 202 | } catch (Throwable t) { 203 | // Expected 204 | } 205 | 206 | } 207 | 208 | @Test 209 | public void testCtorInitFail() throws Exception { 210 | 211 | seeds.clear(); 212 | reset(configurator); 213 | 214 | DefaultCassandraSession cassandraSession = new DefaultCassandraSession(clusterBuilder, configurator, vertx); 215 | 216 | CompletableFuture future = new CompletableFuture<>(); 217 | onReadyFail.accept(cassandraSession, future); 218 | 219 | verify(configurator).onReady(onReadyCaptor.capture()); 220 | onReadyCaptor.getValue().handle(Future.succeededFuture()); 221 | future.get(); 222 | 223 | future = new CompletableFuture<>(); 224 | onReadyFail.accept(cassandraSession, future); 225 | future.get(); 226 | 227 | } 228 | 229 | @Test 230 | public void testCtorReadyFail() throws Exception { 231 | 232 | reset(configurator); 233 | 234 | DefaultCassandraSession cassandraSession = new DefaultCassandraSession(clusterBuilder, configurator, vertx); 235 | 236 | CompletableFuture future = new CompletableFuture<>(); 237 | onReadyFail.accept(cassandraSession, future); 238 | 239 | verify(configurator).onReady(onReadyCaptor.capture()); 240 | onReadyCaptor.getValue().handle(Future.failedFuture("Test fail")); 241 | future.get(); 242 | 243 | future = new CompletableFuture<>(); 244 | onReadyFail.accept(cassandraSession, future); 245 | future.get(); 246 | 247 | } 248 | 249 | @Test 250 | public void testExecuteAsync() throws Exception { 251 | 252 | Statement statement = mock(Statement.class); 253 | ResultSetFuture future = mock(ResultSetFuture.class); 254 | when(session.executeAsync(any(Statement.class))).thenReturn(future); 255 | 256 | cassandraSession.executeAsync(statement, callback); 257 | verify(session).executeAsync(eq(statement)); 258 | verify(future).addListener(runnableCaptor.capture(), executorCaptor.capture()); 259 | 260 | ResultSet resultSet = mock(ResultSet.class); 261 | RuntimeException e = new RuntimeException("Unit test exception"); 262 | when(future.get()).thenReturn(resultSet).thenThrow(e); 263 | 264 | executorCaptor.getValue().execute(runnableCaptor.getValue()); 265 | verify(context, times(2)).runOnContext(handlerCaptor.capture()); 266 | handlerCaptor.getValue().handle(null); 267 | verify(callback).onSuccess(eq(resultSet)); 268 | 269 | executorCaptor.getValue().execute(runnableCaptor.getValue()); 270 | verify(context, times(3)).runOnContext(handlerCaptor.capture()); 271 | handlerCaptor.getValue().handle(null); 272 | verify(callback, times(3)).onFailure(eq(e)); 273 | 274 | } 275 | 276 | @Test 277 | public void testExecuteAsync_Query() throws Exception { 278 | 279 | String query = "SELECT * FROM table"; 280 | ResultSetFuture future = mock(ResultSetFuture.class); 281 | when(session.executeAsync(anyString())).thenReturn(future); 282 | 283 | cassandraSession.executeAsync(query, callback); 284 | verify(session).executeAsync(queryCaptor.capture()); 285 | assertEquals(query, queryCaptor.getValue()); 286 | verify(future).addListener(any(Runnable.class), any(Executor.class)); 287 | 288 | } 289 | 290 | @Test 291 | public void testExecute() throws Exception { 292 | 293 | String query = "SELECT * FROM table;"; 294 | 295 | cassandraSession.execute(query); 296 | verify(session).execute(queryCaptor.capture()); 297 | assertEquals(query, queryCaptor.getValue()); 298 | 299 | } 300 | 301 | @Test 302 | public void testPrepareAsync_Statement() throws Exception { 303 | RegularStatement statement = QueryBuilder.select() 304 | .from("ks", "table") 305 | .where(QueryBuilder.eq("id", QueryBuilder.bindMarker())); 306 | 307 | cassandraSession.prepareAsync(statement, preparedStatementCallback); 308 | verify(session).prepareAsync(eq(statement)); 309 | verify(preparedStatementFuture).addListener(any(Runnable.class), any(Executor.class)); 310 | } 311 | 312 | @Test 313 | public void testPrepareAsync_Query() throws Exception { 314 | String query = "SELECT * FROM ks.table where id = ?"; 315 | cassandraSession.prepareAsync(query, preparedStatementCallback); 316 | verify(session).prepareAsync(eq(query)); 317 | verify(preparedStatementFuture).addListener(any(Runnable.class), any(Executor.class)); 318 | } 319 | 320 | @Test 321 | public void testPrepare_Statement() throws Exception { 322 | RegularStatement statement = QueryBuilder.select() 323 | .from("ks", "table") 324 | .where(QueryBuilder.eq("id", QueryBuilder.bindMarker())); 325 | 326 | cassandraSession.prepare(statement); 327 | verify(session).prepare(eq(statement)); 328 | } 329 | 330 | @Test 331 | public void testPrepare_Query() throws Exception { 332 | String query = "SELECT * FROM ks.table where id = ?"; 333 | cassandraSession.prepare(query); 334 | verify(session).prepare(eq(query)); 335 | } 336 | 337 | @Test 338 | public void testGetMetadata() throws Exception { 339 | 340 | assertEquals(metadata, cassandraSession.getMetadata()); 341 | 342 | } 343 | 344 | @Test 345 | public void testClose() throws Exception { 346 | cassandraSession.close(); 347 | verify(cluster).closeAsync(); 348 | verify(closeFuture).force(); 349 | } 350 | } 351 | -------------------------------------------------------------------------------- /vertx-cassandra/src/test/java/com/englishtown/vertx/cassandra/impl/EnvironmentCassandraConfiguratorTest.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.impl; 2 | 3 | import com.datastax.driver.core.AuthProvider; 4 | import com.datastax.driver.core.PlainTextAuthProvider; 5 | import com.datastax.driver.core.policies.DCAwareRoundRobinPolicy; 6 | import com.datastax.driver.core.policies.LoadBalancingPolicy; 7 | import io.vertx.core.Context; 8 | import io.vertx.core.Vertx; 9 | import io.vertx.core.json.JsonArray; 10 | import io.vertx.core.json.JsonObject; 11 | import org.junit.Before; 12 | import org.junit.Test; 13 | import org.junit.runner.RunWith; 14 | import org.mockito.Mock; 15 | import org.mockito.runners.MockitoJUnitRunner; 16 | 17 | import java.util.List; 18 | 19 | import static com.englishtown.vertx.cassandra.impl.JsonCassandraConfigurator.CONFIG_CASSANDRA; 20 | import static com.englishtown.vertx.cassandra.impl.JsonCassandraConfigurator.CONFIG_SEEDS; 21 | import static org.hamcrest.CoreMatchers.instanceOf; 22 | import static org.junit.Assert.*; 23 | import static org.mockito.Matchers.eq; 24 | import static org.mockito.Mockito.when; 25 | 26 | /** 27 | * Unit tests for {@link com.englishtown.vertx.cassandra.impl.EnvironmentCassandraConfigurator} 28 | */ 29 | @RunWith(MockitoJUnitRunner.class) 30 | public class EnvironmentCassandraConfiguratorTest { 31 | 32 | JsonObject config = new JsonObject(); 33 | JsonObject cassConfig; 34 | 35 | @Mock 36 | Vertx vertx; 37 | @Mock 38 | Context context; 39 | @Mock 40 | EnvironmentCassandraConfigurator.EnvVarDelegate envVarDelegate; 41 | 42 | @Before 43 | public void setUp() { 44 | when(context.config()).thenReturn(config); 45 | when(vertx.getOrCreateContext()).thenReturn(context); 46 | 47 | config.put(CONFIG_CASSANDRA, cassConfig = new JsonObject()); 48 | } 49 | 50 | 51 | @Test 52 | public void testInitSeeds_Defaults() throws Exception { 53 | 54 | EnvironmentCassandraConfigurator configurator = new EnvironmentCassandraConfigurator(vertx, envVarDelegate); 55 | List seeds = configurator.getSeeds(); 56 | 57 | assertNotNull(seeds); 58 | assertEquals(1, seeds.size()); 59 | assertEquals("127.0.0.1", seeds.get(0)); 60 | } 61 | 62 | @Test 63 | public void testInitSeeds() throws Exception { 64 | 65 | cassConfig.put(CONFIG_SEEDS, new JsonArray().add("127.0.0.5")); 66 | when(envVarDelegate.get(eq(EnvironmentCassandraConfigurator.ENV_VAR_SEEDS))).thenReturn("127.0.0.2|127.0.0.3|127.0.0.4"); 67 | 68 | EnvironmentCassandraConfigurator configurator = new EnvironmentCassandraConfigurator(vertx, envVarDelegate); 69 | List seeds = configurator.getSeeds(); 70 | 71 | assertNotNull(seeds); 72 | assertEquals(3, seeds.size()); 73 | assertEquals("127.0.0.2", seeds.get(0)); 74 | assertEquals("127.0.0.3", seeds.get(1)); 75 | assertEquals("127.0.0.4", seeds.get(2)); 76 | } 77 | 78 | @Test 79 | public void testInitPolicies() throws Exception { 80 | 81 | when(envVarDelegate.get(eq(EnvironmentCassandraConfigurator.ENV_VAR_LOCAL_DC))).thenReturn("LOCAL1"); 82 | 83 | EnvironmentCassandraConfigurator configurator = new EnvironmentCassandraConfigurator(config, envVarDelegate); 84 | LoadBalancingPolicy loadBalancingPolicy = configurator.getLoadBalancingPolicy(); 85 | 86 | assertThat(loadBalancingPolicy, instanceOf(DCAwareRoundRobinPolicy.class)); 87 | } 88 | 89 | @Test 90 | public void testInitAuthProvider() throws Exception { 91 | 92 | EnvironmentCassandraConfigurator configurator = new EnvironmentCassandraConfigurator(config, envVarDelegate); 93 | AuthProvider authProvider = configurator.getAuthProvider(); 94 | 95 | assertNull(authProvider); 96 | 97 | String username = "test"; 98 | String password = "test_password"; 99 | when(envVarDelegate.get(eq(EnvironmentCassandraConfigurator.ENV_VAR_USERNAME))).thenReturn(username); 100 | when(envVarDelegate.get(eq(EnvironmentCassandraConfigurator.ENV_VAR_PASSWORD))).thenReturn(password); 101 | 102 | configurator = new EnvironmentCassandraConfigurator(config, envVarDelegate); 103 | authProvider = configurator.getAuthProvider(); 104 | 105 | assertThat(authProvider, instanceOf(PlainTextAuthProvider.class)); 106 | 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /vertx-cassandra/src/test/java/com/englishtown/vertx/cassandra/integration/CassandraSessionIntegrationTest.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.integration; 2 | 3 | import com.datastax.driver.core.BoundStatement; 4 | import com.datastax.driver.core.CodecRegistry; 5 | import com.datastax.driver.core.PreparedStatement; 6 | import com.datastax.driver.core.ProtocolVersion; 7 | import com.datastax.driver.core.RegularStatement; 8 | import com.datastax.driver.core.ResultSet; 9 | import com.datastax.driver.core.querybuilder.QueryBuilder; 10 | import com.google.common.util.concurrent.FutureCallback; 11 | import io.vertx.core.Context; 12 | import org.junit.Test; 13 | 14 | /** 15 | * Integration test for {@link com.englishtown.vertx.cassandra.CassandraSession} 16 | */ 17 | public abstract class CassandraSessionIntegrationTest extends IntegrationTestBase { 18 | 19 | @Test 20 | public void testExecute() throws Exception { 21 | 22 | session.execute(createTestTableStatement); 23 | 24 | RegularStatement statement = QueryBuilder.select() 25 | .from(keyspace, "test") 26 | .where(QueryBuilder.eq("id", QueryBuilder.bindMarker())); 27 | 28 | PreparedStatement prepared = session.prepare(statement); 29 | 30 | BoundStatement bound = prepared.bind("123"); 31 | ResultSet rs = session.execute(bound); 32 | assertNotNull(rs); 33 | testComplete(); 34 | } 35 | 36 | @Test 37 | public void testExecuteAsync() throws Exception { 38 | 39 | vertx.runOnContext(aVoid -> { 40 | 41 | Context context = vertx.getOrCreateContext(); 42 | 43 | session.executeAsync(createTestTableStatement, new FutureCallback() { 44 | @Override 45 | public void onSuccess(ResultSet result) { 46 | // Make sure we're on the right context 47 | assertEquals(context, vertx.getOrCreateContext()); 48 | assertNotNull(result); 49 | testComplete(); 50 | } 51 | 52 | @Override 53 | public void onFailure(Throwable t) { 54 | handleThrowable(t); 55 | } 56 | }); 57 | 58 | }); 59 | 60 | await(); 61 | 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /vertx-cassandra/src/test/java/com/englishtown/vertx/cassandra/integration/IntegrationTestBase.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.integration; 2 | 3 | import com.datastax.driver.core.*; 4 | import com.datastax.driver.core.policies.LoadBalancingPolicy; 5 | import com.englishtown.promises.When; 6 | import com.englishtown.vertx.cassandra.CassandraSession; 7 | import com.englishtown.vertx.cassandra.keyspacebuilder.KeyspaceBuilder; 8 | import com.englishtown.vertx.cassandra.promises.WhenCassandraSession; 9 | import com.englishtown.vertx.cassandra.tablebuilder.CreateTable; 10 | import com.englishtown.vertx.cassandra.tablebuilder.TableBuilder; 11 | import com.google.common.base.Charsets; 12 | import com.google.common.io.Resources; 13 | import io.vertx.core.json.JsonObject; 14 | import io.vertx.test.core.VertxTestBase; 15 | import org.apache.cassandra.service.EmbeddedCassandraService; 16 | import org.junit.BeforeClass; 17 | 18 | import java.util.concurrent.CompletableFuture; 19 | 20 | /** 21 | * Cassandra base integration test class 22 | */ 23 | public abstract class IntegrationTestBase extends VertxTestBase { 24 | 25 | private Locator locator; 26 | protected CassandraSession session; 27 | protected WhenCassandraSession whenSession; 28 | protected String keyspace; 29 | protected CreateTable createTestTableStatement; 30 | protected When when; 31 | 32 | public static final String TEST_CONFIG_FILE = "test_config.json"; 33 | public static final String TEST_KEYSPACE = "test_vertx_mod_cass"; 34 | 35 | private static EmbeddedCassandraService cassandraService = null; 36 | 37 | protected abstract Locator createLocator(); 38 | 39 | @BeforeClass 40 | public static void beforeClass() throws Exception { 41 | if (cassandraService == null) { 42 | String embedded = System.getProperty("test.embedded", ""); 43 | if (!"true".equals(embedded)) { 44 | return; 45 | } 46 | System.setProperty("cassandra.storagedir", "target/cassandra"); 47 | cassandraService = new EmbeddedCassandraService(); 48 | cassandraService.start(); 49 | } 50 | } 51 | 52 | /** 53 | * Override to run additional initialization before your integration tests run 54 | */ 55 | @Override 56 | public void setUp() throws Exception { 57 | super.setUp(); 58 | locator = createLocator(); 59 | 60 | CompletableFuture future = new CompletableFuture<>(); 61 | 62 | vertx.runOnContext(aVoid -> { 63 | 64 | // Load the test config file, if we have one 65 | JsonObject config = loadConfig(); 66 | vertx.getOrCreateContext().config().mergeIn(config); 67 | 68 | // String dateTime = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()); 69 | keyspace = TEST_KEYSPACE; //dateTime; 70 | 71 | session = getInstance(CassandraSession.class); 72 | when = getInstance(When.class); 73 | whenSession = getInstance(WhenCassandraSession.class); 74 | 75 | session.onReady(result -> { 76 | if (result.failed()) { 77 | future.completeExceptionally(result.cause()); 78 | return; 79 | } 80 | 81 | Metadata metadata = session.getMetadata(); 82 | KeyspaceMetadata keyspaceMetadata = metadata.getKeyspace(keyspace); 83 | if (keyspaceMetadata != null) { 84 | for (TableMetadata tableMetadata : keyspaceMetadata.getTables()) { 85 | session.execute(TableBuilder.drop(keyspace, tableMetadata.getName()).ifExists()); 86 | } 87 | } else { 88 | createKeyspace(metadata); 89 | } 90 | 91 | createTestTableStatement = TableBuilder.create(keyspace, "test") 92 | .ifNotExists() 93 | .column("id", "text") 94 | .column("value", "text") 95 | .primaryKey("id"); 96 | 97 | future.complete(null); 98 | }); 99 | }); 100 | 101 | future.get(); 102 | } 103 | 104 | protected T getInstance(Class clazz) { 105 | return locator.getInstance(clazz); 106 | } 107 | 108 | private void createKeyspace(Metadata metadata) { 109 | 110 | Statement createKeyspaceStatement = null; 111 | 112 | // Find out which node is closest and use that for the networktopologystrategy 113 | LoadBalancingPolicy lbPolicy = session.getCluster().getConfiguration().getPolicies().getLoadBalancingPolicy(); 114 | for (Host host : metadata.getAllHosts()) { 115 | if (lbPolicy.distance(host) == HostDistance.LOCAL) { 116 | createKeyspaceStatement = KeyspaceBuilder.create(keyspace) 117 | .ifNotExists() 118 | .networkTopologyStrategy() 119 | .dc(host.getDatacenter(), 1); 120 | break; 121 | } 122 | } 123 | 124 | if (createKeyspaceStatement == null) { 125 | fail("Could not find a local host for the test"); 126 | return; 127 | } 128 | 129 | session.execute(createKeyspaceStatement); 130 | 131 | } 132 | 133 | private JsonObject loadConfig() { 134 | try { 135 | return new JsonObject(Resources.toString(Resources.getResource(TEST_CONFIG_FILE), Charsets.UTF_8)); 136 | } catch (Exception e) { 137 | return new JsonObject(); 138 | } 139 | } 140 | 141 | /** 142 | * Vert.x calls the stop method when the verticle is undeployed. 143 | * Put any cleanup code for your verticle in here 144 | */ 145 | @Override 146 | public void tearDown() throws Exception { 147 | try { 148 | if (session != null) { 149 | session.close(); 150 | } 151 | } catch (Exception e) { 152 | e.printStackTrace(); 153 | } 154 | 155 | super.tearDown(); 156 | } 157 | 158 | protected void handleThrowable(Throwable t) { 159 | t.printStackTrace(); 160 | fail(); 161 | } 162 | 163 | } 164 | -------------------------------------------------------------------------------- /vertx-cassandra/src/test/java/com/englishtown/vertx/cassandra/integration/Locator.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.integration; 2 | 3 | /** 4 | * Created by adriangonzalez on 5/29/15. 5 | */ 6 | public interface Locator { 7 | 8 | T getInstance(Class clazz); 9 | 10 | } 11 | -------------------------------------------------------------------------------- /vertx-cassandra/src/test/java/com/englishtown/vertx/cassandra/integration/TableBuilderIntegrationTest.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.integration; 2 | 3 | import com.datastax.driver.core.Statement; 4 | import com.datastax.driver.core.TableMetadata; 5 | import com.datastax.driver.core.exceptions.QueryValidationException; 6 | import com.englishtown.vertx.cassandra.tablebuilder.AlterTable; 7 | import com.englishtown.vertx.cassandra.tablebuilder.CreateTable; 8 | import com.englishtown.vertx.cassandra.tablebuilder.TableBuilder; 9 | import org.junit.Test; 10 | 11 | import java.util.List; 12 | 13 | /** 14 | * Integration tests for {@link com.englishtown.vertx.cassandra.tablebuilder.TableBuilder} 15 | */ 16 | public abstract class TableBuilderIntegrationTest extends IntegrationTestBase { 17 | 18 | @Test 19 | public void testTableBuilder() throws Exception { 20 | 21 | assertNotNull(session.getMetadata().getKeyspace(keyspace)); 22 | 23 | String table = "test_table"; 24 | Statement statement; 25 | 26 | assertNull(session.getMetadata().getKeyspace(keyspace).getTable(table)); 27 | 28 | // Create the table 29 | statement = TableBuilder.create(keyspace, table) 30 | .column("col1", "text") 31 | .column("col2", "text") 32 | .primaryKey("col1"); 33 | 34 | session.execute(statement); 35 | 36 | assertNotNull(session.getMetadata().getKeyspace(keyspace).getTable(table)); 37 | 38 | try { 39 | session.execute(statement); 40 | fail("Table already exists, create should have throw AlreadyExistsException"); 41 | } catch (QueryValidationException e) { 42 | // Expected 43 | } 44 | 45 | // Should not fail with the "IF NOT EXISTS" statement 46 | statement = TableBuilder.create(keyspace, table) 47 | .ifNotExists() 48 | .column("col1", "text") 49 | .column("col2", "text") 50 | .primaryKey("col1"); 51 | 52 | session.execute(statement); 53 | 54 | CreateTable createTable = TableBuilder.create(keyspace, table) 55 | .column("col1", "text") 56 | .column("col2", "text") 57 | .column("col3", "int") 58 | .column("col4", "boolean") 59 | .column("col5", "uuid") 60 | .primaryKey("col1"); 61 | 62 | TableMetadata tableMetadata = session.getMetadata().getKeyspace(keyspace).getTable(table); 63 | List alterStatements = TableBuilder.alter(tableMetadata, createTable); 64 | 65 | for (AlterTable alterTable : alterStatements) { 66 | session.execute(alterTable); 67 | } 68 | 69 | tableMetadata = session.getMetadata().getKeyspace(keyspace).getTable(table); 70 | assertEquals(5, tableMetadata.getColumns().size()); 71 | 72 | statement = TableBuilder.drop(keyspace, table); 73 | session.execute(statement); 74 | 75 | statement = TableBuilder.drop(keyspace, table) 76 | .ifExists(); 77 | session.execute(statement); 78 | 79 | try { 80 | statement = TableBuilder.drop(keyspace, table); 81 | session.execute(statement); 82 | fail("Table should not exist, drop should have throw InvalidQueryException"); 83 | } catch (QueryValidationException e) { 84 | // Expected 85 | } 86 | 87 | testComplete(); 88 | 89 | } 90 | 91 | } 92 | -------------------------------------------------------------------------------- /vertx-cassandra/src/test/java/com/englishtown/vertx/cassandra/integration/WhenCassandraSessionIntegrationTest.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.integration; 2 | 3 | import com.datastax.driver.core.Statement; 4 | import com.englishtown.vertx.cassandra.tablebuilder.TableBuilder; 5 | import io.vertx.core.Context; 6 | import org.junit.Test; 7 | 8 | /** 9 | * Integration test for {@link com.englishtown.vertx.cassandra.CassandraSession} 10 | */ 11 | public abstract class WhenCassandraSessionIntegrationTest extends IntegrationTestBase { 12 | 13 | @Test 14 | public void testExecuteAsync() throws Exception { 15 | 16 | vertx.runOnContext(aVoid -> { 17 | 18 | final Context context = vertx.getOrCreateContext(); 19 | 20 | whenSession.executeAsync(createTestTableStatement) 21 | .then(value -> { 22 | // Make sure we're on the right context 23 | assertEquals(context, vertx.getOrCreateContext()); 24 | assertNotNull(value); 25 | 26 | Statement statement = TableBuilder.create(keyspace, "test") 27 | .column("id", "text") 28 | .primaryKey("id"); 29 | 30 | // This promise will reject 31 | return whenSession.executeAsync(statement); 32 | }) 33 | .then(value -> { 34 | // Should have reject, keyspace already exists 35 | fail(); 36 | return null; 37 | }, 38 | value -> { 39 | // Make sure we're on the right context 40 | assertEquals(context, vertx.getOrCreateContext()); 41 | assertNotNull(value); 42 | return null; 43 | }) 44 | .then(value -> { 45 | testComplete(); 46 | return null; 47 | }) 48 | .otherwise(t -> { 49 | handleThrowable(t); 50 | return null; 51 | }); 52 | 53 | }); 54 | 55 | await(); 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /vertx-cassandra/src/test/java/com/englishtown/vertx/cassandra/integration/guice/GuiceCassandraSessionIntegrationTest.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.integration.guice; 2 | 3 | import com.englishtown.vertx.cassandra.integration.CassandraSessionIntegrationTest; 4 | import com.englishtown.vertx.cassandra.integration.Locator; 5 | 6 | /** 7 | * Guice version of {@link CassandraSessionIntegrationTest} 8 | */ 9 | public class GuiceCassandraSessionIntegrationTest extends CassandraSessionIntegrationTest { 10 | 11 | @Override 12 | protected Locator createLocator() { 13 | return new GuiceLocator(vertx); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /vertx-cassandra/src/test/java/com/englishtown/vertx/cassandra/integration/guice/GuiceLocator.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.integration.guice; 2 | 3 | import com.englishtown.vertx.cassandra.guice.GuiceWhenCassandraBinder; 4 | import com.englishtown.vertx.cassandra.integration.Locator; 5 | import com.englishtown.vertx.guice.GuiceVertxBinder; 6 | import com.englishtown.vertx.promises.guice.GuiceWhenBinder; 7 | import com.google.inject.Guice; 8 | import com.google.inject.Injector; 9 | import com.google.inject.Module; 10 | import io.vertx.core.Vertx; 11 | 12 | import java.util.ArrayList; 13 | import java.util.Collections; 14 | import java.util.List; 15 | 16 | /** 17 | * Guice {@link Locator} implementation 18 | */ 19 | public class GuiceLocator implements Locator { 20 | 21 | private Injector injector; 22 | 23 | public GuiceLocator(Vertx vertx, Module... modules) { 24 | 25 | List list = new ArrayList<>(); 26 | list.add(new GuiceWhenBinder()); 27 | list.add(new GuiceWhenCassandraBinder()); 28 | list.add(new GuiceVertxBinder(vertx)); 29 | 30 | if (modules != null) { 31 | Collections.addAll(list, modules); 32 | } 33 | 34 | injector = Guice.createInjector(list); 35 | 36 | } 37 | 38 | public Injector getInjector() { 39 | return injector; 40 | } 41 | 42 | @Override 43 | public T getInstance(Class clazz) { 44 | return injector.getInstance(clazz); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /vertx-cassandra/src/test/java/com/englishtown/vertx/cassandra/integration/guice/GuiceTableBuilderIntegrationTest.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.integration.guice; 2 | 3 | import com.englishtown.vertx.cassandra.integration.Locator; 4 | import com.englishtown.vertx.cassandra.integration.TableBuilderIntegrationTest; 5 | 6 | /** 7 | * Guice version of {@link TableBuilderIntegrationTest} 8 | */ 9 | public class GuiceTableBuilderIntegrationTest extends TableBuilderIntegrationTest { 10 | 11 | @Override 12 | protected Locator createLocator() { 13 | return new GuiceLocator(vertx); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /vertx-cassandra/src/test/java/com/englishtown/vertx/cassandra/integration/guice/GuiceWhenCassandraSessionIntegrationTest.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.integration.guice; 2 | 3 | import com.englishtown.vertx.cassandra.integration.Locator; 4 | import com.englishtown.vertx.cassandra.integration.WhenCassandraSessionIntegrationTest; 5 | 6 | /** 7 | * Guice version of {@link WhenCassandraSessionIntegrationTest} 8 | */ 9 | public class GuiceWhenCassandraSessionIntegrationTest extends WhenCassandraSessionIntegrationTest { 10 | 11 | @Override 12 | protected Locator createLocator() { 13 | return new GuiceLocator(vertx); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /vertx-cassandra/src/test/java/com/englishtown/vertx/cassandra/integration/hk2/HK2CassandraSessionIntegrationTest.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.integration.hk2; 2 | 3 | import com.englishtown.vertx.cassandra.integration.CassandraSessionIntegrationTest; 4 | import com.englishtown.vertx.cassandra.integration.Locator; 5 | 6 | /** 7 | * HK2 version of {@link CassandraSessionIntegrationTest} 8 | */ 9 | public class HK2CassandraSessionIntegrationTest extends CassandraSessionIntegrationTest { 10 | 11 | @Override 12 | protected Locator createLocator() { 13 | return new HK2Locator(vertx); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /vertx-cassandra/src/test/java/com/englishtown/vertx/cassandra/integration/hk2/HK2Locator.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.integration.hk2; 2 | 3 | import com.englishtown.vertx.cassandra.hk2.HK2WhenCassandraBinder; 4 | import com.englishtown.vertx.cassandra.integration.Locator; 5 | import com.englishtown.vertx.hk2.HK2VertxBinder; 6 | import com.englishtown.vertx.promises.hk2.HK2WhenBinder; 7 | import io.vertx.core.Vertx; 8 | import org.glassfish.hk2.api.ServiceLocator; 9 | import org.glassfish.hk2.api.ServiceLocatorFactory; 10 | import org.glassfish.hk2.utilities.Binder; 11 | import org.glassfish.hk2.utilities.ServiceLocatorUtilities; 12 | 13 | /** 14 | * HK2 {@link Locator} implementation 15 | */ 16 | public class HK2Locator implements Locator { 17 | 18 | private ServiceLocator locator; 19 | 20 | public HK2Locator(Vertx vertx, Binder... binders) { 21 | 22 | locator = ServiceLocatorFactory.getInstance().create(null); 23 | ServiceLocatorUtilities.bind(locator, 24 | new HK2WhenBinder(), 25 | new HK2WhenCassandraBinder(), 26 | new HK2VertxBinder(vertx)); 27 | 28 | if (binders != null) { 29 | ServiceLocatorUtilities.bind(locator, binders); 30 | } 31 | 32 | } 33 | 34 | @Override 35 | public T getInstance(Class clazz) { 36 | return locator.getService(clazz); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /vertx-cassandra/src/test/java/com/englishtown/vertx/cassandra/integration/hk2/HK2TableBuilderIntegrationTest.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.integration.hk2; 2 | 3 | import com.englishtown.vertx.cassandra.integration.Locator; 4 | import com.englishtown.vertx.cassandra.integration.TableBuilderIntegrationTest; 5 | 6 | /** 7 | * HK2 version of {@link TableBuilderIntegrationTest} 8 | */ 9 | public class HK2TableBuilderIntegrationTest extends TableBuilderIntegrationTest { 10 | 11 | @Override 12 | protected Locator createLocator() { 13 | return new HK2Locator(vertx); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /vertx-cassandra/src/test/java/com/englishtown/vertx/cassandra/integration/hk2/HK2WhenCassandraSessionIntegrationTest.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.integration.hk2; 2 | 3 | import com.englishtown.vertx.cassandra.integration.Locator; 4 | import com.englishtown.vertx.cassandra.integration.WhenCassandraSessionIntegrationTest; 5 | 6 | /** 7 | * HK2 version of {@link WhenCassandraSessionIntegrationTest} 8 | */ 9 | public class HK2WhenCassandraSessionIntegrationTest extends WhenCassandraSessionIntegrationTest { 10 | 11 | @Override 12 | protected Locator createLocator() { 13 | return new HK2Locator(vertx); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /vertx-cassandra/src/test/java/com/englishtown/vertx/cassandra/keyspacebuilder/AlterKeyspaceTest.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.keyspacebuilder; 2 | 3 | import com.datastax.driver.core.Statement; 4 | import org.junit.Test; 5 | 6 | import static org.junit.Assert.assertEquals; 7 | 8 | public class AlterKeyspaceTest { 9 | 10 | @Test 11 | public void testAlterKeyspace_SimpleStrategy() throws Exception { 12 | 13 | String name = "test_keyspace"; 14 | 15 | Statement alterKeyspace = KeyspaceBuilder.alter(name) 16 | .simpleStrategy(3); 17 | 18 | String cql = alterKeyspace.toString(); 19 | assertEquals("ALTER KEYSPACE test_keyspace WITH REPLICATION = { 'class' : 'SimpleStrategy', 'replication_factor' : 3 }", cql); 20 | 21 | } 22 | 23 | @Test 24 | public void testCreateKeyspace_NetworkTopologyStrategy() throws Exception { 25 | 26 | String name = "test_keyspace"; 27 | 28 | Statement createKeyspace = KeyspaceBuilder.alter(name) 29 | .networkTopologyStrategy() 30 | .dc("dc1", 3) 31 | .dc("dc2", 2) 32 | .dc("dc3", 1); 33 | 34 | String cql = createKeyspace.toString(); 35 | assertEquals("ALTER KEYSPACE test_keyspace WITH REPLICATION = { 'class' : 'NetworkTopologyStrategy', 'dc1' : 3, 'dc2' : 2, 'dc3' : 1 }", cql); 36 | 37 | } 38 | 39 | } -------------------------------------------------------------------------------- /vertx-cassandra/src/test/java/com/englishtown/vertx/cassandra/keyspacebuilder/CreateKeyspaceTest.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.keyspacebuilder; 2 | 3 | import com.datastax.driver.core.Statement; 4 | import org.junit.Test; 5 | 6 | import static org.junit.Assert.assertEquals; 7 | 8 | public class CreateKeyspaceTest { 9 | 10 | @Test 11 | public void testCreateKeyspace_SimpleStrategy() throws Exception { 12 | 13 | String name = "test_keyspace"; 14 | 15 | Statement createKeyspace = KeyspaceBuilder.create(name) 16 | .ifNotExists() 17 | .simpleStrategy(3); 18 | 19 | String cql = createKeyspace.toString(); 20 | assertEquals("CREATE KEYSPACE IF NOT EXISTS test_keyspace WITH REPLICATION = { 'class' : 'SimpleStrategy', 'replication_factor' : 3 }", cql); 21 | 22 | } 23 | 24 | @Test 25 | public void testCreateKeyspace_NetworkTopologyStrategy() throws Exception { 26 | 27 | String name = "test_keyspace"; 28 | 29 | Statement createKeyspace = KeyspaceBuilder.create(name) 30 | .networkTopologyStrategy() 31 | .dc("dc1", 3) 32 | .dc("dc2", 2) 33 | .dc("dc3", 1); 34 | 35 | String cql = createKeyspace.toString(); 36 | assertEquals("CREATE KEYSPACE test_keyspace WITH REPLICATION = { 'class' : 'NetworkTopologyStrategy', 'dc1' : 3, 'dc2' : 2, 'dc3' : 1 }", cql); 37 | 38 | } 39 | 40 | } -------------------------------------------------------------------------------- /vertx-cassandra/src/test/java/com/englishtown/vertx/cassandra/keyspacebuilder/DropKeyspaceTest.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.keyspacebuilder; 2 | 3 | import com.datastax.driver.core.Statement; 4 | import org.junit.Test; 5 | 6 | import static org.junit.Assert.assertEquals; 7 | 8 | public class DropKeyspaceTest { 9 | 10 | String keyspace = "test_keyspace"; 11 | 12 | @Test 13 | public void testDropKeyspace() throws Exception { 14 | 15 | Statement statement = KeyspaceBuilder.drop(keyspace); 16 | String cql = statement.toString(); 17 | 18 | assertEquals("DROP KEYSPACE test_keyspace", cql); 19 | 20 | } 21 | 22 | @Test 23 | public void testDropKeyspace_IfExists() throws Exception { 24 | 25 | Statement statement = KeyspaceBuilder.drop(keyspace) 26 | .ifExists(); 27 | String cql = statement.toString(); 28 | 29 | assertEquals("DROP KEYSPACE IF EXISTS test_keyspace", cql); 30 | 31 | } 32 | 33 | } -------------------------------------------------------------------------------- /vertx-cassandra/src/test/java/com/englishtown/vertx/cassandra/promises/impl/DefaultWhenCassandraSessionTest.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.promises.impl; 2 | 3 | import com.englishtown.promises.*; 4 | import com.englishtown.vertx.cassandra.CassandraSession; 5 | import io.vertx.core.AsyncResult; 6 | import io.vertx.core.Future; 7 | import io.vertx.core.Handler; 8 | import io.vertx.core.Vertx; 9 | import io.vertx.core.spi.FutureFactory; 10 | import org.junit.Before; 11 | import org.junit.Test; 12 | import org.junit.runner.RunWith; 13 | import org.mockito.ArgumentCaptor; 14 | import org.mockito.Captor; 15 | import org.mockito.Mock; 16 | import org.mockito.runners.MockitoJUnitRunner; 17 | 18 | import static org.junit.Assert.assertEquals; 19 | import static org.mockito.Mockito.verify; 20 | 21 | /** 22 | * Unit tests for {@link DefaultWhenCassandraSession} 23 | */ 24 | @RunWith(MockitoJUnitRunner.class) 25 | public class DefaultWhenCassandraSessionTest { 26 | 27 | @Mock 28 | private CassandraSession cassandraSession; 29 | @Mock 30 | private Vertx vertx; 31 | @Captor 32 | private ArgumentCaptor>> onReadyCaptor; 33 | 34 | private When when; 35 | private DefaultWhenCassandraSession whenCassandraSession; 36 | 37 | @Before 38 | public void setUp() throws Exception { 39 | when = WhenFactory.createSync(); 40 | whenCassandraSession = new DefaultWhenCassandraSession(cassandraSession, when, vertx); 41 | } 42 | 43 | @Test 44 | public void testReady() throws Exception { 45 | 46 | Promise p = whenCassandraSession.ready(); 47 | State state = p.inspect(); 48 | assertEquals(HandlerState.PENDING, state.getState()); 49 | 50 | verify(cassandraSession).onReady(onReadyCaptor.capture()); 51 | onReadyCaptor.getValue().handle(Future.succeededFuture()); 52 | 53 | state = p.inspect(); 54 | assertEquals(HandlerState.FULFILLED, state.getState()); 55 | 56 | } 57 | 58 | @Test 59 | public void testReadyReject() throws Exception { 60 | 61 | Promise p = whenCassandraSession.ready(); 62 | State state = p.inspect(); 63 | assertEquals(HandlerState.PENDING, state.getState()); 64 | 65 | verify(cassandraSession).onReady(onReadyCaptor.capture()); 66 | onReadyCaptor.getValue().handle(Future.failedFuture("Test fail")); 67 | 68 | state = p.inspect(); 69 | assertEquals(HandlerState.REJECTED, state.getState()); 70 | 71 | } 72 | 73 | } -------------------------------------------------------------------------------- /vertx-cassandra/src/test/java/com/englishtown/vertx/cassandra/tablebuilder/AlterTableTest.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.tablebuilder; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertEquals; 6 | 7 | public class AlterTableTest { 8 | 9 | @Test 10 | public void testAlter() throws Exception { 11 | AlterTable alter = TableBuilder.alter("test_keyspace", "test_table") 12 | .alterColumn("col1", "text"); 13 | 14 | String cql = alter.getQueryString(); 15 | assertEquals("ALTER TABLE test_keyspace.test_table ALTER col1 TYPE text", cql); 16 | } 17 | 18 | @Test 19 | public void testAdd() throws Exception { 20 | AlterTable alter = TableBuilder.alter("test_keyspace", "test_table") 21 | .addColumn("col1", "text"); 22 | 23 | String cql = alter.getQueryString(); 24 | assertEquals("ALTER TABLE test_keyspace.test_table ADD col1 text", cql); 25 | } 26 | 27 | @Test 28 | public void testDrop() throws Exception { 29 | AlterTable alter = TableBuilder.alter("test_keyspace", "test_table") 30 | .dropColumn("col1"); 31 | 32 | String cql = alter.getQueryString(); 33 | assertEquals("ALTER TABLE test_keyspace.test_table DROP col1", cql); 34 | } 35 | 36 | @Test 37 | public void testRename() throws Exception { 38 | AlterTable alter = TableBuilder.alter("test_keyspace", "test_table") 39 | .renameColumn("col1", "col2"); 40 | 41 | String cql = alter.getQueryString(); 42 | assertEquals("ALTER TABLE test_keyspace.test_table RENAME col1 TO col2", cql); 43 | } 44 | } -------------------------------------------------------------------------------- /vertx-cassandra/src/test/java/com/englishtown/vertx/cassandra/tablebuilder/CreateTableTest.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.tablebuilder; 2 | 3 | import org.junit.Before; 4 | import org.junit.Test; 5 | 6 | import static org.junit.Assert.assertEquals; 7 | 8 | public class CreateTableTest { 9 | 10 | @Before 11 | public void setUp() throws Exception { 12 | } 13 | 14 | @Test 15 | public void testCreateTable() throws Exception { 16 | 17 | CreateTable table = TableBuilder.create("test_keyspace", "test_table") 18 | .ifNotExists() 19 | .column("col1", "text") 20 | .column("col2", "int") 21 | .staticColumn("col3", "blob") 22 | .primaryKeys("col1", "col2"); 23 | 24 | String cql = table.getQueryString(); 25 | assertEquals("CREATE TABLE IF NOT EXISTS test_keyspace.test_table (col1 text, col2 int, col3 blob STATIC, PRIMARY KEY(col1, col2))", cql); 26 | 27 | } 28 | 29 | @Test 30 | public void testCreateTable_Composite_Partition_Key() throws Exception { 31 | 32 | CreateTable table = TableBuilder.create("test_keyspace", "test_table") 33 | .column("col1", "text") 34 | .column("col2", "int") 35 | .column("col3", "blob") 36 | .column("col4", "uuid") 37 | .primaryKey("col1", PrimaryKeyType.PARTITIONING) 38 | .primaryKey("col2", PrimaryKeyType.PARTITIONING) 39 | .primaryKey("col3", PrimaryKeyType.CLUSTERING) 40 | .primaryKey("col4"); 41 | 42 | String cql = table.getQueryString(); 43 | assertEquals("CREATE TABLE test_keyspace.test_table (col1 text, col2 int, col3 blob, col4 uuid, PRIMARY KEY((col1, col2), col3, col4))", cql); 44 | 45 | } 46 | 47 | @Test 48 | public void testColumns() throws Exception { 49 | 50 | CreateTable table = TableBuilder.create("test_keyspace", "test_table") 51 | .columns(new String[]{"col1", "col2", "col3"}, new String[]{"text", "int", "blob"}) 52 | .column("col4", "text") 53 | .column("col3", "text") 54 | .column("col1", "int") 55 | .primaryKey("col1"); 56 | 57 | String cql = table.getQueryString(); 58 | assertEquals("CREATE TABLE test_keyspace.test_table (col1 int, col2 int, col3 text, col4 text, PRIMARY KEY(col1))", cql); 59 | 60 | } 61 | 62 | } -------------------------------------------------------------------------------- /vertx-cassandra/src/test/java/com/englishtown/vertx/cassandra/tablebuilder/DropTableTest.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.tablebuilder; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertEquals; 6 | 7 | public class DropTableTest { 8 | 9 | @Test 10 | public void testDropTable() throws Exception { 11 | 12 | DropTable table = TableBuilder.drop("test_keyspace", "test_table"); 13 | 14 | String cql = table.getQueryString(); 15 | assertEquals("DROP TABLE test_keyspace.test_table", cql); 16 | 17 | } 18 | 19 | @Test 20 | public void testIfExists() throws Exception { 21 | 22 | DropTable table = TableBuilder.drop("test_keyspace", "test_table").ifExists(); 23 | 24 | String cql = table.getQueryString(); 25 | assertEquals("DROP TABLE IF EXISTS test_keyspace.test_table", cql); 26 | 27 | } 28 | 29 | } -------------------------------------------------------------------------------- /vertx-cassandra/src/test/java/com/englishtown/vertx/cassandra/tablebuilder/TableBuilderTest.java: -------------------------------------------------------------------------------- 1 | package com.englishtown.vertx.cassandra.tablebuilder; 2 | 3 | import com.datastax.driver.core.AbstractTableMetadata; 4 | import com.datastax.driver.core.ColumnMetadata; 5 | import com.datastax.driver.core.DataType; 6 | import org.junit.Before; 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | import org.mockito.Mock; 10 | import org.mockito.runners.MockitoJUnitRunner; 11 | 12 | import java.util.HashMap; 13 | import java.util.List; 14 | import java.util.Map; 15 | 16 | import static org.junit.Assert.assertEquals; 17 | import static org.mockito.Mockito.when; 18 | 19 | @RunWith(MockitoJUnitRunner.class) 20 | public class TableBuilderTest { 21 | 22 | private TestTableMetadata existing; 23 | @Mock 24 | private ColumnMetadata col1; 25 | @Mock 26 | private ColumnMetadata col2; 27 | 28 | @Before 29 | public void setUp() throws Exception { 30 | 31 | existing = new TestTableMetadata(); 32 | existing.getColumnMap().put("col1", col1); 33 | existing.getColumnMap().put("col2", col2); 34 | 35 | when(col1.getType()).thenReturn(DataType.text()); 36 | when(col2.getType()).thenReturn(DataType.cint()); 37 | 38 | } 39 | 40 | @Test 41 | public void testAlter() throws Exception { 42 | 43 | CreateTable desired = TableBuilder.create("test_keyspace", "test_table") 44 | .column("col1", "text") 45 | .column("col2", "bigint") 46 | .column("col3", "int") 47 | .column("col4", "text") 48 | .primaryKey("col1"); 49 | 50 | List statements = TableBuilder.alter(existing, desired); 51 | 52 | assertEquals(3, statements.size()); 53 | assertEquals("ALTER TABLE test_keyspace.test_table ALTER col2 TYPE bigint", statements.get(0).toString()); 54 | assertEquals("ALTER TABLE test_keyspace.test_table ADD col3 int", statements.get(1).toString()); 55 | assertEquals("ALTER TABLE test_keyspace.test_table ADD col4 text", statements.get(2).toString()); 56 | 57 | } 58 | 59 | private static class TestTableMetadata extends AbstractTableMetadata { 60 | 61 | public TestTableMetadata() { 62 | super(null, null, null, null, null, new HashMap<>(), null, null, null); 63 | } 64 | 65 | @Override 66 | protected String asCQLQuery(boolean formatted) { 67 | throw new UnsupportedOperationException(); 68 | } 69 | 70 | public Map getColumnMap() { 71 | return columns; 72 | } 73 | } 74 | } -------------------------------------------------------------------------------- /vertx-cassandra/src/test/resources/test_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "cassandra": { 3 | "seeds": [${test.cassandra.seeds}], 4 | "port": ${test.cassandra.port}, 5 | "auth": { 6 | "username": "cassandra", 7 | "password": "cassandra" 8 | } 9 | } 10 | } --------------------------------------------------------------------------------