You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by dm...@apache.org on 2020/09/30 23:44:20 UTC
[ignite] branch IGNITE-7595 updated: Ported the Cassandra
integration's documentation from readme.io to the new docs engine
This is an automated email from the ASF dual-hosted git repository.
dmagda pushed a commit to branch IGNITE-7595
in repository https://gitbox.apache.org/repos/asf/ignite.git
The following commit(s) were added to refs/heads/IGNITE-7595 by this push:
new 0cb8389 Ported the Cassandra integration's documentation from readme.io to the new docs engine
new fdef11c Merge remote-tracking branch 'origin/IGNITE-7595' into IGNITE-7595
0cb8389 is described below
commit 0cb83898200e81c05fd6e90fb2b82473df3aba61
Author: Denis Magda <dm...@gridgain.com>
AuthorDate: Wed Sep 30 16:39:41 2020 -0700
Ported the Cassandra integration's documentation from readme.io to the new docs engine
---
docs/_data/toc.yaml | 10 +
.../cassandra/configuration.adoc | 574 +++++++++++++++++
.../cassandra/ddl-generator.adoc | 85 +++
.../cassandra/overview.adoc | 40 ++
.../cassandra/usage-examples.adoc | 677 +++++++++++++++++++++
docs/_docs/persistence/external-storage.adoc | 10 +-
6 files changed, 1391 insertions(+), 5 deletions(-)
diff --git a/docs/_data/toc.yaml b/docs/_data/toc.yaml
index c68e4e8..6bd41f0 100644
--- a/docs/_data/toc.yaml
+++ b/docs/_data/toc.yaml
@@ -421,6 +421,16 @@
url: extensions-and-integrations/streaming/zeromq-streamer
- title: Twitter Streamer
url: extensions-and-integrations/streaming/twitter-streamer
+ - title: Cassandra Integration
+ items:
+ - title: Overview
+ url: extensions-and-integrations/cassandra/overview
+ - title: Configuration
+ url: extensions-and-integrations/cassandra/configuration
+ - title: Usage Examples
+ url: extensions-and-integrations/cassandra/usage-examples
+ - title: DDL Generator
+ url: extensions-and-integrations/cassandra/ddl-generator
- title: C# and .NET Specific
items:
- title: Configuration Options
diff --git a/docs/_docs/extensions-and-integrations/cassandra/configuration.adoc b/docs/_docs/extensions-and-integrations/cassandra/configuration.adoc
new file mode 100644
index 0000000..d35d32d
--- /dev/null
+++ b/docs/_docs/extensions-and-integrations/cassandra/configuration.adoc
@@ -0,0 +1,574 @@
+= Ignite Cassandra Integration Configuration
+
+= Overview
+
+To setup Cassandra as a persistent store, you need to set `CacheStoreFactory` for your Ignite caches to
+`org.apache.ignite.cache.store.cassandra.CassandraCacheStoreFactory`.
+
+This could be done using Spring context configuration like this:
+
+[tabs]
+--
+tab:XML[]
+[source, xml]
+----
+<bean id="ignite.cfg" class="org.apache.ignite.configuration.IgniteConfiguration">
+ <property name="cacheConfiguration">
+ <list>
+ ...
+ <!-- Configuring persistence for "cache1" cache -->
+ <bean class="org.apache.ignite.configuration.CacheConfiguration">
+ <property name="name" value="cache1"/>
+ <!-- Tune on Read-Through and Write-Through mode -->
+ <property name="readThrough" value="true"/>
+ <property name="writeThrough" value="true"/>
+ <!-- Specifying CacheStoreFactory -->
+ <property name="cacheStoreFactory">
+ <bean class="org.apache.ignite.cache.store.cassandra.CassandraCacheStoreFactory">
+ <!-- Datasource configuration bean which is responsible for Cassandra connection details -->
+ <property name="dataSourceBean" value="cassandraDataSource"/>
+ <!-- Persistent settings bean which is responsible for the details of how objects will be persisted to Cassandra -->
+ <property name="persistenceSettingsBean" value="cache1_persistence_settings"/>
+ </bean>
+ </property>
+ </bean>
+ ...
+ </list>
+ ...
+ </property>
+</bean>
+----
+--
+
+There are two main properties which should be specified for `CassandraCacheStoreFactory`:
+
+* `dataSourceBean` - instance of the `org.apache.ignite.cache.store.cassandra.datasource.DataSource` class responsible for
+all the aspects of Cassandra database connection (credentials, contact points, read/write consistency level, load balancing policy and etc...)
+* `persistenceSettingsBean` - instance of the `org.apache.ignite.cache.store.cassandra.persistence.KeyValuePersistenceSettings`
+class responsible for all the aspects of how objects should be persisted into Cassandra (keyspace and its options, table
+and its options, partition and cluster key options, POJO object fields mapping, secondary indexes, serializer for BLOB objects and etc...)
+
+In the below section these two beans and their configuration settings will be described in details.
+
+== DataSourceBean
+
+This bean stores all the details required for Cassandra database connection and CRUD operations. In the table below you can find all the bean properties:
+
+[cols="20%,70%,10%",opts="header"]
+|===
+| Property | Description | Default
+| `user`| User name used to connect to Cassandra|
+| `password`| User password used to connect to Cassandra|
+| `credentials`| Credentials bean providing `username` and `password`|
+| `authProvider`| Use the specified AuthProvider when connecting to Cassandra. Use this method when a custom authentication scheme is in place.|
+| `port`| Port to use to connect to Cassandra (if it's not provided in connection point specification)|
+| `contactPoints`| Array of contact points (`hostaname:[port]`) to use for Cassandra connection|
+| `maxSchemaAgreementWaitSeconds`| Maximum time to wait for schema agreement before returning from a DDL query| `10` seconds
+| `protocolVersion`| Specifies what version of Cassandra driver protocol should be used (could be helpful for backward compatibility with old versions of Cassandra)| `3`
+| `compression`| Compression to use for the transport. Supported compressions: `snappy`, `lz4`|
+| `useSSL`| Enables the use of SSL| `false`
+| `sslOptions`| Enables the use of SSL using the provided options|`false`
+| `collectMetrix`| Enables metrics collection|`false`
+| `jmxReporting`| Enables JMX reporting of the metrics|`false`
+| `fetchSize`| Specifies query fetch size. Fetch size controls how much resulting rows will be retrieved simultaneously.|
+| `readConsistency`| Specifies consistency level for READ queries|
+| `writeConsistency`| Specifies consistency level for WRITE/DELETE/UPDATE queries|
+| `loadBalancingPolicy`| Specifies load balancing policy to use| `TokenAwarePolicy`
+| `reconnectionPolicy`| Specifies reconnection policy to use| `ExponentialReconnectionPolicy`
+| `retryPolicy`| Specifies retry policy to use| `DefaultRetryPolicy`
+| `addressTranslater`| Specifies address translater to use| `IdentityTranslater`
+| `speculativeExecutionPolicy`| Specifies speculative execution policy to use| `NoSpeculativeExecutionPolicy`
+| `poolingOptions`| Specifies connection pooling options|
+| `socketOptions`| Specifies low-level socket options for the connections kept to the Cassandra hosts|
+| `nettyOptions`| Hooks that allow clients to customize Cassandra driver's underlying Netty layer|
+|===
+
+
+== PersistenceSettingsBean
+
+This bean stores all the details(keyspace, table, partition options, POJO fields mapping and etc...) of how objects
+(keys and values) should be persisted into Cassandra database.
+
+The constructor of `org.apache.ignite.cache.store.cassandra.persistence.KeyValuePersistenceSettings` allows to create such
+a bean from a string which contains XML configuration document of specific structure (see below) or from the resource pointing to XML document.
+
+Here is the generic example of an XML configuration document (*persistence descriptor*) which specifies how Ignite cache
+keys and values should be serialized/deserialized to/from Cassandra:
+
+[tabs]
+--
+tab:XML[]
+[source, xml]
+----
+<!--
+Root container for persistence settings configuration.
+
+Note: required element
+
+Attributes:
+ 1) keyspace [required] - specifies keyspace for Cassandra tables which should be used to store key/value pairs
+ 2) table [required] - specifies Cassandra table which should be used to store key/value pairs
+ 3) ttl [optional] - specifies expiration period for the table rows (in seconds)
+-->
+<persistence keyspace="my_keyspace" table="my_table" ttl="86400">
+ <!--
+ Specifies Cassandra keyspace options which should be used to create provided keyspace if it doesn't exist.
+
+ Note: optional element
+ -->
+ <keyspaceOptions>
+ REPLICATION = {'class' : 'SimpleStrategy', 'replication_factor' : 3}
+ AND DURABLE_WRITES = true
+ </keyspaceOptions>
+
+ <!--
+ Specifies Cassandra table options which should be used to create provided table if it doesn't exist.
+
+ Note: optional element
+ -->
+ <tableOptions>
+ comment = 'A most excellent and useful table'
+ AND read_repair_chance = 0.2
+ </tableOptions>
+
+ <!--
+ Specifies persistent settings for Ignite cache keys.
+
+ Note: required element
+
+ Attributes:
+ 1) class [required] - java class name for Ignite cache key
+ 2) strategy [required] - one of three possible persistent strategies:
+ a) PRIMITIVE - stores key value as is, by mapping it to Cassandra table column with corresponding type.
+ Should be used only for simple java types (int, long, String, double, Date) which could be mapped
+ to corresponding Cassadra types.
+ b) BLOB - stores key value as BLOB, by mapping it to Cassandra table column with blob type.
+ Could be used for any java object. Conversion of java object to BLOB is handled by "serializer"
+ which could be specified in serializer attribute (see below).
+ c) POJO - stores each field of an object as a column having corresponding type in Cassandra table.
+ Provides ability to utilize Cassandra secondary indexes for object fields.
+ 3) serializer [optional] - specifies serializer class for BLOB strategy. Shouldn't be used for PRIMITIVE and
+ POJO strategies. Available implementations:
+ a) org.apache.ignite.cache.store.cassandra.serializer.JavaSerializer - uses standard Java
+ serialization framework
+ b) org.apache.ignite.cache.store.cassandra.serializer.KryoSerializer - uses Kryo
+ serialization framework
+ 4) column [optional] - specifies column name for PRIMITIVE and BLOB strategies where to store key value.
+ If not specified column having 'key' name will be used. Shouldn't be used for POJO strategy.
+ -->
+ <keyPersistence class="org.mycompany.MyKeyClass" strategy="..." serializer="..." column="...">
+ <!--
+ Specifies partition key fields if POJO strategy used.
+
+ Note: optional element, only required for POJO strategy in case you want to manually specify
+ POJO fields to Cassandra columns mapping, instead of relying on dynamic discovering of
+ POJO fields and mapping them to the same columns of Cassandra table.
+ -->
+ <partitionKey>
+ <!--
+ Specifies mapping from POJO field to Cassandra table column.
+
+ Note: required element
+
+ Attributes:
+ 1) name [required] - POJO field name
+ 2) column [optional] - Cassandra table column name. If not specified lowercase
+ POJO field name will be used.
+ -->
+ <field name="companyCode" column="company" />
+ ...
+ ...
+ </partitionKey>
+
+ <!--
+ Specifies cluster key fields if POJO strategy used.
+
+ Note: optional element, only required for POJO strategy in case you want to manually specify
+ POJO fields to Cassandra columns mapping, instead of relying on dynamic discovering of
+ POJO fields and mapping them to the same columns of Cassandra table.
+ -->
+ <clusterKey>
+ <!--
+ Specifies mapping from POJO field to Cassandra table column.
+
+ Note: required element
+
+ Attributes:
+ 1) name [required] - POJO field name
+ 2) column [optional] - Cassandra table column name. If not specified lowercase
+ POJO field name will be used.
+ 3) sort [optional] - specifies sort order (asc or desc)
+ -->
+ <field name="personNumber" column="number" sort="desc"/>
+ ...
+ ...
+ </clusterKey>
+ </keyPersistence>
+
+ <!--
+ Specifies persistent settings for Ignite cache values.
+
+ Note: required element
+
+ Attributes:
+ 1) class [required] - java class name for Ignite cache value
+ 2) strategy [required] - one of three possible persistent strategies:
+ a) PRIMITIVE - stores key value as is, by mapping it to Cassandra table column with corresponding type.
+ Should be used only for simple java types (int, long, String, double, Date) which could be mapped
+ to corresponding Cassadra types.
+ b) BLOB - stores key value as BLOB, by mapping it to Cassandra table column with blob type.
+ Could be used for any java object. Conversion of java object to BLOB is handled by "serializer"
+ which could be specified in serializer attribute (see below).
+ c) POJO - stores each field of an object as a column having corresponding type in Cassandra table.
+ Provides ability to utilize Cassandra secondary indexes for object fields.
+ 3) serializer [optional] - specifies serializer class for BLOB strategy. Shouldn't be used for PRIMITIVE and
+ POJO strategies. Available implementations:
+ a) org.apache.ignite.cache.store.cassandra.serializer.JavaSerializer - uses standard Java
+ serialization framework
+ b) org.apache.ignite.cache.store.cassandra.serializer.KryoSerializer - uses Kryo
+ serialization framework
+ 4) column [optional] - specifies column name for PRIMITIVE and BLOB strategies where to store value.
+ If not specified column having 'value' name will be used. Shouldn't be used for POJO strategy.
+ -->
+ <valuePersistence class="org.mycompany.MyValueClass" strategy="..." serializer="..." column="">
+ <!--
+ Specifies mapping from POJO field to Cassandra table column.
+
+ Note: required element
+
+ Attributes:
+ 1) name [required] - POJO field name
+ 2) column [optional] - Cassandra table column name. If not specified lowercase
+ POJO field name will be used.
+ 3) static [optional] - boolean flag which specifies that column is static withing a given partition
+ 4) index [optional] - boolean flag specifying that secondary index should be created for the field
+ 5) indexClass [optional] - custom index java class name if you want to use custom index
+ 6) indexOptions [optional] - custom index options
+ -->
+ <field name="firstName" column="first_name" static="..." index="..." indexClass="..." indexOptions="..."/>
+ ...
+ ...
+ </valuePersistence>
+</persistence>
+----
+--
+
+Below are provided all the details about persistence descriptor configuration and its elements:
+
+=== persistence
+
+[CAUTION]
+====
+[discrete]
+=== ! Required Element
+Root container for persistence settings configuration.
+====
+
+[cols="20%,20%,60%",opts="header"]
+|===
+| Attribute | Required | Description
+| `keyspace`| yes | Keyspace for Cassandra tables which should be used to store key/value pairs. If keyspace doesn't
+exist it will be created (if specified Cassandra account has appropriate permissions).
+| `table`| no | Cassandra table which should be used to store key/value pairs. If table doesn't exist it will be created
+(if specified Cassandra account has appropriate permissions). If table name doesn't specified Ignite cache name will be used as a table name.
+| `ttl`| no | Expiration period for the table rows (in seconds).
+|===
+
+In the next chapters you'll find what child elements could be placed inside persistence settings container.
+
+=== keyspaceOptions
+
+[NOTE]
+====
+[discrete]
+=== Optional Element
+Options to create Cassandra keyspace specified in the `keyspace` attribute of persistence settings container.
+====
+
+Keyspace will be created only if it doesn't exist and if an account used to connect to Cassandra has appropriate permissions.
+
+The text specified in this XML element is just a chunk of
+http://docs.datastax.com/en/cql/3.0/cql/cql_reference/create_keyspace_r.html[CREATE KEYSPACE, window=_blank] Cassandra DDL statement which goes after *WITH* keyword.
+
+=== tableOptions
+
+[NOTE]
+====
+[discrete]
+=== Optional Element
+Options to create Cassandra table specified in the table attribute of persistence settings container.
+====
+
+A table will be created only if it doesn't exist and if an account used to connect to Cassandra has appropriate permissions.
+
+The text specified in this XML element is just a chunk of
+http://docs.datastax.com/en/cql/3.0/cql/cql_reference/create_table_r.html[CREATE TABLE, window=_blank] Cassandra DDL statement which goes after *WITH* keyword.
+
+=== keyPersistence
+
+[CAUTION]
+====
+[discrete]
+=== ! Required Element
+Persistent settings for Ignite cache keys.
+====
+
+These settings specify how key objects from Ignite cache should be stored/loaded to/from Cassandra table:
+
+[cols="20%,20%,60%",opts="header"]
+|===
+| Attribute | Required | Description
+
+| `class`
+| yes
+| Java class name for Ignite cache keys.
+
+| `strategy`
+| yes
+| Specifies one of three possible persistent strategies (see below) which controls how object should be persisted/loaded to/from Cassandra table.
+
+| `serializer`
+| no
+| Serializer class for BLOB strategy (see below for available implementations). Shouldn't be used for PRIMITIVE and POJO strategies.
+
+| `column`
+| no
+| Column name for PRIMITIVE and BLOB strategies where to store key. If not specified, column having 'key' name will be
+used. Attribute shouldn't be specified for POJO strategy.
+|===
+
+Persistence strategies:
+
+[cols="1,3",opts="header"]
+|===
+| Name | Description
+
+| `PRIMITIVE`
+| Stores object as is, by mapping it to Cassandra table column with corresponding type. Should be used only for simple java types
+(int, long, String, double, Date) which could be directly mapped to corresponding Cassadra types. Use this
+https://docs.datastax.com/en/developer/java-driver/4.4/manual/core/#cql-to-java-type-mapping[link, window=_blank] to figure out Java to Cassandra types mapping.
+
+| `BLOB`
+| Stores object as BLOB, by mapping it to Cassandra table column with blob type. Could be used for any java object.
+Conversion of java object to BLOB is handled by "serializer" which could be specified in serializer attribute of *keyPersistence* container.
+
+| `POJO`
+| Stores each field of an object as a column having corresponding type in Cassandra table. Provides ability to utilize
+Cassandra secondary indexes for object fields. Could be used only for POJO objects following Java Beans convention and
+having their fields of https://docs.datastax.com/en/developer/java-driver/4.4/manual/core/#cql-to-java-type-mapping[simple java type which could be directly mapped to corresponding Cassandra types, window=_blank].
+|===
+
+Available serializer implementations:
+
+[cols="1,3",opts="header"]
+|===
+| Class | Description
+
+| `org.apache.ignite.cache.store.cassandra.serializer.JavaSerializer`
+| Uses standard Java serialization framework
+
+| `org.apache.ignite.cache.store.cassandra.serializer.KryoSerializer`
+| Uses Kryo serialization framework
+|===
+
+If you are using `PRIMITIVE` or `BLOB` persistence strategy you don't need to specify internal elements of `keyPersistence`
+tag, cause the idea of these two strategies is that the whole object should be persisted into one column of Cassandra table
+(which could be specified by `column` attribute).
+
+If you are using the `POJO` persistence strategy you have two option:
+
+* Leave `keyPersistence` tag empty - in a such case, all the fields of POJO object class will be detected automatically using such rules:
+ ** Only fields having simple java types which could be directly mapped to
+http://docs.datastax.com/en/developer/java-driver/1.0/java-driver/reference/javaClass2Cql3Datatypes_r.html[appropriate Cassandra types, window=_blank]
+will be detected.
+ ** Fields discovery mechanism takes into account `@QuerySqlField` annotation:
+ *** If `name` attribute is specified it will be used as a column name for Cassandra table. Otherwise field name in a lowercase will be used as a column name.
+ *** If `descending` attribute is specified for a field mapped to *cluster key* column, it will be used to set sort order for the column.
+ ** Fields discovery mechanism takes into account `@AffinityKeyMapped` annotation. All the fields marked by this annotation
+will be treated as http://docs.datastax.com/en/cql/3.0/cql/ddl/ddl_compound_keys_c.html[partition key, window=_blank]
+fields (in an order as they are declared in a class). All other fields will be treated as
+http://docs.datastax.com/en/cql/3.0/cql/ddl/ddl_compound_keys_c.html[cluster key] fields.
+ ** If there are no fields annotated with `@AffinityKeyMapped` all the discovered fields will be treated as
+http://docs.datastax.com/en/cql/3.0/cql/ddl/ddl_compound_keys_c.html[partition key, window=_blank] fields.
+* Specify persistence details inside `keyPersistence` tag - in such case, you have to specify *partition key* fields
+mapping to Cassandra table columns inside `partitionKey` tag. This tag is used just as a container for mapping settings
+and doesn't have any attributes. Optionally (if you are going to use cluster key) you can also specify *cluster key*
+fields mapping to appropriate Cassandra table columns inside `clusterKey` tag. This tag is used just as a container for
+mapping settings and doesn't have any attributes.
+
+Next two sections are providing a detailed specification for `partition` and `cluster` key fields mappings (which makes
+sense if you choose the second option from the list above).
+
+=== partitionKey
+
+[NOTE]
+====
+[discrete]
+=== Optional Element
+Container for `field` elements specifying Cassandra partition key.
+====
+
+Defines the Ignite cache KEY object fields (inside it), which should be used as a *partition key* fields in Cassandra
+table and specifies fields mappings to table columns.
+
+Mappings are specified by using `<field>` tag having such attributes:
+
+[cols="20%,20%,60%",opts="header"]
+|===
+| Attribute | Required | Description
+
+| `name`
+| yes
+| POJO object field name.
+
+| `column`
+| no
+| Cassandra table column name. If not specified lowercase POJO field name will be used.
+|===
+
+=== clusterKey
+
+[NOTE]
+====
+[discrete]
+=== Optional Element
+Container for `field` elements specifying Cassandra cluster key.
+====
+
+Defines the Ignite cache KEY object fields (inside it), which should be used as a *cluster key* fields in Cassandra
+table and specifies fields mappings to table columns.
+
+Mapping are specified by using `<field>` tag having such attributes:
+
+[cols="20%,20%,60%",opts="header"]
+|===
+| Attribute | Required | Description
+
+| `name`
+| yes
+| POJO object field name.
+
+| `column`
+| no
+| Cassandra table column name. If not specified lowercase POJO field name will be used.
+
+
+| `sort`
+| no
+| Specifies sort order for the field (`asc` or `desc`).
+|===
+
+=== valuePersistence
+
+[CAUTION]
+====
+[discrete]
+=== ! Required Element
+Persistent settings for Ignite cache values.
+====
+
+These settings specify how value objects from Ignite cache should be stored/loaded to/from Cassandra table. The settings attributes
+look very similar to corresponding settings for Ignite cache keys:
+
+[cols="20%,20%,60%",opts="header"]
+|===
+| Attribute | Required | Description
+
+| `class`
+| yes
+| Java class name for Ignite cache values.
+
+| `strategy`
+| yes
+| Specifies one of three possible persistent strategies (see below) which controls how object should be persisted/loaded to/from Cassandra table.
+
+| `serializer`
+| no
+| Serializer class for BLOB strategy (see below for available implementations). Shouldn't be used for `PRIMITIVE` and `POJO` strategies.
+
+| `column`
+| no
+| Column name for `PRIMITIVE` and `BLOB` strategies where to store value. If not specified, column having `value` name will be used.
+Attribute shouldn't be specified for POJO strategy.
+|===
+
+Persistence strategies (same as for key persistence settings):
+
+[cols="1,3",opts="header"]
+|===
+| Name | Description
+
+| `PRIMITIVE`
+| Stores object as is, by mapping it to Cassandra table column with corresponding type. Should be used only for simple java types
+(int, long, String, double, Date) which could be directly mapped to corresponding Cassadra types. Use this
+http://docs.datastax.com/en/developer/java-driver/2.0/java-driver/reference/javaClass2Cql3Datatypes_r.html[link, window=_blank] to figure out Java to Cassandra types mapping.
+
+| `BLOB`
+| Stores object as `BLOB`, by mapping it to Cassandra table column with blob type. Could be used for any java object. Conversion of
+java object to `BLOB` is handled by "serializer" which could be specified in serializer attribute of `keyPersistence` container.
+
+| `POJO`
+| Stores each field of an object as a column having a corresponding type in Cassandra table. Provides ability to utilize Cassandra
+secondary indexes for object fields. Could be used only for POJO objects following Java Beans convention and having their fields
+of http://docs.datastax.com/en/developer/java-driver/1.0/java-driver/reference/javaClass2Cql3Datatypes_r.html[simple java type which could be directly mapped to corresponding Cassandra types, window=_blank].
+|===
+
+Available serializer implementations (same as for key persistence settings):
+
+[cols="1,3",opts="header"]
+|===
+| Class | Description
+
+| `org.apache.ignite.cache.store.cassandra.serializer.JavaSerializer`
+| Uses standard Java serialization framework.
+
+| `org.apache.ignite.cache.store.cassandra.serializer.KryoSerializer`
+| Uses Kryo serialization framework.
+|===
+
+If you are using `PRIMITIVE` or `BLOB` persistence strategy you don't need to specify internal elements of `valuePersistence`
+tag, cause the idea of these two strategies is that the whole object should be persisted into one column of Cassandra table
+(which could be specified by `column` attribute).
+
+If you are using `POJO` persistence strategy you have two option (similar to the same options for keys):
+
+* Leave `valuePersistence` tag empty - in such a case, all the fields of POJO object class will be detected automatically using such rules:
+ ** Only fields having simple java types which could be directly mapped to
+http://docs.datastax.com/en/developer/java-driver/1.0/java-driver/reference/javaClass2Cql3Datatypes_r.html[appropriate Cassandra types, window=_blank] will be detected.
+ ** Fields discovery mechanism takes into account `@QuerySqlField` annotation:
+ *** If `name` attribute is specified it will be used as a column name for Cassandra table. Otherwise, field name in a lower case will be used as a column name.
+ *** If `index` attribute is specified, secondary index will be created for a corresponding column in Cassandra table (if such table doesn't exist).
+* Specify persistence details inside `valuePersistence` tag - in such a case, you have to specify your POJO fields mapping to Cassandra table columns
+inside `valuePersistence` tag.
+
+If you selected the second option from the list above, you have to use `<field>` tag to specify POJO fields to Cassandra
+table columns mapping. The tag has following attributes:
+
+[cols="20%,20%,60%",opts="header"]
+|===
+| Attribute | Required | Description
+
+| `name`
+| yes
+| POJO object field name.
+
+| `column`
+| no
+| Cassandra table column name. If not specified lowercase POJO field name will be used.
+
+| `static`
+| no
+| Boolean flag which specifies that column is static withing a given partition.
+
+| `index`
+| no
+| Boolean flag specifying that secondary index should be created for the field.
+
+| `indexClass`
+| no
+| Custom index java class name, in case you want to use custom index.
+
+| `indexOptions`
+| no
+| Custom index options.
+|===
diff --git a/docs/_docs/extensions-and-integrations/cassandra/ddl-generator.adoc b/docs/_docs/extensions-and-integrations/cassandra/ddl-generator.adoc
new file mode 100644
index 0000000..4935648
--- /dev/null
+++ b/docs/_docs/extensions-and-integrations/cassandra/ddl-generator.adoc
@@ -0,0 +1,85 @@
+= DDL Generator
+
+== Overview
+
+One of the benefits of the Ignite Cassandra integration is that you don't need to care about Cassandra DDL syntax for
+table creation and Java to Cassandra type mapping details.
+
+You just need to create an XML configuration which specifies how Ignite cache keys and values should be serialized/deserialized to/from Cassandra.
+Based on this settings all the absent Cassandra keyspaces and tables will be created automatically. The only requirement for all this "magic" to work:
+
+[CAUTION]
+====
+[discrete]
+===
+In connection settings for Cassandra, you should specify user having enough permissions to create keyspaces/tables
+====
+
+However, for some of the deployments it's not possible because of a very strict security policy. Thus the only solution in
+a such situation is to provide DDL scripts for DevOps team to create all the necessary Cassandra keyspaces/tables in advance.
+
+That's the exact use-case for DDL generator utility that generates DDLs from
+link:extensions-and-integrations/cassandra/configuration#persistencesettingsbean[PersistenceSettingsBean settings].
+
+Below is a sample syntax for the Cassandra DDL generation:
+
+[tabs]
+--
+tab:Shell[]
+[source, shell]
+----
+java org.apache.ignite.cache.store.cassandra.utils.DDLGenerator /opt/dev/ignite/persistence-settings-1.xml /opt/dev/ignite/persistence-settings-2.xml
+----
+--
+
+The generated DDL can look as follows:
+
+[tabs]
+--
+tab:Generated Cassandra DDL[]
+[source, sql]
+----
+-------------------------------------------------------------
+DDL for keyspace/table from file: /opt/dev/ignite/persistence-settings-1.xml
+-------------------------------------------------------------
+
+create keyspace if not exists test1
+with replication = {'class' : 'SimpleStrategy', 'replication_factor' : 3} and durable_writes = true;
+
+create table if not exists test1.primitive_test1
+(
+ key int,
+ value int,
+ primary key ((key))
+);
+
+-------------------------------------------------------------
+DDL for keyspace/table from file: /opt/dev/ignite/persistence-settings-2.xml
+-------------------------------------------------------------
+
+create keyspace if not exists test1
+with REPLICATION = {'class' : 'SimpleStrategy', 'replication_factor' : 3} AND DURABLE_WRITES = true;
+
+create table if not exists test1.pojo_test3
+(
+ company text,
+ department text,
+ number int,
+ first_name text,
+ last_name text,
+ age int,
+ married boolean,
+ height bigint,
+ weight float,
+ birth_date timestamp,
+ phones blob,
+ primary key ((company, department), number)
+)
+with comment = 'A most excellent and useful table' AND read_repair_chance = 0.2 and clustering order by (number desc);
+----
+--
+
+Just don't forget to set the `CLASSPATH` environment variable correctly:
+
+. Include the jar file for Ignite Cassandra module (`ignite-cassandra-<version-number>.jar`) in your `CLASSPATH`.
+. If you are using `POJO` persistence strategy for some of your custom java classes you need to include jars with these classes in your CLASSPATH as well.
diff --git a/docs/_docs/extensions-and-integrations/cassandra/overview.adoc b/docs/_docs/extensions-and-integrations/cassandra/overview.adoc
new file mode 100644
index 0000000..cbe3935
--- /dev/null
+++ b/docs/_docs/extensions-and-integrations/cassandra/overview.adoc
@@ -0,0 +1,40 @@
+= Apache Cassandra Acceleration With Apache Ignite
+
+== Overview
+
+The Ignite Cassandra integration implements the link:persistence/external-storage#overview[CacheStore] interface allowing
+to deploy Ignite as a high-performance caching layer on top of Cassandra.
+
+Some observations in regards to the integration:
+
+. The integration uses Cassandra http://www.datastax.com/dev/blog/java-driver-async-queries[asynchronous queries, window=_blank]
+for `CacheStore` batch operations such as such as `loadAll()`, `writeAll()` and `deleteAll()` to provide extremely high performance.
+. The integration automatically creates all necessary tables (and keyspaces) in Cassandra if they are absent. Also, it
+automatically detects all the necessary fields for Ignite key-value tuples that will be stored as POJOs, and creates an
+appropriate table structure. Thus you don't need to care about the Cassandra DDL syntax for table creation and Java to
+Cassandra type mapping details.
+. You can optionally specify the settings (replication factor, replication strategy, bloom filter and etc.) for Cassandra
+tables and keyspaces which should be created.
+. Combines functionality of BLOB and POJO storage, allowing to specify how you prefer to store (as a BLOB or as a POJO)
+key-value tuples from your Ignite cache.
+. Supports standard https://docs.oracle.com/javase/tutorial/jndi/objects/serial.html[Java, window=_blank] and
+https://github.com/EsotericSoftware/kryo[Kryo, window=_blank] serialization for key-values which should be stored as BLOBs in Cassandra
+. Supports Cassandra http://docs.datastax.com/en/cql/3.0/cql/cql_reference/create_index_r.html[secondary indexes, window=_blank] (including custom indexes)
+through persistence configuration settings for particular Ignite cache or such settings could be detected automatically
+if you configured link:SQL/indexes#configuring-indexes-using-annotations[SQL Indexes by Annotations] by using `@QuerySqlField(index = true)` annotation
+. Supports sort order for Cassandra cluster key fields through persistence configuration settings or such settings could be
+detected automatically if you are using `@QuerySqlField(descending = true)` annotation.
+. Supports link:data-modeling/affinity-collocation[affinity co-location] for the POJO key classes having one of their fields
+annotated by `@AffinityKeyMapped`. In such a way, key-values tuples which were stored on one node in an Ignite cache will
+be also stored (co-located) on one node in Cassandra.
+
+[CAUTION]
+====
+[discrete]
+=== Ignite SQL Queries and Cassandra
+Note that in order to execute SQL queries you need to have all the data loaded from Cassandra into an Ignite cluster.
+The Ignite SQL engine doesn't assumes that all the records are available in memory and won't try to query Cassandra.
+
+An alternative would be to use Ignite Native Persistence - a distributed, ACID, and SQL-compliant disk store that allows
+performing SQL queries on the data stored in-memory as well as on disk.
+====
diff --git a/docs/_docs/extensions-and-integrations/cassandra/usage-examples.adoc b/docs/_docs/extensions-and-integrations/cassandra/usage-examples.adoc
new file mode 100644
index 0000000..894228b
--- /dev/null
+++ b/docs/_docs/extensions-and-integrations/cassandra/usage-examples.adoc
@@ -0,0 +1,677 @@
+= Ignite Cassandra Integration Usage Examples
+
+== Overview
+
+As described in link:extensions-and-integrations/cassandra/configuration[configuration section], to configure Cassandra
+as a cache store you need to set `CacheStoreFactory` for your Ignite caches to `org.apache.ignite.cache.store.cassandra.CassandraCacheStoreFactory`.
+
+Below is an example of a typical configuration for Ignite cache to use Cassandra as a cache store. We will go step-by-step
+through all the configuration items, further down. The example is taken from the unit tests resource file
+`store/src/test/resources/org/apache/ignite/tests/persistence/blob/ignite-config.xml` of the Cassandra module source code.
+
+[tabs]
+--
+tab:XML[]
+[source, xml]
+----
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="
+ http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+ <!-- Cassandra connection settings -->
+ <import resource="classpath:org/apache/ignite/tests/cassandra/connection-settings.xml" />
+
+ <!-- Persistence settings for 'cache1' -->
+ <bean id="cache1_persistence_settings" class="org.apache.ignite.cache.store.cassandra.persistence.KeyValuePersistenceSettings">
+ <constructor-arg type="org.springframework.core.io.Resource" value="classpath:org/apache/ignite/tests/persistence/blob/persistence-settings-1.xml" />
+ </bean>
+
+ <!-- Persistence settings for 'cache2' -->
+ <bean id="cache2_persistence_settings" class="org.apache.ignite.cache.store.cassandra.persistence.KeyValuePersistenceSettings">
+ <constructor-arg type="org.springframework.core.io.Resource" value="classpath:org/apache/ignite/tests/persistence/blob/persistence-settings-3.xml" />
+ </bean>
+
+ <!-- Ignite configuration -->
+ <bean id="ignite.cfg" class="org.apache.ignite.configuration.IgniteConfiguration">
+ <property name="cacheConfiguration">
+ <list>
+ <!-- Configuring persistence for "cache1" cache -->
+ <bean class="org.apache.ignite.configuration.CacheConfiguration">
+ <property name="name" value="cache1"/>
+ <property name="readThrough" value="true"/>
+ <property name="writeThrough" value="true"/>
+ <property name="cacheStoreFactory">
+ <bean class="org.apache.ignite.cache.store.cassandra.CassandraCacheStoreFactory">
+ <property name="dataSourceBean" value="cassandraAdminDataSource"/>
+ <property name="persistenceSettingsBean" value="cache1_persistence_settings"/>
+ </bean>
+ </property>
+ </bean>
+
+ <!-- Configuring persistence for "cache2" cache -->
+ <bean class="org.apache.ignite.configuration.CacheConfiguration">
+ <property name="name" value="cache2"/>
+ <property name="readThrough" value="true"/>
+ <property name="writeThrough" value="true"/>
+ <property name="cacheStoreFactory">
+ <bean class="org.apache.ignite.cache.store.cassandra.CassandraCacheStoreFactory">
+ <property name="dataSourceBean" value="cassandraAdminDataSource"/>
+ <property name="persistenceSettingsBean" value="cache2_persistence_settings"/>
+ </bean>
+ </property>
+ </bean>
+ </list>
+ </property>
+
+ <!-- Explicitly configure TCP discovery SPI to provide list of initial nodes. -->
+ <property name="discoverySpi">
+ <bean class="org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi">
+ <property name="ipFinder">
+ <!--
+ Ignite provides several options for automatic discovery that can be used
+ instead os static IP based discovery. For information on all options refer
+ to our documentation: http://apacheignite.readme.io/docs/cluster-config
+ -->
+ <!-- Uncomment static IP finder to enable static-based discovery of initial nodes. -->
+ <!--<bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder">-->
+ <bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.multicast.TcpDiscoveryMulticastIpFinder">
+ <property name="addresses">
+ <list>
+ <!-- In distributed environment, replace with actual host IP address. -->
+ <value>127.0.0.1:47500..47509</value>
+ </list>
+ </property>
+ </bean>
+ </property>
+ </bean>
+ </property>
+ </bean>
+</beans>
+----
+--
+
+In the specified example we have two Ignite caches configured: `cache1` and `cache2`. So lets look at the configuration details.
+
+Lets start from the cache configuration details. They are pretty similar for both caches (`cache1` and `cache2`) and looks like that:
+
+[tabs]
+--
+tab:XML[]
+[source, xml]
+----
+<bean class="org.apache.ignite.configuration.CacheConfiguration">
+ <property name="name" value="cache1"/>
+ <property name="readThrough" value="true"/>
+ <property name="writeThrough" value="true"/>
+ <property name="cacheStoreFactory">
+ <bean class="org.apache.ignite.cache.store.cassandra.CassandraCacheStoreFactory">
+ <property name="dataSourceBean" value="cassandraAdminDataSource"/>
+ <property name="persistenceSettingsBean" value="cache1_persistence_settings"/>
+ </bean>
+ </property>
+</bean>
+----
+--
+
+First of all we can see that `read-through` and `write-through` options are enabled:
+
+[tabs]
+--
+tab:XML[]
+[source, xml]
+----
+<property name="readThrough" value="true"/>
+<property name="writeThrough" value="true"/>
+----
+--
+
+which is required for Ignite cache, if you plan to use a persistent store for cache entries which expired.
+
+You can optionally specify the `write-behind` setting if you prefer persistent store to be updated asynchronously:
+
+[tabs]
+--
+tab:XML[]
+[source, xml]
+----
+<property name="readThrough" value="true"/>
+<property name="writeThrough" value="true"/>
+----
+--
+
+The next important thing is `CacheStoreFactory` configuration:
+
+[tabs]
+--
+tab:XML[]
+[source, xml]
+----
+<property name="cacheStoreFactory">
+ <bean class="org.apache.ignite.cache.store.cassandra.CassandraCacheStoreFactory">
+ <property name="dataSourceBean" value="cassandraAdminDataSource"/>
+ <property name="persistenceSettingsBean" value="cache1_persistence_settings"/>
+ </bean>
+</property>
+----
+--
+
+You should use `org.apache.ignite.cache.store.cassandra.CassandraCacheStoreFactory` as a `CacheStoreFactory` for your
+Ignite caches to utilize Cassandra as a persistent store. For `CassandraCacheStoreFactory` you should specify two required properties:
+
+* `dataSourceBean` - name of the Spring bean, which specifies all the details about Cassandra database connection.
+
+* `persistenceSettingsBean` - name of the Spring bean, which specifies all the details about how objects should be persisted into Cassandra database.
+
+In the specified example `cassandraAdminDataSource` is a data source bean, which is imported into Ignite cache config file using this directive:
+
+[tabs]
+--
+tab:XML[]
+[source, xml]
+----
+<import resource="classpath:org/apache/ignite/tests/cassandra/connection-settings.xml" />
+----
+--
+
+and `cache1_persistence_settings` is a persistence settings bean, which is defined in Ignite cache config file using such directive:
+
+[tabs]
+--
+tab:XML[]
+[source, xml]
+----
+<bean id="cache1_persistence_settings" class="org.apache.ignite.cache.store.cassandra.utils.persistence.KeyValuePersistenceSettings">
+ <constructor-arg type="org.springframework.core.io.Resource" value="classpath:org/apache/ignite/tests/persistence/blob/persistence-settings-1.xml" />
+</bean>
+----
+--
+
+Now lets look at the specification of `cassandraAdminDataSource` from `store/src/test/resources/org/apache/ignite/tests/cassandra/connection-settings.xml`
+test resource.
+
+Specifically,`CassandraAdminCredentials` and `CassandraRegularCredentials` are classes which extend
+`org.apache.ignite.cache.store.cassandra.datasource.Credentials`. You are welcome to implement these classes and reference them afterwards.
+
+[tabs]
+--
+tab:XML[]
+[source, xml]
+----
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="
+ http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+ <bean id="cassandraAdminCredentials" class="org.my.project.CassandraAdminCredentials"/>
+ <bean id="cassandraRegularCredentials" class="org.my.project.CassandraRegularCredentials"/>
+
+ <bean id="loadBalancingPolicy" class="com.datastax.driver.core.policies.TokenAwarePolicy">
+ <constructor-arg type="com.datastax.driver.core.policies.LoadBalancingPolicy">
+ <bean class="com.datastax.driver.core.policies.RoundRobinPolicy"/>
+ </constructor-arg>
+ </bean>
+
+ <bean id="contactPoints" class="org.apache.ignite.tests.utils.CassandraHelper" factory-method="getContactPointsArray"/>
+
+ <bean id="cassandraAdminDataSource" class="org.apache.ignite.cache.store.cassandra.datasource.DataSource">
+ <property name="credentials" ref="cassandraAdminCredentials"/>
+ <property name="contactPoints" ref="contactPoints"/>
+ <property name="readConsistency" value="ONE"/>
+ <property name="writeConsistency" value="ONE"/>
+ <property name="loadBalancingPolicy" ref="loadBalancingPolicy"/>
+ </bean>
+
+ <bean id="cassandraRegularDataSource" class="org.apache.ignite.cache.store.cassandra.datasource.DataSource">
+ <property name="credentials" ref="cassandraRegularCredentials"/>
+ <property name="contactPoints" ref="contactPoints"/>
+ <property name="readConsistency" value="ONE"/>
+ <property name="writeConsistency" value="ONE"/>
+ <property name="loadBalancingPolicy" ref="loadBalancingPolicy"/>
+ </bean>
+</beans>
+----
+--
+
+For more details about Cassandra data source connection configuration visit the link:extensions-and-integrations/cassandra/configuration[integration configuration page].
+
+Finally, the last piece which wasn't still described is persistence settings configuration. Lets look at the
+`cache1_persistence_settings` from the `org/apache/ignite/tests/persistence/blob/persistence-settings-1.xml` test resource.
+
+[tabs]
+--
+tab:XML[]
+[source, xml]
+----
+<persistence keyspace="test1" table="blob_test1">
+ <keyPersistence class="java.lang.Integer" strategy="PRIMITIVE" />
+ <valuePersistence strategy="BLOB"/>
+</persistence>
+----
+--
+
+In the configuration above, we can see that Cassandra `test1.blob_test1` table will be used to store key/value objects for
+**cache1** cache. Key objects of the cache will be stored as **integer** in `key` column. Value objects of the cache will be
+stored as **blob** in `value` column. For more information about persistence settings configuration visit the
+link:extensions-and-integrations/cassandra/configuration[integration configuration page].
+
+Next sections will provide examples of persistence settings configuration for different kind of persistence strategies
+(see more details about persistence strategies on the link:extensions-and-integrations/cassandra/configuration[integration configuration page].
+
+== Example 1
+
+Persistence setting for Ignite cache with keys of `Integer` type to be persisted as `int` in Cassandra and values of
+`String` type to be persisted as `text` in Cassandra.
+
+[tabs]
+--
+tab:XML[]
+[source, xml]
+----
+<persistence keyspace="test1" table="my_table">
+ <keyPersistence class="java.lang.Integer" strategy="PRIMITIVE" column="my_key"/>
+ <valuePersistence class="java.lang.String" strategy="PRIMITIVE" />
+</persistence>
+----
+--
+
+Keys will be stored in `my_key` column. Values will be stored in `value` column (which is used by default if `column` attribute wasn't specified).
+
+== Example 2
+
+Persistence setting for Ignite cache with keys of `Integer` type to be persisted as `int` in Cassandra and values of `any`
+type (you don't need to specify the type for **BLOB** persistence strategy) to be persisted as `blob` in Cassandra.
+The only solution for this situation is to store value as a `BLOB` in Cassandra table.
+
+[tabs]
+--
+tab:XML[]
+[source, xml]
+----
+<persistence keyspace="test1" table="my_table">
+ <keyPersistence class="java.lang.Integer" strategy="PRIMITIVE" />
+ <valuePersistence strategy="BLOB"/>
+</persistence>
+----
+--
+
+Keys will be stored in `key` column (which is used by default if `column` attribute wasn't specified). Values will be stored in `value` column.
+
+== Example 3
+
+Persistence setting for Ignite cache with keys of `Integer` type and values of **any** type, both to be persisted as `BLOB` in Cassandra.
+
+[tabs]
+--
+tab:XML[]
+[source, xml]
+----
+<persistence keyspace="test1" table="my_table">
+ <!-- By default Java standard serialization is going to be used -->
+ <keyPersistence class="java.lang.Integer"
+ strategy="BLOB"/>
+
+ <!-- Kryo serialization specified to be used -->
+ <valuePersistence class="org.apache.ignite.tests.pojos.Person"
+ strategy="BLOB"
+ serializer="org.apache.ignite.cache.store.cassandra.serializer.KryoSerializer"/>
+</persistence>
+----
+--
+
+Keys will be stored in `key` column having `blob` type and using
+https://docs.oracle.com/javase/tutorial/jndi/objects/serial.html[Java standard serialization, window=_blank]. Values will be stored in
+`value` column having `blob` type and using https://github.com/EsotericSoftware/kryo[Kryo serialization, window=_blank].
+
+== Example 4
+
+Persistence setting for Ignite cache with keys of `Integer` type to be persisted as `int` in Cassandra and values of custom
+POJO `org.apache.ignite.tests.pojos.Person` type to be dynamically analyzed and persisted into a set of table columns,
+so that each POJO field will be mapped to appropriate table column. For more details about dynamic POJO fields discovery
+refer to link:extensions-and-integrations/cassandra/configuration#persistencesettingsbean[PersistenceSettingsBean] documentation section.
+
+[tabs]
+--
+tab:XML[]
+[source, xml]
+----
+<persistence keyspace="test1" table="my_table">
+ <keyPersistence class="java.lang.Integer" strategy="PRIMITIVE"/>
+ <valuePersistence class="org.apache.ignite.tests.pojos.Person" strategy="POJO"/>
+</persistence>
+----
+--
+
+Keys will be stored in `key` column having `int` type.
+
+Now lets imagine that the `org.apache.ignite.tests.pojos.Person` class has such an implementation:
+
+[tabs]
+--
+tab:Java[]
+[source, java]
+----
+public class Person {
+ private String firstName;
+ private String lastName;
+ private int age;
+ private boolean married;
+ private long height;
+ private float weight;
+ private Date birthDate;
+ private List<String> phones;
+
+ public void setFirstName(String name) {
+ firstName = name;
+ }
+
+ public String getFirstName() {
+ return firstName;
+ }
+
+ public void setLastName(String name) {
+ lastName = name;
+ }
+
+ public String getLastName() {
+ return lastName;
+ }
+
+ public void setAge(int age) {
+ this.age = age;
+ }
+
+ public int getAge() {
+ return age;
+ }
+
+ public void setMarried(boolean married) {
+ this.married = married;
+ }
+
+ public boolean getMarried() {
+ return married;
+ }
+
+ public void setHeight(long height) {
+ this.height = height;
+ }
+
+ public long getHeight() {
+ return height;
+ }
+
+ public void setWeight(float weight) {
+ this.weight = weight;
+ }
+
+ public float getWeight() {
+ return weight;
+ }
+
+ public void setBirthDate(Date date) {
+ birthDate = date;
+ }
+
+ public Date getBirthDate() {
+ return birthDate;
+ }
+
+ public void setPhones(List<String> phones) {
+ this.phones = phones;
+ }
+
+ public List<String> getPhones() {
+ return phones;
+ }
+}
+----
+--
+
+In this case Ignite cache values of the `org.apache.ignite.tests.pojos.Person` type will be persisted into a set of
+Cassandra table columns using such dynamically configured mapping rule:
+
+[opts="header"]
+|===
+| POJO field | Table column | Column type
+| firstName | firstname | text
+| lastName | lastname | text
+| age | age | int
+| married | married | boolean
+| height | height | bigint
+| weight | weight | float
+| birthDate | birthdate | timestamp
+|===
+
+As you can see from the table above, `phones` field will not be persisted into table. That's because it's not of simple
+java type which could be directly mapped to http://docs.datastax.com/en/developer/java-driver/1.0/java-driver/reference/javaClass2Cql3Datatypes_r.html[appropriate, window=_blank] Cassandra type.
+Such kind of fields could be persisted into Cassandra only if you manually specify all mapping details for the object type
+and if field type itself is implementing `java.io.Serializable` interface. In a such case field will be persisted into a
+separate table column as `blob`. See more details in the next example.
+
+== Example 5
+
+Persistence setting for Ignite cache with keys of custom POJO `org.apache.ignite.tests.pojos.PersonId` and values of
+custom POJO `org.apache.ignite.tests.pojos.Person` types, both to be persisted into a set of table columns based on
+manually specified mapping rules.
+
+[tabs]
+--
+tab:XML[]
+[source, xml]
+----
+<persistence keyspace="test1" table="my_table" ttl="86400">
+ <!-- Cassandra keyspace options which should be used to create provided keyspace if it doesn't exist -->
+ <keyspaceOptions>
+ REPLICATION = {'class' : 'SimpleStrategy', 'replication_factor' : 3}
+ AND DURABLE_WRITES = true
+ </keyspaceOptions>
+
+ <!-- Cassandra table options which should be used to create provided table if it doesn't exist -->
+ <tableOptions>
+ comment = 'A most excellent and useful table'
+ AND read_repair_chance = 0.2
+ </tableOptions>
+
+ <!-- Persistent settings for Ignite cache keys -->
+ <keyPersistence class="org.apache.ignite.tests.pojos.PersonId" strategy="POJO">
+ <!-- Partition key fields if POJO strategy used -->
+ <partitionKey>
+ <!-- Mapping from POJO field to Cassandra table column -->
+ <field name="companyCode" column="company" />
+ <field name="departmentCode" column="department" />
+ </partitionKey>
+
+ <!-- Cluster key fields if POJO strategy used -->
+ <clusterKey>
+ <!-- Mapping from POJO field to Cassandra table column -->
+ <field name="personNumber" column="number" sort="desc"/>
+ </clusterKey>
+ </keyPersistence>
+
+ <!-- Persistent settings for Ignite cache values -->
+ <valuePersistence class="org.apache.ignite.tests.pojos.Person"
+ strategy="POJO"
+ serializer="org.apache.ignite.cache.store.cassandra.serializer.KryoSerializer">
+ <!-- Mapping from POJO field to Cassandra table column -->
+ <field name="firstName" column="first_name" />
+ <field name="lastName" column="last_name" />
+ <field name="age" />
+ <field name="married" index="true"/>
+ <field name="height" />
+ <field name="weight" />
+ <field name="birthDate" column="birth_date" />
+ <field name="phones" />
+ </valuePersistence>
+</persistence>
+----
+--
+
+These persistence settings looks rather complicated. Lets go step by step and analyse them.
+
+Lets first look at the root tag:
+
+[tabs]
+--
+tab:XML[]
+[source, xml]
+----
+<persistence keyspace="test1" table="my_table" ttl="86400">
+----
+--
+
+It specifies that Ignite cache keys and values should be stored in `test1.my_table` table and that data in each row
+http://docs.datastax.com/en/cql/3.1/cql/cql_using/use_expire_c.html[expires, window=_blank] after `86400` sec which is `24` hours.
+
+Then we can see the advanced settings for Cassandra keyspace. The setting will be used to create keyspace if it's not exist.
+
+[tabs]
+--
+tab:XML[]
+[source, xml]
+----
+<keyspaceOptions>
+ REPLICATION = {'class' : 'SimpleStrategy', 'replication_factor' : 3}
+ AND DURABLE_WRITES = true
+</keyspaceOptions>
+----
+--
+
+Then by analogy to keyspace setting we can see table advanced setting, which will be used only for table creation.
+
+[tabs]
+--
+tab:XML[]
+[source, xml]
+----
+<tableOptions>
+ comment = 'A most excellent and useful table'
+ AND read_repair_chance = 0.2
+</tableOptions>
+----
+--
+
+Next section specifies how Ignite cache keys should be persisted:
+
+[tabs]
+--
+tab:XML[]
+[source, xml]
+----
+<keyPersistence class="org.apache.ignite.tests.pojos.PersonId" strategy="POJO">
+ <!-- Partition key fields if POJO strategy used -->
+ <partitionKey>
+ <!-- Mapping from POJO field to Cassandra table column -->
+ <field name="companyCode" column="company" />
+ <field name="departmentCode" column="department" />
+ </partitionKey>
+
+ <!-- Cluster key fields if POJO strategy used -->
+ <clusterKey>
+ <!-- Mapping from POJO field to Cassandra table column -->
+ <field name="personNumber" column="number" sort="desc"/>
+ </clusterKey>
+</keyPersistence>
+----
+--
+
+Lets assume that `org.apache.ignite.tests.pojos.PersonId` has such implementation:
+
+[tabs]
+--
+tab:Java[]
+[source, java]
+----
+public class PersonId {
+ private String companyCode;
+ private String departmentCode;
+ private int personNumber;
+
+ public void setCompanyCode(String code) {
+ companyCode = code;
+ }
+
+ public String getCompanyCode() {
+ return companyCode;
+ }
+
+ public void setDepartmentCode(String code) {
+ departmentCode = code;
+ }
+
+ public String getDepartmentCode() {
+ return departmentCode;
+ }
+
+ public void setPersonNumber(int number) {
+ personNumber = number;
+ }
+
+ public int getPersonNumber() {
+ return personNumber;
+ }
+}
+----
+--
+
+In such case Ignite cache keys of `org.apache.ignite.tests.pojos.PersonId` type will be persisted into a set of Cassandra
+table columns representing `PARTITION` and `CLUSTER` key using this mapping rule:
+
+[opts="header"]
+|===
+| POJO field | Table column | Column type
+| companyCode | company | text
+| departmentCode | department | text
+| personNumber | number | int
+|===
+
+In addition to that, combination of columns `(company, department)` will be used as Cassandra `PARTITION` key and column
+`number` will be used as a `CLUSTER` key sorted in descending order.
+
+Finally lets move to the last section, which specifies persistence settings for Ignite cache values:
+
+[tabs]
+--
+tab:XML[]
+[source, xml]
+----
+<valuePersistence class="org.apache.ignite.tests.pojos.Person"
+ strategy="POJO"
+ serializer="org.apache.ignite.cache.store.cassandra.serializer.KryoSerializer">
+ <!-- Mapping from POJO field to Cassandra table column -->
+ <field name="firstName" column="first_name" />
+ <field name="lastName" column="last_name" />
+ <field name="age" />
+ <field name="married" index="true"/>
+ <field name="height" />
+ <field name="weight" />
+ <field name="birthDate" column="birth_date" />
+ <field name="phones" />
+</valuePersistence>
+----
+--
+
+Lets assume `that org.apache.ignite.tests.pojos.Person` class has the same implementation like in link:extensions-and-integrations/cassandra/usage-examples#example-4[Example 4].
+In this case Ignite cache values of `org.apache.ignite.tests.pojos.Person` type will be persisted into a set of Cassandra
+table columns using such mapping rule:
+
+[opts="header"]
+|===
+| POJO field | Table column | Column type
+| firstName | first_name | text
+| lastName | last_name | text
+| age | age | int
+| married | married | boolean
+| height | height | bigint
+| weight | weight | float
+| birthDate | birth_date | timestamp
+| phones | phones | blob
+|===
+
+Comparing to link:extensions-and-integrations/cassandra/usage-examples#example-4[Example 4] we can see that now `phones`
+field will be serialized to `phones` column of `blob` type using https://github.com/EsotericSoftware/kryo[Kryo, window=_blank] serializer.
+In addition to that, Cassandra secondary index will be created for the `married` column.
diff --git a/docs/_docs/persistence/external-storage.adoc b/docs/_docs/persistence/external-storage.adoc
index b163ab8..47188ad2 100644
--- a/docs/_docs/persistence/external-storage.adoc
+++ b/docs/_docs/persistence/external-storage.adoc
@@ -196,12 +196,12 @@ CAUTION: Even though Ignite supports distributed transactions, it doesn't make y
=== Cassandra Integration
-Ignite provides an out-of-the-box implementation of `CacheStore` that enables you to use Apache Cassandra as a persistent storage. This implementation utilizes Cassandra's link:http://www.datastax.com/dev/blog/java-driver-async-queries[asynchronous queries] to provide high performance batch operations such as `loadAll()`, `writeAll()` and `deleteAll()`, and automatically creates all necessary tables and namespaces in Cassandra.
+Ignite provides an out-of-the-box implementation of `CacheStore` that enables you to use Apache Cassandra as a persistent
+storage. This implementation utilizes Cassandra's link:http://www.datastax.com/dev/blog/java-driver-async-queries[asynchronous queries, window=_blank]
+to provide high performance batch operations such as `loadAll()`, `writeAll()` and `deleteAll()`, and automatically creates
+all necessary tables and namespaces in Cassandra.
-////
-TODO
-Refer to the dedicated section on Cassandra integration for more information.
-////
+Refer to link:extensions-and-integrations/cassandra/overview[this documentation section] for configuration and usage guidelines.
////
== Implementing Custom CacheStore