Skip to content

Camel component for Apache Cassandra using Datastax java driver

Notifications You must be signed in to change notification settings

oscerd/camel-cassandra

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 

Repository files navigation

Maven Central License

Cassandra Component

Introduction

This component use the Apache Cassandra Datastax Java driver: http://docs.datastax.com/en/drivers/java/3.7/

Apache Cassandra is an open source distributed database management system designed to handle large amounts of data across many commodity servers, providing high availability with no single point of failure. Cassandra offers robust support for clusters spanning multiple datacenters, with asynchronous masterless replication allowing low latency operations for all clients.

The camel-cassandra component integrates Camel with Cassandra allowing you to interact with Cassandra keyspace both as a producer (performing operations on the keyspace tables) and as a consumer (consuming rows from keyspace tables).

Usage

Maven users will need to add the following dependency to their pom.xml for this component:

<dependency>
    <groupId>com.github.oscerd</groupId>
    <artifactId>camel-cassandra</artifactId>
    <version>3.0.0</version>
</dependency>

The latest release uses camel-core version 3.0.0 as dependency.

Use this component on Apache Karaf

Camel-Cassandra component is based on camel-core 3.0.0 release.

  • Inside Karaf execute the following instructions:
karaf@root> features:repo-add mvn:com.github.oscerd/camel-cassandra/3.0.0/xml/features

  • Install camel-cassandra feature
karaf@root> feature:install camel-cassandra

Now we are ready to deploy bundle based on camel-cassandra component. See Code Examples section for a ready bundle to use.

URI format


cassandra:name[?options]

Options

Cassandra endpoints support the following options, depending on whether they are acting like a Producer or as a Consumer.

Option Default Description Producer Consumer
host null The hosts of the Cassandra Instance, separated by comma x
port null The port exposing the Cassandra Instance x x
keyspace null The keyspace to work on with the component x x
table null The table to work on with the component x
operation null The operation to do (operations are listed in the following of this document) x
pollingQuery null The query to submit when using the component as consumer x
format normalResultSet The format of resultSet (values normalResultSet or rowsList) x
username null The username to connect to a Cassandra Cluster using Authentication/Authorization x x
password null The password to connect to a Cassandra Cluster using Authentication/Authorization x x
bean:clusterRef null Provided cluster reference x

If you need to interact with a Cassandra instance as producer you'll need to set some headers in the message. This solution was developed to make the interested camel route more readable and to create a cluster connection and a working session each time you'll use the component as producer in the route. This approach is a good solution to take advantage of flexibility and functionalities of the Cassandra Datastax Java Driver. Let's list those Headers.

Camel-Cassandra component provides fifteen headers by which you can define a different behaviour. We will talk about plain query in the following of this documentation.

Header Type Description
CassandraConstants.CASSANDRA_CONTACT_POINTS List of String A contact points list to connect to the different Cassandra instances
CassandraConstants.CASSANDRA_PORT String The (same) port where the different Cassandra Instances are exposed
CassandraConstants.CASSANDRA_OPERATION_HEADER String The operation to do on the keyspace and table of Cassandra instances
CassandraConstants.CASSANDRA_SELECT_COLUMN String If you need to select a specific column in a query, define this header
CassandraConstants.CASSANDRA_DELETE_COLUMN String If you need to delete on a specific column in a query, define this header
CassandraConstants.CASSANDRA_WHERE_COLUMN String If you need to specify a where clause, define the interested column in this header
CassandraConstants.CASSANDRA_WHERE_VALUE Object Define the value of the interested where column in this header
CassandraConstants.CASSANDRA_OPERATOR String Define the operator to work with on a clause (eq, in, lt, lte etc.)
CassandraConstants.CASSANDRA_ORDERBY_COLUMN String If you need to specify an order by clause, define the interested column in this header
CassandraConstants.CASSANDRA_ORDER_DIRECTION String Define the direction of the order by column in this header (asc or desc)
CassandraConstants.CASSANDRA_UPDATE_OBJECT HashMap of String, Object Define an updating object to use
CassandraConstants.CASSANDRA_INSERT_OBJECT HashMap of String, Object Define an inserting object to use
CassandraConstants.CASSANDRA_COUNTER_COLUMN String Define the name of a counter column you need to increment or decrement
CassandraConstants.CASSANDRA_COUNTER_VALUE String Define the incrementing or decrementing value of a counter column specified
CassandraConstants.CASSANDRA_BATCH_QUERY String A query to use in a batch operation
CassandraConstants.CASSANDRA_BATCH_QUERY_LIST List of Object[] The object arrays to use in the batch query
CassandraConstants.CASSANDRA_LIMIT_NUMBER Integer Limit the number of rows returned by a query
CassandraConstants.CASSANDRA_INDEX_NAME String An index name
CassandraConstants.CASSANDRA_INDEX_COLUMN String A column to associate an index with

