DATACASS-125 WIP Docbook.
Testing how fast changes make it to the reference guide site.
This commit is contained in:
@@ -7,6 +7,6 @@
|
||||
3.2.x and above.
|
||||
</para>
|
||||
<para>
|
||||
Currently we support Cassandra 1.X using the DataStax Java Driver (1.0.6-dse)
|
||||
Currently we support Cassandra 2.X using the DataStax Java Driver (2.0.X)
|
||||
</para>
|
||||
</chapter>
|
||||
@@ -1,77 +1,69 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
|
||||
"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
|
||||
<chapter id="mongo.core">
|
||||
<title>Cassandra support</title>
|
||||
|
||||
<para>The Cassandra support contains a wide range of features which are summarized below.</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>Spring configuration support using Java based @Configuration classes or an XML namespace
|
||||
for a Cassandra driver instance and replica sets</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>CassandraTemplate helper class that increases productivity performing common Cassandra
|
||||
operations. Includes integrated object mapping between CQL Tables and POJOs.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Exception translation into Spring's portable Data Access Exception
|
||||
hierarchy</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Feature Rich Object Mapping integrated with Spring's Conversion
|
||||
Service</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Annotation based mapping metadata but extensible to support other
|
||||
metadata formats</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Persistence and mapping lifecycle events</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Java based Query, Criteria, and Update DSLs</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Automatic implementation of Repository interfaces including
|
||||
support for custom finder methods.</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para>For most tasks you will find yourself using <classname>CassandraTemplate</classname> or the
|
||||
Repository support that both leverage the rich mapping functionality. CassandraTemplate is the
|
||||
place to look for accessing functionality such as incrementing counters or ad-hoc CRUD
|
||||
operations. CassandraTemplate also provides callback methods so that it is easy for you to get a
|
||||
hold of the low level API artifacts such as <literal>com.datastax.driver.core.Session</literal>
|
||||
to communicate directly with Cassandra. The goal with naming conventions on various API
|
||||
artifacts is to copy those in the base DataStax Java driver so you can easily map your existing
|
||||
knowledge onto the Spring APIs.</para>
|
||||
|
||||
<section id="mongodb-getting-started">
|
||||
<title>Getting Started</title>
|
||||
|
||||
<para>Spring Cassandra support requires Cassanra 1.1 or higher (but not Cassandra 2.0) and Java
|
||||
SE 6 or higher. The latest commerical release (1.2.X as of this writing) is recommended. An
|
||||
easy way to bootstrap setting up a working environment is to create a Spring based project in
|
||||
<ulink url="http://spring.io/tools/sts">STS</ulink>.</para>
|
||||
|
||||
<para>First you need to set up a running Cassandra server. </para>
|
||||
|
||||
<para>To create a Spring project in STS go to File -> New -> Spring Template Project ->
|
||||
Simple Spring Utility Project -> press Yes when prompted. Then enter a project and a
|
||||
package name such as org.spring.cassandra.example.</para>
|
||||
|
||||
<para>Then add the following to pom.xml dependencies section.</para>
|
||||
|
||||
<programlisting lang="" language="xml"><dependencies>
|
||||
<?xml version='1.0'?>
|
||||
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
|
||||
<chapter id="cassandra.core">
|
||||
<title>Cassandra support</title>
|
||||
<para>The Cassandra support contains a wide range of features which
|
||||
are summarized below.</para>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>Spring configuration support using Java based @Configuration
|
||||
classes or an XML namespace for a Cassandra driver instance and
|
||||
replica sets</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>CassandraTemplate helper class that increases productivity
|
||||
performing common Cassandra operations. Includes integrated object
|
||||
mapping between CQL Tables and POJOs.</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>Exception translation into Spring's portable Data Access
|
||||
Exception hierarchy</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>Feature Rich Object Mapping integrated with Spring's
|
||||
Conversion Service</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>Annotation based mapping metadata but extensible to support
|
||||
other metadata formats</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>Persistence and mapping lifecycle events</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>Java based Query, Criteria, and Update DSLs</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>Automatic implementation of Repository interfaces including
|
||||
support for custom finder methods.</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
<para>For most tasks you will find yourself using <classname>
|
||||
CassandraTemplate</classname> or the Repository support that both
|
||||
leverage the rich mapping functionality. CassandraTemplate is the
|
||||
place to look for accessing functionality such as incrementing
|
||||
counters or ad-hoc CRUD operations. CassandraTemplate also provides
|
||||
callback methods so that it is easy for you to get a hold of the low
|
||||
level API artifacts such as <literal>
|
||||
com.datastax.driver.core.Session</literal> to communicate directly
|
||||
with Cassandra. The goal with naming conventions on various API
|
||||
artifacts is to copy those in the base DataStax Java driver so you can
|
||||
easily map your existing knowledge onto the Spring APIs.</para>
|
||||
<section id="cassandra-getting-started">
|
||||
<title>Getting Started</title>
|
||||
<para>Spring Data Cassandra uses the DataStax Java Driver version
|
||||
2.X, which supports DataStax Enterprise 4/Cassandra 2.0, and Java SE
|
||||
6 or higher. The latest commercial release (2.X as of this writing)
|
||||
is recommended. An easy way to bootstrap setting up a working
|
||||
environment is to create a Spring based project in
|
||||
<ulink url="http://spring.io/tools/sts">STS</ulink>.</para>
|
||||
<para>First you need to set up a running Cassandra server.</para>
|
||||
<para>To create a Spring project in STS go to File -> New ->
|
||||
Spring Template Project -> Simple Spring Utility Project ->
|
||||
press Yes when prompted. Then enter a project and a package name such
|
||||
as org.spring.cassandra.example.</para>
|
||||
<para>Then add the following to pom.xml dependencies section.</para>
|
||||
<programlisting lang="" language="xml"><dependencies>
|
||||
|
||||
<!-- other dependency elements omitted -->
|
||||
|
||||
@@ -81,165 +73,250 @@
|
||||
<version>1.0.0.RELEASE</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies></programlisting>
|
||||
|
||||
<para>Also change the version of Spring in the pom.xml to be</para>
|
||||
|
||||
<programlisting lang="" language="xml"><spring.framework.version>3.2.8.RELEASE</spring.framework.version></programlisting>
|
||||
|
||||
<para>You will also need to add the location of the Spring Milestone
|
||||
repository for maven to your pom.xml which is at the same level of your
|
||||
<dependencies/> element</para>
|
||||
|
||||
<programlisting language="xml"><repositories>
|
||||
</dependencies></programlisting>
|
||||
<para>Also change the version of Spring in the pom.xml to be</para>
|
||||
<programlisting lang="" language="xml"><spring.framework.version>3.2.8.RELEASE</spring.framework.version></programlisting>
|
||||
<para>You will also need to add the location of the Spring Milestone
|
||||
repository for maven to your pom.xml which is at the same level of
|
||||
your <dependencies/> element</para>
|
||||
<programlisting language="xml"><repositories>
|
||||
<repository>
|
||||
<id>spring-milestone</id>
|
||||
<name>Spring Maven MILESTONE Repository</name>
|
||||
<url>http://repo.spring.io/libs-milestone</url>
|
||||
</repository>
|
||||
</repositories></programlisting>
|
||||
|
||||
<para>The repository is also <ulink
|
||||
url="http://shrub.appspot.com/maven.springframework.org/milestone/org/springframework/data/">browseable
|
||||
here</ulink>.</para>
|
||||
<para>TODO</para>
|
||||
</section>
|
||||
|
||||
<section id="mongo.examples-repo">
|
||||
<title>Examples Repository</title>
|
||||
|
||||
<para>TODO</para>
|
||||
</section>
|
||||
|
||||
<section id="mongodb-connectors">
|
||||
<title>Connecting to Cassandra with Spring</title>
|
||||
</section>
|
||||
|
||||
<section id="mongo.auditing">
|
||||
<title>General auditing configuration</title>
|
||||
<para>Auditing support is not available in the current version.</para>
|
||||
</section>
|
||||
|
||||
<section id="mongo-template">
|
||||
<title>Introduction to CassandraTemplate</title>
|
||||
|
||||
<section id="mongo-template.instantiating" label=" ">
|
||||
<title>Instantiating CassandraTemplate</title>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<section id="mongo-template.save-update-remove">
|
||||
<title>Saving, Updating, and Removing Rows</title>
|
||||
|
||||
<para><classname>CassandraTemplate</classname> provides a simple way for you to save, update,
|
||||
and delete your domain objects and map those objects to documents stored in Cassandra.</para>
|
||||
|
||||
<section id="mongo-template.id-handling">
|
||||
<title>How the Composite Primary Key fields are handled in the mapping layer</title>
|
||||
|
||||
<para>Cassandra requires that you have at least 1 Partition Key field for a CQL Table.
|
||||
Alternately, you can have one or more Clustering Key fields.</para>
|
||||
<para>TODO With Examples</para>
|
||||
</section>
|
||||
|
||||
<section id="mongo-template.type-mapping">
|
||||
<title>Type mapping</title>
|
||||
</section>
|
||||
|
||||
<section id="mongo-template.save-insert">
|
||||
<title>Methods for saving and inserting rows</title>
|
||||
</section>
|
||||
|
||||
<section id="mongodb-template-update">
|
||||
<title>Updating rows in a CQL table</title>
|
||||
</section>
|
||||
|
||||
<section id="mongo-template.upserts">
|
||||
<title>Upserting rows in a CQL table</title>
|
||||
</section>
|
||||
|
||||
<section id="mongo-template.find-and-upsert">
|
||||
<title>Finding and Upserting rowa in a CQL table</title>
|
||||
</section>
|
||||
|
||||
<section id="mongo-template.delete">
|
||||
<title>Methods for removing rows</title>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<section id="mongo.query">
|
||||
<title>Querying CQL Tables</title>
|
||||
</section>
|
||||
|
||||
<section id="mongo.custom-converters">
|
||||
<title>Overriding default mapping with custom converters</title>
|
||||
|
||||
<para>In order to have more fine grained control over the mapping process you can register
|
||||
Spring converters with the <classname>CassandraConverter</classname> implementations such as
|
||||
the <classname>MappingCassandraConverter</classname>.</para>
|
||||
|
||||
<para>The <classname>MappingCassandraConverter</classname> checks to see if there are any Spring
|
||||
converters that can handle a specific class before attempting to map the object itself. To
|
||||
'hijack' the normal mapping strategies of the
|
||||
<classname>MappingCassandraConverter</classname>, perhaps for increased performance or other
|
||||
custom mapping needs, you first need to create an implementation of the Spring
|
||||
<interfacename>Converter</interfacename> interface and then register it with the
|
||||
MappingConverter.</para>
|
||||
|
||||
<note>
|
||||
<para>For more information on the Spring type conversion service see the
|
||||
reference docs <ulink
|
||||
url="http://docs.spring.io/spring/docs/current/spring-framework-reference/html/validation.html#core-convert">here</ulink>.</para>
|
||||
</note>
|
||||
|
||||
<section id="mongo.custom-converters.writer">
|
||||
<title>Saving using a registered Spring Converter</title>
|
||||
</section>
|
||||
|
||||
<section id="mongo.custom-converters.reader">
|
||||
<title>Reading using a Spring Converter</title>
|
||||
</section>
|
||||
|
||||
<section id="mongo.custom-converters.xml">
|
||||
<title>Registering Spring Converters with the CassandraConverter</title>
|
||||
</section>
|
||||
|
||||
<section id="mongo.converter-disambiguation">
|
||||
<title>Converter disambiguation</title>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<section id="mongo-template.commands">
|
||||
<title>Executing Commands</title>
|
||||
|
||||
<section id="mongo-template.commands.execution">
|
||||
<title>Methods for executing commands</title>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<section id="mongodb.mapping-usage.events">
|
||||
<title>Lifecycle Events</title>
|
||||
</section>
|
||||
|
||||
<section id="mongo.exception">
|
||||
<title>Exception Translation</title>
|
||||
|
||||
<para>The Spring framework provides exception translation for a wide variety of database and
|
||||
mapping technologies. This has traditionally been for JDBC and JPA. The Spring support for
|
||||
Cassandra extends this feature to the Cassandra Database by providing an implementation of the
|
||||
<classname>org.springframework.dao.support.PersistenceExceptionTranslator</classname>
|
||||
interface.</para>
|
||||
|
||||
<para>The motivation behind mapping to Spring's <ulink
|
||||
url="http://docs.spring.io/spring/docs/current/spring-framework-reference/html/dao.html#dao-exceptions"
|
||||
>consistent data access exception hierarchy</ulink> is that you are then able to write
|
||||
portable and descriptive exception handling code without resorting to coding against Cassandra
|
||||
Exceptions. All of Spring's data access exceptions are inherited from the root
|
||||
<classname>DataAccessException</classname> class so you can be sure that you will be able to
|
||||
catch all database related exception within a single try-catch block. </para>
|
||||
</section>
|
||||
|
||||
<section id="mongo.executioncallback">
|
||||
<title>Execution callbacks</title>
|
||||
</section>
|
||||
</chapter>
|
||||
</repositories></programlisting>
|
||||
<para>The repository is also
|
||||
<ulink url="http://shrub.appspot.com/maven.springframework.org/milestone/org/springframework/data/">
|
||||
browseable here</ulink>.</para>
|
||||
<para>Create a simple Employee class to persist.</para>
|
||||
<para>
|
||||
<programlisting>package org.spring.cassandra.example;
|
||||
|
||||
import org.springframework.data.cassandra.mapping.PrimaryKey;
|
||||
import org.springframework.data.cassandra.mapping.Table;
|
||||
|
||||
@Table
|
||||
public class Person {
|
||||
|
||||
@PrimaryKey
|
||||
private String id;
|
||||
|
||||
private String name;
|
||||
private int age;
|
||||
|
||||
public Person(String id, String name, int age) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Person [id=" + id + ", name=" + name + ", age=" + age + "]";
|
||||
}
|
||||
|
||||
}</programlisting>
|
||||
</para>
|
||||
<para>And a main application to run</para>
|
||||
<para>
|
||||
<programlisting>package org.spring.cassandra.example;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.data.cassandra.core.CassandraOperations;
|
||||
import org.springframework.data.cassandra.core.CassandraTemplate;
|
||||
|
||||
import com.datastax.driver.core.Cluster;
|
||||
import com.datastax.driver.core.Session;
|
||||
import com.datastax.driver.core.querybuilder.QueryBuilder;
|
||||
import com.datastax.driver.core.querybuilder.Select;
|
||||
|
||||
public class CassandraApp {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(CassandraApp.class);
|
||||
|
||||
private static Cluster cluster;
|
||||
private static Session session;
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
try {
|
||||
|
||||
cluster = Cluster.builder().addContactPoints(InetAddress.getLocalHost()).build();
|
||||
|
||||
session = cluster.connect("mykeyspace");
|
||||
|
||||
CassandraOperations cassandraOps = new CassandraTemplate(session);
|
||||
|
||||
cassandraOps.insert(new Person("1234567890", "David", 40));
|
||||
|
||||
Select s = QueryBuilder.select().from("person");
|
||||
s.where(QueryBuilder.eq("id", "1234567890"));
|
||||
|
||||
LOG.info(cassandraOps.queryForObject(s, Person.class).getId());
|
||||
|
||||
cassandraOps.truncate("person");
|
||||
|
||||
} catch (UnknownHostException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</programlisting>
|
||||
</para>
|
||||
<para>Even in this simple example, there are a few things to
|
||||
observe.</para>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>You can create an instance of CassandraTemplate with a
|
||||
Cassandra Session, derived from the Cluster.</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>You must annotate your POJO as a Cassandra @Table, and also
|
||||
annotate the @PrimaryKey. Optionally you can override these
|
||||
mapping names to match your Cassandra database table and column
|
||||
names.</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>You can use CQL String, or the DataStax QueryBuilder to
|
||||
construct you queries.</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</section>
|
||||
<section>
|
||||
<title>Examples Repository</title>
|
||||
<para>After the initial release of Spring Data Cassandra 1.0.0, we
|
||||
will start working on a showcase repository with full examples.</para>
|
||||
</section>
|
||||
<section id="cassandra-connectors">
|
||||
<title>Connecting to Cassandra with Spring</title>
|
||||
</section>
|
||||
<section id="cassandra.auditing">
|
||||
<title>General auditing configuration</title>
|
||||
<para>Auditing support is not available in the current version.</para>
|
||||
</section>
|
||||
<section id="cassandra-template">
|
||||
<title>Introduction to CassandraTemplate</title>
|
||||
<section id="cassandra-template.instantiating" label=" ">
|
||||
<title>Instantiating CassandraTemplate</title>
|
||||
</section>
|
||||
</section>
|
||||
<section id="cassandra-template.save-update-remove">
|
||||
<title>Saving, Updating, and Removing Rows</title>
|
||||
<para><classname>CassandraTemplate</classname> provides a simple way
|
||||
for you to save, update, and delete your domain objects and map those
|
||||
objects to documents stored in Cassandra.</para>
|
||||
<section id="cassandra-template.id-handling">
|
||||
<title>How the Composite Primary Key fields are handled in the
|
||||
mapping layer</title>
|
||||
<para>Cassandra requires that you have at least 1 Partition Key
|
||||
field for a CQL Table. Alternately, you can have one or more
|
||||
Clustering Key fields.</para>
|
||||
<para>TODO With Examples</para>
|
||||
</section>
|
||||
<section id="cassandra-template.type-mapping">
|
||||
<title>Type mapping</title>
|
||||
</section>
|
||||
<section id="cassandra-template.save-insert">
|
||||
<title>Methods for saving and inserting rows</title>
|
||||
</section>
|
||||
<section id="cassandra-template-update">
|
||||
<title>Updating rows in a CQL table</title>
|
||||
</section>
|
||||
<section id="cassandra-template.upserts">
|
||||
<title>Upserting rows in a CQL table</title>
|
||||
</section>
|
||||
<section id="cassandra-template.find-and-upsert">
|
||||
<title>Finding and Upserting rowa in a CQL table</title>
|
||||
</section>
|
||||
<section id="cassandra-template.delete">
|
||||
<title>Methods for removing rows</title>
|
||||
</section>
|
||||
</section>
|
||||
<section id="cassandra.query">
|
||||
<title>Querying CQL Tables</title>
|
||||
</section>
|
||||
<section id="cassandra.custom-converters">
|
||||
<title>Overriding default mapping with custom converters</title>
|
||||
<para>In order to have more fine grained control over the mapping
|
||||
process you can register Spring converters with the <classname>
|
||||
CassandraConverter</classname> implementations such as the <classname>
|
||||
MappingCassandraConverter</classname>.</para>
|
||||
<para>The <classname>MappingCassandraConverter</classname> checks to
|
||||
see if there are any Spring converters that can handle a specific
|
||||
class before attempting to map the object itself. To
|
||||
'hijack' the normal mapping strategies of the <classname>
|
||||
MappingCassandraConverter</classname>, perhaps for increased
|
||||
performance or other custom mapping needs, you first need to create
|
||||
an implementation of the Spring <interfacename>
|
||||
Converter</interfacename> interface and then register it with the
|
||||
MappingConverter.</para>
|
||||
<note>
|
||||
<para>For more information on the Spring type conversion service see
|
||||
the reference docs
|
||||
<ulink url="http://docs.spring.io/spring/docs/current/spring-framework-reference/html/validation.html#core-convert">
|
||||
here</ulink>.</para>
|
||||
</note>
|
||||
<section id="cassandra.custom-converters.writer">
|
||||
<title>Saving using a registered Spring Converter</title>
|
||||
</section>
|
||||
<section id="cassandra.custom-converters.reader">
|
||||
<title>Reading using a Spring Converter</title>
|
||||
</section>
|
||||
<section id="cassandra.custom-converters.xml">
|
||||
<title>Registering Spring Converters with the
|
||||
CassandraConverter</title>
|
||||
</section>
|
||||
<section id="cassandra.converter-disambiguation">
|
||||
<title>Converter disambiguation</title>
|
||||
</section>
|
||||
</section>
|
||||
<section id="cassandra-template.commands">
|
||||
<title>Executing Commands</title>
|
||||
<section id="cassandra-template.commands.execution">
|
||||
<title>Methods for executing commands</title>
|
||||
</section>
|
||||
</section>
|
||||
<section id="cassandra.mapping-usage.events">
|
||||
<title>Lifecycle Events</title>
|
||||
</section>
|
||||
<section id="cassandra.exception">
|
||||
<title>Exception Translation</title>
|
||||
<para>The Spring framework provides exception translation for a wide
|
||||
variety of database and mapping technologies. This has traditionally
|
||||
been for JDBC and JPA. The Spring support for Cassandra extends this
|
||||
feature to the Cassandra Database by providing an implementation of
|
||||
the <classname>
|
||||
org.springframework.dao.support.PersistenceExceptionTranslator</classname>
|
||||
interface.</para>
|
||||
<para>The motivation behind mapping to Spring's
|
||||
<ulink url="http://docs.spring.io/spring/docs/current/spring-framework-reference/html/dao.html#dao-exceptions">
|
||||
consistent data access exception hierarchy</ulink> is that you are
|
||||
then able to write portable and descriptive exception handling code
|
||||
without resorting to coding against Cassandra Exceptions. All of
|
||||
Spring's data access exceptions are inherited from the root
|
||||
<classname>DataAccessException</classname> class so you can be sure
|
||||
that you will be able to catch all database related exception within
|
||||
a single try-catch block.</para>
|
||||
</section>
|
||||
<section id="cassandra.executioncallback">
|
||||
<title>Execution callbacks</title>
|
||||
</section>
|
||||
</chapter>
|
||||
|
||||
Reference in New Issue
Block a user