If you need to execute a complex query you can set the body of your message with the plain query and execute a plain query operation.

Operations

Here we list the possible operation to specify in the operation parameter of the URI.

  • selectAll: A select all operation on a table of a keyspace
  • selectAllWhere: A select all operation with a where clause on a table of a keyspace
  • selectColumn: A select for a specific column on a table of a keyspace
  • selectColumnWhere: A select for a specific column with a where clause on a table of a keyspace
  • update: An update
  • insert: An insert
  • deleteColumnWhere: A delete for a specific column with a where clause on a table of a keyspace
  • deleteWhere: A delete with a where clause
  • incrCounter: An increment of a counter
  • decrCounter: A decrement of a counter
  • batchOperation: A batch operation
  • createIndex: A create index operation
  • dropIndex: A drop index operation

Operators

Here we list the possible operator to specify in CASSANDRA_OPERATOR header of a message.

  • eq: equal
  • lt: less than
  • lte: less than or equal
  • gt: greater than
  • gte: greater than or equal
  • in: in
  • asc: ascending
  • desc: descending

Examples

  • Consumer

Example of camel-cassandra used as Consumer:

from("cassandra:cluster?host=127.0.0.1&port=9042&keyspace=simplex&pollingQuery=select * from songs")
    .to("mock:result");

This route will poll a Cassandra instances running on 127.0.0.1 on port 9042. The keyspace will be simplex and the polling query select * from songs . The result will be a Datastax Java Driver result set.

  • Producer

Examples of camel-cassandra used as Producer:

Example 1: Select All

String addr = "127.0.0.1";
List<String> collAddr = new ArrayList<String>();
collAddr.add(addr);
    
from("direct:in")
    .setHeader(CassandraConstants.CASSANDRA_CONTACT_POINTS, constant(collAddr))
    .to("cassandra:cassandraConnection?keyspace=simplex&table=songs&operation=selectAll")
    .to("mock:result");

This route will connect to the cassandra instance running on 127.0.0.1 and port 9042, and will query all rows on the keyspace simplex and table songs.

Example 2: Select All with Where Clause

String addr = "127.0.0.1";
List<String> collAddr = new ArrayList<String>();
collAddr.add(addr);
    
from("direct:in")
    .setHeader(CassandraConstants.CASSANDRA_CONTACT_POINTS, constant(collAddr))
    .setHeader(CassandraConstants.CASSANDRA_WHERE_COLUMN, constant("album"))
    .setHeader(CassandraConstants.CASSANDRA_WHERE_VALUE, constant("The gathering"))
    .setHeader(CassandraConstants.CASSANDRA_OPERATOR, constant("eq"))
    .to("cassandra:cassandraConnection?keyspace=simplex&table=songs&operation=selectAllWhere")
    .to("mock:result");

This route will connect to the cassandra instance running on 127.0.0.1 and port 9042, and will query all rows on the keyspace simplex and table songs where the column album is equal to "The gathering". Obviously we need to ensure index on the column album to make this query works.

Example 3: Select column

String addr = "127.0.0.1";
List<String> collAddr = new ArrayList<String>();
collAddr.add(addr);
    
from("direct:in")
    .setHeader(CassandraConstants.CASSANDRA_CONTACT_POINTS, constant(collAddr))
    .setHeader(CassandraConstants.CASSANDRA_SELECT_COLUMN, constant("title"))
    .to("cassandra:cassandraConnection?keyspace=simplex&table=songs&operation=selectColumn")
    .to("mock:result");

This route will connect to the cassandra instance running on 127.0.0.1 and port 9042, and will query for title column on all the rows on the keyspace simplex and table songs.

Example 4: Select specific column with Where Clause

String addr = "127.0.0.1";
List<String> collAddr = new ArrayList<String>();
collAddr.add(addr);
    
from("direct:in")
    .setHeader(CassandraConstants.CASSANDRA_CONTACT_POINTS, constant(collAddr))
    .setHeader(CassandraConstants.CASSANDRA_WHERE_COLUMN, constant("album"))
    .setHeader(CassandraConstants.CASSANDRA_WHERE_VALUE, constant("The gathering"))
    .setHeader(CassandraConstants.CASSANDRA_SELECT_COLUMN, constant("title"))
    .setHeader(CassandraConstants.CASSANDRA_OPERATOR, constant("eq"))
    .to("cassandra:cassandraConnection?keyspace=simplex&table=songs&operation=selectColumnWhere")
    .to("mock:result");

This route will connect to the cassandra instance running on 127.0.0.1 and port 9042, and will query for title column on all the rows on the keyspace simplex and table songs, where the album column is equal to "The gathering". Obviously we need to ensure index on the columns album and title to make this query works.

Example 5: Insert object

String addr = "127.0.0.1";
List<String> collAddr = new ArrayList<String>();
collAddr.add(addr);

Set<String> tags = new HashSet<String>();
tags.add("2003");
tags.add("Trash");
HashMap<String, Object> insert = new HashMap<String, Object>();
insert.put("id", 6);
insert.put("album", "St. Anger");
insert.put("title", "St. Anger");
insert.put("artist", "Metallica");
insert.put("tags", tags);
    
from("direct:in")
    .setHeader(CassandraConstants.CASSANDRA_CONTACT_POINTS, constant(collAddr))
    .setHeader(CassandraConstants.CASSANDRA_INSERT_OBJECT, constant(insert))
    .to("cassandra:cassandraConnection?keyspace=simplex&table=songs&operation=insert")
    .to("mock:result");

This route will connect to the cassandra instance running on 127.0.0.1 and port 9042, and will insert a song into the songs table of simplex keyspace.

Example 6: Update with Where clause

String addr = "127.0.0.1";
List<String> collAddr = new ArrayList<String>();
collAddr.add(addr);

HashMap<String, Object> updatingObject = new HashMap<String, Object>();
updatingObject.put("album", "Low");
updatingObject.put("title", "Low");
    
from("direct:in")
    .setHeader(CassandraConstants.CASSANDRA_CONTACT_POINTS, constant(collAddr))
    .setHeader(CassandraConstants.CASSANDRA_WHERE_COLUMN, constant("id"))
    .setHeader(CassandraConstants.CASSANDRA_WHERE_VALUE, constant(1))
    .setHeader(CassandraConstants.CASSANDRA_OPERATOR, constant("eq"))
    .setHeader(CassandraConstants.CASSANDRA_UPDATE_OBJECT, constant(updatingObject))
    .to("cassandra:simplex?keyspace=simplex&table=songs&operation=update")
    .to("mock:result");

This route will connect to the cassandra instance running on 127.0.0.1 and port 9042, and will update the song with id equal to 1 into the songs table of simplex keyspace, changing the album and title columns.

Example 7: Delete with Where clause

String addr = "127.0.0.1";
List<String> collAddr = new ArrayList<String>();
collAddr.add(addr);
    
from("direct:in")
    .setHeader(CassandraConstants.CASSANDRA_CONTACT_POINTS, constant(collAddr))
    .setHeader(CassandraConstants.CASSANDRA_WHERE_COLUMN, constant("id"))
    .setHeader(CassandraConstants.CASSANDRA_WHERE_VALUE, constant(6))
    .setHeader(CassandraConstants.CASSANDRA_OPERATOR, constant("eq"))
    .to("cassandra:cassandraConnection?keyspace=simplex&table=songs&operation=deleteWhere")
    .to("mock:result");

This route will connect to the cassandra instance running on 127.0.0.1 and port 9042, and will delete the song with id equal to 6 into the songs table of simplex keyspace.

Example 8: Delete Column with Where clause

String addr = "127.0.0.1";
List<String> collAddr = new ArrayList<String>();
collAddr.add(addr);
    
from("direct:in")
    .setHeader(CassandraConstants.CASSANDRA_CONTACT_POINTS, constant(collAddr))
    .setHeader(CassandraConstants.CASSANDRA_WHERE_COLUMN, constant("id"))
    .setHeader(CassandraConstants.CASSANDRA_WHERE_VALUE, constant(6))
    .setHeader(CassandraConstants.CASSANDRA_OPERATOR, constant("eq"))
    .setHeader(CassandraConstants.CASSANDRA_DELETE_COLUMN, constant("tags"))
    .to("cassandra:cassandraConnection?keyspace=simplex&table=songs&operation=deleteColumnWhere")
    .to("mock:result");

This route will connect to the cassandra instance running on 127.0.0.1 and port 9042, and will delete the column tags of the song with id equal to 6 into the songs table of simplex keyspace.

Example 9: Increment a counter column

String addr = "127.0.0.1";
List<String> collAddr = new ArrayList<String>();
collAddr.add(addr);
    
from("direct:in")
    .setHeader(CassandraConstants.CASSANDRA_CONTACT_POINTS, constant(collAddr))
    .setHeader(CassandraConstants.CASSANDRA_WHERE_COLUMN, constant("id"))
    .setHeader(CassandraConstants.CASSANDRA_WHERE_VALUE, constant(1))
    .setHeader(CassandraConstants.CASSANDRA_OPERATOR, constant("eq"))
    .setHeader(CassandraConstants.CASSANDRA_COUNTER_COLUMN, constant("like"))
    .setHeader(CassandraConstants.CASSANDRA_COUNTER_VALUE, constant(new Long(5)))
    .to("cassandra:cassandraConnection?keyspace=simplex&table=counter&operation=incrCounter")
    .to("mock:result");

This route will connect to the cassandra instance running on 127.0.0.1 and port 9042, and will increment of 5 units the like counter of the song with id equal to 1, into the songs table of simplex keyspace.

Example 10: Decrement a counter column

String addr = "127.0.0.1";
List<String> collAddr = new ArrayList<String>();
collAddr.add(addr);
    
from("direct:in")
    .setHeader(CassandraConstants.CASSANDRA_CONTACT_POINTS, constant(collAddr))
    .setHeader(CassandraConstants.CASSANDRA_WHERE_COLUMN, constant("id"))
    .setHeader(CassandraConstants.CASSANDRA_WHERE_VALUE, constant(1))
    .setHeader(CassandraConstants.CASSANDRA_OPERATOR, constant("eq"))
    .setHeader(CassandraConstants.CASSANDRA_COUNTER_COLUMN, constant("like"))
    .setHeader(CassandraConstants.CASSANDRA_COUNTER_VALUE, constant(new Long(5)))
    .to("cassandra:cassandraConnection?keyspace=simplex&table=counter&operation=decrCounter")
    .to("mock:result");

This route will connect to the cassandra instance running on 127.0.0.1 and port 9042, and will decrement of 5 units the like counter of the song with id equal to 1, into the songs table of simplex keyspace.

Example 11: Plain query

String addr = "127.0.0.1";
List<String> collAddr = new ArrayList<String>();
collAddr.add(addr);
    
from("direct:in")
    .setHeader(CassandraConstants.CASSANDRA_CONTACT_POINTS, constant(collAddr))
    .setBody(constant("SELECT id, album, title FROM songs"))
    .to("cassandra:cassandraConnection?keyspace=simplex")
    .to("mock:result");

This route will connect to the cassandra instance running on 127.0.0.1 and port 9042, and will submit the plain query SELECT id, album, title FROM songs

Example 12: Batch Insert

String addr = "127.0.0.1";
List<String> collAddr = new ArrayList<String>();
collAddr.add(addr);

List<Object[]> objectArrayList = new ArrayList<Object[]>();
Object[] object = {7, "Fight Fire with Fire", "Ride the Lightning", "Metallica"};
Object[] object1 = {8, "Ride the Lightning", "Ride the Lightning", "Metallica"};
Object[] object2 = {9, "For Whom the Bell Tolls", "Ride the Lightning", "Metallica"};
Object[] object3 = {10, "Fade To Black", "Ride the Lightning", "Metallica"};
Object[] object4 = {11, "Trapped Under Ice", "Ride the Lightning", "Metallica"};
Object[] object5 = {12, "Escape", "Ride the Lightning", "Metallica"};
Object[] object6 = {13, "Creeping Death", "Ride the Lightning", "Metallica"};
Object[] object7 = {14, "The Call of Ktulu", "Ride the Lightning", "Metallica"};
objectArrayList.add(object);
objectArrayList.add(object1);
objectArrayList.add(object2);
objectArrayList.add(object3);
objectArrayList.add(object4);
objectArrayList.add(object5);
objectArrayList.add(object6);
objectArrayList.add(object7);
    
from("direct:in")
    .setHeader(CassandraConstants.CASSANDRA_CONTACT_POINTS, constant(collAddr))
    .setHeader(CassandraConstants.CASSANDRA_BATCH_QUERY, constant("INSERT INTO songs (id, title, album, artist) VALUES (?, ?, ?, ?);"))
    .setHeader(CassandraConstants.CASSANDRA_BATCH_QUERY_LIST, constant(objectArrayList))
    .to("cassandra:cassandraConnection?keyspace=simplex&table=songs&operation=batchOperation")
    .to("mock:result");

Example 13: Select with Where Clause, Order by Clause and Limit clause

String addr = "127.0.0.1";
List<String> collAddr = new ArrayList<String>();
collAddr.add(addr);
    
from("direct:in")
    .setHeader(CassandraConstants.CASSANDRA_CONTACT_POINTS, constant(collAddr))
    .setHeader(CassandraConstants.CASSANDRA_WHERE_COLUMN, constant("id"))
    .setHeader(CassandraConstants.CASSANDRA_WHERE_VALUE, constant(UUID.fromString("62c36092-82a1-3a00-93d1-46196ee77204")))
    .setHeader(CassandraConstants.CASSANDRA_OPERATOR, constant("eq"))
    .setHeader(CassandraConstants.CASSANDRA_ORDERBY_COLUMN, constant("song_order"))
    .setHeader(CassandraConstants.CASSANDRA_ORDER_DIRECTION, constant("desc"))
    .setHeader(CassandraConstants.CASSANDRA_LIMIT_NUMBER, constant(2))
    .to("cassandra:cassandraConnection?keyspace=simplex&table=songs&operation=batchInsert")
    .to("mock:result");

This route will connect to the cassandra instance running on 127.0.0.1 and port 9042, and will query for a specific song with id 62c36092-82a1-3a00-93d1-46196ee77204, order the result for column "song_order" and limit the result to 2 rows.

Example 14: Using a Cluster reference

String addr = "127.0.0.1";
List<String> collAddr = new ArrayList<String>();
collAddr.add(addr);

Cluster cluster = Cluster.builder().addContactPoint("localhost").build();
JndiRegistry reg = getContext().getRegistry();
registry.bind("cassandraConnection", cluster);
    
from("direct:in")
    .setHeader(CassandraConstants.CASSANDRA_CONTACT_POINTS, constant(collAddr))
    .to("cassandra:bean:cassandraConnection?keyspace=simplex&table=songs&operation=selectAll")
    .to("mock:result");

Example 15: Multiple Batch Operation

String addr = "127.0.0.1";
List<String> collAddr = new ArrayList<String>();
collAddr.add(addr);

final List<Object[]> objectArrayListInsert = new ArrayList<Object[]>();
Object[] object = {7, "Fight Fire with Fire", "Ride the Lightning", "Metallica"};
Object[] object1 = {8, "Ride the Lightning", "Ride the Lightning", "Metallica"};
Object[] object2 = {9, "For Whom the Bell Tolls", "Ride the Lightning", "Metallica"};
Object[] object3 = {10, "Fade To Black", "Ride the Lightning", "Metallica"};
Object[] object4 = {11, "Trapped Under Ice", "Ride the Lightning", "Metallica"};
Object[] object5 = {12, "Escape", "Ride the Lightning", "Metallica"};
Object[] object6 = {13, "Creeping Death", "Ride the Lightning", "Metallica"};
Object[] object7 = {14, "The Call of Ktulu", "Ride the Lightning", "Metallica"};
objectArrayListInsert.add(object);
objectArrayListInsert.add(object1);
objectArrayListInsert.add(object2);
objectArrayListInsert.add(object3);
objectArrayListInsert.add(object4);
objectArrayListInsert.add(object5);
objectArrayListInsert.add(object6);
objectArrayListInsert.add(object7);
        
final String insertBatch = "INSERT INTO songs (id, title, album, artist) VALUES (?, ?, ?, ?);";
        
final List<Object[]> objectArrayListUpdate = new ArrayList<Object[]>();
Object[] object8 = {"Wings for Marie", "10000 days", "Tool", 1};
Object[] object9 = {"10000 days", "10000 days", "Tool", 2};
Object[] object10 = {"Vicarious", "10000 days", "Tool", 3};
objectArrayListUpdate.add(object8);
objectArrayListUpdate.add(object9);
objectArrayListUpdate.add(object10);
        
final String updateBatch = "UPDATE songs SET title = ?, album = ?, artist = ? where id = ?;";
        
final List<Object[]> objectArrayListDelete = new ArrayList<Object[]>();
Object[] object11 = {1};
objectArrayListDelete.add(object11);
        
final String deleteBatch =  "DELETE FROM songs where id = ?";
    
from("direct:in")
    .setHeader(CassandraConstants.CASSANDRA_CONTACT_POINTS, constant(collAddr))
    .setHeader(CassandraConstants.CASSANDRA_BATCH_QUERY, constant(insertBatch))
    .setHeader(CassandraConstants.CASSANDRA_BATCH_QUERY_LIST, constant(objectArrayListInsert))
    .to("cassandra:cassandraConnection?keyspace=simplex&table=songs&operation=batchOperation")
    .setBody(constant(""))
    .setHeader(CassandraConstants.CASSANDRA_BATCH_QUERY, constant(updateBatch))
    .setHeader(CassandraConstants.CASSANDRA_BATCH_QUERY_LIST, constant(objectArrayListUpdate))
    .to("cassandra:cassandraConnection?keyspace=simplex&table=songs&operation=batchOperation")
    .setBody(constant(""))
    .setHeader(CassandraConstants.CASSANDRA_BATCH_QUERY, constant(deleteBatch))
    .setHeader(CassandraConstants.CASSANDRA_BATCH_QUERY_LIST, constant(objectArrayListDelete))
    .to("cassandra:cassandraConnection?keyspace=simplex&table=songs&operation=batchOperation")
    .to("mock:result");

Example 16: Creating an index

String addr = "127.0.0.1";
List<String> collAddr = new ArrayList<String>();
collAddr.add(addr);

Cluster cluster = Cluster.builder().addContactPoint("localhost").build();
JndiRegistry reg = getContext().getRegistry();
registry.bind("cassandraConnection", cluster);
    
from("direct:in")
    .setHeader(CassandraConstants.CASSANDRA_CONTACT_POINTS, constant(collAddr))
    .setHeader(CassandraConstants.CASSANDRA_INDEX_COLUMN, constant("artist"))
    .setHeader(CassandraConstants.CASSANDRA_INDEX_NAME, constant("artist_idx"))
    .to("cassandra:bean:cassandraConnection?keyspace=simplex&table=songs&operation=createIndex")
    .to("mock:result");

This route will connect to the cassandra instance running on 127.0.0.1 and port 9042, and will create an index named artist_idx on the column artist on table songs of keyspace simplex

Example 17: Dropping an index

String addr = "127.0.0.1";
List<String> collAddr = new ArrayList<String>();
collAddr.add(addr);

Cluster cluster = Cluster.builder().addContactPoint("localhost").build();
JndiRegistry reg = getContext().getRegistry();
registry.bind("cassandraConnection", cluster);
    
from("direct:in")
    .setHeader(CassandraConstants.CASSANDRA_CONTACT_POINTS, constant(collAddr))
    .setHeader(CassandraConstants.CASSANDRA_INDEX_NAME, constant("artist_idx"))
    .to("cassandra:bean:cassandraConnection?keyspace=simplex&table=songs&operation=dropIndex")
    .to("mock:result");

This route will connect to the cassandra instance running on 127.0.0.1 and port 9042, and will drop an index named artist_idx on table songs of keyspace simplex

Code Examples

ToDo List

  • Add support for username/password authentication to cassandra producer [x]
  • Add support for username/password authentication to cassandra consumer [x]
  • Add limit parameter as header [x]
  • Add support for Cluster bean reference in Cassandra Producer [x]
  • Improve testing [x]
  • Define a ResultSet transform parameter in Cassandra Producer [x]
  • Add createIndex/dropIndex operation [x]

About

Camel component for Apache Cassandra using Datastax java driver

Resources

Stars

Watchers

Forks

Packages

 
 
 

Languages